summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXinyu Chen <xinyu.chen@freescale.com>2012-07-25 16:54:33 +0800
committerXinyu Chen <xinyu.chen@freescale.com>2012-07-25 16:54:33 +0800
commit10ca2f12149b8c3fde9af51da89736529892dc69 (patch)
tree1a5118db41796df0a40c20467f37542e957e87a0
parent3fb99edfabe05a47803eba7f39109b5eb86e25df (diff)
parentcf3095062b75f6e518c6ef8a25b47a5b2ced7668 (diff)
Merge remote branch 'fsl-linux-sdk/imx_3.0.35' into imx_3.0.35_android
Conflicts: arch/arm/configs/imx6_defconfig arch/arm/configs/imx6_updater_defconfig arch/arm/configs/imx6s_defconfig arch/arm/include/asm/dma-mapping.h arch/arm/kernel/smp.c arch/arm/mach-mx6/Kconfig arch/arm/mach-mx6/board-mx6dl_arm2.h arch/arm/mach-mx6/board-mx6dl_sabresd.h arch/arm/mach-mx6/board-mx6q_arm2.c arch/arm/mach-mx6/board-mx6q_arm2.h arch/arm/mach-mx6/board-mx6q_sabreauto.c arch/arm/mach-mx6/board-mx6q_sabreauto.h arch/arm/mach-mx6/board-mx6q_sabrelite.c arch/arm/mach-mx6/board-mx6q_sabresd.c arch/arm/mach-mx6/board-mx6q_sabresd.h arch/arm/mach-mx6/board-mx6sl_arm2.c arch/arm/mach-mx6/board-mx6sl_arm2.h arch/arm/mach-mx6/board-mx6solo_sabreauto.h arch/arm/mach-mx6/bus_freq.c arch/arm/mach-mx6/clock.c arch/arm/mach-mx6/clock_mx6sl.c arch/arm/mach-mx6/cpu.c arch/arm/mach-mx6/crm_regs.h arch/arm/mach-mx6/devices-imx6q.h arch/arm/mach-mx6/devices.c arch/arm/mach-mx6/mx6_anatop_regulator.c arch/arm/mach-mx6/pcie.c arch/arm/mach-mx6/system.c arch/arm/mm/dma-mapping.c arch/arm/plat-mxc/devices/Makefile arch/arm/plat-mxc/devices/platform-imx-dcp.c arch/arm/plat-mxc/devices/platform-imx-ocotp.c arch/arm/plat-mxc/devices/platform-imx-rngb.c arch/arm/plat-mxc/devices/platform-mxc_hdmi.c arch/arm/plat-mxc/include/mach/devices-common.h arch/arm/plat-mxc/include/mach/esdhc.h arch/arm/plat-mxc/include/mach/iomux-mx6dl.h arch/arm/plat-mxc/include/mach/iomux-mx6q.h arch/arm/plat-mxc/include/mach/memory.h arch/arm/plat-mxc/include/mach/mx6.h arch/arm/plat-mxc/include/mach/mxc_edid.h arch/arm/plat-mxc/include/mach/mxc_hdmi.h arch/arm/plat-mxc/system.c drivers/Kconfig drivers/char/hw_random/fsl-rngc.c drivers/cpufreq/Makefile drivers/cpufreq/cpufreq_interactive.c drivers/crypto/Kconfig drivers/crypto/caam/caamalg.c drivers/crypto/caam/compat.h drivers/crypto/caam/ctrl.c drivers/crypto/caam/desc_constr.h drivers/crypto/caam/intern.h drivers/crypto/dcp.c drivers/dma/pch_dma.c drivers/input/keyboard/gpio_keys.c drivers/input/touchscreen/egalax_ts.c drivers/input/touchscreen/max11801_ts.c drivers/media/video/mxc/capture/Kconfig drivers/media/video/mxc/capture/adv7180.c drivers/media/video/mxc/capture/ipu_csi_enc.c drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c drivers/media/video/mxc/capture/mxc_v4l2_capture.c drivers/media/video/mxc/capture/ov5640_mipi.c drivers/media/video/mxc/output/mxc_vout.c drivers/misc/Kconfig drivers/misc/Makefile drivers/mmc/card/block.c drivers/mmc/core/mmc.c drivers/mmc/host/mmci.c drivers/mmc/host/sdhci-esdhc-imx.c drivers/mmc/host/sdhci.c drivers/mmc/host/sdhci.h drivers/mxc/Kconfig drivers/mxc/Makefile drivers/mxc/asrc/mxc_asrc.c drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c drivers/mxc/ipu3/ipu_device.c drivers/mxc/vpu/mxc_vpu.c drivers/net/fec.c drivers/net/wireless/Makefile drivers/power/sabresd_battery.c drivers/regulator/core.c drivers/tty/serial/imx.c drivers/usb/core/hub.c drivers/usb/gadget/arcotg_udc.c drivers/usb/gadget/fsl_updater.c drivers/usb/gadget/inode.c drivers/usb/host/ehci-hub.c drivers/video/mxc/ldb.c drivers/video/mxc/mipi_dsi.c drivers/video/mxc/mxc_dispdrv.c drivers/video/mxc/mxc_dispdrv.h drivers/video/mxc/mxc_edid.c drivers/video/mxc/mxc_elcdif_fb.c drivers/video/mxc/mxc_ipuv3_fb.c drivers/video/mxc/mxc_spdc_fb.c drivers/video/mxc_hdmi.c drivers/watchdog/imx2_wdt.c fs/proc/base.c include/linux/mmc/host.h include/linux/mmc/sdhci.h include/linux/mxc_v4l2.h kernel/power/main.c sound/soc/codecs/mxc_hdmi.c sound/soc/codecs/mxc_spdif.c sound/soc/codecs/wm8962.c sound/soc/imx/Kconfig sound/soc/imx/Makefile sound/soc/imx/imx-cs42888.c sound/soc/imx/imx-esai.c sound/soc/imx/imx-wm8958.c sound/soc/imx/imx-wm8962.c
-rw-r--r--Documentation/HOWTO34
-rw-r--r--Documentation/development-process/5.Posting8
-rw-r--r--Documentation/hwmon/jc4226
-rw-r--r--Documentation/networking/ip-sysctl.txt4
-rw-r--r--Documentation/usb/usbmon.txt14
-rw-r--r--MAINTAINERS2
-rw-r--r--Makefile2
-rw-r--r--arch/alpha/include/asm/futex.h2
-rwxr-xr-xarch/arm/Kconfig2
-rw-r--r--arch/arm/configs/imx6_android_defconfig7
-rw-r--r--arch/arm/configs/imx6_defconfig11
-rw-r--r--arch/arm/configs/imx6_updater_defconfig38
-rw-r--r--arch/arm/configs/imx6s_defconfig12
-rw-r--r--arch/arm/include/asm/dma-mapping.h16
-rw-r--r--arch/arm/include/asm/tls.h4
-rw-r--r--arch/arm/kernel/ptrace.c8
-rw-r--r--arch/arm/kernel/signal.c5
-rw-r--r--arch/arm/kernel/smp.c6
-rw-r--r--arch/arm/kernel/sys_arm.c2
-rw-r--r--arch/arm/mach-dove/common.c3
-rw-r--r--arch/arm/mach-imx/mach-mx21ads.c2
-rw-r--r--arch/arm/mach-kirkwood/common.c3
-rw-r--r--arch/arm/mach-kirkwood/mpp.h320
-rw-r--r--arch/arm/mach-lpc32xx/include/mach/irqs.h2
-rw-r--r--arch/arm/mach-lpc32xx/irq.c25
-rw-r--r--arch/arm/mach-lpc32xx/serial.c20
-rw-r--r--arch/arm/mach-mv78xx0/common.c3
-rw-r--r--arch/arm/mach-mv78xx0/mpp.h226
-rw-r--r--arch/arm/mach-mx6/Kconfig8
-rw-r--r--arch/arm/mach-mx6/board-mx6dl_arm2.h10
-rw-r--r--arch/arm/mach-mx6/board-mx6dl_sabresd.h9
-rw-r--r--arch/arm/mach-mx6/board-mx6q_arm2.c30
-rw-r--r--arch/arm/mach-mx6/board-mx6q_arm2.h10
-rw-r--r--arch/arm/mach-mx6/board-mx6q_sabreauto.c95
-rw-r--r--arch/arm/mach-mx6/board-mx6q_sabreauto.h140
-rw-r--r--arch/arm/mach-mx6/board-mx6q_sabrelite.c30
-rw-r--r--arch/arm/mach-mx6/board-mx6q_sabresd.c34
-rw-r--r--arch/arm/mach-mx6/board-mx6q_sabresd.h18
-rwxr-xr-xarch/arm/mach-mx6/board-mx6sl_arm2.c50
-rwxr-xr-xarch/arm/mach-mx6/board-mx6sl_arm2.h3
-rw-r--r--arch/arm/mach-mx6/board-mx6solo_sabreauto.h142
-rw-r--r--arch/arm/mach-mx6/bus_freq.c186
-rw-r--r--arch/arm/mach-mx6/clock.c19
-rwxr-xr-xarch/arm/mach-mx6/clock_mx6sl.c2
-rw-r--r--arch/arm/mach-mx6/cpu.c2
-rw-r--r--arch/arm/mach-mx6/crm_regs.h1
-rw-r--r--arch/arm/mach-mx6/devices-imx6q.h10
-rw-r--r--arch/arm/mach-mx6/mx6_anatop_regulator.c139
-rw-r--r--arch/arm/mach-mx6/pcie.c18
-rw-r--r--arch/arm/mach-mx6/system.c2
-rw-r--r--arch/arm/mach-omap2/board-4430sdp.c31
-rw-r--r--arch/arm/mach-omap2/board-omap4panda.c22
-rw-r--r--arch/arm/mach-omap2/board-rx51-peripherals.c2
-rw-r--r--arch/arm/mach-omap2/gpmc.c6
-rw-r--r--arch/arm/mach-orion5x/common.c4
-rw-r--r--arch/arm/mach-orion5x/mpp.h4
-rw-r--r--arch/arm/mach-ux500/Kconfig1
-rw-r--r--arch/arm/mm/dma-mapping.c16
-rw-r--r--arch/arm/mm/fault.c4
-rw-r--r--arch/arm/mm/proc-v7.S16
-rw-r--r--arch/arm/oprofile/common.c2
-rwxr-xr-xarch/arm/plat-mxc/devices/Makefile1
-rwxr-xr-xarch/arm/plat-mxc/devices/platform-imx-dcp.c46
-rwxr-xr-xarch/arm/plat-mxc/devices/platform-imx-ocotp.c4
-rw-r--r--arch/arm/plat-mxc/devices/platform-imx-pmu.c44
-rwxr-xr-xarch/arm/plat-mxc/devices/platform-imx-rngb.c11
-rw-r--r--arch/arm/plat-mxc/devices/platform-imx2-wdt.c5
-rw-r--r--arch/arm/plat-mxc/devices/platform-mxc_hdmi.c5
-rwxr-xr-xarch/arm/plat-mxc/include/mach/devices-common.h3
-rw-r--r--arch/arm/plat-mxc/include/mach/iomux-mx6dl.h12
-rw-r--r--arch/arm/plat-mxc/include/mach/iomux-mx6q.h19
-rw-r--r--arch/arm/plat-mxc/include/mach/mx6.h14
-rwxr-xr-xarch/arm/plat-mxc/include/mach/mxc_edid.h28
-rw-r--r--arch/arm/plat-mxc/include/mach/mxc_hdmi.h29
-rwxr-xr-xarch/arm/plat-mxc/pwm.c12
-rw-r--r--arch/arm/plat-mxc/system.c1
-rw-r--r--arch/arm/plat-orion/common.c9
-rw-r--r--arch/arm/plat-orion/include/plat/common.h3
-rw-r--r--arch/arm/plat-orion/mpp.c3
-rw-r--r--arch/arm/plat-s3c24xx/dma.c2
-rw-r--r--arch/avr32/Kconfig1
-rw-r--r--arch/ia64/include/asm/futex.h9
-rw-r--r--arch/ia64/include/asm/unistd.h3
-rw-r--r--arch/ia64/kernel/acpi.c10
-rw-r--r--arch/ia64/kernel/entry.S3
-rw-r--r--arch/m68k/mac/config.c3
-rw-r--r--arch/parisc/include/asm/prefetch.h7
-rw-r--r--arch/parisc/kernel/entry.S28
-rw-r--r--arch/parisc/kernel/pacache.S38
-rw-r--r--arch/parisc/kernel/vmlinux.lds.S6
-rw-r--r--arch/powerpc/include/asm/time.h2
-rw-r--r--arch/powerpc/kernel/irq.c15
-rw-r--r--arch/powerpc/kernel/module_32.c11
-rw-r--r--arch/powerpc/kernel/perf_event.c8
-rw-r--r--arch/powerpc/kernel/time.c9
-rw-r--r--arch/powerpc/platforms/powermac/smp.c2
-rw-r--r--arch/powerpc/platforms/pseries/hvCall_inst.c4
-rw-r--r--arch/powerpc/platforms/pseries/lpar.c2
-rw-r--r--arch/s390/Kconfig4
-rw-r--r--arch/s390/include/asm/compat.h7
-rw-r--r--arch/s390/include/asm/pgalloc.h3
-rw-r--r--arch/s390/include/asm/tlb.h22
-rw-r--r--arch/s390/kernel/process.c1
-rw-r--r--arch/s390/kernel/ptrace.c2
-rw-r--r--arch/s390/kernel/setup.c1
-rw-r--r--arch/s390/mm/fault.c15
-rw-r--r--arch/s390/mm/mmap.c2
-rw-r--r--arch/s390/mm/pgtable.c63
-rw-r--r--arch/s390/oprofile/init.c2
-rw-r--r--arch/score/kernel/entry.S2
-rw-r--r--arch/sh/oprofile/common.c4
-rw-r--r--arch/sparc/Kconfig3
-rw-r--r--arch/sparc/Makefile2
-rw-r--r--arch/sparc/include/asm/pgtable_32.h20
-rw-r--r--arch/sparc/include/asm/pgtable_64.h20
-rw-r--r--arch/sparc/kernel/central.c2
-rw-r--r--arch/sparc/kernel/ds.c2
-rw-r--r--arch/sparc/kernel/entry.h7
-rw-r--r--arch/sparc/kernel/module.c27
-rw-r--r--arch/sparc/kernel/pci_sun4v.c4
-rw-r--r--arch/sparc/kernel/rtrap_64.S7
-rw-r--r--arch/sparc/kernel/setup_64.c48
-rw-r--r--arch/sparc/kernel/signal32.c18
-rw-r--r--arch/sparc/kernel/signal_32.c30
-rw-r--r--arch/sparc/kernel/signal_64.c42
-rw-r--r--arch/sparc/kernel/systbls_64.S2
-rw-r--r--arch/sparc/kernel/visemul.c32
-rw-r--r--arch/sparc/lib/memcpy.S804
-rw-r--r--arch/sparc/mm/Makefile1
-rw-r--r--arch/sparc/mm/btfixup.c3
-rw-r--r--arch/sparc/mm/generic_32.c98
-rw-r--r--arch/sparc/mm/generic_64.c164
-rw-r--r--arch/sparc/mm/ultra.S6
-rw-r--r--arch/tile/Kconfig1
-rw-r--r--arch/tile/include/asm/bitops.h12
-rw-r--r--arch/tile/kernel/compat_signal.c12
-rw-r--r--arch/um/include/asm/pgtable.h10
-rw-r--r--arch/x86/crypto/aesni-intel_asm.S6
-rw-r--r--arch/x86/include/asm/amd_nb.h2
-rw-r--r--arch/x86/include/asm/i387.h284
-rw-r--r--arch/x86/include/asm/kvm_emulate.h16
-rw-r--r--arch/x86/include/asm/pgtable-3level.h50
-rw-r--r--arch/x86/include/asm/processor.h1
-rw-r--r--arch/x86/include/asm/thread_info.h2
-rw-r--r--arch/x86/include/asm/timer.h8
-rw-r--r--arch/x86/include/asm/uv/uv_hub.h4
-rw-r--r--arch/x86/kernel/amd_iommu_init.c24
-rw-r--r--arch/x86/kernel/amd_nb.c31
-rw-r--r--arch/x86/kernel/apic/apic.c34
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c7
-rw-r--r--arch/x86/kernel/cpu/intel_cacheinfo.c44
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce-severity.c16
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_amd.c55
-rw-r--r--arch/x86/kernel/cpu/perf_event_amd.c11
-rw-r--r--arch/x86/kernel/entry_32.S17
-rw-r--r--arch/x86/kernel/kgdb.c60
-rw-r--r--arch/x86/kernel/microcode_amd.c24
-rw-r--r--arch/x86/kernel/process_32.c25
-rw-r--r--arch/x86/kernel/process_64.c29
-rw-r--r--arch/x86/kernel/setup_percpu.c14
-rw-r--r--arch/x86/kernel/tls.c4
-rw-r--r--arch/x86/kernel/traps.c41
-rw-r--r--arch/x86/kernel/tsc.c13
-rw-r--r--arch/x86/kernel/vm86_32.c2
-rw-r--r--arch/x86/kernel/xsave.c12
-rw-r--r--arch/x86/kvm/emulate.c51
-rw-r--r--arch/x86/kvm/vmx.c2
-rw-r--r--arch/x86/kvm/x86.c23
-rw-r--r--arch/x86/lib/delay.c4
-rw-r--r--arch/x86/mm/mmap.c4
-rw-r--r--arch/x86/mm/srat.c4
-rw-r--r--arch/x86/net/bpf_jit_comp.c50
-rw-r--r--arch/x86/pci/Makefile3
-rw-r--r--arch/x86/pci/acpi.c28
-rw-r--r--arch/x86/pci/amd_bus.c42
-rw-r--r--arch/x86/pci/xen.c2
-rw-r--r--arch/x86/platform/uv/tlb_uv.c13
-rw-r--r--arch/x86/xen/enlighten.c7
-rw-r--r--arch/x86/xen/mmu.c7
-rw-r--r--arch/x86/xen/smp.c15
-rw-r--r--arch/x86/xen/xen-asm.S2
-rw-r--r--block/blk-core.c14
-rw-r--r--block/bsg.c3
-rw-r--r--block/cfq-iosched.c16
-rw-r--r--block/genhd.c52
-rw-r--r--block/scsi_ioctl.c52
-rw-r--r--crypto/sha512_generic.c61
-rw-r--r--drivers/acpi/acpica/acobject.h1
-rw-r--r--drivers/acpi/acpica/dsargs.c26
-rw-r--r--drivers/acpi/acpica/excreate.c6
-rw-r--r--drivers/acpi/acpica/tbfadt.c8
-rw-r--r--drivers/acpi/battery.c10
-rw-r--r--drivers/acpi/numa.c6
-rw-r--r--drivers/acpi/pci_root.c7
-rw-r--r--drivers/acpi/processor_core.c26
-rw-r--r--drivers/acpi/processor_thermal.c45
-rw-r--r--drivers/acpi/sleep.c24
-rw-r--r--drivers/acpi/video.c5
-rw-r--r--drivers/ata/ahci.c2
-rw-r--r--drivers/ata/ahci_platform.c66
-rw-r--r--drivers/ata/libata-eh.c3
-rw-r--r--drivers/ata/pata_legacy.c3
-rw-r--r--drivers/atm/solos-pci.c4
-rw-r--r--drivers/base/core.c6
-rw-r--r--drivers/base/firmware_class.c14
-rw-r--r--drivers/block/cciss.c6
-rw-r--r--drivers/block/cciss_scsi.c3
-rw-r--r--drivers/block/sx8.c2
-rw-r--r--drivers/block/ub.c3
-rw-r--r--drivers/block/virtio_blk.c4
-rw-r--r--drivers/bluetooth/ath3k.c13
-rw-r--r--drivers/bluetooth/btusb.c29
-rw-r--r--drivers/bluetooth/hci_ldisc.c4
-rw-r--r--drivers/cdrom/cdrom.c11
-rw-r--r--drivers/char/agp/intel-agp.c1
-rw-r--r--drivers/char/agp/intel-agp.h1
-rw-r--r--drivers/char/hw_random/fsl-rngc.c4
-rw-r--r--drivers/cpufreq/Makefile2
-rw-r--r--drivers/cpufreq/cpufreq_interactive.c72
-rw-r--r--drivers/cpufreq/powernow-k8.c30
-rw-r--r--drivers/crypto/Kconfig11
-rw-r--r--drivers/crypto/caam/Kconfig41
-rw-r--r--drivers/crypto/caam/Makefile5
-rw-r--r--drivers/crypto/caam/caamalg.c833
-rw-r--r--drivers/crypto/caam/caamhash.c1962
-rw-r--r--drivers/crypto/caam/caamrng.c381
-rw-r--r--drivers/crypto/caam/compat.h2
-rw-r--r--drivers/crypto/caam/ctrl.c158
-rw-r--r--drivers/crypto/caam/desc.h2293
-rw-r--r--drivers/crypto/caam/desc_constr.h64
-rw-r--r--drivers/crypto/caam/error.c5
-rw-r--r--drivers/crypto/caam/intern.h24
-rw-r--r--drivers/crypto/caam/key_gen.c124
-rw-r--r--drivers/crypto/caam/key_gen.h17
-rw-r--r--drivers/crypto/caam/regs.h129
-rw-r--r--drivers/crypto/caam/sg_sw_sec4.h165
-rw-r--r--drivers/crypto/dcp.c4
-rw-r--r--drivers/crypto/mv_cesa.c1
-rw-r--r--drivers/dma/Kconfig13
-rw-r--r--drivers/dma/at_hdmac.c8
-rw-r--r--drivers/dma/at_hdmac_regs.h17
-rw-r--r--drivers/dma/pch_dma.c137
-rw-r--r--drivers/firewire/core-cdev.c24
-rw-r--r--drivers/firewire/core-device.c15
-rw-r--r--drivers/firewire/ohci.c11
-rw-r--r--drivers/firmware/efivars.c222
-rwxr-xr-xdrivers/gpio/Kconfig11
-rw-r--r--drivers/gpio/pca953x.c6
-rw-r--r--drivers/gpio/pch_gpio.c1
-rw-r--r--drivers/gpu/drm/drm_auth.c6
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c8
-rw-r--r--drivers/gpu/drm/drm_fops.c5
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c10
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c9
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h3
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c8
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c22
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h31
-rw-r--r--drivers/gpu/drm/i915/i915_suspend.c4
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c23
-rw-r--r--drivers/gpu/drm/i915/intel_display.c43
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c1
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h2
-rw-r--r--drivers/gpu/drm/i915/intel_fb.c10
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c8
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c16
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c2
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c54
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo_regs.h5
-rw-r--r--drivers/gpu/drm/i915/intel_tv.c21
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c23
-rw-r--r--drivers/gpu/drm/radeon/atom.c15
-rw-r--r--drivers/gpu/drm/radeon/atom.h1
-rw-r--r--drivers/gpu/drm/radeon/atombios_crtc.c4
-rw-r--r--drivers/gpu/drm/radeon/evergreen.c21
-rw-r--r--drivers/gpu/drm/radeon/evergreend.h1
-rw-r--r--drivers/gpu/drm/radeon/r100.c9
-rw-r--r--drivers/gpu/drm/radeon/r600_blit_shaders.c8
-rw-r--r--drivers/gpu/drm/radeon/r600_hdmi.c7
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c24
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c6
-rw-r--r--drivers/gpu/drm/radeon/radeon_cursor.c13
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c9
-rw-r--r--drivers/gpu/drm/radeon/radeon_i2c.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_irq_kms.c12
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.c18
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.h2
-rw-r--r--drivers/gpu/drm/radeon/rs600.c8
-rw-r--r--drivers/gpu/drm/radeon/rv770.c2
-rw-r--r--drivers/gpu/drm/radeon/rv770d.h1
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c1
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c2
-rw-r--r--drivers/hid/hid-chicony.c7
-rw-r--r--drivers/hid/hid-core.c15
-rw-r--r--drivers/hid/hid-ids.h18
-rw-r--r--drivers/hid/hid-multitouch.c32
-rw-r--r--drivers/hid/usbhid/hid-quirks.c1
-rwxr-xr-xdrivers/hwmon/Kconfig5
-rw-r--r--drivers/hwmon/ads1015.c3
-rw-r--r--drivers/hwmon/coretemp.c6
-rw-r--r--drivers/hwmon/f71805f.c10
-rw-r--r--drivers/hwmon/f75375s.c9
-rw-r--r--drivers/hwmon/fam15h_power.c52
-rw-r--r--drivers/hwmon/jc42.c30
-rw-r--r--drivers/hwmon/max6639.c22
-rw-r--r--drivers/hwmon/pmbus_core.c3
-rw-r--r--drivers/hwmon/sht15.c3
-rw-r--r--drivers/hwmon/w83627ehf.c41
-rw-r--r--drivers/i2c/algos/i2c-algo-bit.c8
-rw-r--r--drivers/i2c/busses/i2c-ali1535.c11
-rw-r--r--drivers/i2c/busses/i2c-davinci.c2
-rw-r--r--drivers/i2c/busses/i2c-eg20t.c2
-rw-r--r--drivers/i2c/busses/i2c-mxs.c13
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c2
-rw-r--r--drivers/i2c/busses/i2c-omap.c2
-rw-r--r--drivers/i2c/busses/i2c-pnx.c3
-rw-r--r--drivers/i2c/busses/i2c-sis5595.c4
-rw-r--r--drivers/i2c/busses/i2c-sis630.c6
-rw-r--r--drivers/i2c/busses/i2c-viapro.c7
-rw-r--r--drivers/ide/ide-floppy_ioctl.c3
-rw-r--r--drivers/idle/intel_idle.c9
-rw-r--r--drivers/infiniband/core/addr.c16
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.c16
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c52
-rw-r--r--drivers/infiniband/hw/mlx4/mad.c7
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c2
-rw-r--r--drivers/infiniband/hw/nes/nes_cm.c8
-rw-r--r--drivers/infiniband/hw/qib/qib_iba6120.c4
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7220.c4
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7322.c6
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h6
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c100
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c23
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.c18
-rw-r--r--drivers/infiniband/ulp/iser/iscsi_iser.h1
-rw-r--r--drivers/infiniband/ulp/iser/iser_initiator.c30
-rw-r--r--drivers/input/mouse/alps.c7
-rw-r--r--drivers/input/mouse/synaptics.c11
-rwxr-xr-xdrivers/input/touchscreen/max11801_ts.c8
-rw-r--r--drivers/isdn/gigaset/capi.c22
-rw-r--r--drivers/md/bitmap.c4
-rw-r--r--drivers/md/dm-crypt.c38
-rw-r--r--drivers/md/dm-exception-store.c2
-rw-r--r--drivers/md/dm-flakey.c11
-rw-r--r--drivers/md/dm-io.c23
-rw-r--r--drivers/md/dm-linear.c12
-rw-r--r--drivers/md/dm-mpath.c6
-rw-r--r--drivers/md/dm-raid.c1
-rw-r--r--drivers/md/md.c4
-rw-r--r--drivers/md/raid1.c17
-rw-r--r--drivers/md/raid10.c17
-rw-r--r--drivers/media/dvb/frontends/lgdt330x.c6
-rw-r--r--drivers/media/dvb/siano/smsusb.c2
-rw-r--r--drivers/media/rc/ene_ir.c32
-rw-r--r--drivers/media/rc/fintek-cir.c20
-rw-r--r--drivers/media/rc/ite-cir.c20
-rw-r--r--drivers/media/rc/nuvoton-cir.c36
-rw-r--r--drivers/media/rc/winbond-cir.c79
-rw-r--r--drivers/media/video/hdpvr/hdpvr-video.c3
-rw-r--r--drivers/media/video/mxc/capture/Kconfig7
-rw-r--r--drivers/media/video/mxc/capture/adv7180.c197
-rw-r--r--drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c76
-rw-r--r--drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c20
-rw-r--r--drivers/media/video/mxc/capture/mxc_v4l2_capture.c45
-rw-r--r--drivers/media/video/mxc/capture/ov5640_mipi.c4
-rw-r--r--drivers/media/video/mxc/output/mxc_vout.c58
-rw-r--r--drivers/media/video/pvrusb2/pvrusb2-devattr.c10
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.c2
-rw-r--r--drivers/media/video/uvc/uvc_v4l2.c11
-rw-r--r--drivers/media/video/uvc/uvcvideo.h1
-rw-r--r--drivers/media/video/v4l2-ioctl.c4
-rw-r--r--drivers/mfd/cs5535-mfd.c6
-rw-r--r--drivers/mfd/mfd-core.c2
-rw-r--r--drivers/mfd/twl-core.c16
-rw-r--r--drivers/mfd/twl4030-madc.c35
-rw-r--r--drivers/mfd/twl6030-irq.c13
-rw-r--r--drivers/misc/cb710/core.c1
-rw-r--r--drivers/misc/cs5535-mfgpt.c2
-rw-r--r--drivers/misc/kgdbts.c160
-rw-r--r--drivers/misc/pch_phub.c62
-rw-r--r--drivers/mmc/card/block.c92
-rw-r--r--drivers/mmc/core/bus.c1
-rw-r--r--drivers/mmc/core/core.c19
-rw-r--r--drivers/mmc/core/mmc.c2
-rw-r--r--drivers/mmc/core/sd.c32
-rw-r--r--drivers/mmc/core/sd_ops.c43
-rw-r--r--drivers/mmc/core/sd_ops.h1
-rw-r--r--drivers/mmc/core/sdio.c2
-rwxr-xr-xdrivers/mmc/core/sdio_io.c33
-rw-r--r--drivers/mmc/core/sdio_irq.c11
-rw-r--r--drivers/mmc/host/atmel-mci.c9
-rw-r--r--drivers/mmc/host/mmci.c14
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c161
-rwxr-xr-xdrivers/mmc/host/sdhci.c68
-rw-r--r--drivers/mmc/host/sdhci.h5
-rw-r--r--drivers/mmc/host/vub300.c2
-rw-r--r--drivers/mtd/devices/block2mtd.c1
-rw-r--r--drivers/mtd/devices/lart.c1
-rw-r--r--drivers/mtd/devices/m25p80.c1
-rw-r--r--drivers/mtd/devices/sst25l.c1
-rw-r--r--drivers/mtd/mtd_blkdevs.c3
-rw-r--r--drivers/mtd/mtdoops.c5
-rw-r--r--drivers/mtd/nand/nand_bbt.c1
-rw-r--r--drivers/mtd/sm_ftl.c2
-rw-r--r--drivers/mtd/tests/mtd_stresstest.c7
-rw-r--r--drivers/mtd/ubi/cdev.c3
-rw-r--r--drivers/mtd/ubi/debug.h5
-rw-r--r--drivers/mtd/ubi/eba.c6
-rw-r--r--drivers/mtd/ubi/scan.c8
-rw-r--r--drivers/mtd/ubi/ubi.h2
-rw-r--r--drivers/mtd/ubi/wl.c22
-rw-r--r--drivers/mxc/Kconfig1
-rw-r--r--drivers/mxc/Makefile1
-rw-r--r--drivers/mxc/asrc/mxc_asrc.c20
-rwxr-xr-xdrivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c5
-rwxr-xr-xdrivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c54
-rwxr-xr-xdrivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c157
-rwxr-xr-xdrivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h5
-rwxr-xr-xdrivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c10
-rwxr-xr-xdrivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c19
-rwxr-xr-xdrivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h12
-rw-r--r--drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h4
-rwxr-xr-xdrivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h2
-rwxr-xr-xdrivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c65
-rw-r--r--drivers/mxc/hdmi-cec/Kconfig14
-rw-r--r--drivers/mxc/hdmi-cec/Makefile6
-rw-r--r--drivers/mxc/hdmi-cec/mxc_hdmi-cec.c584
-rw-r--r--drivers/mxc/hdmi-cec/mxc_hdmi-cec.h37
-rw-r--r--drivers/mxc/ipu3/ipu_device.c17
-rw-r--r--drivers/mxc/vpu/mxc_vpu.c41
-rw-r--r--drivers/net/3c59x.c2
-rw-r--r--drivers/net/8139cp.c10
-rw-r--r--drivers/net/Kconfig11
-rw-r--r--drivers/net/atl1c/atl1c_main.c4
-rw-r--r--drivers/net/atlx/atl1.c12
-rw-r--r--drivers/net/atlx/atl1.h3
-rw-r--r--drivers/net/atlx/atlx.c2
-rw-r--r--drivers/net/bonding/bond_alb.c27
-rw-r--r--drivers/net/bonding/bond_main.c15
-rw-r--r--drivers/net/can/c_can/c_can.c16
-rw-r--r--drivers/net/can/c_can/c_can.h1
-rw-r--r--drivers/net/cxgb3/cxgb3_offload.c8
-rw-r--r--drivers/net/davinci_emac.c6
-rw-r--r--drivers/net/davinci_mdio.c5
-rw-r--r--drivers/net/dummy.c6
-rw-r--r--drivers/net/e1000/e1000.h2
-rw-r--r--drivers/net/e1000/e1000_main.c18
-rw-r--r--drivers/net/e1000e/e1000.h1
-rw-r--r--drivers/net/e1000e/netdev.c23
-rwxr-xr-xdrivers/net/fec.c1
-rw-r--r--drivers/net/jme.c10
-rw-r--r--drivers/net/jme.h2
-rw-r--r--drivers/net/ks8851_mll.c2
-rw-r--r--drivers/net/ksz884x.c2
-rw-r--r--drivers/net/macvlan.c2
-rw-r--r--drivers/net/pch_gbe/pch_gbe_main.c50
-rw-r--r--drivers/net/pch_gbe/pch_gbe_param.c15
-rw-r--r--drivers/net/phy/mdio-gpio.c2
-rw-r--r--drivers/net/ppp_generic.c26
-rw-r--r--drivers/net/pptp.c4
-rw-r--r--drivers/net/sfc/rx.c4
-rw-r--r--drivers/net/sky2.c42
-rw-r--r--drivers/net/sky2.h1
-rw-r--r--drivers/net/smsc911x.c14
-rw-r--r--drivers/net/sungem.c2
-rw-r--r--drivers/net/tg3.c18
-rw-r--r--drivers/net/usb/asix.c14
-rw-r--r--drivers/net/usb/cdc_eem.c1
-rw-r--r--drivers/net/usb/cdc_ether.c37
-rw-r--r--drivers/net/usb/ipheth.c5
-rw-r--r--drivers/net/usb/sierra_net.c14
-rw-r--r--drivers/net/usb/smsc75xx.c1
-rw-r--r--drivers/net/usb/smsc95xx.c2
-rw-r--r--drivers/net/usb/usbnet.c66
-rw-r--r--drivers/net/usb/zaurus.c12
-rw-r--r--drivers/net/veth.c4
-rw-r--r--drivers/net/via-velocity.c3
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c7
-rw-r--r--drivers/net/vmxnet3/vmxnet3_int.h4
-rw-r--r--drivers/net/wimax/i2400m/netdev.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/ar5008_phy.c25
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_hw.c19
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c6
-rw-r--r--drivers/net/wireless/ath/carl9170/tx.c1
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.c13
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-3945.c7
-rw-r--r--drivers/net/wireless/iwlegacy/iwl3945-base.c11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rxon.c7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-sta.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c10
-rw-r--r--drivers/net/wireless/p54/p54spi.c14
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c28
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c38
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c9
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c3
-rw-r--r--drivers/net/wireless/rtlwifi/pci.c24
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c15
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/fw.c4
-rw-r--r--drivers/net/wireless/wl1251/main.c1
-rw-r--r--drivers/net/wireless/wl1251/sdio.c4
-rw-r--r--drivers/net/wireless/wl1251/spi.c3
-rw-r--r--drivers/net/wireless/wl12xx/boot.c14
-rw-r--r--drivers/net/wireless/wl12xx/cmd.c22
-rw-r--r--drivers/oprofile/oprofile_files.c7
-rw-r--r--drivers/oprofile/oprofilefs.c11
-rw-r--r--drivers/pci/msi.c10
-rw-r--r--drivers/pci/pci-acpi.c1
-rw-r--r--drivers/pci/pcie/aspm.c68
-rw-r--r--drivers/pci/probe.c5
-rw-r--r--drivers/pci/quirks.c34
-rw-r--r--drivers/pcmcia/ds.c4
-rw-r--r--drivers/platform/x86/acer-wmi.c122
-rw-r--r--drivers/platform/x86/sony-laptop.c2
-rw-r--r--drivers/pnp/pnpacpi/core.c7
-rw-r--r--drivers/pnp/quirks.c42
-rwxr-xr-xdrivers/power/sabresd_battery.c123
-rw-r--r--drivers/regulator/88pm8607.c6
-rw-r--r--drivers/regulator/max8997.c2
-rw-r--r--drivers/regulator/tps6524x-regulator.c2
-rw-r--r--drivers/rtc/interface.c39
-rw-r--r--drivers/rtc/rtc-m41t80.c9
-rw-r--r--drivers/rtc/rtc-pl031.c21
-rw-r--r--drivers/s390/block/dasd_eckd.c2
-rw-r--r--drivers/s390/block/dasd_ioctl.c1
-rw-r--r--drivers/s390/char/fs3270.c1
-rw-r--r--drivers/s390/char/vmcp.c1
-rw-r--r--drivers/s390/cio/chsc_sch.c1
-rw-r--r--drivers/s390/net/qeth_l3_main.c25
-rw-r--r--drivers/s390/scsi/zfcp_cfdc.c1
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c4
-rw-r--r--drivers/scsi/cxgbi/cxgb3i/cxgb3i.c2
-rw-r--r--drivers/scsi/cxgbi/cxgb4i/cxgb4i.c2
-rw-r--r--drivers/scsi/cxgbi/libcxgbi.c4
-rw-r--r--drivers/scsi/fcoe/fcoe.c1
-rw-r--r--drivers/scsi/hpsa.c38
-rw-r--r--drivers/scsi/isci/init.c2
-rw-r--r--drivers/scsi/libsas/sas_expander.c26
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c148
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h4
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c14
-rw-r--r--drivers/scsi/osd/osd_uld.c4
-rw-r--r--drivers/scsi/scsi_lib.c11
-rw-r--r--drivers/scsi/scsi_pm.c16
-rw-r--r--drivers/scsi/scsi_priv.h1
-rw-r--r--drivers/scsi/scsi_scan.c4
-rw-r--r--drivers/scsi/scsi_wait_scan.c2
-rw-r--r--drivers/scsi/sd.c13
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c4
-rw-r--r--drivers/spi/spi.c2
-rw-r--r--drivers/ssb/driver_pcicore.c8
-rw-r--r--drivers/staging/asus_oled/asus_oled.c13
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wlc_bmac.c3
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wlc_bmac.h1
-rw-r--r--drivers/staging/brcm80211/brcmsmac/wlc_main.c8
-rw-r--r--drivers/staging/comedi/comedi_fops.c2
-rw-r--r--drivers/staging/iio/magnetometer/hmc5843.c4
-rw-r--r--drivers/staging/lirc/lirc_serial.c100
-rw-r--r--drivers/staging/rtl8712/usb_intf.c1
-rw-r--r--drivers/target/loopback/tcm_loop.c6
-rw-r--r--drivers/target/target_core_alua.c7
-rw-r--r--drivers/target/target_core_cdb.c14
-rw-r--r--drivers/target/target_core_pr.c5
-rw-r--r--drivers/target/target_core_transport.c22
-rw-r--r--drivers/target/tcm_fc/tfc_cmd.c6
-rw-r--r--drivers/tty/amiserial.c4
-rw-r--r--drivers/tty/moxa.c2
-rw-r--r--drivers/tty/serial/8250_pci.c10
-rw-r--r--drivers/tty/serial/altera_uart.c4
-rw-r--r--drivers/tty/serial/amba-pl011.c29
-rw-r--r--drivers/tty/serial/atmel_serial.c5
-rw-r--r--drivers/tty/serial/clps711x.c14
-rw-r--r--drivers/tty/serial/imx.c16
-rw-r--r--drivers/tty/serial/jsm/jsm_driver.c1
-rw-r--r--drivers/tty/serial/mxs-auart.c2
-rw-r--r--drivers/tty/serial/pch_uart.c7
-rw-r--r--drivers/tty/serial/serial_core.c1
-rw-r--r--drivers/tty/serial/sh-sci.c15
-rw-r--r--drivers/tty/tty_port.c12
-rw-r--r--drivers/tty/vt/consolemap.c51
-rw-r--r--drivers/tty/vt/vt_ioctl.c1
-rw-r--r--drivers/usb/class/cdc-acm.c16
-rw-r--r--drivers/usb/class/cdc-wdm.c81
-rw-r--r--drivers/usb/core/devio.c33
-rw-r--r--drivers/usb/core/hcd-pci.c14
-rw-r--r--drivers/usb/core/hcd.c11
-rw-r--r--drivers/usb/core/hub.c41
-rw-r--r--drivers/usb/core/message.c17
-rw-r--r--drivers/usb/core/quirks.c8
-rwxr-xr-xdrivers/usb/gadget/Kconfig7
-rwxr-xr-xdrivers/usb/gadget/arcotg_udc.c4
-rw-r--r--drivers/usb/gadget/f_fs.c2
-rw-r--r--drivers/usb/gadget/f_loopback.c2
-rw-r--r--drivers/usb/gadget/f_mass_storage.c2
-rw-r--r--drivers/usb/gadget/file_storage.c11
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c20
-rw-r--r--drivers/usb/gadget/fsl_updater.c4
-rw-r--r--drivers/usb/gadget/hid.c6
-rw-r--r--drivers/usb/gadget/inode.c1
-rw-r--r--drivers/usb/gadget/pch_udc.c97
-rw-r--r--drivers/usb/gadget/uvc.h2
-rw-r--r--drivers/usb/gadget/uvc_v4l2.c2
-rw-r--r--drivers/usb/host/ehci-fsl.c6
-rwxr-xr-xdrivers/usb/host/ehci-fsl.h1
-rw-r--r--drivers/usb/host/ehci-hcd.c9
-rw-r--r--drivers/usb/host/ehci-hub.c4
-rw-r--r--drivers/usb/host/ehci-pci.c12
-rw-r--r--drivers/usb/host/ehci-q.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c15
-rw-r--r--drivers/usb/host/ohci-pci.c26
-rw-r--r--drivers/usb/host/ohci.h1
-rw-r--r--drivers/usb/host/pci-quirks.c95
-rw-r--r--drivers/usb/host/uhci-q.c2
-rw-r--r--drivers/usb/host/whci/qset.c4
-rw-r--r--drivers/usb/host/xhci-ext-caps.h5
-rw-r--r--drivers/usb/host/xhci-hub.c2
-rw-r--r--drivers/usb/host/xhci-mem.c42
-rw-r--r--drivers/usb/host/xhci-pci.c3
-rw-r--r--drivers/usb/host/xhci-ring.c33
-rw-r--r--drivers/usb/host/xhci.c18
-rw-r--r--drivers/usb/host/xhci.h6
-rw-r--r--drivers/usb/misc/isight_firmware.c6
-rw-r--r--drivers/usb/misc/usbsevseg.c2
-rw-r--r--drivers/usb/misc/usbtest.c17
-rw-r--r--drivers/usb/misc/yurex.c10
-rw-r--r--drivers/usb/musb/musb_core.c2
-rw-r--r--drivers/usb/musb/musb_gadget.c18
-rw-r--r--drivers/usb/musb/omap2430.c9
-rw-r--r--drivers/usb/serial/cp210x.c157
-rw-r--r--drivers/usb/serial/ftdi_sio.c46
-rw-r--r--drivers/usb/serial/ftdi_sio.h3
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h47
-rw-r--r--drivers/usb/serial/generic.c4
-rw-r--r--drivers/usb/serial/io_ti.c10
-rw-r--r--drivers/usb/serial/mos7840.c83
-rw-r--r--drivers/usb/serial/omninet.c2
-rw-r--r--drivers/usb/serial/option.c72
-rw-r--r--drivers/usb/serial/pl2303.c2
-rw-r--r--drivers/usb/serial/qcaux.c7
-rw-r--r--drivers/usb/serial/qcserial.c109
-rw-r--r--drivers/usb/serial/sierra.c5
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.c8
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.h5
-rw-r--r--drivers/usb/serial/usb-serial.c8
-rw-r--r--drivers/usb/storage/unusual_devs.h7
-rw-r--r--drivers/usb/storage/usb.c90
-rw-r--r--drivers/usb/storage/usb.h7
-rw-r--r--drivers/uwb/hwa-rc.c3
-rw-r--r--drivers/uwb/neh.c12
-rw-r--r--drivers/video/atmel_lcdfb.c2
-rw-r--r--drivers/video/backlight/tosa_lcd.c2
-rw-r--r--drivers/video/fbmem.c18
-rw-r--r--drivers/video/mxc/mxc_edid.c160
-rw-r--r--drivers/video/mxc/mxc_spdc_fb.c22
-rw-r--r--drivers/video/mxc_hdmi.c39
-rw-r--r--drivers/video/offb.c52
-rw-r--r--drivers/video/omap2/dss/hdmi.c86
-rw-r--r--drivers/video/udlfb.c2
-rw-r--r--drivers/video/uvesafb.c11
-rw-r--r--drivers/watchdog/hpwdt.c6
-rw-r--r--drivers/watchdog/imx2_wdt.c68
-rw-r--r--drivers/xen/gntdev.c2
-rw-r--r--drivers/xen/swiotlb-xen.c2
-rw-r--r--drivers/xen/xenbus/xenbus_probe_frontend.c69
-rw-r--r--drivers/xen/xenbus/xenbus_xs.c6
-rw-r--r--fs/afs/internal.h2
-rw-r--r--fs/afs/rxrpc.c3
-rw-r--r--fs/aio.c52
-rw-r--r--fs/autofs4/autofs_i.h11
-rw-r--r--fs/autofs4/dev-ioctl.c2
-rw-r--r--fs/autofs4/inode.c2
-rw-r--r--fs/autofs4/waitq.c2
-rw-r--r--fs/binfmt_elf.c2
-rw-r--r--fs/block_dev.c22
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/buffer.c4
-rw-r--r--fs/cifs/cifsglob.h1
-rw-r--r--fs/cifs/connect.c3
-rw-r--r--fs/cifs/dir.c20
-rw-r--r--fs/cifs/file.c57
-rw-r--r--fs/cifs/sess.c7
-rw-r--r--fs/dcache.c17
-rw-r--r--fs/ecryptfs/crypto.c49
-rw-r--r--fs/ecryptfs/inode.c50
-rw-r--r--fs/ecryptfs/miscdev.c56
-rw-r--r--fs/ecryptfs/read_write.c23
-rw-r--r--fs/eventpoll.c268
-rw-r--r--fs/ext3/ialloc.c8
-rw-r--r--fs/ext3/inode.c24
-rw-r--r--fs/ext4/ext4_jbd2.h56
-rw-r--r--fs/ext4/extents.c4
-rw-r--r--fs/ext4/ialloc.c8
-rw-r--r--fs/ext4/inode.c45
-rw-r--r--fs/ext4/ioctl.c13
-rw-r--r--fs/ext4/mballoc.c6
-rw-r--r--fs/ext4/super.c11
-rw-r--r--fs/ext4/xattr.c7
-rw-r--r--fs/fuse/dir.c1
-rw-r--r--fs/fuse/fuse_i.h3
-rw-r--r--fs/fuse/inode.c17
-rw-r--r--fs/hfsplus/catalog.c4
-rw-r--r--fs/hfsplus/dir.c11
-rw-r--r--fs/hugetlbfs/inode.c25
-rw-r--r--fs/jbd2/commit.c4
-rw-r--r--fs/jbd2/transaction.c2
-rw-r--r--fs/jffs2/gc.c2
-rw-r--r--fs/lockd/clnt4xdr.c2
-rw-r--r--fs/lockd/clntxdr.c2
-rw-r--r--fs/lockd/svc.c2
-rw-r--r--fs/namei.c4
-rw-r--r--fs/namespace.c3
-rw-r--r--fs/nfs/callback_proc.c2
-rw-r--r--fs/nfs/delegation.c11
-rw-r--r--fs/nfs/delegation.h1
-rw-r--r--fs/nfs/nfs4_fs.h3
-rw-r--r--fs/nfs/nfs4proc.c57
-rw-r--r--fs/nfs/nfs4state.c35
-rw-r--r--fs/nfs/objlayout/objio_osd.c3
-rw-r--r--fs/nfs/objlayout/objlayout.c10
-rw-r--r--fs/nfs/pnfs.c12
-rw-r--r--fs/nfs/pnfs.h1
-rw-r--r--fs/nfs/super.c51
-rw-r--r--fs/nfsd/export.c2
-rw-r--r--fs/nfsd/nfs3xdr.c22
-rw-r--r--fs/nfsd/nfs4proc.c7
-rw-r--r--fs/nfsd/nfs4state.c23
-rw-r--r--fs/nilfs2/ioctl.c13
-rw-r--r--fs/nilfs2/the_nilfs.c1
-rw-r--r--fs/notify/mark.c8
-rw-r--r--fs/ocfs2/alloc.c2
-rw-r--r--fs/ocfs2/refcounttree.c12
-rw-r--r--fs/ocfs2/suballoc.c4
-rw-r--r--fs/partitions/check.c48
-rw-r--r--fs/pipe.c31
-rw-r--r--fs/proc/base.c227
-rw-r--r--fs/proc/namespaces.c2
-rw-r--r--fs/proc/task_mmu.c12
-rw-r--r--fs/proc/uptime.c9
-rw-r--r--fs/reiserfs/super.c27
-rw-r--r--fs/signalfd.c15
-rw-r--r--fs/splice.c5
-rw-r--r--fs/super.c2
-rw-r--r--fs/sysfs/inode.c11
-rw-r--r--fs/ubifs/debug.h17
-rw-r--r--fs/udf/file.c8
-rw-r--r--fs/udf/inode.c21
-rw-r--r--fs/udf/super.c6
-rw-r--r--fs/xfs/linux-2.6/xfs_acl.c2
-rw-r--r--fs/xfs/linux-2.6/xfs_discard.c4
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c30
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c37
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.h2
-rw-r--r--fs/xfs/xfs_iget.c18
-rw-r--r--fs/xfs/xfs_log_recover.c33
-rw-r--r--fs/xfs/xfs_vnodeops.c3
-rw-r--r--include/acpi/acpi_numa.h1
-rw-r--r--include/asm-generic/pgtable.h79
-rw-r--r--include/asm-generic/poll.h2
-rw-r--r--include/asm-generic/statfs.h2
-rw-r--r--include/asm-generic/unistd.h2
-rw-r--r--include/drm/drmP.h1
-rw-r--r--include/drm/drm_pciids.h2
-rw-r--r--include/linux/ahci_platform.h2
-rw-r--r--include/linux/bitops.h20
-rw-r--r--include/linux/blkdev.h6
-rw-r--r--include/linux/compat.h4
-rw-r--r--include/linux/dcache.h1
-rw-r--r--include/linux/dmapool.h5
-rw-r--r--include/linux/efi.h13
-rw-r--r--include/linux/eventpoll.h1
-rw-r--r--include/linux/fb.h1
-rw-r--r--include/linux/fs.h2
-rw-r--r--include/linux/genhd.h7
-rw-r--r--include/linux/i2c/twl4030-madc.h4
-rw-r--r--include/linux/kernel.h13
-rw-r--r--include/linux/kgdb.h7
-rw-r--r--include/linux/kvm_host.h6
-rw-r--r--include/linux/lglock.h36
-rw-r--r--include/linux/math64.h4
-rw-r--r--include/linux/memcontrol.h6
-rw-r--r--include/linux/mmc/host.h2
-rw-r--r--include/linux/netdevice.h9
-rw-r--r--include/linux/pci-aspm.h4
-rw-r--r--include/linux/pci_regs.h2
-rw-r--r--include/linux/pipe_fs_i.h1
-rw-r--r--include/linux/proportions.h4
-rw-r--r--include/linux/regset.h10
-rw-r--r--include/linux/seqlock.h2
-rw-r--r--include/linux/signalfd.h5
-rw-r--r--include/linux/skbuff.h12
-rw-r--r--include/linux/socket.h2
-rw-r--r--include/linux/sunrpc/svcsock.h2
-rw-r--r--include/linux/usb.h1
-rw-r--r--include/linux/usb/ch11.h10
-rw-r--r--include/linux/usb/ch9.h20
-rw-r--r--include/linux/usb/hcd.h2
-rw-r--r--include/linux/usb/usbnet.h3
-rw-r--r--include/linux/videodev2.h1
-rw-r--r--include/linux/workqueue.h4
-rw-r--r--include/net/arp.h1
-rw-r--r--include/net/bluetooth/hci.h1
-rw-r--r--include/net/dst.h28
-rw-r--r--include/net/flow.h10
-rw-r--r--include/net/inet_sock.h2
-rw-r--r--include/net/netns/generic.h1
-rw-r--r--include/net/route.h4
-rw-r--r--include/net/sch_generic.h9
-rw-r--r--include/net/sctp/sctp.h13
-rw-r--r--include/net/sctp/structs.h4
-rw-r--r--include/target/target_core_base.h1
-rw-r--r--include/trace/events/writeback.h5
-rw-r--r--include/video/omapdss.h5
-rw-r--r--include/xen/interface/io/xs_wire.h3
-rw-r--r--init/do_mounts.c37
-rw-r--r--init/main.c7
-rw-r--r--kernel/cgroup.c11
-rw-r--r--kernel/compat.c63
-rw-r--r--kernel/cred.c2
-rw-r--r--kernel/debug/debug_core.c53
-rw-r--r--kernel/exit.c9
-rw-r--r--kernel/fork.c8
-rw-r--r--kernel/hung_task.c14
-rw-r--r--kernel/irq/autoprobe.c4
-rw-r--r--kernel/irq/chip.c45
-rw-r--r--kernel/irq/internals.h2
-rw-r--r--kernel/irq/manage.c48
-rw-r--r--kernel/irq/migration.c10
-rw-r--r--kernel/kprobes.c8
-rw-r--r--kernel/module.c3
-rw-r--r--kernel/panic.c12
-rw-r--r--kernel/power/hibernate.c7
-rw-r--r--kernel/printk.c6
-rw-r--r--kernel/relay.c10
-rw-r--r--kernel/sched.c62
-rw-r--r--kernel/sched_rt.c5
-rw-r--r--kernel/sysctl.c8
-rw-r--r--kernel/sysctl_binary.c2
-rw-r--r--kernel/time/ntp.c2
-rw-r--r--kernel/time/tick-sched.c4
-rw-r--r--kernel/trace/ftrace.c76
-rw-r--r--kernel/trace/trace_entries.h16
-rw-r--r--kernel/trace/trace_export.c2
-rw-r--r--kernel/workqueue.c16
-rw-r--r--lib/btree.c4
-rw-r--r--lib/kobject_uevent.c19
-rw-r--r--mm/bootmem.c5
-rw-r--r--mm/compaction.c24
-rw-r--r--mm/dmapool.c88
-rw-r--r--mm/filemap.c33
-rw-r--r--mm/filemap_xip.c7
-rw-r--r--mm/huge_memory.c10
-rw-r--r--mm/hugetlb.c34
-rw-r--r--mm/madvise.c16
-rw-r--r--mm/memcontrol.c62
-rw-r--r--mm/memory.c16
-rw-r--r--mm/mempolicy.c43
-rw-r--r--mm/mincore.c2
-rw-r--r--mm/nobootmem.c3
-rw-r--r--mm/nommu.c9
-rw-r--r--mm/oom_kill.c2
-rw-r--r--mm/page_alloc.c11
-rw-r--r--mm/pagewalk.c2
-rw-r--r--mm/percpu.c16
-rw-r--r--mm/slub.c3
-rw-r--r--mm/sparse.c30
-rw-r--r--mm/swap.c2
-rw-r--r--mm/swap_state.c2
-rw-r--r--mm/swapfile.c4
-rw-r--r--mm/vmalloc.c11
-rw-r--r--mm/vmscan.c2
-rw-r--r--net/8021q/vlan_dev.c2
-rw-r--r--net/atm/clip.c16
-rw-r--r--net/ax25/af_ax25.c9
-rw-r--r--net/bluetooth/hci_core.c7
-rw-r--r--net/bridge/br_multicast.c88
-rw-r--r--net/bridge/br_netfilter.c6
-rw-r--r--net/bridge/br_private.h4
-rw-r--r--net/caif/caif_dev.c11
-rw-r--r--net/caif/cfcnfg.c1
-rw-r--r--net/core/dev.c69
-rw-r--r--net/core/dst.c15
-rw-r--r--net/core/neighbour.c21
-rw-r--r--net/core/net_namespace.c64
-rw-r--r--net/core/netpoll.c2
-rw-r--r--net/core/pktgen.c10
-rw-r--r--net/core/skbuff.c4
-rw-r--r--net/core/sock.c7
-rw-r--r--net/decnet/dn_neigh.c8
-rw-r--r--net/decnet/dn_route.c18
-rw-r--r--net/ipv4/ah4.c8
-rw-r--r--net/ipv4/arp.c31
-rw-r--r--net/ipv4/devinet.c5
-rw-r--r--net/ipv4/esp4.c24
-rw-r--r--net/ipv4/fib_semantics.c20
-rw-r--r--net/ipv4/fib_trie.c2
-rw-r--r--net/ipv4/igmp.c2
-rw-r--r--net/ipv4/ip_forward.c2
-rw-r--r--net/ipv4/ip_gre.c2
-rw-r--r--net/ipv4/ip_options.c4
-rw-r--r--net/ipv4/ip_output.c22
-rw-r--r--net/ipv4/ipconfig.c4
-rw-r--r--net/ipv4/ipip.c7
-rw-r--r--net/ipv4/route.c213
-rw-r--r--net/ipv4/syncookies.c30
-rw-r--r--net/ipv4/tcp.c14
-rw-r--r--net/ipv4/tcp_input.c62
-rw-r--r--net/ipv4/tcp_ipv4.c17
-rw-r--r--net/ipv4/tcp_output.c6
-rw-r--r--net/ipv4/xfrm4_mode_beet.c5
-rw-r--r--net/ipv4/xfrm4_mode_tunnel.c6
-rw-r--r--net/ipv6/addrconf.c6
-rw-r--r--net/ipv6/ah6.c8
-rw-r--r--net/ipv6/esp6.c18
-rw-r--r--net/ipv6/ip6_fib.c2
-rw-r--r--net/ipv6/ip6_output.c108
-rw-r--r--net/ipv6/ip6mr.c8
-rw-r--r--net/ipv6/mcast.c3
-rw-r--r--net/ipv6/ndisc.c4
-rw-r--r--net/ipv6/route.c63
-rw-r--r--net/ipv6/sit.c11
-rw-r--r--net/ipv6/tcp_ipv6.c6
-rw-r--r--net/ipv6/xfrm6_mode_beet.c6
-rw-r--r--net/ipv6/xfrm6_mode_tunnel.c6
-rw-r--r--net/l2tp/l2tp_eth.c2
-rw-r--r--net/l2tp/l2tp_ip.c38
-rw-r--r--net/l2tp/l2tp_ppp.c2
-rw-r--r--net/llc/af_llc.c14
-rw-r--r--net/mac80211/agg-rx.c3
-rw-r--r--net/mac80211/agg-tx.c86
-rw-r--r--net/mac80211/iface.c12
-rw-r--r--net/mac80211/main.c4
-rw-r--r--net/mac80211/offchannel.c16
-rw-r--r--net/mac80211/rate.c2
-rw-r--r--net/mac80211/rx.c2
-rw-r--r--net/mac80211/tx.c3
-rw-r--r--net/mac80211/util.c12
-rw-r--r--net/mac80211/wpa.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c2
-rw-r--r--net/netlink/af_netlink.c24
-rw-r--r--net/phonet/pep.c3
-rw-r--r--net/rds/af_rds.c20
-rw-r--r--net/rds/send.c1
-rw-r--r--net/rose/rose_dev.c4
-rw-r--r--net/sched/sch_choke.c3
-rw-r--r--net/sched/sch_gred.c9
-rw-r--r--net/sched/sch_mqprio.c2
-rw-r--r--net/sched/sch_netem.c13
-rw-r--r--net/sched/sch_sfb.c3
-rw-r--r--net/sched/sch_teql.c31
-rw-r--r--net/sctp/associola.c2
-rw-r--r--net/sctp/output.c12
-rw-r--r--net/sctp/outqueue.c6
-rw-r--r--net/sctp/protocol.c3
-rw-r--r--net/sctp/socket.c7
-rw-r--r--net/sctp/sysctl.c13
-rw-r--r--net/sctp/transport.c17
-rw-r--r--net/socket.c6
-rw-r--r--net/sunrpc/cache.c2
-rw-r--r--net/sunrpc/sched.c15
-rw-r--r--net/sunrpc/svc.c20
-rw-r--r--net/sunrpc/svc_xprt.c53
-rw-r--r--net/wireless/nl80211.c29
-rw-r--r--net/wireless/reg.c10
-rw-r--r--net/wireless/util.c21
-rw-r--r--net/xfrm/xfrm_policy.c5
-rw-r--r--net/xfrm/xfrm_replay.c6
-rw-r--r--scripts/kconfig/streamline_config.pl52
-rw-r--r--scripts/mod/file2alias.c4
-rw-r--r--scripts/mod/modpost.c36
-rw-r--r--scripts/mod/modpost.h1
-rw-r--r--scripts/package/builddeb12
-rw-r--r--scripts/recordmcount.h2
-rw-r--r--security/commoncap.c6
-rw-r--r--security/integrity/ima/ima_api.c4
-rw-r--r--security/integrity/ima/ima_queue.c17
-rw-r--r--security/selinux/netport.c4
-rw-r--r--security/selinux/selinuxfs.c1
-rw-r--r--security/tomoyo/mount.c38
-rw-r--r--sound/pci/echoaudio/echoaudio_dsp.c2
-rw-r--r--sound/pci/hda/hda_codec.c10
-rw-r--r--sound/pci/hda/hda_codec.h3
-rw-r--r--sound/pci/hda/hda_intel.c6
-rw-r--r--sound/pci/hda/hda_local.h7
-rw-r--r--sound/pci/hda/hda_proc.c2
-rw-r--r--sound/pci/hda/patch_conexant.c42
-rw-r--r--sound/pci/hda/patch_realtek.c11
-rw-r--r--sound/pci/hda/patch_sigmatel.c12
-rw-r--r--sound/pci/ice1712/amp.c7
-rw-r--r--sound/pci/intel8x0.c6
-rw-r--r--sound/pci/oxygen/xonar_wm87x6.c1
-rw-r--r--sound/soc/codecs/ak4642.c2
-rw-r--r--sound/soc/codecs/mxc_hdmi.c22
-rw-r--r--sound/soc/codecs/mxc_spdif.c6
-rw-r--r--sound/soc/codecs/wm8962.c6
-rw-r--r--sound/soc/codecs/wm_hubs.c18
-rw-r--r--sound/soc/imx/Makefile1
-rw-r--r--sound/soc/imx/imx-cs42888.c2
-rw-r--r--sound/soc/imx/imx-esai.c4
-rw-r--r--sound/soc/imx/imx-ssi.c45
-rw-r--r--sound/soc/imx/imx-ssi.h5
-rwxr-xr-xsound/soc/imx/imx-wm8958.c89
-rw-r--r--sound/soc/imx/imx-wm8962.c7
-rw-r--r--sound/soc/pxa/pxa-ssp.c61
-rw-r--r--sound/soc/samsung/neo1973_wm8753.c4
-rw-r--r--sound/soc/soc-core.c18
-rw-r--r--sound/soc/soc-dapm.c14
-rw-r--r--sound/usb/pcm.c3
-rw-r--r--sound/usb/usx2y/usb_stream.c6
-rw-r--r--tools/perf/bench/mem-memcpy-x86-64-asm.S6
-rw-r--r--tools/perf/util/evsel.c1
-rw-r--r--tools/perf/util/hist.c12
-rw-r--r--tools/perf/util/sort.c3
-rw-r--r--tools/perf/util/trace-event-parse.c2
-rw-r--r--tools/usb/ffs-test.c2
-rw-r--r--virt/kvm/iommu.c12
-rw-r--r--virt/kvm/kvm_main.c5
1022 files changed, 17132 insertions, 8413 deletions
diff --git a/Documentation/HOWTO b/Documentation/HOWTO
index 81bc1a9ab9d8..59c080f084ef 100644
--- a/Documentation/HOWTO
+++ b/Documentation/HOWTO
@@ -218,16 +218,16 @@ The development process
Linux kernel development process currently consists of a few different
main kernel "branches" and lots of different subsystem-specific kernel
branches. These different branches are:
- - main 2.6.x kernel tree
- - 2.6.x.y -stable kernel tree
- - 2.6.x -git kernel patches
+ - main 3.x kernel tree
+ - 3.x.y -stable kernel tree
+ - 3.x -git kernel patches
- subsystem specific kernel trees and patches
- - the 2.6.x -next kernel tree for integration tests
+ - the 3.x -next kernel tree for integration tests
-2.6.x kernel tree
+3.x kernel tree
-----------------
-2.6.x kernels are maintained by Linus Torvalds, and can be found on
-kernel.org in the pub/linux/kernel/v2.6/ directory. Its development
+3.x kernels are maintained by Linus Torvalds, and can be found on
+kernel.org in the pub/linux/kernel/v3.x/ directory. Its development
process is as follows:
- As soon as a new kernel is released a two weeks window is open,
during this period of time maintainers can submit big diffs to
@@ -262,21 +262,21 @@ mailing list about kernel releases:
released according to perceived bug status, not according to a
preconceived timeline."
-2.6.x.y -stable kernel tree
+3.x.y -stable kernel tree
---------------------------
-Kernels with 4-part versions are -stable kernels. They contain
+Kernels with 3-part versions are -stable kernels. They contain
relatively small and critical fixes for security problems or significant
-regressions discovered in a given 2.6.x kernel.
+regressions discovered in a given 3.x kernel.
This is the recommended branch for users who want the most recent stable
kernel and are not interested in helping test development/experimental
versions.
-If no 2.6.x.y kernel is available, then the highest numbered 2.6.x
+If no 3.x.y kernel is available, then the highest numbered 3.x
kernel is the current stable kernel.
-2.6.x.y are maintained by the "stable" team <stable@kernel.org>, and are
-released as needs dictate. The normal release period is approximately
+3.x.y are maintained by the "stable" team <stable@vger.kernel.org>, and
+are released as needs dictate. The normal release period is approximately
two weeks, but it can be longer if there are no pressing problems. A
security-related problem, instead, can cause a release to happen almost
instantly.
@@ -285,7 +285,7 @@ The file Documentation/stable_kernel_rules.txt in the kernel tree
documents what kinds of changes are acceptable for the -stable tree, and
how the release process works.
-2.6.x -git patches
+3.x -git patches
------------------
These are daily snapshots of Linus' kernel tree which are managed in a
git repository (hence the name.) These patches are usually released
@@ -317,13 +317,13 @@ revisions to it, and maintainers can mark patches as under review,
accepted, or rejected. Most of these patchwork sites are listed at
http://patchwork.kernel.org/.
-2.6.x -next kernel tree for integration tests
+3.x -next kernel tree for integration tests
---------------------------------------------
-Before updates from subsystem trees are merged into the mainline 2.6.x
+Before updates from subsystem trees are merged into the mainline 3.x
tree, they need to be integration-tested. For this purpose, a special
testing repository exists into which virtually all subsystem trees are
pulled on an almost daily basis:
- http://git.kernel.org/?p=linux/kernel/git/sfr/linux-next.git
+ http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
http://linux.f-seidel.de/linux-next/pmwiki/
This way, the -next kernel gives a summary outlook onto what will be
diff --git a/Documentation/development-process/5.Posting b/Documentation/development-process/5.Posting
index 903a2546f138..8a48c9b62864 100644
--- a/Documentation/development-process/5.Posting
+++ b/Documentation/development-process/5.Posting
@@ -271,10 +271,10 @@ copies should go to:
the linux-kernel list.
- If you are fixing a bug, think about whether the fix should go into the
- next stable update. If so, stable@kernel.org should get a copy of the
- patch. Also add a "Cc: stable@kernel.org" to the tags within the patch
- itself; that will cause the stable team to get a notification when your
- fix goes into the mainline.
+ next stable update. If so, stable@vger.kernel.org should get a copy of
+ the patch. Also add a "Cc: stable@vger.kernel.org" to the tags within
+ the patch itself; that will cause the stable team to get a notification
+ when your fix goes into the mainline.
When selecting recipients for a patch, it is good to have an idea of who
you think will eventually accept the patch and get it merged. While it
diff --git a/Documentation/hwmon/jc42 b/Documentation/hwmon/jc42
index a22ecf48f255..52729a756c1b 100644
--- a/Documentation/hwmon/jc42
+++ b/Documentation/hwmon/jc42
@@ -7,21 +7,29 @@ Supported chips:
Addresses scanned: I2C 0x18 - 0x1f
Datasheets:
http://www.analog.com/static/imported-files/data_sheets/ADT7408.pdf
- * IDT TSE2002B3, TS3000B3
- Prefix: 'tse2002b3', 'ts3000b3'
+ * Atmel AT30TS00
+ Prefix: 'at30ts00'
Addresses scanned: I2C 0x18 - 0x1f
Datasheets:
- http://www.idt.com/products/getdoc.cfm?docid=18715691
- http://www.idt.com/products/getdoc.cfm?docid=18715692
+ http://www.atmel.com/Images/doc8585.pdf
+ * IDT TSE2002B3, TSE2002GB2, TS3000B3, TS3000GB2
+ Prefix: 'tse2002', 'ts3000'
+ Addresses scanned: I2C 0x18 - 0x1f
+ Datasheets:
+ http://www.idt.com/sites/default/files/documents/IDT_TSE2002B3C_DST_20100512_120303152056.pdf
+ http://www.idt.com/sites/default/files/documents/IDT_TSE2002GB2A1_DST_20111107_120303145914.pdf
+ http://www.idt.com/sites/default/files/documents/IDT_TS3000B3A_DST_20101129_120303152013.pdf
+ http://www.idt.com/sites/default/files/documents/IDT_TS3000GB2A1_DST_20111104_120303151012.pdf
* Maxim MAX6604
Prefix: 'max6604'
Addresses scanned: I2C 0x18 - 0x1f
Datasheets:
http://datasheets.maxim-ic.com/en/ds/MAX6604.pdf
- * Microchip MCP9805, MCP98242, MCP98243, MCP9843
- Prefixes: 'mcp9805', 'mcp98242', 'mcp98243', 'mcp9843'
+ * Microchip MCP9804, MCP9805, MCP98242, MCP98243, MCP9843
+ Prefixes: 'mcp9804', 'mcp9805', 'mcp98242', 'mcp98243', 'mcp9843'
Addresses scanned: I2C 0x18 - 0x1f
Datasheets:
+ http://ww1.microchip.com/downloads/en/DeviceDoc/22203C.pdf
http://ww1.microchip.com/downloads/en/DeviceDoc/21977b.pdf
http://ww1.microchip.com/downloads/en/DeviceDoc/21996a.pdf
http://ww1.microchip.com/downloads/en/DeviceDoc/22153c.pdf
@@ -48,6 +56,12 @@ Supported chips:
Datasheets:
http://www.st.com/stonline/products/literature/ds/13447/stts424.pdf
http://www.st.com/stonline/products/literature/ds/13448/stts424e02.pdf
+ * ST Microelectronics STTS2002, STTS3000
+ Prefix: 'stts2002', 'stts3000'
+ Addresses scanned: I2C 0x18 - 0x1f
+ Datasheets:
+ http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00225278.pdf
+ http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATA_BRIEF/CD00270920.pdf
* JEDEC JC 42.4 compliant temperature sensor chips
Prefix: 'jc42'
Addresses scanned: I2C 0x18 - 0x1f
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index bfe924217f24..7d4ecaa57cfa 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -147,7 +147,7 @@ tcp_adv_win_scale - INTEGER
(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
+ Default: 1
tcp_allowed_congestion_control - STRING
Show/set the congestion control choices available to non-privileged
@@ -407,7 +407,7 @@ tcp_rmem - vector of 3 INTEGERs: min, default, max
net.core.rmem_max. Calling setsockopt() with SO_RCVBUF disables
automatic tuning of that socket's receive buffer size, in which
case this value is ignored.
- Default: between 87380B and 4MB, depending on RAM size.
+ Default: between 87380B and 6MB, depending on RAM size.
tcp_sack - BOOLEAN
Enable select acknowledgments (SACKS).
diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt
index a4efa0462f05..5335fa8b06eb 100644
--- a/Documentation/usb/usbmon.txt
+++ b/Documentation/usb/usbmon.txt
@@ -47,10 +47,11 @@ This allows to filter away annoying devices that talk continuously.
2. Find which bus connects to the desired device
-Run "cat /proc/bus/usb/devices", and find the T-line which corresponds to
-the device. Usually you do it by looking for the vendor string. If you have
-many similar devices, unplug one and compare two /proc/bus/usb/devices outputs.
-The T-line will have a bus number. Example:
+Run "cat /sys/kernel/debug/usb/devices", and find the T-line which corresponds
+to the device. Usually you do it by looking for the vendor string. If you have
+many similar devices, unplug one and compare the two
+/sys/kernel/debug/usb/devices outputs. The T-line will have a bus number.
+Example:
T: Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 0
D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
@@ -58,7 +59,10 @@ P: Vendor=0557 ProdID=2004 Rev= 1.00
S: Manufacturer=ATEN
S: Product=UC100KM V2.00
-Bus=03 means it's bus 3.
+"Bus=03" means it's bus 3. Alternatively, you can look at the output from
+"lsusb" and get the bus number from the appropriate line. Example:
+
+Bus 003 Device 002: ID 0557:2004 ATEN UC100KM V2.00
3. Start 'cat'
diff --git a/MAINTAINERS b/MAINTAINERS
index 34e24186584f..de85391c021a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6039,7 +6039,7 @@ F: arch/alpha/kernel/srm_env.c
STABLE BRANCH
M: Greg Kroah-Hartman <greg@kroah.com>
-L: stable@kernel.org
+L: stable@vger.kernel.org
S: Maintained
STAGING SUBSYSTEM
diff --git a/Makefile b/Makefile
index 5b8c185be2e8..fe910769ed63 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 3
PATCHLEVEL = 0
-SUBLEVEL = 15
+SUBLEVEL = 35
EXTRAVERSION =
NAME = Sneaky Weasel
diff --git a/arch/alpha/include/asm/futex.h b/arch/alpha/include/asm/futex.h
index e8a761aee088..f939794363ac 100644
--- a/arch/alpha/include/asm/futex.h
+++ b/arch/alpha/include/asm/futex.h
@@ -108,7 +108,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
" lda $31,3b-2b(%0)\n"
" .previous\n"
: "+r"(ret), "=&r"(prev), "=&r"(cmp)
- : "r"(uaddr), "r"((long)oldval), "r"(newval)
+ : "r"(uaddr), "r"((long)(int)oldval), "r"(newval)
: "memory");
*uval = prev;
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 28e6a29e95c6..25fa0ede0d1b 100755
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1192,7 +1192,7 @@ config ARM_ERRATA_743622
depends on CPU_V7
help
This option enables the workaround for the 743622 Cortex-A9
- (r2p0..r2p2) erratum. Under very rare conditions, a faulty
+ (r2p*) erratum. Under very rare conditions, a faulty
optimisation in the Cortex-A9 Store Buffer may lead to data
corruption. This workaround sets a specific bit in the diagnostic
register of the Cortex-A9 which disables the Store Buffer
diff --git a/arch/arm/configs/imx6_android_defconfig b/arch/arm/configs/imx6_android_defconfig
index d8d1b11202aa..5439d9c922d2 100644
--- a/arch/arm/configs/imx6_android_defconfig
+++ b/arch/arm/configs/imx6_android_defconfig
@@ -1,6 +1,6 @@
#
# Automatically generated make config: don't edit
-# Linux/arm 3.0.15 Kernel Configuration
+# Linux/arm 3.0.35 Kernel Configuration
#
CONFIG_ARM=y
CONFIG_HAVE_PWM=y
@@ -2594,6 +2594,11 @@ CONFIG_ANATOP_THERMAL=y
CONFIG_MXC_MIPI_CSI2=y
#
+# MXC HDMI CEC (Consumer Electronics Control) support
+#
+# CONFIG_MXC_HDMI_CEC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
diff --git a/arch/arm/configs/imx6_defconfig b/arch/arm/configs/imx6_defconfig
index 5cae7c249854..e032e6cc3de3 100644
--- a/arch/arm/configs/imx6_defconfig
+++ b/arch/arm/configs/imx6_defconfig
@@ -1126,7 +1126,7 @@ CONFIG_VT=y
CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
-# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
@@ -1832,7 +1832,6 @@ CONFIG_SND_SOC_IMX_CS42888=y
# CONFIG_SND_SOC_IMX_SI4763 is not set
CONFIG_SND_SOC_IMX_SPDIF=y
CONFIG_SND_SOC_IMX_HDMI=y
-CONFIG_SND_SOC_IMX_WM8958=y
CONFIG_SND_SOC_I2C_AND_SPI=y
# CONFIG_SND_SOC_ALL_CODECS is not set
CONFIG_SND_SOC_WM_HUBS=y
@@ -2316,6 +2315,11 @@ CONFIG_ANATOP_THERMAL=y
CONFIG_MXC_MIPI_CSI2=y
#
+# MXC HDMI CEC (Consumer Electronics Control) support
+#
+# CONFIG_MXC_HDMI_CEC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -2664,6 +2668,9 @@ CONFIG_CRYPTO_DEV_FSL_CAAM_INTC=y
CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_COUNT_THLD=255
CONFIG_CRYPTO_DEV_FSL_CAAM_INTC_TIME_THLD=2048
CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API=y
+# CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API is not set
+CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API=y
+# CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST is not set
# CONFIG_BINARY_PRINTF is not set
#
diff --git a/arch/arm/configs/imx6_updater_defconfig b/arch/arm/configs/imx6_updater_defconfig
index 56406344b130..5fad815940e8 100644
--- a/arch/arm/configs/imx6_updater_defconfig
+++ b/arch/arm/configs/imx6_updater_defconfig
@@ -23,6 +23,7 @@ CONFIG_ARCH_HAS_CPUFREQ=y
CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_FIQ=y
CONFIG_VECTORS_BASE=0xffff0000
@@ -92,7 +93,6 @@ CONFIG_RD_GZIP=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
-CONFIG_PANIC_TIMEOUT=0
CONFIG_EXPERT=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
@@ -108,7 +108,6 @@ CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
-# CONFIG_ASHMEM is not set
CONFIG_AIO=y
CONFIG_EMBEDDED=y
CONFIG_HAVE_PERF_EVENTS=y
@@ -383,7 +382,6 @@ CONFIG_ARM_ERRATA_751472=y
CONFIG_ARM_ERRATA_754322=y
# CONFIG_ARM_ERRATA_754327 is not set
CONFIG_ARM_GIC=y
-# CONFIG_FIQ_DEBUGGER is not set
#
# Bus support
@@ -433,7 +431,7 @@ CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_COMPACTION is not set
# CONFIG_PHYS_ADDR_T_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=0
+CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
# CONFIG_KSM is not set
@@ -444,7 +442,6 @@ CONFIG_ALIGNMENT_TRAP=y
# CONFIG_SECCOMP is not set
# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_DEPRECATED_PARAM_STRUCT is not set
-# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set
#
# Boot options
@@ -514,7 +511,6 @@ CONFIG_SUSPEND=y
# CONFIG_PM_TEST_SUSPEND is not set
CONFIG_SUSPEND_DEVICE_TIME_DEBUG=y
CONFIG_SUSPEND_FREEZER=y
-# CONFIG_WAKELOCK is not set
CONFIG_PM_SLEEP=y
CONFIG_PM_SLEEP_SMP=y
CONFIG_PM_RUNTIME=y
@@ -524,7 +520,6 @@ CONFIG_PM_DEBUG=y
CONFIG_CAN_PM_TRACE=y
CONFIG_APM_EMULATION=y
CONFIG_PM_RUNTIME_CLK=y
-# CONFIG_SUSPEND_TIME is not set
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_NET=y
@@ -567,8 +562,6 @@ CONFIG_TCP_CONG_CUBIC=y
CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6 is not set
-CONFIG_ANDROID_PARANOID_NETWORK=y
-CONFIG_NET_ACTIVITY_STATS=y
# CONFIG_NETWORK_SECMARK is not set
# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
# CONFIG_NETFILTER is not set
@@ -648,7 +641,6 @@ CONFIG_WIRELESS=y
#
# CONFIG_WIMAX is not set
CONFIG_RFKILL=y
-CONFIG_RFKILL_PM=y
CONFIG_RFKILL_INPUT=y
# CONFIG_RFKILL_REGULATOR is not set
# CONFIG_RFKILL_GPIO is not set
@@ -739,7 +731,6 @@ CONFIG_M25PXX_USE_FAST_READ=y
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
-CONFIG_MTD_NAND_IDS=y
CONFIG_MTD_NAND_ECC=y
# CONFIG_MTD_NAND_ECC_SMC is not set
CONFIG_MTD_NAND=y
@@ -748,6 +739,7 @@ CONFIG_MTD_NAND=y
# CONFIG_MTD_SM_COMMON is not set
# CONFIG_MTD_NAND_MUSEUM_IDS is not set
# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
# CONFIG_MTD_NAND_DISKONCHIP is not set
# CONFIG_MTD_NAND_NANDSIM is not set
# CONFIG_MTD_NAND_GPMI_NAND is not set
@@ -919,9 +911,6 @@ CONFIG_FEC=y
# CONFIG_NETDEV_10000 is not set
CONFIG_WLAN=y
# CONFIG_USB_ZD1201 is not set
-# CONFIG_WIFI_CONTROL_FUNC is not set
-# CONFIG_BCM4329 is not set
-# CONFIG_BCMDHD is not set
# CONFIG_HOSTAP is not set
#
@@ -970,7 +959,6 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set
# CONFIG_INPUT_APMPOWER is not set
-# CONFIG_INPUT_KEYRESET is not set
#
# Input Device Drivers
@@ -1001,7 +989,6 @@ CONFIG_TOUCHSCREEN_EGALAX=y
# CONFIG_TOUCHSCREEN_INEXIO is not set
# CONFIG_TOUCHSCREEN_MK712 is not set
# CONFIG_TOUCHSCREEN_PENMOUNT is not set
-# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI is not set
# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
# CONFIG_TOUCHSCREEN_WM97XX is not set
@@ -1017,13 +1004,11 @@ CONFIG_INPUT_MISC=y
# CONFIG_INPUT_AD714X is not set
# CONFIG_INPUT_ATI_REMOTE is not set
# CONFIG_INPUT_ATI_REMOTE2 is not set
-# CONFIG_INPUT_KEYCHORD is not set
# CONFIG_INPUT_KEYSPAN_REMOTE is not set
# CONFIG_INPUT_POWERMATE is not set
# CONFIG_INPUT_YEALINK is not set
# CONFIG_INPUT_CM109 is not set
CONFIG_INPUT_UINPUT=y
-# CONFIG_INPUT_GPIO is not set
# CONFIG_INPUT_PCF8574 is not set
# CONFIG_INPUT_PWM_BEEPER is not set
# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
@@ -1052,7 +1037,6 @@ CONFIG_LEGACY_PTY_COUNT=256
# CONFIG_SERIAL_NONSTANDARD is not set
# CONFIG_N_GSM is not set
# CONFIG_TRACE_SINK is not set
-CONFIG_DEVMEM=y
CONFIG_DEVKMEM=y
#
@@ -1083,7 +1067,6 @@ CONFIG_HW_RANDOM=y
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
-# CONFIG_DCC_TTY is not set
# CONFIG_RAMOOPS is not set
CONFIG_MXS_VIIM=y
CONFIG_I2C=y
@@ -1449,7 +1432,6 @@ CONFIG_VIDEO_MXC_IPU_OUTPUT=y
# Graphics support
#
# CONFIG_DRM is not set
-# CONFIG_ION is not set
# CONFIG_VGASTATE is not set
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
CONFIG_FB=y
@@ -1787,8 +1769,6 @@ CONFIG_MMC=y
# CONFIG_MMC_DEBUG is not set
CONFIG_MMC_UNSAFE_RESUME=y
# CONFIG_MMC_CLKGATE is not set
-# CONFIG_MMC_EMBEDDED_SDIO is not set
-# CONFIG_MMC_PARANOID_SD_INIT is not set
#
# MMC/SD/SDIO Card Drivers
@@ -1796,7 +1776,6 @@ CONFIG_MMC_UNSAFE_RESUME=y
CONFIG_MMC_BLOCK=y
CONFIG_MMC_BLOCK_MINORS=8
CONFIG_MMC_BLOCK_BOUNCE=y
-# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set
# CONFIG_SDIO_UART is not set
# CONFIG_MMC_TEST is not set
@@ -1813,7 +1792,6 @@ CONFIG_MMC_SDHCI_ESDHC_IMX=y
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
# CONFIG_NFC_DEVICES is not set
-# CONFIG_SWITCH is not set
# CONFIG_ACCESSIBILITY is not set
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
@@ -1828,8 +1806,6 @@ CONFIG_RTC_INTF_SYSFS=y
CONFIG_RTC_INTF_PROC=y
CONFIG_RTC_INTF_DEV=y
CONFIG_RTC_INTF_DEV_UIE_EMUL=y
-CONFIG_RTC_INTF_ALARM=y
-CONFIG_RTC_INTF_ALARM_DEV=y
# CONFIG_RTC_DRV_TEST is not set
#
@@ -1901,6 +1877,7 @@ CONFIG_DMADEVICES=y
# CONFIG_MXC_PXP_V2 is not set
# CONFIG_TIMB_DMA is not set
CONFIG_IMX_SDMA=y
+# CONFIG_MXS_DMA is not set
CONFIG_DMA_ENGINE=y
#
@@ -1918,11 +1895,6 @@ CONFIG_STAGING=y
# CONFIG_ASUS_OLED is not set
# CONFIG_R8712U is not set
# CONFIG_TRANZPORT is not set
-
-#
-# Android
-#
-# CONFIG_ANDROID is not set
# CONFIG_POHMELFS is not set
# CONFIG_LINE6_USB is not set
# CONFIG_VT6656 is not set
@@ -2115,7 +2087,6 @@ CONFIG_MISC_FILESYSTEMS=y
# CONFIG_BEFS_FS is not set
# CONFIG_BFS_FS is not set
# CONFIG_EFS_FS is not set
-# CONFIG_YAFFS_FS is not set
CONFIG_JFFS2_FS=y
CONFIG_JFFS2_FS_DEBUG=0
CONFIG_JFFS2_FS_WRITEBUFFER=y
@@ -2243,7 +2214,6 @@ CONFIG_DEBUG_FS=y
# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_SLUB_STATS is not set
# CONFIG_SPARSE_RCU_POINTER is not set
-CONFIG_STACKTRACE=y
CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_DEBUG_MEMORY_INIT is not set
CONFIG_RCU_CPU_STALL_TIMEOUT=60
diff --git a/arch/arm/configs/imx6s_defconfig b/arch/arm/configs/imx6s_defconfig
index 01f9bed4d721..78efc6b7563e 100644
--- a/arch/arm/configs/imx6s_defconfig
+++ b/arch/arm/configs/imx6s_defconfig
@@ -274,6 +274,8 @@ CONFIG_IMX_HAVE_PLATFORM_IMX_DVFS=y
CONFIG_IMX_HAVE_PLATFORM_AHCI=y
CONFIG_IMX_HAVE_PLATFORM_IMX_OCOTP=y
CONFIG_IMX_HAVE_PLATFORM_IMX_VIIM=y
+CONFIG_IMX_HAVE_PLATFORM_IMX_DCP=y
+CONFIG_IMX_HAVE_PLATFORM_RANDOM_RNGC=y
CONFIG_IMX_HAVE_PLATFORM_PERFMON=y
CONFIG_IMX_HAVE_PLATFORM_LDB=y
CONFIG_IMX_HAVE_PLATFORM_IMX_PXP=y
@@ -317,13 +319,14 @@ CONFIG_MACH_MX6Q_SABRESD=y
# MX6 Options:
#
# CONFIG_IMX_PCIE is not set
-# CONFIG_MX6_INTER_LDO_BYPASS is not set
+CONFIG_MX6_INTER_LDO_BYPASS=y
CONFIG_ISP1504_MXC=y
# CONFIG_MXC_IRQ_PRIOR is not set
CONFIG_MXC_PWM=y
# CONFIG_MXC_DEBUG_BOARD is not set
# CONFIG_MXC_REBOOT_MFGMODE is not set
# CONFIG_MXC_REBOOT_ANDROID_CMD is not set
+CONFIG_ARCH_HAS_RNGC=y
CONFIG_ARCH_MXC_IOMUX_V3=y
CONFIG_ARCH_MXC_AUDMUX_V2=y
CONFIG_IRAM_ALLOC=y
@@ -1147,6 +1150,7 @@ CONFIG_FSL_OTP=y
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+CONFIG_HW_RANDOM_FSL_RNGC=y
# CONFIG_R3964 is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_TCG_TPM is not set
@@ -2287,6 +2291,11 @@ CONFIG_ANATOP_THERMAL=y
CONFIG_MXC_MIPI_CSI2=y
#
+# MXC HDMI CEC (Consumer Electronics Control) support
+#
+# CONFIG_MXC_HDMI_CEC is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -2628,6 +2637,7 @@ CONFIG_CRYPTO_LZO=y
# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_FSL_CAAM is not set
+CONFIG_CRYPTO_DEV_DCP=y
# CONFIG_BINARY_PRINTF is not set
#
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index d5070022a407..a9098ca89a33 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -211,6 +211,22 @@ extern void *dma_alloc_coherent(struct device *, size_t, dma_addr_t *, gfp_t);
*/
extern void *dma_alloc_writethrough(struct device *, size_t, dma_addr_t *, gfp_t);
+
+#ifdef CONFIG_FSL_UTP
+/**
+ * dma_alloc_noncacheable - allocate consistent memory for DMA
+ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
+ * @size: required memory size
+ * @handle: bus-specific DMA address
+ *
+ * Allocate some noncacheable memory, for a device for
+ * performing DMA. This function allocates pages, and will
+ * return the CPU-viewed address, and sets @handle to be the
+ * device-viewed address.
+ */
+extern void *dma_alloc_noncacheable(struct device *, size_t, dma_addr_t *, gfp_t);
+#endif
+
/**
* dma_free_coherent - free memory allocated by dma_alloc_coherent
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
diff --git a/arch/arm/include/asm/tls.h b/arch/arm/include/asm/tls.h
index 60843eb0f61c..73409e6c0251 100644
--- a/arch/arm/include/asm/tls.h
+++ b/arch/arm/include/asm/tls.h
@@ -7,6 +7,8 @@
.macro set_tls_v6k, tp, tmp1, tmp2
mcr p15, 0, \tp, c13, c0, 3 @ set TLS register
+ mov \tmp1, #0
+ mcr p15, 0, \tmp1, c13, c0, 2 @ clear user r/w TLS register
.endm
.macro set_tls_v6, tp, tmp1, tmp2
@@ -15,6 +17,8 @@
mov \tmp2, #0xffff0fff
tst \tmp1, #HWCAP_TLS @ hardware TLS available?
mcrne p15, 0, \tp, c13, c0, 3 @ yes, set TLS register
+ movne \tmp1, #0
+ mcrne p15, 0, \tmp1, c13, c0, 2 @ clear user r/w TLS register
streq \tp, [\tmp2, #-15] @ set TLS value at 0xffff0ff0
.endm
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 97260060bf26..172ae01c26e0 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -719,10 +719,13 @@ static int vfp_set(struct task_struct *target,
{
int ret;
struct thread_info *thread = task_thread_info(target);
- struct vfp_hard_struct new_vfp = thread->vfpstate.hard;
+ struct vfp_hard_struct new_vfp;
const size_t user_fpregs_offset = offsetof(struct user_vfp, fpregs);
const size_t user_fpscr_offset = offsetof(struct user_vfp, fpscr);
+ vfp_sync_hwstate(thread);
+ new_vfp = thread->vfpstate.hard;
+
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
&new_vfp.fpregs,
user_fpregs_offset,
@@ -743,9 +746,8 @@ static int vfp_set(struct task_struct *target,
if (ret)
return ret;
- vfp_sync_hwstate(thread);
- thread->vfpstate.hard = new_vfp;
vfp_flush_hwstate(thread);
+ thread->vfpstate.hard = new_vfp;
return 0;
}
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 0340224cf73c..9e617bd4a146 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -227,6 +227,8 @@ static int restore_vfp_context(struct vfp_sigframe __user *frame)
if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE)
return -EINVAL;
+ vfp_flush_hwstate(thread);
+
/*
* Copy the floating point registers. There can be unused
* registers see asm/hwcap.h for details.
@@ -251,9 +253,6 @@ static int restore_vfp_context(struct vfp_sigframe __user *frame)
__get_user_error(h->fpinst, &frame->ufp_exc.fpinst, err);
__get_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err);
- if (!err)
- vfp_flush_hwstate(thread);
-
return err ? -EFAULT : 0;
}
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 1d43ba28ebb5..24cdba4e9614 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -274,8 +274,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
struct mm_struct *mm = &init_mm;
unsigned int cpu = smp_processor_id();
- printk("CPU%u: Booted secondary processor\n", cpu);
-
/*
* All kernel threads share the same mm context; grab a
* reference and switch to it.
@@ -287,6 +285,8 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
enter_lazy_tlb(mm, current);
local_flush_tlb_all();
+ printk("CPU%u: Booted secondary processor\n", cpu);
+
cpu_init();
preempt_disable();
trace_hardirqs_off();
@@ -449,7 +449,9 @@ asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs)
if (local_timer_ack()) {
__inc_irq_stat(cpu, local_timer_irqs);
+ irq_enter();
ipi_timer();
+ irq_exit();
}
set_irq_regs(old_regs);
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
index 62e7c61d0342..0264ab433e9e 100644
--- a/arch/arm/kernel/sys_arm.c
+++ b/arch/arm/kernel/sys_arm.c
@@ -115,7 +115,7 @@ int kernel_execve(const char *filename,
"Ir" (THREAD_START_SP - sizeof(regs)),
"r" (&regs),
"Ir" (sizeof(regs))
- : "r0", "r1", "r2", "r3", "ip", "lr", "memory");
+ : "r0", "r1", "r2", "r3", "r8", "r9", "ip", "lr", "memory");
out:
return ret;
diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
index cf7e5985eebf..46c044986294 100644
--- a/arch/arm/mach-dove/common.c
+++ b/arch/arm/mach-dove/common.c
@@ -31,6 +31,7 @@
#include <asm/mach/arch.h>
#include <linux/irq.h>
#include <plat/time.h>
+#include <plat/ehci-orion.h>
#include <plat/common.h>
#include "common.h"
@@ -74,7 +75,7 @@ void __init dove_map_io(void)
void __init dove_ehci0_init(void)
{
orion_ehci_init(&dove_mbus_dram_info,
- DOVE_USB0_PHYS_BASE, IRQ_DOVE_USB0);
+ DOVE_USB0_PHYS_BASE, IRQ_DOVE_USB0, EHCI_PHY_NA);
}
/*****************************************************************************
diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c
index 74ac88978ddd..a37fe021d69f 100644
--- a/arch/arm/mach-imx/mach-mx21ads.c
+++ b/arch/arm/mach-imx/mach-mx21ads.c
@@ -32,7 +32,7 @@
* Memory-mapped I/O on MX21ADS base board
*/
#define MX21ADS_MMIO_BASE_ADDR 0xf5000000
-#define MX21ADS_MMIO_SIZE SZ_16M
+#define MX21ADS_MMIO_SIZE 0xc00000
#define MX21ADS_REG_ADDR(offset) (void __force __iomem *) \
(MX21ADS_MMIO_BASE_ADDR + (offset))
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index f3248cfbe51d..c5dbbb35e0b1 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -28,6 +28,7 @@
#include <plat/cache-feroceon-l2.h>
#include <plat/mvsdio.h>
#include <plat/orion_nand.h>
+#include <plat/ehci-orion.h>
#include <plat/common.h>
#include <plat/time.h>
#include "common.h"
@@ -74,7 +75,7 @@ void __init kirkwood_ehci_init(void)
{
kirkwood_clk_ctrl |= CGC_USB0;
orion_ehci_init(&kirkwood_mbus_dram_info,
- USB_PHYS_BASE, IRQ_KIRKWOOD_USB);
+ USB_PHYS_BASE, IRQ_KIRKWOOD_USB, EHCI_PHY_NA);
}
diff --git a/arch/arm/mach-kirkwood/mpp.h b/arch/arm/mach-kirkwood/mpp.h
index ac787957e2d9..7afccf472205 100644
--- a/arch/arm/mach-kirkwood/mpp.h
+++ b/arch/arm/mach-kirkwood/mpp.h
@@ -31,313 +31,313 @@
#define MPP_F6282_MASK MPP( 0, 0x0, 0, 0, 0, 0, 0, 0, 1 )
#define MPP0_GPIO MPP( 0, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP0_NF_IO2 MPP( 0, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP0_SPI_SCn MPP( 0, 0x2, 0, 1, 1, 1, 1, 1, 1 )
+#define MPP0_NF_IO2 MPP( 0, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP0_SPI_SCn MPP( 0, 0x2, 0, 0, 1, 1, 1, 1, 1 )
#define MPP1_GPO MPP( 1, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP1_NF_IO3 MPP( 1, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP1_SPI_MOSI MPP( 1, 0x2, 0, 1, 1, 1, 1, 1, 1 )
+#define MPP1_NF_IO3 MPP( 1, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP1_SPI_MOSI MPP( 1, 0x2, 0, 0, 1, 1, 1, 1, 1 )
#define MPP2_GPO MPP( 2, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP2_NF_IO4 MPP( 2, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP2_SPI_SCK MPP( 2, 0x2, 0, 1, 1, 1, 1, 1, 1 )
+#define MPP2_NF_IO4 MPP( 2, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP2_SPI_SCK MPP( 2, 0x2, 0, 0, 1, 1, 1, 1, 1 )
#define MPP3_GPO MPP( 3, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP3_NF_IO5 MPP( 3, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP3_SPI_MISO MPP( 3, 0x2, 1, 0, 1, 1, 1, 1, 1 )
+#define MPP3_NF_IO5 MPP( 3, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP3_SPI_MISO MPP( 3, 0x2, 0, 0, 1, 1, 1, 1, 1 )
#define MPP4_GPIO MPP( 4, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP4_NF_IO6 MPP( 4, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP4_UART0_RXD MPP( 4, 0x2, 1, 0, 1, 1, 1, 1, 1 )
-#define MPP4_SATA1_ACTn MPP( 4, 0x5, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP4_NF_IO6 MPP( 4, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP4_UART0_RXD MPP( 4, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP4_SATA1_ACTn MPP( 4, 0x5, 0, 0, 0, 0, 1, 1, 1 )
#define MPP4_LCD_VGA_HSYNC MPP( 4, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-#define MPP4_PTP_CLK MPP( 4, 0xd, 1, 0, 1, 1, 1, 1, 0 )
+#define MPP4_PTP_CLK MPP( 4, 0xd, 0, 0, 1, 1, 1, 1, 0 )
#define MPP5_GPO MPP( 5, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP5_NF_IO7 MPP( 5, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP5_UART0_TXD MPP( 5, 0x2, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP5_PTP_TRIG_GEN MPP( 5, 0x4, 0, 1, 1, 1, 1, 1, 0 )
-#define MPP5_SATA0_ACTn MPP( 5, 0x5, 0, 1, 0, 1, 1, 1, 1 )
+#define MPP5_NF_IO7 MPP( 5, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP5_UART0_TXD MPP( 5, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP5_PTP_TRIG_GEN MPP( 5, 0x4, 0, 0, 1, 1, 1, 1, 0 )
+#define MPP5_SATA0_ACTn MPP( 5, 0x5, 0, 0, 0, 1, 1, 1, 1 )
#define MPP5_LCD_VGA_VSYNC MPP( 5, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-#define MPP6_SYSRST_OUTn MPP( 6, 0x1, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP6_SPI_MOSI MPP( 6, 0x2, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP6_PTP_TRIG_GEN MPP( 6, 0x3, 0, 1, 1, 1, 1, 1, 0 )
+#define MPP6_SYSRST_OUTn MPP( 6, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP6_SPI_MOSI MPP( 6, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP6_PTP_TRIG_GEN MPP( 6, 0x3, 0, 0, 1, 1, 1, 1, 0 )
#define MPP7_GPO MPP( 7, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP7_PEX_RST_OUTn MPP( 7, 0x1, 0, 1, 1, 1, 1, 1, 0 )
-#define MPP7_SPI_SCn MPP( 7, 0x2, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP7_PTP_TRIG_GEN MPP( 7, 0x3, 0, 1, 1, 1, 1, 1, 0 )
-#define MPP7_LCD_PWM MPP( 7, 0xb, 0, 1, 0, 0, 0, 0, 1 )
+#define MPP7_PEX_RST_OUTn MPP( 7, 0x1, 0, 0, 1, 1, 1, 1, 0 )
+#define MPP7_SPI_SCn MPP( 7, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP7_PTP_TRIG_GEN MPP( 7, 0x3, 0, 0, 1, 1, 1, 1, 0 )
+#define MPP7_LCD_PWM MPP( 7, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP8_GPIO MPP( 8, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP8_TW0_SDA MPP( 8, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP8_UART0_RTS MPP( 8, 0x2, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP8_UART1_RTS MPP( 8, 0x3, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP8_MII0_RXERR MPP( 8, 0x4, 1, 0, 0, 1, 1, 1, 1 )
-#define MPP8_SATA1_PRESENTn MPP( 8, 0x5, 0, 1, 0, 0, 1, 1, 1 )
-#define MPP8_PTP_CLK MPP( 8, 0xc, 1, 0, 1, 1, 1, 1, 0 )
-#define MPP8_MII0_COL MPP( 8, 0xd, 1, 0, 1, 1, 1, 1, 1 )
+#define MPP8_TW0_SDA MPP( 8, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP8_UART0_RTS MPP( 8, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP8_UART1_RTS MPP( 8, 0x3, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP8_MII0_RXERR MPP( 8, 0x4, 0, 0, 0, 1, 1, 1, 1 )
+#define MPP8_SATA1_PRESENTn MPP( 8, 0x5, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP8_PTP_CLK MPP( 8, 0xc, 0, 0, 1, 1, 1, 1, 0 )
+#define MPP8_MII0_COL MPP( 8, 0xd, 0, 0, 1, 1, 1, 1, 1 )
#define MPP9_GPIO MPP( 9, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP9_TW0_SCK MPP( 9, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP9_UART0_CTS MPP( 9, 0x2, 1, 0, 1, 1, 1, 1, 1 )
-#define MPP9_UART1_CTS MPP( 9, 0x3, 1, 0, 1, 1, 1, 1, 1 )
-#define MPP9_SATA0_PRESENTn MPP( 9, 0x5, 0, 1, 0, 1, 1, 1, 1 )
-#define MPP9_PTP_EVENT_REQ MPP( 9, 0xc, 1, 0, 1, 1, 1, 1, 0 )
-#define MPP9_MII0_CRS MPP( 9, 0xd, 1, 0, 1, 1, 1, 1, 1 )
+#define MPP9_TW0_SCK MPP( 9, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP9_UART0_CTS MPP( 9, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP9_UART1_CTS MPP( 9, 0x3, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP9_SATA0_PRESENTn MPP( 9, 0x5, 0, 0, 0, 1, 1, 1, 1 )
+#define MPP9_PTP_EVENT_REQ MPP( 9, 0xc, 0, 0, 1, 1, 1, 1, 0 )
+#define MPP9_MII0_CRS MPP( 9, 0xd, 0, 0, 1, 1, 1, 1, 1 )
#define MPP10_GPO MPP( 10, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP10_SPI_SCK MPP( 10, 0x2, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP10_UART0_TXD MPP( 10, 0X3, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP10_SATA1_ACTn MPP( 10, 0x5, 0, 1, 0, 0, 1, 1, 1 )
-#define MPP10_PTP_TRIG_GEN MPP( 10, 0xc, 0, 1, 1, 1, 1, 1, 0 )
+#define MPP10_SPI_SCK MPP( 10, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP10_UART0_TXD MPP( 10, 0X3, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP10_SATA1_ACTn MPP( 10, 0x5, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP10_PTP_TRIG_GEN MPP( 10, 0xc, 0, 0, 1, 1, 1, 1, 0 )
#define MPP11_GPIO MPP( 11, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP11_SPI_MISO MPP( 11, 0x2, 1, 0, 1, 1, 1, 1, 1 )
-#define MPP11_UART0_RXD MPP( 11, 0x3, 1, 0, 1, 1, 1, 1, 1 )
-#define MPP11_PTP_EVENT_REQ MPP( 11, 0x4, 1, 0, 1, 1, 1, 1, 0 )
-#define MPP11_PTP_TRIG_GEN MPP( 11, 0xc, 0, 1, 1, 1, 1, 1, 0 )
-#define MPP11_PTP_CLK MPP( 11, 0xd, 1, 0, 1, 1, 1, 1, 0 )
-#define MPP11_SATA0_ACTn MPP( 11, 0x5, 0, 1, 0, 1, 1, 1, 1 )
+#define MPP11_SPI_MISO MPP( 11, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP11_UART0_RXD MPP( 11, 0x3, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP11_PTP_EVENT_REQ MPP( 11, 0x4, 0, 0, 1, 1, 1, 1, 0 )
+#define MPP11_PTP_TRIG_GEN MPP( 11, 0xc, 0, 0, 1, 1, 1, 1, 0 )
+#define MPP11_PTP_CLK MPP( 11, 0xd, 0, 0, 1, 1, 1, 1, 0 )
+#define MPP11_SATA0_ACTn MPP( 11, 0x5, 0, 0, 0, 1, 1, 1, 1 )
#define MPP12_GPO MPP( 12, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP12_SD_CLK MPP( 12, 0x1, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP12_AU_SPDIF0 MPP( 12, 0xa, 0, 1, 0, 0, 0, 0, 1 )
-#define MPP12_SPI_MOSI MPP( 12, 0xb, 0, 1, 0, 0, 0, 0, 1 )
-#define MPP12_TW1_SDA MPP( 12, 0xd, 1, 0, 0, 0, 0, 0, 1 )
+#define MPP12_SD_CLK MPP( 12, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP12_AU_SPDIF0 MPP( 12, 0xa, 0, 0, 0, 0, 0, 0, 1 )
+#define MPP12_SPI_MOSI MPP( 12, 0xb, 0, 0, 0, 0, 0, 0, 1 )
+#define MPP12_TW1_SDA MPP( 12, 0xd, 0, 0, 0, 0, 0, 0, 1 )
#define MPP13_GPIO MPP( 13, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP13_SD_CMD MPP( 13, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP13_UART1_TXD MPP( 13, 0x3, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP13_AU_SPDIFRMCLK MPP( 13, 0xa, 0, 1, 0, 0, 0, 0, 1 )
-#define MPP13_LCDPWM MPP( 13, 0xb, 0, 1, 0, 0, 0, 0, 1 )
+#define MPP13_SD_CMD MPP( 13, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP13_UART1_TXD MPP( 13, 0x3, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP13_AU_SPDIFRMCLK MPP( 13, 0xa, 0, 0, 0, 0, 0, 0, 1 )
+#define MPP13_LCDPWM MPP( 13, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP14_GPIO MPP( 14, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP14_SD_D0 MPP( 14, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP14_UART1_RXD MPP( 14, 0x3, 1, 0, 1, 1, 1, 1, 1 )
-#define MPP14_SATA1_PRESENTn MPP( 14, 0x4, 0, 1, 0, 0, 1, 1, 1 )
-#define MPP14_AU_SPDIFI MPP( 14, 0xa, 1, 0, 0, 0, 0, 0, 1 )
-#define MPP14_AU_I2SDI MPP( 14, 0xb, 1, 0, 0, 0, 0, 0, 1 )
-#define MPP14_MII0_COL MPP( 14, 0xd, 1, 0, 1, 1, 1, 1, 1 )
+#define MPP14_SD_D0 MPP( 14, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP14_UART1_RXD MPP( 14, 0x3, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP14_SATA1_PRESENTn MPP( 14, 0x4, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP14_AU_SPDIFI MPP( 14, 0xa, 0, 0, 0, 0, 0, 0, 1 )
+#define MPP14_AU_I2SDI MPP( 14, 0xb, 0, 0, 0, 0, 0, 0, 1 )
+#define MPP14_MII0_COL MPP( 14, 0xd, 0, 0, 1, 1, 1, 1, 1 )
#define MPP15_GPIO MPP( 15, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP15_SD_D1 MPP( 15, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP15_UART0_RTS MPP( 15, 0x2, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP15_UART1_TXD MPP( 15, 0x3, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP15_SATA0_ACTn MPP( 15, 0x4, 0, 1, 0, 1, 1, 1, 1 )
-#define MPP15_SPI_CSn MPP( 15, 0xb, 0, 1, 0, 0, 0, 0, 1 )
+#define MPP15_SD_D1 MPP( 15, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP15_UART0_RTS MPP( 15, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP15_UART1_TXD MPP( 15, 0x3, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP15_SATA0_ACTn MPP( 15, 0x4, 0, 0, 0, 1, 1, 1, 1 )
+#define MPP15_SPI_CSn MPP( 15, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP16_GPIO MPP( 16, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP16_SD_D2 MPP( 16, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP16_UART0_CTS MPP( 16, 0x2, 1, 0, 1, 1, 1, 1, 1 )
-#define MPP16_UART1_RXD MPP( 16, 0x3, 1, 0, 1, 1, 1, 1, 1 )
-#define MPP16_SATA1_ACTn MPP( 16, 0x4, 0, 1, 0, 0, 1, 1, 1 )
-#define MPP16_LCD_EXT_REF_CLK MPP( 16, 0xb, 1, 0, 0, 0, 0, 0, 1 )
-#define MPP16_MII0_CRS MPP( 16, 0xd, 1, 0, 1, 1, 1, 1, 1 )
+#define MPP16_SD_D2 MPP( 16, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP16_UART0_CTS MPP( 16, 0x2, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP16_UART1_RXD MPP( 16, 0x3, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP16_SATA1_ACTn MPP( 16, 0x4, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP16_LCD_EXT_REF_CLK MPP( 16, 0xb, 0, 0, 0, 0, 0, 0, 1 )
+#define MPP16_MII0_CRS MPP( 16, 0xd, 0, 0, 1, 1, 1, 1, 1 )
#define MPP17_GPIO MPP( 17, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP17_SD_D3 MPP( 17, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP17_SATA0_PRESENTn MPP( 17, 0x4, 0, 1, 0, 1, 1, 1, 1 )
-#define MPP17_SATA1_ACTn MPP( 17, 0xa, 0, 1, 0, 0, 0, 0, 1 )
-#define MPP17_TW1_SCK MPP( 17, 0xd, 1, 1, 0, 0, 0, 0, 1 )
+#define MPP17_SD_D3 MPP( 17, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP17_SATA0_PRESENTn MPP( 17, 0x4, 0, 0, 0, 1, 1, 1, 1 )
+#define MPP17_SATA1_ACTn MPP( 17, 0xa, 0, 0, 0, 0, 0, 0, 1 )
+#define MPP17_TW1_SCK MPP( 17, 0xd, 0, 0, 0, 0, 0, 0, 1 )
#define MPP18_GPO MPP( 18, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP18_NF_IO0 MPP( 18, 0x1, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP18_PEX0_CLKREQ MPP( 18, 0x2, 0, 1, 0, 0, 0, 0, 1 )
+#define MPP18_NF_IO0 MPP( 18, 0x1, 0, 0, 1, 1, 1, 1, 1 )
+#define MPP18_PEX0_CLKREQ MPP( 18, 0x2, 0, 0, 0, 0, 0, 0, 1 )
#define MPP19_GPO MPP( 19, 0x0, 0, 1, 1, 1, 1, 1, 1 )
-#define MPP19_NF_IO1 MPP( 19, 0x1, 1, 1, 1, 1, 1, 1, 1 )
+#define MPP19_NF_IO1 MPP( 19, 0x1, 0, 0, 1, 1, 1, 1, 1 )
#define MPP20_GPIO MPP( 20, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP20_TSMP0 MPP( 20, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP20_TDM_CH0_TX_QL MPP( 20, 0x2, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP20_TSMP0 MPP( 20, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP20_TDM_CH0_TX_QL MPP( 20, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP20_GE1_TXD0 MPP( 20, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP20_AU_SPDIFI MPP( 20, 0x4, 1, 0, 0, 0, 1, 1, 1 )
-#define MPP20_SATA1_ACTn MPP( 20, 0x5, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP20_AU_SPDIFI MPP( 20, 0x4, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP20_SATA1_ACTn MPP( 20, 0x5, 0, 0, 0, 0, 1, 1, 1 )
#define MPP20_LCD_D0 MPP( 20, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP21_GPIO MPP( 21, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP21_TSMP1 MPP( 21, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP21_TDM_CH0_RX_QL MPP( 21, 0x2, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP21_TSMP1 MPP( 21, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP21_TDM_CH0_RX_QL MPP( 21, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP21_GE1_TXD1 MPP( 21, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP21_AU_SPDIFO MPP( 21, 0x4, 0, 1, 0, 0, 1, 1, 1 )
-#define MPP21_SATA0_ACTn MPP( 21, 0x5, 0, 1, 0, 1, 1, 1, 1 )
+#define MPP21_AU_SPDIFO MPP( 21, 0x4, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP21_SATA0_ACTn MPP( 21, 0x5, 0, 0, 0, 1, 1, 1, 1 )
#define MPP21_LCD_D1 MPP( 21, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP22_GPIO MPP( 22, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP22_TSMP2 MPP( 22, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP22_TDM_CH2_TX_QL MPP( 22, 0x2, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP22_TSMP2 MPP( 22, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP22_TDM_CH2_TX_QL MPP( 22, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP22_GE1_TXD2 MPP( 22, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP22_AU_SPDIFRMKCLK MPP( 22, 0x4, 0, 1, 0, 0, 1, 1, 1 )
-#define MPP22_SATA1_PRESENTn MPP( 22, 0x5, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP22_AU_SPDIFRMKCLK MPP( 22, 0x4, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP22_SATA1_PRESENTn MPP( 22, 0x5, 0, 0, 0, 0, 1, 1, 1 )
#define MPP22_LCD_D2 MPP( 22, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP23_GPIO MPP( 23, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP23_TSMP3 MPP( 23, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP23_TDM_CH2_RX_QL MPP( 23, 0x2, 1, 0, 0, 0, 1, 1, 1 )
+#define MPP23_TSMP3 MPP( 23, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP23_TDM_CH2_RX_QL MPP( 23, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP23_GE1_TXD3 MPP( 23, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP23_AU_I2SBCLK MPP( 23, 0x4, 0, 1, 0, 0, 1, 1, 1 )
-#define MPP23_SATA0_PRESENTn MPP( 23, 0x5, 0, 1, 0, 1, 1, 1, 1 )
+#define MPP23_AU_I2SBCLK MPP( 23, 0x4, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP23_SATA0_PRESENTn MPP( 23, 0x5, 0, 0, 0, 1, 1, 1, 1 )
#define MPP23_LCD_D3 MPP( 23, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP24_GPIO MPP( 24, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP24_TSMP4 MPP( 24, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP24_TDM_SPI_CS0 MPP( 24, 0x2, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP24_TSMP4 MPP( 24, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP24_TDM_SPI_CS0 MPP( 24, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP24_GE1_RXD0 MPP( 24, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP24_AU_I2SDO MPP( 24, 0x4, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP24_AU_I2SDO MPP( 24, 0x4, 0, 0, 0, 0, 1, 1, 1 )
#define MPP24_LCD_D4 MPP( 24, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP25_GPIO MPP( 25, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP25_TSMP5 MPP( 25, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP25_TDM_SPI_SCK MPP( 25, 0x2, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP25_TSMP5 MPP( 25, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP25_TDM_SPI_SCK MPP( 25, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP25_GE1_RXD1 MPP( 25, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP25_AU_I2SLRCLK MPP( 25, 0x4, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP25_AU_I2SLRCLK MPP( 25, 0x4, 0, 0, 0, 0, 1, 1, 1 )
#define MPP25_LCD_D5 MPP( 25, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP26_GPIO MPP( 26, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP26_TSMP6 MPP( 26, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP26_TDM_SPI_MISO MPP( 26, 0x2, 1, 0, 0, 0, 1, 1, 1 )
+#define MPP26_TSMP6 MPP( 26, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP26_TDM_SPI_MISO MPP( 26, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP26_GE1_RXD2 MPP( 26, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP26_AU_I2SMCLK MPP( 26, 0x4, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP26_AU_I2SMCLK MPP( 26, 0x4, 0, 0, 0, 0, 1, 1, 1 )
#define MPP26_LCD_D6 MPP( 26, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP27_GPIO MPP( 27, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP27_TSMP7 MPP( 27, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP27_TDM_SPI_MOSI MPP( 27, 0x2, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP27_TSMP7 MPP( 27, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP27_TDM_SPI_MOSI MPP( 27, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP27_GE1_RXD3 MPP( 27, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP27_AU_I2SDI MPP( 27, 0x4, 1, 0, 0, 0, 1, 1, 1 )
+#define MPP27_AU_I2SDI MPP( 27, 0x4, 0, 0, 0, 0, 1, 1, 1 )
#define MPP27_LCD_D7 MPP( 27, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP28_GPIO MPP( 28, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP28_TSMP8 MPP( 28, 0x1, 1, 1, 0, 0, 1, 1, 1 )
+#define MPP28_TSMP8 MPP( 28, 0x1, 0, 0, 0, 0, 1, 1, 1 )
#define MPP28_TDM_CODEC_INTn MPP( 28, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP28_GE1_COL MPP( 28, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP28_AU_EXTCLK MPP( 28, 0x4, 1, 0, 0, 0, 1, 1, 1 )
+#define MPP28_AU_EXTCLK MPP( 28, 0x4, 0, 0, 0, 0, 1, 1, 1 )
#define MPP28_LCD_D8 MPP( 28, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP29_GPIO MPP( 29, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP29_TSMP9 MPP( 29, 0x1, 1, 1, 0, 0, 1, 1, 1 )
+#define MPP29_TSMP9 MPP( 29, 0x1, 0, 0, 0, 0, 1, 1, 1 )
#define MPP29_TDM_CODEC_RSTn MPP( 29, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP29_GE1_TCLK MPP( 29, 0x3, 0, 0, 0, 1, 1, 1, 1 )
#define MPP29_LCD_D9 MPP( 29, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP30_GPIO MPP( 30, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP30_TSMP10 MPP( 30, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP30_TDM_PCLK MPP( 30, 0x2, 1, 1, 0, 0, 1, 1, 1 )
+#define MPP30_TSMP10 MPP( 30, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP30_TDM_PCLK MPP( 30, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP30_GE1_RXCTL MPP( 30, 0x3, 0, 0, 0, 1, 1, 1, 1 )
#define MPP30_LCD_D10 MPP( 30, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP31_GPIO MPP( 31, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP31_TSMP11 MPP( 31, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP31_TDM_FS MPP( 31, 0x2, 1, 1, 0, 0, 1, 1, 1 )
+#define MPP31_TSMP11 MPP( 31, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP31_TDM_FS MPP( 31, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP31_GE1_RXCLK MPP( 31, 0x3, 0, 0, 0, 1, 1, 1, 1 )
#define MPP31_LCD_D11 MPP( 31, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP32_GPIO MPP( 32, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP32_TSMP12 MPP( 32, 0x1, 1, 1, 0, 0, 1, 1, 1 )
-#define MPP32_TDM_DRX MPP( 32, 0x2, 1, 0, 0, 0, 1, 1, 1 )
+#define MPP32_TSMP12 MPP( 32, 0x1, 0, 0, 0, 0, 1, 1, 1 )
+#define MPP32_TDM_DRX MPP( 32, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP32_GE1_TCLKOUT MPP( 32, 0x3, 0, 0, 0, 1, 1, 1, 1 )
#define MPP32_LCD_D12 MPP( 32, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP33_GPO MPP( 33, 0x0, 0, 1, 0, 1, 1, 1, 1 )
-#define MPP33_TDM_DTX MPP( 33, 0x2, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP33_TDM_DTX MPP( 33, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP33_GE1_TXCTL MPP( 33, 0x3, 0, 0, 0, 1, 1, 1, 1 )
#define MPP33_LCD_D13 MPP( 33, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP34_GPIO MPP( 34, 0x0, 1, 1, 0, 1, 1, 1, 1 )
-#define MPP34_TDM_SPI_CS1 MPP( 34, 0x2, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP34_TDM_SPI_CS1 MPP( 34, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP34_GE1_TXEN MPP( 34, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP34_SATA1_ACTn MPP( 34, 0x5, 0, 1, 0, 0, 0, 1, 1 )
+#define MPP34_SATA1_ACTn MPP( 34, 0x5, 0, 0, 0, 0, 0, 1, 1 )
#define MPP34_LCD_D14 MPP( 34, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP35_GPIO MPP( 35, 0x0, 1, 1, 1, 1, 1, 1, 1 )
-#define MPP35_TDM_CH0_TX_QL MPP( 35, 0x2, 0, 1, 0, 0, 1, 1, 1 )
+#define MPP35_TDM_CH0_TX_QL MPP( 35, 0x2, 0, 0, 0, 0, 1, 1, 1 )
#define MPP35_GE1_RXERR MPP( 35, 0x3, 0, 0, 0, 1, 1, 1, 1 )
-#define MPP35_SATA0_ACTn MPP( 35, 0x5, 0, 1, 0, 1, 1, 1, 1 )
+#define MPP35_SATA0_ACTn MPP( 35, 0x5, 0, 0, 0, 1, 1, 1, 1 )
#define MPP35_LCD_D15 MPP( 22, 0xb, 0, 0, 0, 0, 0, 0, 1 )
-#define MPP35_MII0_RXERR MPP( 35, 0xc, 1, 0, 1, 1, 1, 1, 1 )
+#define MPP35_MII0_RXERR MPP( 35, 0xc, 0, 0, 1, 1, 1, 1, 1 )
#define MPP36_GPIO MPP( 36, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP36_TSMP0 MPP( 36, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP36_TDM_SPI_CS1 MPP( 36, 0x2, 0, 1, 0, 0, 0, 1, 1 )
-#define MPP36_AU_SPDIFI MPP( 36, 0x4, 1, 0, 1, 0, 0, 1, 1 )
-#define MPP36_TW1_SDA MPP( 36, 0xb, 1, 1, 0, 0, 0, 0, 1 )
+#define MPP36_TSMP0 MPP( 36, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP36_TDM_SPI_CS1 MPP( 36, 0x2, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP36_AU_SPDIFI MPP( 36, 0x4, 0, 0, 1, 0, 0, 1, 1 )
+#define MPP36_TW1_SDA MPP( 36, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP37_GPIO MPP( 37, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP37_TSMP1 MPP( 37, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP37_TDM_CH2_TX_QL MPP( 37, 0x2, 0, 1, 0, 0, 0, 1, 1 )
-#define MPP37_AU_SPDIFO MPP( 37, 0x4, 0, 1, 1, 0, 0, 1, 1 )
-#define MPP37_TW1_SCK MPP( 37, 0xb, 1, 1, 0, 0, 0, 0, 1 )
+#define MPP37_TSMP1 MPP( 37, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP37_TDM_CH2_TX_QL MPP( 37, 0x2, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP37_AU_SPDIFO MPP( 37, 0x4, 0, 0, 1, 0, 0, 1, 1 )
+#define MPP37_TW1_SCK MPP( 37, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP38_GPIO MPP( 38, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP38_TSMP2 MPP( 38, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP38_TDM_CH2_RX_QL MPP( 38, 0x2, 0, 1, 0, 0, 0, 1, 1 )
-#define MPP38_AU_SPDIFRMLCLK MPP( 38, 0x4, 0, 1, 1, 0, 0, 1, 1 )
+#define MPP38_TSMP2 MPP( 38, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP38_TDM_CH2_RX_QL MPP( 38, 0x2, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP38_AU_SPDIFRMLCLK MPP( 38, 0x4, 0, 0, 1, 0, 0, 1, 1 )
#define MPP38_LCD_D18 MPP( 38, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP39_GPIO MPP( 39, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP39_TSMP3 MPP( 39, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP39_TDM_SPI_CS0 MPP( 39, 0x2, 0, 1, 0, 0, 0, 1, 1 )
-#define MPP39_AU_I2SBCLK MPP( 39, 0x4, 0, 1, 1, 0, 0, 1, 1 )
+#define MPP39_TSMP3 MPP( 39, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP39_TDM_SPI_CS0 MPP( 39, 0x2, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP39_AU_I2SBCLK MPP( 39, 0x4, 0, 0, 1, 0, 0, 1, 1 )
#define MPP39_LCD_D19 MPP( 39, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP40_GPIO MPP( 40, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP40_TSMP4 MPP( 40, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP40_TDM_SPI_SCK MPP( 40, 0x2, 0, 1, 0, 0, 0, 1, 1 )
-#define MPP40_AU_I2SDO MPP( 40, 0x4, 0, 1, 1, 0, 0, 1, 1 )
+#define MPP40_TSMP4 MPP( 40, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP40_TDM_SPI_SCK MPP( 40, 0x2, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP40_AU_I2SDO MPP( 40, 0x4, 0, 0, 1, 0, 0, 1, 1 )
#define MPP40_LCD_D20 MPP( 40, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP41_GPIO MPP( 41, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP41_TSMP5 MPP( 41, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP41_TDM_SPI_MISO MPP( 41, 0x2, 1, 0, 0, 0, 0, 1, 1 )
-#define MPP41_AU_I2SLRCLK MPP( 41, 0x4, 0, 1, 1, 0, 0, 1, 1 )
+#define MPP41_TSMP5 MPP( 41, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP41_TDM_SPI_MISO MPP( 41, 0x2, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP41_AU_I2SLRCLK MPP( 41, 0x4, 0, 0, 1, 0, 0, 1, 1 )
#define MPP41_LCD_D21 MPP( 41, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP42_GPIO MPP( 42, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP42_TSMP6 MPP( 42, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP42_TDM_SPI_MOSI MPP( 42, 0x2, 0, 1, 0, 0, 0, 1, 1 )
-#define MPP42_AU_I2SMCLK MPP( 42, 0x4, 0, 1, 1, 0, 0, 1, 1 )
+#define MPP42_TSMP6 MPP( 42, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP42_TDM_SPI_MOSI MPP( 42, 0x2, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP42_AU_I2SMCLK MPP( 42, 0x4, 0, 0, 1, 0, 0, 1, 1 )
#define MPP42_LCD_D22 MPP( 42, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP43_GPIO MPP( 43, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP43_TSMP7 MPP( 43, 0x1, 1, 1, 0, 0, 0, 1, 1 )
+#define MPP43_TSMP7 MPP( 43, 0x1, 0, 0, 0, 0, 0, 1, 1 )
#define MPP43_TDM_CODEC_INTn MPP( 43, 0x2, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP43_AU_I2SDI MPP( 43, 0x4, 1, 0, 1, 0, 0, 1, 1 )
+#define MPP43_AU_I2SDI MPP( 43, 0x4, 0, 0, 1, 0, 0, 1, 1 )
#define MPP43_LCD_D23 MPP( 22, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP44_GPIO MPP( 44, 0x0, 1, 1, 1, 0, 0, 1, 1 )
-#define MPP44_TSMP8 MPP( 44, 0x1, 1, 1, 0, 0, 0, 1, 1 )
+#define MPP44_TSMP8 MPP( 44, 0x1, 0, 0, 0, 0, 0, 1, 1 )
#define MPP44_TDM_CODEC_RSTn MPP( 44, 0x2, 0, 0, 0, 0, 0, 1, 1 )
-#define MPP44_AU_EXTCLK MPP( 44, 0x4, 1, 0, 1, 0, 0, 1, 1 )
+#define MPP44_AU_EXTCLK MPP( 44, 0x4, 0, 0, 1, 0, 0, 1, 1 )
#define MPP44_LCD_CLK MPP( 44, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP45_GPIO MPP( 45, 0x0, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP45_TSMP9 MPP( 45, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP45_TDM_PCLK MPP( 45, 0x2, 1, 1, 0, 0, 0, 1, 1 )
+#define MPP45_TSMP9 MPP( 45, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP45_TDM_PCLK MPP( 45, 0x2, 0, 0, 0, 0, 0, 1, 1 )
#define MPP245_LCD_E MPP( 45, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP46_GPIO MPP( 46, 0x0, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP46_TSMP10 MPP( 46, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP46_TDM_FS MPP( 46, 0x2, 1, 1, 0, 0, 0, 1, 1 )
+#define MPP46_TSMP10 MPP( 46, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP46_TDM_FS MPP( 46, 0x2, 0, 0, 0, 0, 0, 1, 1 )
#define MPP46_LCD_HSYNC MPP( 46, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP47_GPIO MPP( 47, 0x0, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP47_TSMP11 MPP( 47, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP47_TDM_DRX MPP( 47, 0x2, 1, 0, 0, 0, 0, 1, 1 )
+#define MPP47_TSMP11 MPP( 47, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP47_TDM_DRX MPP( 47, 0x2, 0, 0, 0, 0, 0, 1, 1 )
#define MPP47_LCD_VSYNC MPP( 47, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP48_GPIO MPP( 48, 0x0, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP48_TSMP12 MPP( 48, 0x1, 1, 1, 0, 0, 0, 1, 1 )
-#define MPP48_TDM_DTX MPP( 48, 0x2, 0, 1, 0, 0, 0, 1, 1 )
+#define MPP48_TSMP12 MPP( 48, 0x1, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP48_TDM_DTX MPP( 48, 0x2, 0, 0, 0, 0, 0, 1, 1 )
#define MPP48_LCD_D16 MPP( 22, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP49_GPIO MPP( 49, 0x0, 1, 1, 0, 0, 0, 1, 0 )
#define MPP49_GPO MPP( 49, 0x0, 0, 1, 0, 0, 0, 0, 1 )
-#define MPP49_TSMP9 MPP( 49, 0x1, 1, 1, 0, 0, 0, 1, 0 )
-#define MPP49_TDM_CH0_RX_QL MPP( 49, 0x2, 0, 1, 0, 0, 0, 1, 1 )
-#define MPP49_PTP_CLK MPP( 49, 0x5, 1, 0, 0, 0, 0, 1, 0 )
-#define MPP49_PEX0_CLKREQ MPP( 49, 0xa, 0, 1, 0, 0, 0, 0, 1 )
+#define MPP49_TSMP9 MPP( 49, 0x1, 0, 0, 0, 0, 0, 1, 0 )
+#define MPP49_TDM_CH0_RX_QL MPP( 49, 0x2, 0, 0, 0, 0, 0, 1, 1 )
+#define MPP49_PTP_CLK MPP( 49, 0x5, 0, 0, 0, 0, 0, 1, 0 )
+#define MPP49_PEX0_CLKREQ MPP( 49, 0xa, 0, 0, 0, 0, 0, 0, 1 )
#define MPP49_LCD_D17 MPP( 49, 0xb, 0, 0, 0, 0, 0, 0, 1 )
#define MPP_MAX 49
diff --git a/arch/arm/mach-lpc32xx/include/mach/irqs.h b/arch/arm/mach-lpc32xx/include/mach/irqs.h
index 2667f52e3b04..9e3b90df32e1 100644
--- a/arch/arm/mach-lpc32xx/include/mach/irqs.h
+++ b/arch/arm/mach-lpc32xx/include/mach/irqs.h
@@ -61,7 +61,7 @@
*/
#define IRQ_LPC32XX_JTAG_COMM_TX LPC32XX_SIC1_IRQ(1)
#define IRQ_LPC32XX_JTAG_COMM_RX LPC32XX_SIC1_IRQ(2)
-#define IRQ_LPC32XX_GPI_11 LPC32XX_SIC1_IRQ(4)
+#define IRQ_LPC32XX_GPI_28 LPC32XX_SIC1_IRQ(4)
#define IRQ_LPC32XX_TS_P LPC32XX_SIC1_IRQ(6)
#define IRQ_LPC32XX_TS_IRQ LPC32XX_SIC1_IRQ(7)
#define IRQ_LPC32XX_TS_AUX LPC32XX_SIC1_IRQ(8)
diff --git a/arch/arm/mach-lpc32xx/irq.c b/arch/arm/mach-lpc32xx/irq.c
index 4eae566dfdc7..c74de01ab5b6 100644
--- a/arch/arm/mach-lpc32xx/irq.c
+++ b/arch/arm/mach-lpc32xx/irq.c
@@ -118,6 +118,10 @@ static const struct lpc32xx_event_info lpc32xx_events[NR_IRQS] = {
.event_group = &lpc32xx_event_pin_regs,
.mask = LPC32XX_CLKPWR_EXTSRC_GPI_06_BIT,
},
+ [IRQ_LPC32XX_GPI_28] = {
+ .event_group = &lpc32xx_event_pin_regs,
+ .mask = LPC32XX_CLKPWR_EXTSRC_GPI_28_BIT,
+ },
[IRQ_LPC32XX_GPIO_00] = {
.event_group = &lpc32xx_event_int_regs,
.mask = LPC32XX_CLKPWR_INTSRC_GPIO_00_BIT,
@@ -305,9 +309,18 @@ static int lpc32xx_irq_wake(struct irq_data *d, unsigned int state)
if (state)
eventreg |= lpc32xx_events[d->irq].mask;
- else
+ else {
eventreg &= ~lpc32xx_events[d->irq].mask;
+ /*
+ * When disabling the wakeup, clear the latched
+ * event
+ */
+ __raw_writel(lpc32xx_events[d->irq].mask,
+ lpc32xx_events[d->irq].
+ event_group->rawstat_reg);
+ }
+
__raw_writel(eventreg,
lpc32xx_events[d->irq].event_group->enab_reg);
@@ -380,13 +393,15 @@ void __init lpc32xx_init_irq(void)
/* Setup SIC1 */
__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC1_BASE));
- __raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC1_BASE));
- __raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC1_BASE));
+ __raw_writel(SIC1_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC1_BASE));
+ __raw_writel(SIC1_ATR_DEFAULT,
+ LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC1_BASE));
/* Setup SIC2 */
__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE));
- __raw_writel(MIC_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC2_BASE));
- __raw_writel(MIC_ATR_DEFAULT, LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC2_BASE));
+ __raw_writel(SIC2_APR_DEFAULT, LPC32XX_INTC_POLAR(LPC32XX_SIC2_BASE));
+ __raw_writel(SIC2_ATR_DEFAULT,
+ LPC32XX_INTC_ACT_TYPE(LPC32XX_SIC2_BASE));
/* Configure supported IRQ's */
for (i = 0; i < NR_IRQS; i++) {
diff --git a/arch/arm/mach-lpc32xx/serial.c b/arch/arm/mach-lpc32xx/serial.c
index 429cfdbb2b3d..f2735281616a 100644
--- a/arch/arm/mach-lpc32xx/serial.c
+++ b/arch/arm/mach-lpc32xx/serial.c
@@ -88,6 +88,7 @@ struct uartinit {
char *uart_ck_name;
u32 ck_mode_mask;
void __iomem *pdiv_clk_reg;
+ resource_size_t mapbase;
};
static struct uartinit uartinit_data[] __initdata = {
@@ -97,6 +98,7 @@ static struct uartinit uartinit_data[] __initdata = {
.ck_mode_mask =
LPC32XX_UART_CLKMODE_LOAD(LPC32XX_UART_CLKMODE_ON, 5),
.pdiv_clk_reg = LPC32XX_CLKPWR_UART5_CLK_CTRL,
+ .mapbase = LPC32XX_UART5_BASE,
},
#endif
#ifdef CONFIG_ARCH_LPC32XX_UART3_SELECT
@@ -105,6 +107,7 @@ static struct uartinit uartinit_data[] __initdata = {
.ck_mode_mask =
LPC32XX_UART_CLKMODE_LOAD(LPC32XX_UART_CLKMODE_ON, 3),
.pdiv_clk_reg = LPC32XX_CLKPWR_UART3_CLK_CTRL,
+ .mapbase = LPC32XX_UART3_BASE,
},
#endif
#ifdef CONFIG_ARCH_LPC32XX_UART4_SELECT
@@ -113,6 +116,7 @@ static struct uartinit uartinit_data[] __initdata = {
.ck_mode_mask =
LPC32XX_UART_CLKMODE_LOAD(LPC32XX_UART_CLKMODE_ON, 4),
.pdiv_clk_reg = LPC32XX_CLKPWR_UART4_CLK_CTRL,
+ .mapbase = LPC32XX_UART4_BASE,
},
#endif
#ifdef CONFIG_ARCH_LPC32XX_UART6_SELECT
@@ -121,6 +125,7 @@ static struct uartinit uartinit_data[] __initdata = {
.ck_mode_mask =
LPC32XX_UART_CLKMODE_LOAD(LPC32XX_UART_CLKMODE_ON, 6),
.pdiv_clk_reg = LPC32XX_CLKPWR_UART6_CLK_CTRL,
+ .mapbase = LPC32XX_UART6_BASE,
},
#endif
};
@@ -165,11 +170,24 @@ void __init lpc32xx_serial_init(void)
/* pre-UART clock divider set to 1 */
__raw_writel(0x0101, uartinit_data[i].pdiv_clk_reg);
+
+ /*
+ * Force a flush of the RX FIFOs to work around a
+ * HW bug
+ */
+ puart = uartinit_data[i].mapbase;
+ __raw_writel(0xC1, LPC32XX_UART_IIR_FCR(puart));
+ __raw_writel(0x00, LPC32XX_UART_DLL_FIFO(puart));
+ j = LPC32XX_SUART_FIFO_SIZE;
+ while (j--)
+ tmp = __raw_readl(
+ LPC32XX_UART_DLL_FIFO(puart));
+ __raw_writel(0, LPC32XX_UART_IIR_FCR(puart));
}
/* This needs to be done after all UART clocks are setup */
__raw_writel(clkmodes, LPC32XX_UARTCTL_CLKMODE);
- for (i = 0; i < ARRAY_SIZE(uartinit_data) - 1; i++) {
+ for (i = 0; i < ARRAY_SIZE(uartinit_data); i++) {
/* Force a flush of the RX FIFOs to work around a HW bug */
puart = serial_std_platform_data[i].mapbase;
__raw_writel(0xC1, LPC32XX_UART_IIR_FCR(puart));
diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c
index 23d3980ef59d..d90e244e05e7 100644
--- a/arch/arm/mach-mv78xx0/common.c
+++ b/arch/arm/mach-mv78xx0/common.c
@@ -20,6 +20,7 @@
#include <mach/mv78xx0.h>
#include <mach/bridge-regs.h>
#include <plat/cache-feroceon-l2.h>
+#include <plat/ehci-orion.h>
#include <plat/orion_nand.h>
#include <plat/time.h>
#include <plat/common.h>
@@ -170,7 +171,7 @@ void __init mv78xx0_map_io(void)
void __init mv78xx0_ehci0_init(void)
{
orion_ehci_init(&mv78xx0_mbus_dram_info,
- USB0_PHYS_BASE, IRQ_MV78XX0_USB_0);
+ USB0_PHYS_BASE, IRQ_MV78XX0_USB_0, EHCI_PHY_NA);
}
diff --git a/arch/arm/mach-mv78xx0/mpp.h b/arch/arm/mach-mv78xx0/mpp.h
index b61b50927123..3752302ae2ee 100644
--- a/arch/arm/mach-mv78xx0/mpp.h
+++ b/arch/arm/mach-mv78xx0/mpp.h
@@ -24,296 +24,296 @@
#define MPP_78100_A0_MASK MPP(0, 0x0, 0, 0, 1)
#define MPP0_GPIO MPP(0, 0x0, 1, 1, 1)
-#define MPP0_GE0_COL MPP(0, 0x1, 1, 0, 1)
-#define MPP0_GE1_TXCLK MPP(0, 0x2, 0, 1, 1)
+#define MPP0_GE0_COL MPP(0, 0x1, 0, 0, 1)
+#define MPP0_GE1_TXCLK MPP(0, 0x2, 0, 0, 1)
#define MPP0_UNUSED MPP(0, 0x3, 0, 0, 1)
#define MPP1_GPIO MPP(1, 0x0, 1, 1, 1)
-#define MPP1_GE0_RXERR MPP(1, 0x1, 1, 0, 1)
-#define MPP1_GE1_TXCTL MPP(1, 0x2, 0, 1, 1)
+#define MPP1_GE0_RXERR MPP(1, 0x1, 0, 0, 1)
+#define MPP1_GE1_TXCTL MPP(1, 0x2, 0, 0, 1)
#define MPP1_UNUSED MPP(1, 0x3, 0, 0, 1)
#define MPP2_GPIO MPP(2, 0x0, 1, 1, 1)
-#define MPP2_GE0_CRS MPP(2, 0x1, 1, 0, 1)
-#define MPP2_GE1_RXCTL MPP(2, 0x2, 1, 0, 1)
+#define MPP2_GE0_CRS MPP(2, 0x1, 0, 0, 1)
+#define MPP2_GE1_RXCTL MPP(2, 0x2, 0, 0, 1)
#define MPP2_UNUSED MPP(2, 0x3, 0, 0, 1)
#define MPP3_GPIO MPP(3, 0x0, 1, 1, 1)
-#define MPP3_GE0_TXERR MPP(3, 0x1, 0, 1, 1)
-#define MPP3_GE1_RXCLK MPP(3, 0x2, 1, 0, 1)
+#define MPP3_GE0_TXERR MPP(3, 0x1, 0, 0, 1)
+#define MPP3_GE1_RXCLK MPP(3, 0x2, 0, 0, 1)
#define MPP3_UNUSED MPP(3, 0x3, 0, 0, 1)
#define MPP4_GPIO MPP(4, 0x0, 1, 1, 1)
-#define MPP4_GE0_TXD4 MPP(4, 0x1, 0, 1, 1)
-#define MPP4_GE1_TXD0 MPP(4, 0x2, 0, 1, 1)
+#define MPP4_GE0_TXD4 MPP(4, 0x1, 0, 0, 1)
+#define MPP4_GE1_TXD0 MPP(4, 0x2, 0, 0, 1)
#define MPP4_UNUSED MPP(4, 0x3, 0, 0, 1)
#define MPP5_GPIO MPP(5, 0x0, 1, 1, 1)
-#define MPP5_GE0_TXD5 MPP(5, 0x1, 0, 1, 1)
-#define MPP5_GE1_TXD1 MPP(5, 0x2, 0, 1, 1)
+#define MPP5_GE0_TXD5 MPP(5, 0x1, 0, 0, 1)
+#define MPP5_GE1_TXD1 MPP(5, 0x2, 0, 0, 1)
#define MPP5_UNUSED MPP(5, 0x3, 0, 0, 1)
#define MPP6_GPIO MPP(6, 0x0, 1, 1, 1)
-#define MPP6_GE0_TXD6 MPP(6, 0x1, 0, 1, 1)
-#define MPP6_GE1_TXD2 MPP(6, 0x2, 0, 1, 1)
+#define MPP6_GE0_TXD6 MPP(6, 0x1, 0, 0, 1)
+#define MPP6_GE1_TXD2 MPP(6, 0x2, 0, 0, 1)
#define MPP6_UNUSED MPP(6, 0x3, 0, 0, 1)
#define MPP7_GPIO MPP(7, 0x0, 1, 1, 1)
-#define MPP7_GE0_TXD7 MPP(7, 0x1, 0, 1, 1)
-#define MPP7_GE1_TXD3 MPP(7, 0x2, 0, 1, 1)
+#define MPP7_GE0_TXD7 MPP(7, 0x1, 0, 0, 1)
+#define MPP7_GE1_TXD3 MPP(7, 0x2, 0, 0, 1)
#define MPP7_UNUSED MPP(7, 0x3, 0, 0, 1)
#define MPP8_GPIO MPP(8, 0x0, 1, 1, 1)
-#define MPP8_GE0_RXD4 MPP(8, 0x1, 1, 0, 1)
-#define MPP8_GE1_RXD0 MPP(8, 0x2, 1, 0, 1)
+#define MPP8_GE0_RXD4 MPP(8, 0x1, 0, 0, 1)
+#define MPP8_GE1_RXD0 MPP(8, 0x2, 0, 0, 1)
#define MPP8_UNUSED MPP(8, 0x3, 0, 0, 1)
#define MPP9_GPIO MPP(9, 0x0, 1, 1, 1)
-#define MPP9_GE0_RXD5 MPP(9, 0x1, 1, 0, 1)
-#define MPP9_GE1_RXD1 MPP(9, 0x2, 1, 0, 1)
+#define MPP9_GE0_RXD5 MPP(9, 0x1, 0, 0, 1)
+#define MPP9_GE1_RXD1 MPP(9, 0x2, 0, 0, 1)
#define MPP9_UNUSED MPP(9, 0x3, 0, 0, 1)
#define MPP10_GPIO MPP(10, 0x0, 1, 1, 1)
-#define MPP10_GE0_RXD6 MPP(10, 0x1, 1, 0, 1)
-#define MPP10_GE1_RXD2 MPP(10, 0x2, 1, 0, 1)
+#define MPP10_GE0_RXD6 MPP(10, 0x1, 0, 0, 1)
+#define MPP10_GE1_RXD2 MPP(10, 0x2, 0, 0, 1)
#define MPP10_UNUSED MPP(10, 0x3, 0, 0, 1)
#define MPP11_GPIO MPP(11, 0x0, 1, 1, 1)
-#define MPP11_GE0_RXD7 MPP(11, 0x1, 1, 0, 1)
-#define MPP11_GE1_RXD3 MPP(11, 0x2, 1, 0, 1)
+#define MPP11_GE0_RXD7 MPP(11, 0x1, 0, 0, 1)
+#define MPP11_GE1_RXD3 MPP(11, 0x2, 0, 0, 1)
#define MPP11_UNUSED MPP(11, 0x3, 0, 0, 1)
#define MPP12_GPIO MPP(12, 0x0, 1, 1, 1)
-#define MPP12_M_BB MPP(12, 0x3, 1, 0, 1)
-#define MPP12_UA0_CTSn MPP(12, 0x4, 1, 0, 1)
-#define MPP12_NAND_FLASH_REn0 MPP(12, 0x5, 0, 1, 1)
-#define MPP12_TDM0_SCSn MPP(12, 0X6, 0, 1, 1)
+#define MPP12_M_BB MPP(12, 0x3, 0, 0, 1)
+#define MPP12_UA0_CTSn MPP(12, 0x4, 0, 0, 1)
+#define MPP12_NAND_FLASH_REn0 MPP(12, 0x5, 0, 0, 1)
+#define MPP12_TDM0_SCSn MPP(12, 0X6, 0, 0, 1)
#define MPP12_UNUSED MPP(12, 0x1, 0, 0, 1)
#define MPP13_GPIO MPP(13, 0x0, 1, 1, 1)
-#define MPP13_SYSRST_OUTn MPP(13, 0x3, 0, 1, 1)
-#define MPP13_UA0_RTSn MPP(13, 0x4, 0, 1, 1)
-#define MPP13_NAN_FLASH_WEn0 MPP(13, 0x5, 0, 1, 1)
-#define MPP13_TDM_SCLK MPP(13, 0x6, 0, 1, 1)
+#define MPP13_SYSRST_OUTn MPP(13, 0x3, 0, 0, 1)
+#define MPP13_UA0_RTSn MPP(13, 0x4, 0, 0, 1)
+#define MPP13_NAN_FLASH_WEn0 MPP(13, 0x5, 0, 0, 1)
+#define MPP13_TDM_SCLK MPP(13, 0x6, 0, 0, 1)
#define MPP13_UNUSED MPP(13, 0x1, 0, 0, 1)
#define MPP14_GPIO MPP(14, 0x0, 1, 1, 1)
-#define MPP14_SATA1_ACTn MPP(14, 0x3, 0, 1, 1)
-#define MPP14_UA1_CTSn MPP(14, 0x4, 1, 0, 1)
-#define MPP14_NAND_FLASH_REn1 MPP(14, 0x5, 0, 1, 1)
-#define MPP14_TDM_SMOSI MPP(14, 0x6, 0, 1, 1)
+#define MPP14_SATA1_ACTn MPP(14, 0x3, 0, 0, 1)
+#define MPP14_UA1_CTSn MPP(14, 0x4, 0, 0, 1)
+#define MPP14_NAND_FLASH_REn1 MPP(14, 0x5, 0, 0, 1)
+#define MPP14_TDM_SMOSI MPP(14, 0x6, 0, 0, 1)
#define MPP14_UNUSED MPP(14, 0x1, 0, 0, 1)
#define MPP15_GPIO MPP(15, 0x0, 1, 1, 1)
-#define MPP15_SATA0_ACTn MPP(15, 0x3, 0, 1, 1)
-#define MPP15_UA1_RTSn MPP(15, 0x4, 0, 1, 1)
-#define MPP15_NAND_FLASH_WEn1 MPP(15, 0x5, 0, 1, 1)
-#define MPP15_TDM_SMISO MPP(15, 0x6, 1, 0, 1)
+#define MPP15_SATA0_ACTn MPP(15, 0x3, 0, 0, 1)
+#define MPP15_UA1_RTSn MPP(15, 0x4, 0, 0, 1)
+#define MPP15_NAND_FLASH_WEn1 MPP(15, 0x5, 0, 0, 1)
+#define MPP15_TDM_SMISO MPP(15, 0x6, 0, 0, 1)
#define MPP15_UNUSED MPP(15, 0x1, 0, 0, 1)
#define MPP16_GPIO MPP(16, 0x0, 1, 1, 1)
-#define MPP16_SATA1_PRESENTn MPP(16, 0x3, 0, 1, 1)
-#define MPP16_UA2_TXD MPP(16, 0x4, 0, 1, 1)
-#define MPP16_NAND_FLASH_REn3 MPP(16, 0x5, 0, 1, 1)
-#define MPP16_TDM_INTn MPP(16, 0x6, 1, 0, 1)
+#define MPP16_SATA1_PRESENTn MPP(16, 0x3, 0, 0, 1)
+#define MPP16_UA2_TXD MPP(16, 0x4, 0, 0, 1)
+#define MPP16_NAND_FLASH_REn3 MPP(16, 0x5, 0, 0, 1)
+#define MPP16_TDM_INTn MPP(16, 0x6, 0, 0, 1)
#define MPP16_UNUSED MPP(16, 0x1, 0, 0, 1)
#define MPP17_GPIO MPP(17, 0x0, 1, 1, 1)
-#define MPP17_SATA0_PRESENTn MPP(17, 0x3, 0, 1, 1)
-#define MPP17_UA2_RXD MPP(17, 0x4, 1, 0, 1)
-#define MPP17_NAND_FLASH_WEn3 MPP(17, 0x5, 0, 1, 1)
-#define MPP17_TDM_RSTn MPP(17, 0x6, 0, 1, 1)
+#define MPP17_SATA0_PRESENTn MPP(17, 0x3, 0, 0, 1)
+#define MPP17_UA2_RXD MPP(17, 0x4, 0, 0, 1)
+#define MPP17_NAND_FLASH_WEn3 MPP(17, 0x5, 0, 0, 1)
+#define MPP17_TDM_RSTn MPP(17, 0x6, 0, 0, 1)
#define MPP17_UNUSED MPP(17, 0x1, 0, 0, 1)
#define MPP18_GPIO MPP(18, 0x0, 1, 1, 1)
-#define MPP18_UA0_CTSn MPP(18, 0x4, 1, 0, 1)
-#define MPP18_BOOT_FLASH_REn MPP(18, 0x5, 0, 1, 1)
+#define MPP18_UA0_CTSn MPP(18, 0x4, 0, 0, 1)
+#define MPP18_BOOT_FLASH_REn MPP(18, 0x5, 0, 0, 1)
#define MPP18_UNUSED MPP(18, 0x1, 0, 0, 1)
#define MPP19_GPIO MPP(19, 0x0, 1, 1, 1)
-#define MPP19_UA0_CTSn MPP(19, 0x4, 0, 1, 1)
-#define MPP19_BOOT_FLASH_WEn MPP(19, 0x5, 0, 1, 1)
+#define MPP19_UA0_CTSn MPP(19, 0x4, 0, 0, 1)
+#define MPP19_BOOT_FLASH_WEn MPP(19, 0x5, 0, 0, 1)
#define MPP19_UNUSED MPP(19, 0x1, 0, 0, 1)
#define MPP20_GPIO MPP(20, 0x0, 1, 1, 1)
-#define MPP20_UA1_CTSs MPP(20, 0x4, 1, 0, 1)
-#define MPP20_TDM_PCLK MPP(20, 0x6, 1, 1, 0)
+#define MPP20_UA1_CTSs MPP(20, 0x4, 0, 0, 1)
+#define MPP20_TDM_PCLK MPP(20, 0x6, 0, 0, 0)
#define MPP20_UNUSED MPP(20, 0x1, 0, 0, 1)
#define MPP21_GPIO MPP(21, 0x0, 1, 1, 1)
-#define MPP21_UA1_CTSs MPP(21, 0x4, 0, 1, 1)
-#define MPP21_TDM_FSYNC MPP(21, 0x6, 1, 1, 0)
+#define MPP21_UA1_CTSs MPP(21, 0x4, 0, 0, 1)
+#define MPP21_TDM_FSYNC MPP(21, 0x6, 0, 0, 0)
#define MPP21_UNUSED MPP(21, 0x1, 0, 0, 1)
#define MPP22_GPIO MPP(22, 0x0, 1, 1, 1)
-#define MPP22_UA3_TDX MPP(22, 0x4, 0, 1, 1)
-#define MPP22_NAND_FLASH_REn2 MPP(22, 0x5, 0, 1, 1)
-#define MPP22_TDM_DRX MPP(22, 0x6, 1, 0, 1)
+#define MPP22_UA3_TDX MPP(22, 0x4, 0, 0, 1)
+#define MPP22_NAND_FLASH_REn2 MPP(22, 0x5, 0, 0, 1)
+#define MPP22_TDM_DRX MPP(22, 0x6, 0, 0, 1)
#define MPP22_UNUSED MPP(22, 0x1, 0, 0, 1)
#define MPP23_GPIO MPP(23, 0x0, 1, 1, 1)
-#define MPP23_UA3_RDX MPP(23, 0x4, 1, 0, 1)
-#define MPP23_NAND_FLASH_WEn2 MPP(23, 0x5, 0, 1, 1)
-#define MPP23_TDM_DTX MPP(23, 0x6, 0, 1, 1)
+#define MPP23_UA3_RDX MPP(23, 0x4, 0, 0, 1)
+#define MPP23_NAND_FLASH_WEn2 MPP(23, 0x5, 0, 0, 1)
+#define MPP23_TDM_DTX MPP(23, 0x6, 0, 0, 1)
#define MPP23_UNUSED MPP(23, 0x1, 0, 0, 1)
#define MPP24_GPIO MPP(24, 0x0, 1, 1, 1)
-#define MPP24_UA2_TXD MPP(24, 0x4, 0, 1, 1)
-#define MPP24_TDM_INTn MPP(24, 0x6, 1, 0, 1)
+#define MPP24_UA2_TXD MPP(24, 0x4, 0, 0, 1)
+#define MPP24_TDM_INTn MPP(24, 0x6, 0, 0, 1)
#define MPP24_UNUSED MPP(24, 0x1, 0, 0, 1)
#define MPP25_GPIO MPP(25, 0x0, 1, 1, 1)
-#define MPP25_UA2_RXD MPP(25, 0x4, 1, 0, 1)
-#define MPP25_TDM_RSTn MPP(25, 0x6, 0, 1, 1)
+#define MPP25_UA2_RXD MPP(25, 0x4, 0, 0, 1)
+#define MPP25_TDM_RSTn MPP(25, 0x6, 0, 0, 1)
#define MPP25_UNUSED MPP(25, 0x1, 0, 0, 1)
#define MPP26_GPIO MPP(26, 0x0, 1, 1, 1)
-#define MPP26_UA2_CTSn MPP(26, 0x4, 1, 0, 1)
-#define MPP26_TDM_PCLK MPP(26, 0x6, 1, 1, 1)
+#define MPP26_UA2_CTSn MPP(26, 0x4, 0, 0, 1)
+#define MPP26_TDM_PCLK MPP(26, 0x6, 0, 0, 1)
#define MPP26_UNUSED MPP(26, 0x1, 0, 0, 1)
#define MPP27_GPIO MPP(27, 0x0, 1, 1, 1)
-#define MPP27_UA2_RTSn MPP(27, 0x4, 0, 1, 1)
-#define MPP27_TDM_FSYNC MPP(27, 0x6, 1, 1, 1)
+#define MPP27_UA2_RTSn MPP(27, 0x4, 0, 0, 1)
+#define MPP27_TDM_FSYNC MPP(27, 0x6, 0, 0, 1)
#define MPP27_UNUSED MPP(27, 0x1, 0, 0, 1)
#define MPP28_GPIO MPP(28, 0x0, 1, 1, 1)
-#define MPP28_UA3_TXD MPP(28, 0x4, 0, 1, 1)
-#define MPP28_TDM_DRX MPP(28, 0x6, 1, 0, 1)
+#define MPP28_UA3_TXD MPP(28, 0x4, 0, 0, 1)
+#define MPP28_TDM_DRX MPP(28, 0x6, 0, 0, 1)
#define MPP28_UNUSED MPP(28, 0x1, 0, 0, 1)
#define MPP29_GPIO MPP(29, 0x0, 1, 1, 1)
-#define MPP29_UA3_RXD MPP(29, 0x4, 1, 0, 1)
-#define MPP29_SYSRST_OUTn MPP(29, 0x5, 0, 1, 1)
-#define MPP29_TDM_DTX MPP(29, 0x6, 0, 1, 1)
+#define MPP29_UA3_RXD MPP(29, 0x4, 0, 0, 1)
+#define MPP29_SYSRST_OUTn MPP(29, 0x5, 0, 0, 1)
+#define MPP29_TDM_DTX MPP(29, 0x6, 0, 0, 1)
#define MPP29_UNUSED MPP(29, 0x1, 0, 0, 1)
#define MPP30_GPIO MPP(30, 0x0, 1, 1, 1)
-#define MPP30_UA3_CTSn MPP(30, 0x4, 1, 0, 1)
+#define MPP30_UA3_CTSn MPP(30, 0x4, 0, 0, 1)
#define MPP30_UNUSED MPP(30, 0x1, 0, 0, 1)
#define MPP31_GPIO MPP(31, 0x0, 1, 1, 1)
-#define MPP31_UA3_RTSn MPP(31, 0x4, 0, 1, 1)
-#define MPP31_TDM1_SCSn MPP(31, 0x6, 0, 1, 1)
+#define MPP31_UA3_RTSn MPP(31, 0x4, 0, 0, 1)
+#define MPP31_TDM1_SCSn MPP(31, 0x6, 0, 0, 1)
#define MPP31_UNUSED MPP(31, 0x1, 0, 0, 1)
#define MPP32_GPIO MPP(32, 0x1, 1, 1, 1)
-#define MPP32_UA3_TDX MPP(32, 0x4, 0, 1, 1)
-#define MPP32_SYSRST_OUTn MPP(32, 0x5, 0, 1, 1)
-#define MPP32_TDM0_RXQ MPP(32, 0x6, 0, 1, 1)
+#define MPP32_UA3_TDX MPP(32, 0x4, 0, 0, 1)
+#define MPP32_SYSRST_OUTn MPP(32, 0x5, 0, 0, 1)
+#define MPP32_TDM0_RXQ MPP(32, 0x6, 0, 0, 1)
#define MPP32_UNUSED MPP(32, 0x3, 0, 0, 1)
#define MPP33_GPIO MPP(33, 0x1, 1, 1, 1)
-#define MPP33_UA3_RDX MPP(33, 0x4, 1, 0, 1)
-#define MPP33_TDM0_TXQ MPP(33, 0x6, 0, 1, 1)
+#define MPP33_UA3_RDX MPP(33, 0x4, 0, 0, 1)
+#define MPP33_TDM0_TXQ MPP(33, 0x6, 0, 0, 1)
#define MPP33_UNUSED MPP(33, 0x3, 0, 0, 1)
#define MPP34_GPIO MPP(34, 0x1, 1, 1, 1)
-#define MPP34_UA2_TDX MPP(34, 0x4, 0, 1, 1)
-#define MPP34_TDM1_RXQ MPP(34, 0x6, 0, 1, 1)
+#define MPP34_UA2_TDX MPP(34, 0x4, 0, 0, 1)
+#define MPP34_TDM1_RXQ MPP(34, 0x6, 0, 0, 1)
#define MPP34_UNUSED MPP(34, 0x3, 0, 0, 1)
#define MPP35_GPIO MPP(35, 0x1, 1, 1, 1)
-#define MPP35_UA2_RDX MPP(35, 0x4, 1, 0, 1)
-#define MPP35_TDM1_TXQ MPP(35, 0x6, 0, 1, 1)
+#define MPP35_UA2_RDX MPP(35, 0x4, 0, 0, 1)
+#define MPP35_TDM1_TXQ MPP(35, 0x6, 0, 0, 1)
#define MPP35_UNUSED MPP(35, 0x3, 0, 0, 1)
#define MPP36_GPIO MPP(36, 0x1, 1, 1, 1)
-#define MPP36_UA0_CTSn MPP(36, 0x2, 1, 0, 1)
-#define MPP36_UA2_TDX MPP(36, 0x4, 0, 1, 1)
-#define MPP36_TDM0_SCSn MPP(36, 0x6, 0, 1, 1)
+#define MPP36_UA0_CTSn MPP(36, 0x2, 0, 0, 1)
+#define MPP36_UA2_TDX MPP(36, 0x4, 0, 0, 1)
+#define MPP36_TDM0_SCSn MPP(36, 0x6, 0, 0, 1)
#define MPP36_UNUSED MPP(36, 0x3, 0, 0, 1)
#define MPP37_GPIO MPP(37, 0x1, 1, 1, 1)
-#define MPP37_UA0_RTSn MPP(37, 0x2, 0, 1, 1)
-#define MPP37_UA2_RXD MPP(37, 0x4, 1, 0, 1)
-#define MPP37_SYSRST_OUTn MPP(37, 0x5, 0, 1, 1)
-#define MPP37_TDM_SCLK MPP(37, 0x6, 0, 1, 1)
+#define MPP37_UA0_RTSn MPP(37, 0x2, 0, 0, 1)
+#define MPP37_UA2_RXD MPP(37, 0x4, 0, 0, 1)
+#define MPP37_SYSRST_OUTn MPP(37, 0x5, 0, 0, 1)
+#define MPP37_TDM_SCLK MPP(37, 0x6, 0, 0, 1)
#define MPP37_UNUSED MPP(37, 0x3, 0, 0, 1)
#define MPP38_GPIO MPP(38, 0x1, 1, 1, 1)
-#define MPP38_UA1_CTSn MPP(38, 0x2, 1, 0, 1)
-#define MPP38_UA3_TXD MPP(38, 0x4, 0, 1, 1)
-#define MPP38_SYSRST_OUTn MPP(38, 0x5, 0, 1, 1)
-#define MPP38_TDM_SMOSI MPP(38, 0x6, 0, 1, 1)
+#define MPP38_UA1_CTSn MPP(38, 0x2, 0, 0, 1)
+#define MPP38_UA3_TXD MPP(38, 0x4, 0, 0, 1)
+#define MPP38_SYSRST_OUTn MPP(38, 0x5, 0, 0, 1)
+#define MPP38_TDM_SMOSI MPP(38, 0x6, 0, 0, 1)
#define MPP38_UNUSED MPP(38, 0x3, 0, 0, 1)
#define MPP39_GPIO MPP(39, 0x1, 1, 1, 1)
-#define MPP39_UA1_RTSn MPP(39, 0x2, 0, 1, 1)
-#define MPP39_UA3_RXD MPP(39, 0x4, 1, 0, 1)
-#define MPP39_SYSRST_OUTn MPP(39, 0x5, 0, 1, 1)
-#define MPP39_TDM_SMISO MPP(39, 0x6, 1, 0, 1)
+#define MPP39_UA1_RTSn MPP(39, 0x2, 0, 0, 1)
+#define MPP39_UA3_RXD MPP(39, 0x4, 0, 0, 1)
+#define MPP39_SYSRST_OUTn MPP(39, 0x5, 0, 0, 1)
+#define MPP39_TDM_SMISO MPP(39, 0x6, 0, 0, 1)
#define MPP39_UNUSED MPP(39, 0x3, 0, 0, 1)
#define MPP40_GPIO MPP(40, 0x1, 1, 1, 1)
-#define MPP40_TDM_INTn MPP(40, 0x6, 1, 0, 1)
+#define MPP40_TDM_INTn MPP(40, 0x6, 0, 0, 1)
#define MPP40_UNUSED MPP(40, 0x0, 0, 0, 1)
#define MPP41_GPIO MPP(41, 0x1, 1, 1, 1)
-#define MPP41_TDM_RSTn MPP(41, 0x6, 0, 1, 1)
+#define MPP41_TDM_RSTn MPP(41, 0x6, 0, 0, 1)
#define MPP41_UNUSED MPP(41, 0x0, 0, 0, 1)
#define MPP42_GPIO MPP(42, 0x1, 1, 1, 1)
-#define MPP42_TDM_PCLK MPP(42, 0x6, 1, 1, 1)
+#define MPP42_TDM_PCLK MPP(42, 0x6, 0, 0, 1)
#define MPP42_UNUSED MPP(42, 0x0, 0, 0, 1)
#define MPP43_GPIO MPP(43, 0x1, 1, 1, 1)
-#define MPP43_TDM_FSYNC MPP(43, 0x6, 1, 1, 1)
+#define MPP43_TDM_FSYNC MPP(43, 0x6, 0, 0, 1)
#define MPP43_UNUSED MPP(43, 0x0, 0, 0, 1)
#define MPP44_GPIO MPP(44, 0x1, 1, 1, 1)
-#define MPP44_TDM_DRX MPP(44, 0x6, 1, 0, 1)
+#define MPP44_TDM_DRX MPP(44, 0x6, 0, 0, 1)
#define MPP44_UNUSED MPP(44, 0x0, 0, 0, 1)
#define MPP45_GPIO MPP(45, 0x1, 1, 1, 1)
-#define MPP45_SATA0_ACTn MPP(45, 0x3, 0, 1, 1)
-#define MPP45_TDM_DRX MPP(45, 0x6, 0, 1, 1)
+#define MPP45_SATA0_ACTn MPP(45, 0x3, 0, 0, 1)
+#define MPP45_TDM_DRX MPP(45, 0x6, 0, 0, 1)
#define MPP45_UNUSED MPP(45, 0x0, 0, 0, 1)
#define MPP46_GPIO MPP(46, 0x1, 1, 1, 1)
-#define MPP46_TDM_SCSn MPP(46, 0x6, 0, 1, 1)
+#define MPP46_TDM_SCSn MPP(46, 0x6, 0, 0, 1)
#define MPP46_UNUSED MPP(46, 0x0, 0, 0, 1)
@@ -323,14 +323,14 @@
#define MPP48_GPIO MPP(48, 0x1, 1, 1, 1)
-#define MPP48_SATA1_ACTn MPP(48, 0x3, 0, 1, 1)
+#define MPP48_SATA1_ACTn MPP(48, 0x3, 0, 0, 1)
#define MPP48_UNUSED MPP(48, 0x2, 0, 0, 1)
#define MPP49_GPIO MPP(49, 0x1, 1, 1, 1)
-#define MPP49_SATA0_ACTn MPP(49, 0x3, 0, 1, 1)
-#define MPP49_M_BB MPP(49, 0x4, 1, 0, 1)
+#define MPP49_SATA0_ACTn MPP(49, 0x3, 0, 0, 1)
+#define MPP49_M_BB MPP(49, 0x4, 0, 0, 1)
#define MPP49_UNUSED MPP(49, 0x2, 0, 0, 1)
diff --git a/arch/arm/mach-mx6/Kconfig b/arch/arm/mach-mx6/Kconfig
index a96597d2d599..5c60c560f03a 100644
--- a/arch/arm/mach-mx6/Kconfig
+++ b/arch/arm/mach-mx6/Kconfig
@@ -65,6 +65,7 @@ config MACH_MX6Q_ARM2
select IMX_HAVE_PLATFORM_IMX_ELCDIF
select IMX_HAVE_PLATFORM_IMX_PXP
select IMX_HAVE_PLATFORM_IMX_PCIE
+ select IMX_HAVE_PLATFORM_IMX_CAAM
help
Include support for i.MX 6Quad Armadillo2 platform. This includes specific
configurations for the board and its peripherals.
@@ -99,6 +100,9 @@ config MACH_MX6SL_ARM2
select IMX_HAVE_PLATFORM_IMX_SPDC
select IMX_HAVE_PLATFORM_IMX_PXP
select IMX_HAVE_PLATFORM_IMX_KEYPAD
+ select IMX_HAVE_PLATFORM_IMX_DCP
+ select IMX_HAVE_PLATFORM_RANDOM_RNGC
+ select ARCH_HAS_RNGC
help
Include support for i.MX 6Sololite Armadillo2 platform. This includes specific
configurations for the board and its peripherals.
@@ -131,6 +135,7 @@ config MACH_MX6Q_SABRELITE
select IMX_HAVE_PLATFORM_MXC_HDMI
select IMX_HAVE_PLATFORM_IMX_ASRC
select IMX_HAVE_PLATFORM_FLEXCAN
+ select IMX_HAVE_PLATFORM_IMX_CAAM
help
Include support for i.MX 6Quad SABRE Lite platform. This includes specific
configurations for the board and its peripherals.
@@ -164,6 +169,7 @@ config MACH_MX6Q_SABRESD
select IMX_HAVE_PLATFORM_IMX_ASRC
select IMX_HAVE_PLATFORM_FLEXCAN
select IMX_HAVE_PLATFORM_IMX_PCIE
+ select IMX_HAVE_PLATFORM_IMX_CAAM
help
Include support for i.MX 6Quad SABRE SD platform. This includes specific
configurations for the board and its peripherals.
@@ -200,6 +206,8 @@ config MACH_MX6Q_SABREAUTO
select IMX_HAVE_PLATFORM_IMX_MIPI_DSI
select IMX_HAVE_PLATFORM_FLEXCAN
select IMX_HAVE_PLATFORM_IMX_MIPI_CSI2
+ select IMX_HAVE_PLATFORM_IMX_PCIE
+ select IMX_HAVE_PLATFORM_IMX_CAAM
help
Include support for i.MX 6Quad SABRE Auto platform. This includes specific
configurations for the board and its peripherals.
diff --git a/arch/arm/mach-mx6/board-mx6dl_arm2.h b/arch/arm/mach-mx6/board-mx6dl_arm2.h
index 4528da53694a..6ed3e65e68ee 100644
--- a/arch/arm/mach-mx6/board-mx6dl_arm2.h
+++ b/arch/arm/mach-mx6/board-mx6dl_arm2.h
@@ -319,3 +319,13 @@ static iomux_v3_cfg_t mx6dl_gpmi_nand[] __initdata = {
MX6DL_PAD_SD4_CLK__RAWNAND_WRN,
MX6DL_PAD_NANDF_WP_B__RAWNAND_RESETN,
};
+
+static iomux_v3_cfg_t mx6dl_arm2_hdmi_ddc_pads[] = {
+ MX6DL_PAD_KEY_COL3__HDMI_TX_DDC_SCL, /* HDMI DDC SCL */
+ MX6DL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA, /* HDMI DDC SDA */
+};
+
+static iomux_v3_cfg_t mx6dl_arm2_i2c2_pads[] = {
+ MX6DL_PAD_KEY_COL3__I2C2_SCL, /* I2C2 SCL */
+ MX6DL_PAD_KEY_ROW3__I2C2_SDA, /* I2C2 SDA */
+};
diff --git a/arch/arm/mach-mx6/board-mx6dl_sabresd.h b/arch/arm/mach-mx6/board-mx6dl_sabresd.h
index 35701a4979d4..7e6a26143a49 100644
--- a/arch/arm/mach-mx6/board-mx6dl_sabresd.h
+++ b/arch/arm/mach-mx6/board-mx6dl_sabresd.h
@@ -390,4 +390,13 @@ static iomux_v3_cfg_t mx6dl_arm2_elan_pads[] = {
MX6DL_PAD_EIM_D28__GPIO_3_28,
};
+static iomux_v3_cfg_t mx6dl_sabresd_hdmi_ddc_pads[] = {
+ MX6DL_PAD_KEY_COL3__HDMI_TX_DDC_SCL, /* HDMI DDC SCL */
+ MX6DL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA, /* HDMI DDC SDA */
+};
+
+static iomux_v3_cfg_t mx6dl_sabresd_i2c2_pads[] = {
+ MX6DL_PAD_KEY_COL3__I2C2_SCL, /* I2C2 SCL */
+ MX6DL_PAD_KEY_ROW3__I2C2_SDA, /* I2C2 SDA */
+};
#endif
diff --git a/arch/arm/mach-mx6/board-mx6q_arm2.c b/arch/arm/mach-mx6/board-mx6q_arm2.c
index 2bfd23e6085b..c335e5e451c0 100644
--- a/arch/arm/mach-mx6/board-mx6q_arm2.c
+++ b/arch/arm/mach-mx6/board-mx6q_arm2.c
@@ -77,7 +77,6 @@
#include "devices-imx6q.h"
#include "crm_regs.h"
#include "cpu_op-mx6.h"
-
#include "board-mx6q_arm2.h"
#include "board-mx6dl_arm2.h"
@@ -1413,8 +1412,34 @@ static void hdmi_init(int ipu_id, int disp_id)
mxc_iomux_set_gpr_register(3, 2, 2, hdmi_mux_setting);
}
+/* On mx6x arm2 board i2c2 iomux with hdmi ddc,
+ * the pins default work at i2c2 function,
+ when hdcp enable, the pins should work at ddc function */
+
+static void hdmi_enable_ddc_pin(void)
+{
+ if (cpu_is_mx6dl())
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_arm2_hdmi_ddc_pads,
+ ARRAY_SIZE(mx6dl_arm2_hdmi_ddc_pads));
+ else
+ mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_hdmi_ddc_pads,
+ ARRAY_SIZE(mx6q_arm2_hdmi_ddc_pads));
+}
+
+static void hdmi_disable_ddc_pin(void)
+{
+ if (cpu_is_mx6dl())
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_arm2_i2c2_pads,
+ ARRAY_SIZE(mx6dl_arm2_i2c2_pads));
+ else
+ mxc_iomux_v3_setup_multiple_pads(mx6q_arm2_i2c2_pads,
+ ARRAY_SIZE(mx6q_arm2_i2c2_pads));
+}
+
static struct fsl_mxc_hdmi_platform_data hdmi_data = {
- .init = hdmi_init,
+ .init = hdmi_init,
+ .enable_pins = hdmi_enable_ddc_pin,
+ .disable_pins = hdmi_disable_ddc_pin,
};
static struct fsl_mxc_hdmi_core_platform_data hdmi_core_data = {
@@ -2184,6 +2209,7 @@ static void __init mx6_arm2_init(void)
mxc_register_device(&max17135_sensor_device, NULL);
imx6dl_add_imx_epdc(&epdc_data);
}
+ /* Add PCIe RC interface support */
imx6q_add_pcie(&mx6_arm2_pcie_data);
imx6q_add_busfreq();
}
diff --git a/arch/arm/mach-mx6/board-mx6q_arm2.h b/arch/arm/mach-mx6/board-mx6q_arm2.h
index 8c3277d869e1..eb06ef89bdd8 100644
--- a/arch/arm/mach-mx6/board-mx6q_arm2.h
+++ b/arch/arm/mach-mx6/board-mx6q_arm2.h
@@ -315,3 +315,13 @@ static iomux_v3_cfg_t mx6q_gpmi_nand[] __initdata = {
MX6Q_PAD_SD4_CLK__RAWNAND_WRN,
MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN,
};
+
+static iomux_v3_cfg_t mx6q_arm2_hdmi_ddc_pads[] = {
+ MX6Q_PAD_KEY_COL3__HDMI_TX_DDC_SCL, /* HDMI DDC SCL */
+ MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA, /* HDMI DDC SDA */
+};
+
+static iomux_v3_cfg_t mx6q_arm2_i2c2_pads[] = {
+ MX6Q_PAD_KEY_COL3__I2C2_SCL, /* I2C2 SCL */
+ MX6Q_PAD_KEY_ROW3__I2C2_SDA, /* I2C2 SDA */
+};
diff --git a/arch/arm/mach-mx6/board-mx6q_sabreauto.c b/arch/arm/mach-mx6/board-mx6q_sabreauto.c
index 2e5cf702a23b..7d2eab2c89f2 100644
--- a/arch/arm/mach-mx6/board-mx6q_sabreauto.c
+++ b/arch/arm/mach-mx6/board-mx6q_sabreauto.c
@@ -104,6 +104,7 @@
#define SABREAUTO_CSI0_RST IMX_GPIO_NR(4, 5)
#define SABREAUTO_DISP0_RESET IMX_GPIO_NR(5, 0)
#define SABREAUTO_I2C3_STEER IMX_GPIO_NR(5, 4)
+#define SABREAUTO_WEIM_NOR_WDOG1 IMX_GPIO_NR(4, 29)
#define SABREAUTO_ANDROID_VOLDOWN IMX_GPIO_NR(5, 14)
#define SABREAUTO_PMIC_INT IMX_GPIO_NR(5, 16)
#define SABREAUTO_ALS_INT IMX_GPIO_NR(5, 17)
@@ -120,6 +121,7 @@
#define SABREAUTO_IO_EXP_GPIO2(x) (SABREAUTO_MAX7310_2_BASE_ADDR + (x))
#define SABREAUTO_IO_EXP_GPIO3(x) (SABREAUTO_MAX7310_3_BASE_ADDR + (x))
+#define SABREAUTO_PCIE_RST_B_REVB (SABREAUTO_MAX7310_1_BASE_ADDR + 2)
/*
* CAN2 STBY and EN lines are the same as the CAN1. These lines are not
* independent.
@@ -140,6 +142,7 @@ static int can0_enable;
static int uart3_en;
static int tuner_en;
static int spinor_en;
+static int weimnor_en;
static int __init spinor_enable(char *p)
{
@@ -148,6 +151,13 @@ static int __init spinor_enable(char *p)
}
early_param("spi-nor", spinor_enable);
+static int __init weimnor_enable(char *p)
+{
+ weimnor_en = 1;
+ return 0;
+}
+early_param("weim-nor", weimnor_enable);
+
static int __init uart3_enable(char *p)
{
uart3_en = 1;
@@ -903,8 +913,34 @@ static void hdmi_init(int ipu_id, int disp_id)
mxc_iomux_set_gpr_register(3, 2, 2, hdmi_mux_setting);
}
+/* On mx6x sabreauto board i2c2 iomux with hdmi ddc,
+ * the pins default work at i2c2 function,
+ when hdcp enable, the pins should work at ddc function */
+
+static void hdmi_enable_ddc_pin(void)
+{
+ if (cpu_is_mx6dl())
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_sabreauto_hdmi_ddc_pads,
+ ARRAY_SIZE(mx6dl_sabreauto_hdmi_ddc_pads));
+ else
+ mxc_iomux_v3_setup_multiple_pads(mx6q_sabreauto_hdmi_ddc_pads,
+ ARRAY_SIZE(mx6q_sabreauto_hdmi_ddc_pads));
+}
+
+static void hdmi_disable_ddc_pin(void)
+{
+ if (cpu_is_mx6dl())
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_sabreauto_i2c2_pads,
+ ARRAY_SIZE(mx6dl_sabreauto_i2c2_pads));
+ else
+ mxc_iomux_v3_setup_multiple_pads(mx6q_sabreauto_i2c2_pads,
+ ARRAY_SIZE(mx6q_sabreauto_i2c2_pads));
+}
+
static struct fsl_mxc_hdmi_platform_data hdmi_data = {
.init = hdmi_init,
+ .enable_pins = hdmi_enable_ddc_pin,
+ .disable_pins = hdmi_disable_ddc_pin,
};
static struct fsl_mxc_hdmi_core_platform_data hdmi_core_data = {
@@ -1300,6 +1336,12 @@ static struct fsl_mxc_capture_platform_data capture_data[] = {
},
};
+static const struct imx_pcie_platform_data mx6_sabreauto_pcie_data __initconst = {
+ .pcie_pwr_en = -EINVAL,
+ .pcie_rst = SABREAUTO_PCIE_RST_B_REVB,
+ .pcie_wake_up = -EINVAL,
+ .pcie_dis = -EINVAL,
+};
/*!
* Board specific initialization.
@@ -1314,6 +1356,8 @@ static void __init mx6_board_init(void)
iomux_v3_cfg_t *mipi_sensor_pads = NULL;
iomux_v3_cfg_t *i2c3_pads = NULL;
iomux_v3_cfg_t *tuner_pads = NULL;
+ iomux_v3_cfg_t *spinor_pads = NULL;
+ iomux_v3_cfg_t *weimnor_pads = NULL;
int common_pads_cnt;
int can0_pads_cnt;
@@ -1321,6 +1365,8 @@ static void __init mx6_board_init(void)
int mipi_sensor_pads_cnt;
int i2c3_pads_cnt;
int tuner_pads_cnt;
+ int spinor_pads_cnt;
+ int weimnor_pads_cnt;
if (cpu_is_mx6q()) {
common_pads = mx6q_sabreauto_pads;
@@ -1328,12 +1374,16 @@ static void __init mx6_board_init(void)
can1_pads = mx6q_sabreauto_can1_pads;
mipi_sensor_pads = mx6q_sabreauto_mipi_sensor_pads;
tuner_pads = mx6q_tuner_pads;
+ spinor_pads = mx6q_spinor_pads;
+ weimnor_pads = mx6q_weimnor_pads;
common_pads_cnt = ARRAY_SIZE(mx6q_sabreauto_pads);
can0_pads_cnt = ARRAY_SIZE(mx6q_sabreauto_can0_pads);
can1_pads_cnt = ARRAY_SIZE(mx6q_sabreauto_can1_pads);
mipi_sensor_pads_cnt = ARRAY_SIZE(mx6q_sabreauto_mipi_sensor_pads);
tuner_pads_cnt = ARRAY_SIZE(mx6q_tuner_pads);
+ spinor_pads_cnt = ARRAY_SIZE(mx6q_spinor_pads);
+ weimnor_pads_cnt = ARRAY_SIZE(mx6q_weimnor_pads);
if (board_is_mx6_reva()) {
i2c3_pads = mx6q_i2c3_pads_rev_a;
i2c3_pads_cnt = ARRAY_SIZE(mx6q_i2c3_pads_rev_a);
@@ -1347,12 +1397,17 @@ static void __init mx6_board_init(void)
can1_pads = mx6dl_sabreauto_can1_pads;
mipi_sensor_pads = mx6dl_sabreauto_mipi_sensor_pads;
tuner_pads = mx6dl_tuner_pads;
+ spinor_pads = mx6dl_spinor_pads;
+ weimnor_pads = mx6dl_weimnor_pads;
common_pads_cnt = ARRAY_SIZE(mx6dl_sabreauto_pads);
can0_pads_cnt = ARRAY_SIZE(mx6dl_sabreauto_can0_pads);
can1_pads_cnt = ARRAY_SIZE(mx6dl_sabreauto_can1_pads);
mipi_sensor_pads_cnt = ARRAY_SIZE(mx6dl_sabreauto_mipi_sensor_pads);
tuner_pads_cnt = ARRAY_SIZE(mx6dl_tuner_pads);
+ spinor_pads_cnt = ARRAY_SIZE(mx6dl_spinor_pads);
+ weimnor_pads_cnt = ARRAY_SIZE(mx6dl_weimnor_pads);
+
if (board_is_mx6_reva()) {
i2c3_pads = mx6dl_i2c3_pads_rev_a;
i2c3_pads_cnt = ARRAY_SIZE(mx6dl_i2c3_pads_rev_a);
@@ -1364,11 +1419,19 @@ static void __init mx6_board_init(void)
BUG_ON(!common_pads);
mxc_iomux_v3_setup_multiple_pads(common_pads, common_pads_cnt);
- if (!spinor_en) {
+
+ /*If at least one NOR memory is selected we don't configure IC23 PADS*/
+ if (spinor_en) {
+ BUG_ON(!spinor_pads);
+ mxc_iomux_v3_setup_multiple_pads(spinor_pads, spinor_pads_cnt);
+ } else if (weimnor_en) {
+ BUG_ON(!weimnor_pads);
+ mxc_iomux_v3_setup_multiple_pads(weimnor_pads,
+ weimnor_pads_cnt);
+ } else {
BUG_ON(!i2c3_pads);
mxc_iomux_v3_setup_multiple_pads(i2c3_pads, i2c3_pads_cnt);
}
-
if (can0_enable) {
BUG_ON(!can0_pads);
mxc_iomux_v3_setup_multiple_pads(can0_pads,
@@ -1388,12 +1451,19 @@ static void __init mx6_board_init(void)
gpio_direction_output(SABREAUTO_I2C_EXP_RST, 1);
if (!board_is_mx6_reva()) {
- /* enable i2c3_sda route path */
+ /* enable either EIM_D18 or i2c3_sda route path */
gpio_request(SABREAUTO_I2C3_STEER, "i2c3-steer");
if (spinor_en)
gpio_direction_output(SABREAUTO_I2C3_STEER, 0);
- else
- gpio_direction_output(SABREAUTO_I2C3_STEER, 1);
+ else if (weimnor_en) {
+ /*Put DISP0_DAT8 in ALT5 mode to prevent WDOG1 of
+ resetting WEIM NOR*/
+ gpio_direction_output(SABREAUTO_I2C3_STEER, 0);
+
+ gpio_request(SABREAUTO_WEIM_NOR_WDOG1, "nor-reset");
+ gpio_direction_output(SABREAUTO_WEIM_NOR_WDOG1, 1);
+ } else
+ gpio_direction_output(SABREAUTO_I2C3_STEER, 1);
/* Set GPIO_16 input for IEEE-1588 ts_clk and
* RMII reference clk
* For MX6 GPR1 bit21 meaning:
@@ -1443,6 +1513,8 @@ static void __init mx6_board_init(void)
imx6q_add_imx_snvs_rtc();
+ imx6q_add_imx_caam();
+
imx6q_add_imx_i2c(1, &mx6q_sabreauto_i2c1_data);
i2c_register_board_info(1, mxc_i2c1_board_info,
ARRAY_SIZE(mxc_i2c1_board_info));
@@ -1461,10 +1533,10 @@ static void __init mx6_board_init(void)
/* SPI */
imx6q_add_ecspi(0, &mx6q_sabreauto_spi_data);
#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
- spi_device_init();
+ spi_device_init();
#else
- mx6q_setup_weimcs();
- platform_device_register(&physmap_flash_device);
+ mx6q_setup_weimcs();
+ platform_device_register(&physmap_flash_device);
#endif
imx6q_add_mxc_hdmi(&hdmi_data);
@@ -1547,6 +1619,13 @@ static void __init mx6_board_init(void)
mxc_register_device(&mxc_si4763_audio_device, &si4763_audio_data);
imx6q_add_busfreq();
+
+ /* Add PCIe RC interface support */
+ imx6q_add_pcie(&mx6_sabreauto_pcie_data);
+
+ imx6q_add_perfmon(0);
+ imx6q_add_perfmon(1);
+ imx6q_add_perfmon(2);
}
extern void __iomem *twd_base;
diff --git a/arch/arm/mach-mx6/board-mx6q_sabreauto.h b/arch/arm/mach-mx6/board-mx6q_sabreauto.h
index bffd109115c2..da6e4387d781 100644
--- a/arch/arm/mach-mx6/board-mx6q_sabreauto.h
+++ b/arch/arm/mach-mx6/board-mx6q_sabreauto.h
@@ -215,69 +215,6 @@ static iomux_v3_cfg_t mx6q_sabreauto_pads[] = {
MX6Q_PAD_ENET_TXD1__MLB_MLBCLK,
MX6Q_PAD_GPIO_6__MLB_MLBSIG,
MX6Q_PAD_GPIO_2__MLB_MLBDAT,
-
-#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
- /* eCSPI1 */
- MX6Q_PAD_EIM_D16__ECSPI1_SCLK,
- MX6Q_PAD_EIM_D17__ECSPI1_MISO,
- MX6Q_PAD_EIM_D18__ECSPI1_MOSI,
- MX6Q_PAD_EIM_D19__ECSPI1_SS1,
- MX6Q_PAD_EIM_D19__GPIO_3_19, /*SS1*/
-#else
- /* Parallel NOR */
- MX6Q_PAD_EIM_OE__WEIM_WEIM_OE,
- MX6Q_PAD_EIM_RW__WEIM_WEIM_RW,
- MX6Q_PAD_EIM_WAIT__WEIM_WEIM_WAIT,
- MX6Q_PAD_EIM_CS0__WEIM_WEIM_CS_0,
-
- MX6Q_PAD_EIM_LBA__WEIM_WEIM_LBA,
- MX6Q_PAD_EIM_BCLK__WEIM_WEIM_BCLK,
- /* Parallel Nor Data Bus */
- MX6Q_PAD_EIM_D16__WEIM_WEIM_D_16,
- MX6Q_PAD_EIM_D17__WEIM_WEIM_D_17,
- MX6Q_PAD_EIM_D18__WEIM_WEIM_D_18,
- MX6Q_PAD_EIM_D19__WEIM_WEIM_D_19,
- MX6Q_PAD_EIM_D20__WEIM_WEIM_D_20,
- MX6Q_PAD_EIM_D21__WEIM_WEIM_D_21,
- MX6Q_PAD_EIM_D22__WEIM_WEIM_D_22,
- MX6Q_PAD_EIM_D23__WEIM_WEIM_D_23,
- MX6Q_PAD_EIM_D24__WEIM_WEIM_D_24,
- MX6Q_PAD_EIM_D25__WEIM_WEIM_D_25,
- MX6Q_PAD_EIM_D26__WEIM_WEIM_D_26,
- MX6Q_PAD_EIM_D27__WEIM_WEIM_D_27,
- MX6Q_PAD_EIM_D28__WEIM_WEIM_D_28,
- MX6Q_PAD_EIM_D29__WEIM_WEIM_D_29,
- MX6Q_PAD_EIM_D30__WEIM_WEIM_D_30,
- MX6Q_PAD_EIM_D31__WEIM_WEIM_D_31,
-
- /* Parallel Nor 25 bit Address Bus */
- MX6Q_PAD_EIM_A24__WEIM_WEIM_A_24,
- MX6Q_PAD_EIM_A23__WEIM_WEIM_A_23,
- MX6Q_PAD_EIM_A22__WEIM_WEIM_A_22,
- MX6Q_PAD_EIM_A21__WEIM_WEIM_A_21,
- MX6Q_PAD_EIM_A20__WEIM_WEIM_A_20,
- MX6Q_PAD_EIM_A19__WEIM_WEIM_A_19,
- MX6Q_PAD_EIM_A18__WEIM_WEIM_A_18,
- MX6Q_PAD_EIM_A17__WEIM_WEIM_A_17,
- MX6Q_PAD_EIM_A16__WEIM_WEIM_A_16,
-
- MX6Q_PAD_EIM_DA15__WEIM_WEIM_DA_A_15,
- MX6Q_PAD_EIM_DA14__WEIM_WEIM_DA_A_14,
- MX6Q_PAD_EIM_DA13__WEIM_WEIM_DA_A_13,
- MX6Q_PAD_EIM_DA12__WEIM_WEIM_DA_A_12,
- MX6Q_PAD_EIM_DA11__WEIM_WEIM_DA_A_11,
- MX6Q_PAD_EIM_DA10__WEIM_WEIM_DA_A_10,
- MX6Q_PAD_EIM_DA9__WEIM_WEIM_DA_A_9,
- MX6Q_PAD_EIM_DA8__WEIM_WEIM_DA_A_8,
- MX6Q_PAD_EIM_DA7__WEIM_WEIM_DA_A_7,
- MX6Q_PAD_EIM_DA6__WEIM_WEIM_DA_A_6,
- MX6Q_PAD_EIM_DA5__WEIM_WEIM_DA_A_5,
- MX6Q_PAD_EIM_DA4__WEIM_WEIM_DA_A_4,
- MX6Q_PAD_EIM_DA3__WEIM_WEIM_DA_A_3,
- MX6Q_PAD_EIM_DA2__WEIM_WEIM_DA_A_2,
- MX6Q_PAD_EIM_DA1__WEIM_WEIM_DA_A_1,
- MX6Q_PAD_EIM_DA0__WEIM_WEIM_DA_A_0,
-#endif
};
static iomux_v3_cfg_t mx6q_sabreauto_can0_pads[] = {
@@ -355,3 +292,80 @@ static iomux_v3_cfg_t mx6q_tuner_pads[] __initdata = {
};
+static iomux_v3_cfg_t mx6q_spinor_pads[] __initdata = {
+ /* eCSPI1 */
+ MX6Q_PAD_EIM_D16__ECSPI1_SCLK,
+ MX6Q_PAD_EIM_D17__ECSPI1_MISO,
+ MX6Q_PAD_EIM_D18__ECSPI1_MOSI,
+ MX6Q_PAD_EIM_D19__ECSPI1_SS1,
+
+ MX6Q_PAD_EIM_D19__GPIO_3_19,
+};
+
+static iomux_v3_cfg_t mx6q_weimnor_pads[] __initdata = {
+ /* Parallel NOR */
+ MX6Q_PAD_EIM_OE__WEIM_WEIM_OE,
+ MX6Q_PAD_EIM_RW__WEIM_WEIM_RW,
+ MX6Q_PAD_EIM_WAIT__WEIM_WEIM_WAIT,
+ MX6Q_PAD_EIM_CS0__WEIM_WEIM_CS_0,
+ /*Control NOR reset using gpio mode*/
+ MX6Q_PAD_DISP0_DAT8__GPIO_4_29,
+
+ MX6Q_PAD_EIM_LBA__WEIM_WEIM_LBA,
+ MX6Q_PAD_EIM_BCLK__WEIM_WEIM_BCLK,
+ /* Parallel Nor Data Bus */
+ MX6Q_PAD_EIM_D16__WEIM_WEIM_D_16,
+ MX6Q_PAD_EIM_D17__WEIM_WEIM_D_17,
+ MX6Q_PAD_EIM_D18__WEIM_WEIM_D_18,
+ MX6Q_PAD_EIM_D19__WEIM_WEIM_D_19,
+ MX6Q_PAD_EIM_D20__WEIM_WEIM_D_20,
+ MX6Q_PAD_EIM_D21__WEIM_WEIM_D_21,
+ MX6Q_PAD_EIM_D22__WEIM_WEIM_D_22,
+ MX6Q_PAD_EIM_D23__WEIM_WEIM_D_23,
+ MX6Q_PAD_EIM_D24__WEIM_WEIM_D_24,
+ MX6Q_PAD_EIM_D25__WEIM_WEIM_D_25,
+ MX6Q_PAD_EIM_D26__WEIM_WEIM_D_26,
+ MX6Q_PAD_EIM_D27__WEIM_WEIM_D_27,
+ MX6Q_PAD_EIM_D28__WEIM_WEIM_D_28,
+ MX6Q_PAD_EIM_D29__WEIM_WEIM_D_29,
+ MX6Q_PAD_EIM_D30__WEIM_WEIM_D_30,
+ MX6Q_PAD_EIM_D31__WEIM_WEIM_D_31,
+
+ /* Parallel Nor 25 bit Address Bus */
+ MX6Q_PAD_EIM_A24__GPIO_5_4,
+ MX6Q_PAD_EIM_A23__WEIM_WEIM_A_23,
+ MX6Q_PAD_EIM_A22__WEIM_WEIM_A_22,
+ MX6Q_PAD_EIM_A21__WEIM_WEIM_A_21,
+ MX6Q_PAD_EIM_A20__WEIM_WEIM_A_20,
+ MX6Q_PAD_EIM_A19__WEIM_WEIM_A_19,
+ MX6Q_PAD_EIM_A18__WEIM_WEIM_A_18,
+ MX6Q_PAD_EIM_A17__WEIM_WEIM_A_17,
+ MX6Q_PAD_EIM_A16__WEIM_WEIM_A_16,
+
+ MX6Q_PAD_EIM_DA15__WEIM_WEIM_DA_A_15,
+ MX6Q_PAD_EIM_DA14__WEIM_WEIM_DA_A_14,
+ MX6Q_PAD_EIM_DA13__WEIM_WEIM_DA_A_13,
+ MX6Q_PAD_EIM_DA12__WEIM_WEIM_DA_A_12,
+ MX6Q_PAD_EIM_DA11__WEIM_WEIM_DA_A_11,
+ MX6Q_PAD_EIM_DA10__WEIM_WEIM_DA_A_10,
+ MX6Q_PAD_EIM_DA9__WEIM_WEIM_DA_A_9,
+ MX6Q_PAD_EIM_DA8__WEIM_WEIM_DA_A_8,
+ MX6Q_PAD_EIM_DA7__WEIM_WEIM_DA_A_7,
+ MX6Q_PAD_EIM_DA6__WEIM_WEIM_DA_A_6,
+ MX6Q_PAD_EIM_DA5__WEIM_WEIM_DA_A_5,
+ MX6Q_PAD_EIM_DA4__WEIM_WEIM_DA_A_4,
+ MX6Q_PAD_EIM_DA3__WEIM_WEIM_DA_A_3,
+ MX6Q_PAD_EIM_DA2__WEIM_WEIM_DA_A_2,
+ MX6Q_PAD_EIM_DA1__WEIM_WEIM_DA_A_1,
+ MX6Q_PAD_EIM_DA0__WEIM_WEIM_DA_A_0,
+};
+
+static iomux_v3_cfg_t mx6q_sabreauto_hdmi_ddc_pads[] = {
+ MX6Q_PAD_KEY_COL3__HDMI_TX_DDC_SCL, /* HDMI DDC SCL */
+ MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA, /* HDMI DDC SDA */
+};
+
+static iomux_v3_cfg_t mx6q_sabreauto_i2c2_pads[] = {
+ MX6Q_PAD_KEY_COL3__I2C2_SCL, /* I2C2 SCL */
+ MX6Q_PAD_KEY_ROW3__I2C2_SDA, /* I2C2 SDA */
+};
diff --git a/arch/arm/mach-mx6/board-mx6q_sabrelite.c b/arch/arm/mach-mx6/board-mx6q_sabrelite.c
index 3f00ae563492..925dfb71ea0e 100644
--- a/arch/arm/mach-mx6/board-mx6q_sabrelite.c
+++ b/arch/arm/mach-mx6/board-mx6q_sabrelite.c
@@ -327,6 +327,16 @@ static iomux_v3_cfg_t mx6q_sabrelite_csi0_sensor_pads[] = {
MX6Q_PAD_NANDF_WP_B__GPIO_6_9, /* J16 - MIPI GP */
};
+static iomux_v3_cfg_t mx6q_sabrelite_hdmi_ddc_pads[] = {
+ MX6Q_PAD_KEY_COL3__HDMI_TX_DDC_SCL, /* HDMI DDC SCL */
+ MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA, /* HDMI DDC SDA */
+};
+
+static iomux_v3_cfg_t mx6q_sabrelite_i2c2_pads[] = {
+ MX6Q_PAD_KEY_COL3__I2C2_SCL, /* I2C2 SCL */
+ MX6Q_PAD_KEY_ROW3__I2C2_SDA, /* I2C2 SDA */
+};
+
#define MX6Q_USDHC_PAD_SETTING(id, speed) \
mx6q_sd##id##_##speed##mhz[] = { \
MX6Q_PAD_SD##id##_CLK__USDHC##id##_CLK_##speed##MHZ, \
@@ -804,8 +814,26 @@ static void hdmi_init(int ipu_id, int disp_id)
mxc_iomux_set_gpr_register(3, 2, 2, hdmi_mux_setting);
}
+/* On mx6x sbarelite board i2c2 iomux with hdmi ddc,
+ * the pins default work at i2c2 function,
+ when hdcp enable, the pins should work at ddc function */
+
+static void hdmi_enable_ddc_pin(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx6q_sabrelite_hdmi_ddc_pads,
+ ARRAY_SIZE(mx6q_sabrelite_hdmi_ddc_pads));
+}
+
+static void hdmi_disable_ddc_pin(void)
+{
+ mxc_iomux_v3_setup_multiple_pads(mx6q_sabrelite_i2c2_pads,
+ ARRAY_SIZE(mx6q_sabrelite_i2c2_pads));
+}
+
static struct fsl_mxc_hdmi_platform_data hdmi_data = {
.init = hdmi_init,
+ .enable_pins = hdmi_enable_ddc_pin,
+ .disable_pins = hdmi_disable_ddc_pin,
};
static struct fsl_mxc_hdmi_core_platform_data hdmi_core_data = {
@@ -1145,6 +1173,8 @@ static void __init mx6_sabrelite_board_init(void)
imx6q_add_mipi_csi2(&mipi_csi2_pdata);
imx6q_add_imx_snvs_rtc();
+ imx6q_add_imx_caam();
+
imx6q_add_imx_i2c(0, &mx6q_sabrelite_i2c_data);
imx6q_add_imx_i2c(1, &mx6q_sabrelite_i2c_data);
imx6q_add_imx_i2c(2, &mx6q_sabrelite_i2c_data);
diff --git a/arch/arm/mach-mx6/board-mx6q_sabresd.c b/arch/arm/mach-mx6/board-mx6q_sabresd.c
index 955f47e7ab8c..e03777884aa3 100644
--- a/arch/arm/mach-mx6/board-mx6q_sabresd.c
+++ b/arch/arm/mach-mx6/board-mx6q_sabresd.c
@@ -1277,8 +1277,34 @@ static void hdmi_init(int ipu_id, int disp_id)
mxc_iomux_set_gpr_register(3, 2, 2, hdmi_mux_setting);
}
+/* On mx6x sabresd board i2c2 iomux with hdmi ddc,
+ * the pins default work at i2c2 function,
+ when hdcp enable, the pins should work at ddc function */
+
+static void hdmi_enable_ddc_pin(void)
+{
+ if (cpu_is_mx6dl())
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_sabresd_hdmi_ddc_pads,
+ ARRAY_SIZE(mx6dl_sabresd_hdmi_ddc_pads));
+ else
+ mxc_iomux_v3_setup_multiple_pads(mx6q_sabresd_hdmi_ddc_pads,
+ ARRAY_SIZE(mx6q_sabresd_hdmi_ddc_pads));
+}
+
+static void hdmi_disable_ddc_pin(void)
+{
+ if (cpu_is_mx6dl())
+ mxc_iomux_v3_setup_multiple_pads(mx6dl_sabresd_i2c2_pads,
+ ARRAY_SIZE(mx6dl_sabresd_i2c2_pads));
+ else
+ mxc_iomux_v3_setup_multiple_pads(mx6q_sabresd_i2c2_pads,
+ ARRAY_SIZE(mx6q_sabresd_i2c2_pads));
+}
+
static struct fsl_mxc_hdmi_platform_data hdmi_data = {
.init = hdmi_init,
+ .enable_pins = hdmi_enable_ddc_pin,
+ .disable_pins = hdmi_disable_ddc_pin,
};
static struct fsl_mxc_hdmi_core_platform_data hdmi_core_data = {
@@ -1702,6 +1728,8 @@ static void __init mx6_sabresd_board_init(void)
imx6q_add_mipi_csi2(&mipi_csi2_pdata);
imx6q_add_imx_snvs_rtc();
+ imx6q_add_imx_caam();
+
if (board_is_mx6_reva()) {
strcpy(mxc_i2c0_board_info[0].type, "wm8958");
mxc_i2c0_board_info[0].platform_data = &wm8958_config_data;
@@ -1737,6 +1765,7 @@ static void __init mx6_sabresd_board_init(void)
imx6q_add_anatop_thermal_imx(1, &mx6q_sabresd_anatop_thermal_data);
imx6_init_fec(fec_data);
imx6q_add_pm_imx(0, &mx6q_sabresd_pm_data);
+
/* Move sd4 to first because sd4 connect to emmc.
Mfgtools want emmc is mmcblk0 and other sd card is mmcblk1.
*/
@@ -1842,6 +1871,7 @@ static void __init mx6_sabresd_board_init(void)
pm_power_off = mx6_snvs_poweroff;
imx6q_add_busfreq();
+ /* Add PCIe RC interface support */
imx6q_add_pcie(&mx6_sabresd_pcie_data);
if (cpu_is_mx6dl()) {
mxc_iomux_v3_setup_multiple_pads(mx6dl_arm2_elan_pads,
@@ -1872,6 +1902,10 @@ static void __init mx6_sabresd_board_init(void)
sdio_clk->flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE;
clk_put(sdio_clk);
}
+ imx6_add_armpmu();
+ imx6q_add_perfmon(0);
+ imx6q_add_perfmon(1);
+ imx6q_add_perfmon(2);
}
extern void __iomem *twd_base;
diff --git a/arch/arm/mach-mx6/board-mx6q_sabresd.h b/arch/arm/mach-mx6/board-mx6q_sabresd.h
index af3df8b01092..54ad3ac416b6 100644
--- a/arch/arm/mach-mx6/board-mx6q_sabresd.h
+++ b/arch/arm/mach-mx6/board-mx6q_sabresd.h
@@ -28,7 +28,7 @@ static iomux_v3_cfg_t mx6q_sabresd_pads[] = {
MX6Q_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD,
/* CAN1 */
- MX6Q_PAD_KEY_ROW2__CAN1_RXCAN,
+ MX6Q_PAD_KEY_ROW2__HDMI_TX_CEC_LINE,
/* MX6Q_PAD_KEY_COL2__CAN1_TXCAN, */
MX6Q_PAD_GPIO_1__GPIO_1_1, /* user defiend green led */
MX6Q_PAD_GPIO_2__GPIO_1_2, /* user defined red led */
@@ -128,9 +128,9 @@ static iomux_v3_cfg_t mx6q_sabresd_pads[] = {
MX6Q_PAD_CSI0_DAT8__I2C1_SDA,
MX6Q_PAD_CSI0_DAT9__I2C1_SCL,
- /* I2C2 Camera, MIPI */
- MX6Q_PAD_KEY_COL3__I2C2_SCL, /* GPIO4[12] */
- MX6Q_PAD_KEY_ROW3__I2C2_SDA, /* GPIO4[13] */
+ /* I2C2, Camera, MIPI */
+ MX6Q_PAD_KEY_COL3__I2C2_SCL,
+ MX6Q_PAD_KEY_ROW3__I2C2_SDA,
/* I2C3 */
MX6Q_PAD_GPIO_3__I2C3_SCL, /* GPIO1[3] */
@@ -288,4 +288,14 @@ static iomux_v3_cfg_t mx6q_sabresd_mipi_sensor_pads[] = {
MX6Q_PAD_SD1_DAT2__GPIO_1_19, /* camera PWDN */
MX6Q_PAD_SD1_CLK__GPIO_1_20, /* camera RESET */
};
+
+static iomux_v3_cfg_t mx6q_sabresd_hdmi_ddc_pads[] = {
+ MX6Q_PAD_KEY_COL3__HDMI_TX_DDC_SCL, /* HDMI DDC SCL */
+ MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA, /* HDMI DDC SDA */
+};
+
+static iomux_v3_cfg_t mx6q_sabresd_i2c2_pads[] = {
+ MX6Q_PAD_KEY_COL3__I2C2_SCL, /* I2C2 SCL */
+ MX6Q_PAD_KEY_ROW3__I2C2_SDA, /* I2C2 SDA */
+};
#endif
diff --git a/arch/arm/mach-mx6/board-mx6sl_arm2.c b/arch/arm/mach-mx6/board-mx6sl_arm2.c
index 2507970133eb..2efca1ba5d93 100755
--- a/arch/arm/mach-mx6/board-mx6sl_arm2.c
+++ b/arch/arm/mach-mx6/board-mx6sl_arm2.c
@@ -129,6 +129,7 @@
#define MX6SL_ARM2_ELAN_INT IMX_GPIO_NR(2, 10)
#define MX6SL_ARM2_ELAN_RST IMX_GPIO_NR(4, 4)
+static int spdc_sel;
static int max17135_regulator_init(struct max17135 *max17135);
struct clk *extern_audio_root;
@@ -670,23 +671,17 @@ static int mx6sl_arm2_fec_phy_init(struct phy_device *phydev)
/* power on FEC phy and reset phy */
gpio_request(MX6_ARM2_FEC_PWR_EN, "fec-pwr");
- gpio_direction_output(MX6_ARM2_FEC_PWR_EN, 1);
+ gpio_direction_output(MX6_ARM2_FEC_PWR_EN, 0);
/* wait RC ms for hw reset */
- udelay(50);
+ msleep(1);
+ gpio_direction_output(MX6_ARM2_FEC_PWR_EN, 1);
/* check phy power */
val = phy_read(phydev, 0x0);
if (val & BMCR_PDOWN) {
phy_write(phydev, 0x0, (val & ~BMCR_PDOWN));
- udelay(50);
}
- /* sw reset phy */
- val = phy_read(phydev, 0x0);
- val |= BMCR_RESET;
- phy_write(phydev, 0x0, val);
- udelay(50);
-
return 0;
}
@@ -1084,13 +1079,19 @@ static struct imx_spdc_fb_platform_data spdc_data = {
.disable_pins = spdc_disable_pins,
};
-#if defined(CONFIG_FB_MXC_SIPIX_PANEL)
+static int __init early_use_spdc_sel(char *p)
+{
+ spdc_sel = 1;
+ return 0;
+}
+early_param("spdc", early_use_spdc_sel);
+
static void setup_spdc(void)
{
/* GPR0[8]: 0:EPDC, 1:SPDC */
- mxc_iomux_set_gpr_register(0, 8, 1, 1);
+ if (spdc_sel)
+ mxc_iomux_set_gpr_register(0, 8, 1, 1);
}
-#endif
static void imx6_arm2_usbotg_vbus(bool on)
{
@@ -1207,6 +1208,17 @@ static void __init elan_ts_init(void)
gpio_direction_output(MX6SL_ARM2_ELAN_CE, 1);
}
+#define SNVS_LPCR 0x38
+static void mx6_snvs_poweroff(void)
+{
+ u32 value;
+ void __iomem *mx6_snvs_base = MX6_IO_ADDRESS(MX6Q_SNVS_BASE_ADDR);
+
+ value = readl(mx6_snvs_base + SNVS_LPCR);
+ /* set TOP and DP_EN bit */
+ writel(value | 0x60, mx6_snvs_base + SNVS_LPCR);
+}
+
/*!
* Board specific initialization.
*/
@@ -1270,14 +1282,14 @@ static void __init mx6_arm2_init(void)
imx6dl_add_imx_pxp();
imx6dl_add_imx_pxp_client();
mxc_register_device(&max17135_sensor_device, NULL);
- imx6dl_add_imx_epdc(&epdc_data);
-#if defined(CONFIG_FB_MXC_SIPIX_PANEL)
setup_spdc();
-#endif
- imx6sl_add_imx_spdc(&spdc_data);
+ if (!spdc_sel)
+ imx6dl_add_imx_epdc(&epdc_data);
+ else
+ imx6sl_add_imx_spdc(&spdc_data);
imx6q_add_dvfs_core(&mx6sl_arm2_dvfscore_data);
- imx6q_init_audio();
+ imx6q_init_audio();
imx6q_add_viim();
imx6q_add_imx2_wdt(0, NULL);
@@ -1285,6 +1297,10 @@ static void __init mx6_arm2_init(void)
imx_add_viv_gpu(&imx6_gpu_data, &imx6q_gpu_pdata);
imx6sl_add_imx_keypad(&mx6sl_arm2_map_data);
imx6q_add_busfreq();
+ imx6sl_add_dcp();
+ imx6sl_add_rngb();
+
+ pm_power_off = mx6_snvs_poweroff;
}
extern void __iomem *twd_base;
diff --git a/arch/arm/mach-mx6/board-mx6sl_arm2.h b/arch/arm/mach-mx6/board-mx6sl_arm2.h
index d720ab3465b6..09a211690029 100755
--- a/arch/arm/mach-mx6/board-mx6sl_arm2.h
+++ b/arch/arm/mach-mx6/board-mx6sl_arm2.h
@@ -153,6 +153,9 @@ static iomux_v3_cfg_t mx6sl_arm2_pads[] = {
MX6SL_PAD_KEY_ROW1__KPP_ROW_1,
MX6SL_PAD_KEY_ROW2__KPP_ROW_2,
MX6SL_PAD_KEY_ROW3__KPP_ROW_3,
+
+ /* WDOG */
+ MX6SL_PAD_WDOG_B__WDOG1_WDOG_B,
};
static iomux_v3_cfg_t mx6sl_arm2_epdc_enable_pads[] = {
diff --git a/arch/arm/mach-mx6/board-mx6solo_sabreauto.h b/arch/arm/mach-mx6/board-mx6solo_sabreauto.h
index dd113bab749b..f51925bee9fa 100644
--- a/arch/arm/mach-mx6/board-mx6solo_sabreauto.h
+++ b/arch/arm/mach-mx6/board-mx6solo_sabreauto.h
@@ -215,70 +215,6 @@ static iomux_v3_cfg_t mx6dl_sabreauto_pads[] = {
MX6DL_PAD_ENET_TXD1__MLB_MLBCLK,
MX6DL_PAD_GPIO_6__MLB_MLBSIG,
MX6DL_PAD_GPIO_2__MLB_MLBDAT,
-
-#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
- /* eCSPI1 */
- MX6DL_PAD_EIM_D16__ECSPI1_SCLK,
- MX6DL_PAD_EIM_D17__ECSPI1_MISO,
- MX6DL_PAD_EIM_D18__ECSPI1_MOSI,
- MX6DL_PAD_EIM_D19__ECSPI1_SS1,
-
- MX6DL_PAD_EIM_D19__GPIO_3_19,
-#else
- /* Parallel NOR */
- MX6DL_PAD_EIM_OE__WEIM_WEIM_OE,
- MX6DL_PAD_EIM_RW__WEIM_WEIM_RW,
- MX6DL_PAD_EIM_WAIT__WEIM_WEIM_WAIT,
- MX6DL_PAD_EIM_CS0__WEIM_WEIM_CS_0,
-
- MX6DL_PAD_EIM_LBA__WEIM_WEIM_LBA,
- MX6DL_PAD_EIM_BCLK__WEIM_WEIM_BCLK,
- /* Parallel Nor Data Bus */
- MX6DL_PAD_EIM_D16__WEIM_WEIM_D_16,
- MX6DL_PAD_EIM_D17__WEIM_WEIM_D_17,
- MX6DL_PAD_EIM_D18__WEIM_WEIM_D_18,
- MX6DL_PAD_EIM_D19__WEIM_WEIM_D_19,
- MX6DL_PAD_EIM_D20__WEIM_WEIM_D_20,
- MX6DL_PAD_EIM_D21__WEIM_WEIM_D_21,
- MX6DL_PAD_EIM_D22__WEIM_WEIM_D_22,
- MX6DL_PAD_EIM_D23__WEIM_WEIM_D_23,
- MX6DL_PAD_EIM_D24__WEIM_WEIM_D_24,
- MX6DL_PAD_EIM_D25__WEIM_WEIM_D_25,
- MX6DL_PAD_EIM_D26__WEIM_WEIM_D_26,
- MX6DL_PAD_EIM_D27__WEIM_WEIM_D_27,
- MX6DL_PAD_EIM_D28__WEIM_WEIM_D_28,
- MX6DL_PAD_EIM_D29__WEIM_WEIM_D_29,
- MX6DL_PAD_EIM_D30__WEIM_WEIM_D_30,
- MX6DL_PAD_EIM_D31__WEIM_WEIM_D_31,
-
- /* Parallel Nor 25 bit Address Bus */
- MX6DL_PAD_EIM_A24__WEIM_WEIM_A_24,
- MX6DL_PAD_EIM_A23__WEIM_WEIM_A_23,
- MX6DL_PAD_EIM_A22__WEIM_WEIM_A_22,
- MX6DL_PAD_EIM_A21__WEIM_WEIM_A_21,
- MX6DL_PAD_EIM_A20__WEIM_WEIM_A_20,
- MX6DL_PAD_EIM_A19__WEIM_WEIM_A_19,
- MX6DL_PAD_EIM_A18__WEIM_WEIM_A_18,
- MX6DL_PAD_EIM_A17__WEIM_WEIM_A_17,
- MX6DL_PAD_EIM_A16__WEIM_WEIM_A_16,
-
- MX6DL_PAD_EIM_DA15__WEIM_WEIM_DA_A_15,
- MX6DL_PAD_EIM_DA14__WEIM_WEIM_DA_A_14,
- MX6DL_PAD_EIM_DA13__WEIM_WEIM_DA_A_13,
- MX6DL_PAD_EIM_DA12__WEIM_WEIM_DA_A_12,
- MX6DL_PAD_EIM_DA11__WEIM_WEIM_DA_A_11,
- MX6DL_PAD_EIM_DA10__WEIM_WEIM_DA_A_10,
- MX6DL_PAD_EIM_DA9__WEIM_WEIM_DA_A_9,
- MX6DL_PAD_EIM_DA8__WEIM_WEIM_DA_A_8,
- MX6DL_PAD_EIM_DA7__WEIM_WEIM_DA_A_7,
- MX6DL_PAD_EIM_DA6__WEIM_WEIM_DA_A_6,
- MX6DL_PAD_EIM_DA5__WEIM_WEIM_DA_A_5,
- MX6DL_PAD_EIM_DA4__WEIM_WEIM_DA_A_4,
- MX6DL_PAD_EIM_DA3__WEIM_WEIM_DA_A_3,
- MX6DL_PAD_EIM_DA2__WEIM_WEIM_DA_A_2,
- MX6DL_PAD_EIM_DA1__WEIM_WEIM_DA_A_1,
- MX6DL_PAD_EIM_DA0__WEIM_WEIM_DA_A_0,
-#endif
};
static iomux_v3_cfg_t mx6dl_sabreauto_can0_pads[] = {
@@ -355,3 +291,81 @@ static iomux_v3_cfg_t mx6dl_tuner_pads[] __initdata = {
MX6DL_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS,
MX6DL_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD,
};
+
+static iomux_v3_cfg_t mx6dl_spinor_pads[] __initdata = {
+ /* eCSPI1 */
+ MX6DL_PAD_EIM_D16__ECSPI1_SCLK,
+ MX6DL_PAD_EIM_D17__ECSPI1_MISO,
+ MX6DL_PAD_EIM_D18__ECSPI1_MOSI,
+ MX6DL_PAD_EIM_D19__ECSPI1_SS1,
+
+ MX6DL_PAD_EIM_D19__GPIO_3_19,
+};
+
+static iomux_v3_cfg_t mx6dl_weimnor_pads[] __initdata = {
+ /* Parallel NOR */
+ MX6DL_PAD_EIM_OE__WEIM_WEIM_OE,
+ MX6DL_PAD_EIM_RW__WEIM_WEIM_RW,
+ MX6DL_PAD_EIM_WAIT__WEIM_WEIM_WAIT,
+ MX6DL_PAD_EIM_CS0__WEIM_WEIM_CS_0,
+ /*Control NOR reset using gpio mode*/
+ MX6DL_PAD_DISP0_DAT8__GPIO_4_29,
+
+ MX6DL_PAD_EIM_LBA__WEIM_WEIM_LBA,
+ MX6DL_PAD_EIM_BCLK__WEIM_WEIM_BCLK,
+ /* Parallel Nor Data Bus */
+ MX6DL_PAD_EIM_D16__WEIM_WEIM_D_16,
+ MX6DL_PAD_EIM_D17__WEIM_WEIM_D_17,
+ MX6DL_PAD_EIM_D18__WEIM_WEIM_D_18,
+ MX6DL_PAD_EIM_D19__WEIM_WEIM_D_19,
+ MX6DL_PAD_EIM_D20__WEIM_WEIM_D_20,
+ MX6DL_PAD_EIM_D21__WEIM_WEIM_D_21,
+ MX6DL_PAD_EIM_D22__WEIM_WEIM_D_22,
+ MX6DL_PAD_EIM_D23__WEIM_WEIM_D_23,
+ MX6DL_PAD_EIM_D24__WEIM_WEIM_D_24,
+ MX6DL_PAD_EIM_D25__WEIM_WEIM_D_25,
+ MX6DL_PAD_EIM_D26__WEIM_WEIM_D_26,
+ MX6DL_PAD_EIM_D27__WEIM_WEIM_D_27,
+ MX6DL_PAD_EIM_D28__WEIM_WEIM_D_28,
+ MX6DL_PAD_EIM_D29__WEIM_WEIM_D_29,
+ MX6DL_PAD_EIM_D30__WEIM_WEIM_D_30,
+ MX6DL_PAD_EIM_D31__WEIM_WEIM_D_31,
+
+ /* Parallel Nor 25 bit Address Bus */
+ MX6DL_PAD_EIM_A24__GPIO_5_4,
+ MX6DL_PAD_EIM_A23__WEIM_WEIM_A_23,
+ MX6DL_PAD_EIM_A22__WEIM_WEIM_A_22,
+ MX6DL_PAD_EIM_A21__WEIM_WEIM_A_21,
+ MX6DL_PAD_EIM_A20__WEIM_WEIM_A_20,
+ MX6DL_PAD_EIM_A19__WEIM_WEIM_A_19,
+ MX6DL_PAD_EIM_A18__WEIM_WEIM_A_18,
+ MX6DL_PAD_EIM_A17__WEIM_WEIM_A_17,
+ MX6DL_PAD_EIM_A16__WEIM_WEIM_A_16,
+
+ MX6DL_PAD_EIM_DA15__WEIM_WEIM_DA_A_15,
+ MX6DL_PAD_EIM_DA14__WEIM_WEIM_DA_A_14,
+ MX6DL_PAD_EIM_DA13__WEIM_WEIM_DA_A_13,
+ MX6DL_PAD_EIM_DA12__WEIM_WEIM_DA_A_12,
+ MX6DL_PAD_EIM_DA11__WEIM_WEIM_DA_A_11,
+ MX6DL_PAD_EIM_DA10__WEIM_WEIM_DA_A_10,
+ MX6DL_PAD_EIM_DA9__WEIM_WEIM_DA_A_9,
+ MX6DL_PAD_EIM_DA8__WEIM_WEIM_DA_A_8,
+ MX6DL_PAD_EIM_DA7__WEIM_WEIM_DA_A_7,
+ MX6DL_PAD_EIM_DA6__WEIM_WEIM_DA_A_6,
+ MX6DL_PAD_EIM_DA5__WEIM_WEIM_DA_A_5,
+ MX6DL_PAD_EIM_DA4__WEIM_WEIM_DA_A_4,
+ MX6DL_PAD_EIM_DA3__WEIM_WEIM_DA_A_3,
+ MX6DL_PAD_EIM_DA2__WEIM_WEIM_DA_A_2,
+ MX6DL_PAD_EIM_DA1__WEIM_WEIM_DA_A_1,
+ MX6DL_PAD_EIM_DA0__WEIM_WEIM_DA_A_0,
+};
+
+static iomux_v3_cfg_t mx6dl_sabreauto_hdmi_ddc_pads[] = {
+ MX6DL_PAD_KEY_COL3__HDMI_TX_DDC_SCL, /* HDMI DDC SCL */
+ MX6DL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA, /* HDMI DDC SDA */
+};
+
+static iomux_v3_cfg_t mx6dl_sabreauto_i2c2_pads[] = {
+ MX6DL_PAD_KEY_COL3__I2C2_SCL, /* I2C2 SCL */
+ MX6DL_PAD_KEY_ROW3__I2C2_SDA, /* I2C2 SDA */
+};
diff --git a/arch/arm/mach-mx6/bus_freq.c b/arch/arm/mach-mx6/bus_freq.c
index cb4d6eaf880f..b1a0af0f3d35 100644
--- a/arch/arm/mach-mx6/bus_freq.c
+++ b/arch/arm/mach-mx6/bus_freq.c
@@ -78,7 +78,6 @@ void set_ddr_freq(int ddr_freq);
extern int init_mmdc_settings(void);
extern struct cpu_op *(*get_cpu_op)(int *op);
extern int update_ddr_freq(int ddr_rate);
-extern void __iomem *gpc_base;
struct mutex bus_freq_mutex;
@@ -93,18 +92,18 @@ static struct clk *ahb_clk;
static struct clk *periph_clk;
static struct clk *osc_clk;
static struct clk *cpu_clk;
-static unsigned int org_ldo;
static struct clk *pll3;
static struct clk *pll2;
static struct clk *pll3_sw_clk;
static struct clk *pll2_200;
static struct clk *mmdc_ch0_axi;
+struct regulator *vddsoc_cap_regulator;
static struct delayed_work low_bus_freq_handler;
static void reduce_bus_freq_handler(struct work_struct *work)
{
- unsigned long reg;
+ int ret = 0;
if (low_bus_freq_mode || !low_freq_bus_used())
return;
@@ -152,6 +151,17 @@ static void reduce_bus_freq_handler(struct work_struct *work)
clk_disable(pll2_400);
clk_disable(pll3);
} else {
+ /* Set VDDSOC_CAP to 1.1V */
+ ret = regulator_set_voltage(vddsoc_cap_regulator, 1100000,
+ 1100000);
+ if (ret < 0) {
+ printk(KERN_DEBUG
+ "COULD NOT DECREASE VDDSOC_CAP VOLTAGE!!!!\n");
+ return;
+ }
+
+ udelay(150);
+
/* Set periph_clk to be sourced from OSC_CLK */
/* Set MMDC clk to 25MHz. */
/* First need to set the divider before changing the parent */
@@ -175,48 +185,8 @@ static void reduce_bus_freq_handler(struct work_struct *work)
high_bus_freq_mode = 0;
med_bus_freq_mode = 0;
- /* Do not disable PU LDO if it is not enabled */
- reg = __raw_readl(ANADIG_REG_CORE) & (ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET);
- if ((low_bus_freq_mode || audio_bus_freq_mode) && reg != 0) {
- /* Disable the brown out detection since we are going to be
- * disabling the LDO.
- */
- reg = __raw_readl(ANA_MISC2_BASE_ADDR);
- reg &= ~ANADIG_ANA_MISC2_REG1_BO_EN;
- __raw_writel(reg, ANA_MISC2_BASE_ADDR);
-
- /* Power gate the PU LDO. */
- /* Power gate the PU domain first. */
- /* enable power down request */
- reg = __raw_readl(gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
- __raw_writel(reg | 0x1, gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
- /* power down request */
- reg = __raw_readl(gpc_base + GPC_CNTR_OFFSET);
- __raw_writel(reg | 0x1, gpc_base + GPC_CNTR_OFFSET);
- /* Wait for power down to complete. */
- while (__raw_readl(gpc_base + GPC_CNTR_OFFSET) & 0x1)
- ;
-
- /* Mask the ANATOP brown out interrupt in the GPC. */
- reg = __raw_readl(gpc_base + 0x14);
- reg |= 0x80000000;
- __raw_writel(reg, gpc_base + 0x14);
-
- /* PU power gating. */
- reg = __raw_readl(ANADIG_REG_CORE);
- org_ldo = reg & (ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET);
- reg &= ~(ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET);
- __raw_writel(reg, ANADIG_REG_CORE);
-
- /* Clear the BO interrupt in the ANATOP. */
- reg = __raw_readl(ANADIG_MISC1_REG);
- reg |= 0x80000000;
- __raw_writel(reg, ANADIG_MISC1_REG);
- }
-
mutex_unlock(&bus_freq_mutex);
}
-
/* Set the DDR, AHB to 24MHz.
* This mode will be activated only when none of the modules that
* need a higher DDR or AHB frequency are active.
@@ -241,7 +211,7 @@ int set_low_bus_freq(void)
*/
int set_high_bus_freq(int high_bus_freq)
{
- unsigned long reg;
+ int ret = 0;
if (busfreq_suspended)
return 0;
@@ -255,6 +225,12 @@ int set_high_bus_freq(int high_bus_freq)
if (med_bus_freq_mode && !high_bus_freq)
return 0;
+ if (cpu_is_mx6dl() && high_bus_freq)
+ high_bus_freq = 0;
+
+ if (cpu_is_mx6dl() && med_bus_freq_mode)
+ return 0;
+
while (!mutex_trylock(&bus_freq_mutex))
msleep(1);
@@ -265,11 +241,15 @@ int set_high_bus_freq(int high_bus_freq)
return 0;
}
- /* Enable the PU LDO */
- if (low_bus_freq_mode || audio_bus_freq_mode) {
- /* Set the voltage of VDDPU as in normal mode. */
- __raw_writel(org_ldo | (__raw_readl(ANADIG_REG_CORE) &
- (~(ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET))), ANADIG_REG_CORE);
+ if (cpu_is_mx6sl()) {
+ /* Set the voltage of VDDSOC to 1.2V as in normal mode. */
+ ret = regulator_set_voltage(vddsoc_cap_regulator, 1200000,
+ 1200000);
+ if (ret < 0) {
+ printk(KERN_DEBUG
+ "COULD NOT INCREASE VDDSOC_CAP VOLTAGE!!!!\n");
+ return ret;
+ }
/* Need to wait for the regulator to come back up */
/*
@@ -279,52 +259,27 @@ int set_high_bus_freq(int high_bus_freq)
*/
udelay(150);
- /* enable power up request */
- reg = __raw_readl(gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
- __raw_writel(reg | 0x1, gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
- /* power up request */
- reg = __raw_readl(gpc_base + GPC_CNTR_OFFSET);
- __raw_writel(reg | 0x2, gpc_base + GPC_CNTR_OFFSET);
- /* Wait for the power up bit to clear */
- while (__raw_readl(gpc_base + GPC_CNTR_OFFSET) & 0x2)
- ;
-
- /* Enable the Brown Out detection. */
- reg = __raw_readl(ANA_MISC2_BASE_ADDR);
- reg |= ANADIG_ANA_MISC2_REG1_BO_EN;
- __raw_writel(reg, ANA_MISC2_BASE_ADDR);
-
- /* Unmask the ANATOP brown out interrupt in the GPC. */
- reg = __raw_readl(gpc_base + 0x14);
- reg &= ~0x80000000;
- __raw_writel(reg, gpc_base + 0x14);
-
- if (cpu_is_mx6sl()) {
- /* Set periph_clk to be sourced from pll2_pfd2_400M */
- /* First need to set the divider before changing the */
- /* parent if parent clock is larger than previous one */
- clk_set_rate(ahb_clk, clk_round_rate(ahb_clk,
- LPAPM_CLK / 3));
- clk_set_rate(axi_clk,
- clk_round_rate(axi_clk, LPAPM_CLK / 2));
- clk_set_parent(periph_clk, pll2_400);
-
- /* Set mmdc_clk_root to be sourced */
- /* from pll2_pfd2_400M */
- clk_set_rate(mmdc_ch0_axi,
- clk_round_rate(mmdc_ch0_axi,
- LPAPM_CLK / 2));
- clk_set_parent(mmdc_ch0_axi, pll3_sw_clk);
- clk_set_parent(mmdc_ch0_axi, pll2_400);
- clk_set_rate(mmdc_ch0_axi,
- clk_round_rate(mmdc_ch0_axi, DDR_MED_CLK));
-
- high_bus_freq_mode = 1;
- med_bus_freq_mode = 0;
- }
- }
+ /* Set periph_clk to be sourced from pll2_pfd2_400M */
+ /* First need to set the divider before changing the */
+ /* parent if parent clock is larger than previous one */
+ clk_set_rate(ahb_clk, clk_round_rate(ahb_clk,
+ LPAPM_CLK / 3));
+ clk_set_rate(axi_clk,
+ clk_round_rate(axi_clk, LPAPM_CLK / 2));
+ clk_set_parent(periph_clk, pll2_400);
+
+ /* Set mmdc_clk_root to be sourced */
+ /* from pll2_pfd2_400M */
+ clk_set_rate(mmdc_ch0_axi,
+ clk_round_rate(mmdc_ch0_axi, LPAPM_CLK / 2));
+ clk_set_parent(mmdc_ch0_axi, pll3_sw_clk);
+ clk_set_parent(mmdc_ch0_axi, pll2_400);
+ clk_set_rate(mmdc_ch0_axi,
+ clk_round_rate(mmdc_ch0_axi, DDR_MED_CLK));
- if (!cpu_is_mx6sl()) {
+ high_bus_freq_mode = 1;
+ med_bus_freq_mode = 0;
+ } else {
clk_enable(pll3);
if (high_bus_freq) {
update_ddr_freq(ddr_normal_rate);
@@ -355,7 +310,6 @@ int set_high_bus_freq(int high_bus_freq)
return 0;
}
-
int low_freq_bus_used(void)
{
if (!bus_freq_scaling_initialized)
@@ -411,8 +365,7 @@ static ssize_t bus_freq_scaling_enable_store(struct device *dev,
static int busfreq_suspend(struct platform_device *pdev, pm_message_t message)
{
- if (low_bus_freq_mode || audio_bus_freq_mode)
- set_high_bus_freq(1);
+ set_high_bus_freq(1);
busfreq_suspended = 1;
return 0;
}
@@ -517,6 +470,13 @@ static int __devinit busfreq_probe(struct platform_device *pdev)
return PTR_ERR(mmdc_ch0_axi);
}
+ vddsoc_cap_regulator = regulator_get(NULL, "cpu_vddsoc");
+ if (IS_ERR(vddsoc_cap_regulator)) {
+ printk(KERN_ERR "%s: failed to get vddsoc_cap regulator\n",
+ __func__);
+ return PTR_ERR(vddsoc_cap_regulator);
+ }
+
err = sysfs_create_file(&busfreq_dev->kobj, &dev_attr_enable.attr);
if (err) {
printk(KERN_ERR
@@ -526,8 +486,16 @@ static int __devinit busfreq_probe(struct platform_device *pdev)
cpu_op_tbl = get_cpu_op(&cpu_op_nr);
low_bus_freq_mode = 0;
- high_bus_freq_mode = 1;
- med_bus_freq_mode = 0;
+ if (cpu_is_mx6dl()) {
+ high_bus_freq_mode = 0;
+ med_bus_freq_mode = 1;
+ /* To make pll2_400 use count right, as when
+ system enter 24M, it will disable pll2_400 */
+ clk_enable(pll2_400);
+ } else {
+ high_bus_freq_mode = 1;
+ med_bus_freq_mode = 0;
+ }
bus_freq_scaling_is_active = 0;
bus_freq_scaling_initialized = 1;
@@ -575,18 +543,20 @@ static int __init busfreq_init(void)
printk(KERN_INFO "Bus freq driver module loaded\n");
- if (cpu_is_mx6sl()) {
- /* Enable busfreq by default. */
- bus_freq_scaling_is_active = 1;
+ /* Enable busfreq by default. */
+ bus_freq_scaling_is_active = 1;
+
+ if (cpu_is_mx6q())
+ set_high_bus_freq(1);
+ else
set_high_bus_freq(0);
- /* Make sure system can enter low bus mode if it should be in
- low bus mode */
- if (low_freq_bus_used() && !low_bus_freq_mode)
- set_low_bus_freq();
- printk(KERN_INFO "Bus freq driver Enabled\n");
- }
+ /* Make sure system can enter low bus mode if it should be in
+ low bus mode */
+ if (low_freq_bus_used() && !low_bus_freq_mode)
+ set_low_bus_freq();
+ printk(KERN_INFO "Bus freq driver Enabled\n");
return 0;
}
diff --git a/arch/arm/mach-mx6/clock.c b/arch/arm/mach-mx6/clock.c
index 3efb6b3e6378..600cd8b23414 100644
--- a/arch/arm/mach-mx6/clock.c
+++ b/arch/arm/mach-mx6/clock.c
@@ -1989,15 +1989,26 @@ static struct clk vdo_axi_clk = {
.set_parent = _clk_vdo_axi_set_parent,
};
-static struct clk vdoa_clk = {
+static struct clk vdoa_clk[] = {
+ {
__INIT_CLK_DEBUG(vdoa_clk)
.id = 0,
.parent = &vdo_axi_clk,
- .secondary = &ipg_clk,
.enable_reg = MXC_CCM_CCGR2,
.enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,
.enable = _clk_enable,
.disable = _clk_disable,
+ .secondary = &vdoa_clk[1],
+ .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
+ },
+ {
+ .parent = &mmdc_ch0_axi_clk[0],
+ .secondary = &vdoa_clk[2],
+ },
+ {
+ .parent = &mx6fast1_clk,
+ .secondary = &ocram_clk,
+ },
};
static unsigned long _clk_gpt_get_rate(struct clk *clk)
@@ -4165,7 +4176,6 @@ static struct clk hdmi_clk[] = {
.enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
.enable = _clk_enable,
.disable = _clk_disable,
- .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
},
{
__INIT_CLK_DEBUG(hdmi_iahb_clk)
@@ -4187,7 +4197,6 @@ static struct clk caam_clk[] = {
.enable = _clk_enable,
.disable = _clk_disable,
.secondary = &caam_clk[1],
- .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE,
},
{
__INIT_CLK_DEBUG(caam_aclk_clk)
@@ -5247,7 +5256,7 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "hdmi_isfr_clk", hdmi_clk[0]),
_REGISTER_CLOCK(NULL, "hdmi_iahb_clk", hdmi_clk[1]),
_REGISTER_CLOCK(NULL, "mipi_pllref_clk", mipi_pllref_clk),
- _REGISTER_CLOCK(NULL, "vdoa", vdoa_clk),
+ _REGISTER_CLOCK(NULL, "vdoa", vdoa_clk[0]),
_REGISTER_CLOCK(NULL, NULL, aips_tz2_clk),
_REGISTER_CLOCK(NULL, NULL, aips_tz1_clk),
_REGISTER_CLOCK(NULL, "clko_clk", clko_clk),
diff --git a/arch/arm/mach-mx6/clock_mx6sl.c b/arch/arm/mach-mx6/clock_mx6sl.c
index 42621f73dbbc..577a52277d68 100755
--- a/arch/arm/mach-mx6/clock_mx6sl.c
+++ b/arch/arm/mach-mx6/clock_mx6sl.c
@@ -3910,6 +3910,8 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "gpu2d_clk", gpu2d_core_clk),
_REGISTER_CLOCK(NULL, "gpu2d_axi_clk", gpu2d_axi_clk),
_REGISTER_CLOCK(NULL, "openvg_axi_clk", openvg_axi_clk),
+ _REGISTER_CLOCK(NULL, "rng_clk", dummy_clk),
+ _REGISTER_CLOCK(NULL, "dcp_clk", dummy_clk),
};
static void clk_tree_init(void)
diff --git a/arch/arm/mach-mx6/cpu.c b/arch/arm/mach-mx6/cpu.c
index 651b1ffd4344..5d9749653988 100644
--- a/arch/arm/mach-mx6/cpu.c
+++ b/arch/arm/mach-mx6/cpu.c
@@ -60,6 +60,8 @@ static int mx6_get_srev(void)
return IMX_CHIP_REVISION_1_0;
else if (rev == 1)
return IMX_CHIP_REVISION_1_1;
+ else if (rev == 2)
+ return IMX_CHIP_REVISION_1_2;
return IMX_CHIP_REVISION_UNKNOWN;
}
diff --git a/arch/arm/mach-mx6/crm_regs.h b/arch/arm/mach-mx6/crm_regs.h
index c99caad1e776..2e1f3e4a32c4 100644
--- a/arch/arm/mach-mx6/crm_regs.h
+++ b/arch/arm/mach-mx6/crm_regs.h
@@ -121,6 +121,7 @@
#define ANADIG_PLL_ENET_POWER_DOWN (1 << 12)
#define ANADIG_PLL_ENET_DIV_SELECT_MASK (0x3)
#define ANADIG_PLL_ENET_DIV_SELECT_OFFSET (0)
+#define ANATOP_BYPASS_SRC_LVDS1 0x00004000
/* PFD register defines. */
#define ANADIG_PFD_FRAC_MASK 0x3F
diff --git a/arch/arm/mach-mx6/devices-imx6q.h b/arch/arm/mach-mx6/devices-imx6q.h
index 3255cf79decf..105e1f6d0a0e 100644
--- a/arch/arm/mach-mx6/devices-imx6q.h
+++ b/arch/arm/mach-mx6/devices-imx6q.h
@@ -246,3 +246,13 @@ extern const struct imx_pcie_data imx6q_pcie_data __initconst;
extern const struct imx_imx_keypad_data imx6sl_imx_keypad_data;
#define imx6sl_add_imx_keypad(pdata) \
imx_add_imx_keypad(&imx6sl_imx_keypad_data, pdata)
+
+extern const struct imx_dcp_data imx6sl_dcp_data __initconst;
+#define imx6sl_add_dcp() \
+ imx_add_dcp(&imx6sl_dcp_data);
+
+extern const struct imx_rngb_data imx6sl_rngb_data __initconst;
+#define imx6sl_add_rngb() \
+ imx_add_rngb(&imx6sl_rngb_data);
+
+#define imx6_add_armpmu() imx_add_imx_armpmu()
diff --git a/arch/arm/mach-mx6/mx6_anatop_regulator.c b/arch/arm/mach-mx6/mx6_anatop_regulator.c
index fd7e0c3fbdee..06755dc7a4ee 100644
--- a/arch/arm/mach-mx6/mx6_anatop_regulator.c
+++ b/arch/arm/mach-mx6/mx6_anatop_regulator.c
@@ -34,9 +34,15 @@
#include "crm_regs.h"
#include "regs-anadig.h"
+#define GPC_PGC_GPU_PGCR_OFFSET 0x260
+#define GPC_CNTR_OFFSET 0x0
+
extern struct platform_device sgtl5000_vdda_reg_devices;
extern struct platform_device sgtl5000_vddio_reg_devices;
extern struct platform_device sgtl5000_vddd_reg_devices;
+extern void __iomem *gpc_base;
+/* Default PU voltage value set to 1.1V */
+static unsigned int org_ldo = 0x2000;
static int get_voltage(struct anatop_regulator *sreg)
{
@@ -82,6 +88,108 @@ static int set_voltage(struct anatop_regulator *sreg, int uv)
}
}
+static int pu_enable(struct anatop_regulator *sreg)
+{
+ unsigned int reg;
+
+ /* Do not enable PU LDO if it is already enabled */
+ reg = __raw_readl(ANADIG_REG_CORE) & (ANADIG_REG_TARGET_MASK
+ << ANADIG_REG1_PU_TARGET_OFFSET);
+ if (reg != 0)
+ return 0;
+
+ /* Set the voltage of VDDPU as in normal mode. */
+ __raw_writel(org_ldo | (__raw_readl(ANADIG_REG_CORE) &
+ (~(ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET))), ANADIG_REG_CORE);
+
+ /* Need to wait for the regulator to come back up */
+ /*
+ * Delay time is based on the number of 24MHz clock cycles
+ * programmed in the ANA_MISC2_BASE_ADDR for each
+ * 25mV step.
+ */
+ udelay(150);
+
+ /* enable power up request */
+ reg = __raw_readl(gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
+ __raw_writel(reg | 0x1, gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
+ /* power up request */
+ reg = __raw_readl(gpc_base + GPC_CNTR_OFFSET);
+ __raw_writel(reg | 0x2, gpc_base + GPC_CNTR_OFFSET);
+ /* Wait for the power up bit to clear */
+ while (__raw_readl(gpc_base + GPC_CNTR_OFFSET) & 0x2)
+ ;
+
+ /* Enable the Brown Out detection. */
+ reg = __raw_readl(ANA_MISC2_BASE_ADDR);
+ reg |= ANADIG_ANA_MISC2_REG1_BO_EN;
+ __raw_writel(reg, ANA_MISC2_BASE_ADDR);
+
+ /* Unmask the ANATOP brown out interrupt in the GPC. */
+ reg = __raw_readl(gpc_base + 0x14);
+ reg &= ~0x80000000;
+ __raw_writel(reg, gpc_base + 0x14);
+
+ return 0;
+}
+
+static int pu_disable(struct anatop_regulator *sreg)
+{
+ unsigned int reg;
+
+ /* Do not disable PU LDO if it is not enabled */
+ reg = __raw_readl(ANADIG_REG_CORE) & (ANADIG_REG_TARGET_MASK
+ << ANADIG_REG1_PU_TARGET_OFFSET);
+ if (reg == 0)
+ return 0;
+
+ /* Disable the brown out detection since we are going to be
+ * disabling the LDO.
+ */
+ reg = __raw_readl(ANA_MISC2_BASE_ADDR);
+ reg &= ~ANADIG_ANA_MISC2_REG1_BO_EN;
+ __raw_writel(reg, ANA_MISC2_BASE_ADDR);
+
+ /* Power gate the PU LDO. */
+ /* Power gate the PU domain first. */
+ /* enable power down request */
+ reg = __raw_readl(gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
+ __raw_writel(reg | 0x1, gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
+ /* power down request */
+ reg = __raw_readl(gpc_base + GPC_CNTR_OFFSET);
+ __raw_writel(reg | 0x1, gpc_base + GPC_CNTR_OFFSET);
+ /* Wait for power down to complete. */
+ while (__raw_readl(gpc_base + GPC_CNTR_OFFSET) & 0x1)
+ ;
+
+ /* Mask the ANATOP brown out interrupt in the GPC. */
+ reg = __raw_readl(gpc_base + 0x14);
+ reg |= 0x80000000;
+ __raw_writel(reg, gpc_base + 0x14);
+
+ /* PU power gating. */
+ reg = __raw_readl(ANADIG_REG_CORE);
+ org_ldo = reg & (ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET);
+ reg &= ~(ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET);
+ __raw_writel(reg, ANADIG_REG_CORE);
+
+ /* Clear the BO interrupt in the ANATOP. */
+ reg = __raw_readl(ANADIG_MISC1_REG);
+ reg |= 0x80000000;
+ __raw_writel(reg, ANADIG_MISC1_REG);
+ return 0;
+}
+static int is_pu_enabled(struct anatop_regulator *sreg)
+{
+ unsigned int reg;
+
+ reg = __raw_readl(ANADIG_REG_CORE) & (ANADIG_REG_TARGET_MASK
+ << ANADIG_REG1_PU_TARGET_OFFSET);
+ if (reg == 0)
+ return 0;
+ else
+ return 1;
+}
static int enable(struct anatop_regulator *sreg)
{
return 0;
@@ -101,9 +209,9 @@ static struct anatop_regulator_data vddpu_data = {
.name = "vddpu",
.set_voltage = set_voltage,
.get_voltage = get_voltage,
- .enable = enable,
- .disable = disable,
- .is_enabled = is_enabled,
+ .enable = pu_enable,
+ .disable = pu_disable,
+ .is_enabled = is_pu_enabled,
.control_reg = (u32)(MXC_PLL_BASE + HW_ANADIG_REG_CORE),
.vol_bit_shift = 9,
.vol_bit_mask = 0x1F,
@@ -193,6 +301,21 @@ static struct regulator_consumer_supply vddcore_consumers[] = {
.supply = "cpu_vddgp",
}
};
+/* PU */
+static struct regulator_consumer_supply vddpu_consumers[] = {
+ {
+ .supply = "cpu_vddvpu",
+ },
+ {
+ .supply = "cpu_vddgpu",
+ }
+};
+/* SOC */
+static struct regulator_consumer_supply vddsoc_consumers[] = {
+ {
+ .supply = "cpu_vddsoc",
+ },
+};
static struct regulator_init_data vddpu_init = {
.constraints = {
@@ -202,11 +325,11 @@ static struct regulator_init_data vddpu_init = {
.valid_modes_mask = REGULATOR_MODE_FAST |
REGULATOR_MODE_NORMAL,
.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+ REGULATOR_CHANGE_STATUS |
REGULATOR_CHANGE_MODE,
- .always_on = 1,
},
- .num_consumer_supplies = 0,
- .consumer_supplies = NULL,
+ .num_consumer_supplies = ARRAY_SIZE(vddpu_consumers),
+ .consumer_supplies = vddpu_consumers,
};
static struct regulator_init_data vddcore_init = {
@@ -235,8 +358,8 @@ static struct regulator_init_data vddsoc_init = {
REGULATOR_CHANGE_MODE,
.always_on = 1,
},
- .num_consumer_supplies = 0,
- .consumer_supplies = NULL,
+ .num_consumer_supplies = ARRAY_SIZE(vddsoc_consumers),
+ .consumer_supplies = &vddsoc_consumers[0],
};
static struct regulator_init_data vdd2p5_init = {
diff --git a/arch/arm/mach-mx6/pcie.c b/arch/arm/mach-mx6/pcie.c
index 38e9abcd29cc..f39dd3d4314b 100644
--- a/arch/arm/mach-mx6/pcie.c
+++ b/arch/arm/mach-mx6/pcie.c
@@ -606,6 +606,7 @@ static void imx_pcie_enable_controller(struct device *dev)
pr_err("can't enable pcie clock.\n");
clk_put(pcie_clk);
}
+ imx_pcie_clrset(iomuxc_gpr1_pcie_ref_clk_en, 1 << 16, IOMUXC_GPR1);
}
static void card_reset(struct device *dev)
@@ -652,6 +653,9 @@ static void __init add_pcie_port(void __iomem *base, void __iomem *dbi_base,
clk_disable(pcie_clk);
clk_put(pcie_clk);
+ imx_pcie_clrset(iomuxc_gpr1_pcie_ref_clk_en, 0 << 16,
+ IOMUXC_GPR1);
+
/* Disable PCIE power */
gpio_request(pdata->pcie_pwr_en, "PCIE POWER_EN");
@@ -669,7 +673,6 @@ static int __devinit imx_pcie_pltfm_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct imx_pcie_platform_data *pdata = dev->platform_data;
-
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
dev_err(dev, "no mmio space\n");
@@ -698,15 +701,13 @@ static int __devinit imx_pcie_pltfm_probe(struct platform_device *pdev)
imx_pcie_clrset(iomuxc_gpr8_tx_deemph_gen1, 0 << 0, IOMUXC_GPR8);
imx_pcie_clrset(iomuxc_gpr8_tx_deemph_gen2_3p5db, 0 << 6, IOMUXC_GPR8);
- imx_pcie_clrset(iomuxc_gpr8_tx_deemph_gen2_6db, 0 << 12, IOMUXC_GPR8);
+ imx_pcie_clrset(iomuxc_gpr8_tx_deemph_gen2_6db, 20 << 12, IOMUXC_GPR8);
imx_pcie_clrset(iomuxc_gpr8_tx_swing_full, 127 << 18, IOMUXC_GPR8);
imx_pcie_clrset(iomuxc_gpr8_tx_swing_low, 127 << 25, IOMUXC_GPR8);
/* Enable the pwr, clks and so on */
imx_pcie_enable_controller(dev);
- imx_pcie_clrset(iomuxc_gpr1_pcie_ref_clk_en, 1 << 16, IOMUXC_GPR1);
-
/* togle the external card's reset */
card_reset(dev) ;
@@ -714,13 +715,6 @@ static int __devinit imx_pcie_pltfm_probe(struct platform_device *pdev)
imx_pcie_regions_setup(dbi_base);
usleep_range(3000, 4000);
- /*
- * Force to GEN1 because of PCIE2USB storage stress tests
- * would be failed when GEN2 is enabled
- */
- writel(((readl(dbi_base + LNK_CAP) & 0xfffffff0) | 0x1),
- dbi_base + LNK_CAP);
-
/* start link up */
imx_pcie_clrset(iomuxc_gpr12_app_ltssm_enable, 1 << 10, IOMUXC_GPR12);
@@ -749,6 +743,8 @@ static int __devexit imx_pcie_pltfm_remove(struct platform_device *pdev)
clk_put(pcie_clk);
}
+ imx_pcie_clrset(iomuxc_gpr1_pcie_ref_clk_en, 0 << 16, IOMUXC_GPR1);
+
/* Disable PCIE power */
gpio_request(pdata->pcie_pwr_en, "PCIE POWER_EN");
diff --git a/arch/arm/mach-mx6/system.c b/arch/arm/mach-mx6/system.c
index d16b1eff6cbe..b9efbb64c8f9 100644
--- a/arch/arm/mach-mx6/system.c
+++ b/arch/arm/mach-mx6/system.c
@@ -49,8 +49,6 @@
extern unsigned int gpc_wake_irq[4];
-static unsigned int cpu_idle_mask;
-
static void __iomem *gpc_base = IO_ADDRESS(GPC_BASE_ADDR);
int wait_mode_arm_podf;
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 63de2d396e2d..14a5971d0d48 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -49,8 +49,9 @@
#define ETH_KS8851_QUART 138
#define OMAP4_SFH7741_SENSOR_OUTPUT_GPIO 184
#define OMAP4_SFH7741_ENABLE_GPIO 188
-#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
+#define HDMI_GPIO_CT_CP_HPD 60 /* HPD mode enable/disable */
#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
+#define HDMI_GPIO_HPD 63 /* Hotplug detect */
static const int sdp4430_keymap[] = {
KEY(0, 0, KEY_E),
@@ -578,12 +579,8 @@ static void __init omap_sfh7741prox_init(void)
static void sdp4430_hdmi_mux_init(void)
{
- /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
- omap_mux_init_signal("hdmi_hpd",
- OMAP_PIN_INPUT_PULLUP);
omap_mux_init_signal("hdmi_cec",
OMAP_PIN_INPUT_PULLUP);
- /* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
omap_mux_init_signal("hdmi_ddc_scl",
OMAP_PIN_INPUT_PULLUP);
omap_mux_init_signal("hdmi_ddc_sda",
@@ -591,8 +588,9 @@ static void sdp4430_hdmi_mux_init(void)
}
static struct gpio sdp4430_hdmi_gpios[] = {
- { HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd" },
+ { HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" },
{ HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" },
+ { HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" },
};
static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev)
@@ -609,26 +607,21 @@ static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev)
static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev)
{
- gpio_free(HDMI_GPIO_LS_OE);
- gpio_free(HDMI_GPIO_HPD);
+ gpio_free_array(sdp4430_hdmi_gpios, ARRAY_SIZE(sdp4430_hdmi_gpios));
}
+static struct omap_dss_hdmi_data sdp4430_hdmi_data = {
+ .hpd_gpio = HDMI_GPIO_HPD,
+};
+
static struct omap_dss_device sdp4430_hdmi_device = {
.name = "hdmi",
.driver_name = "hdmi_panel",
.type = OMAP_DISPLAY_TYPE_HDMI,
- .clocks = {
- .dispc = {
- .dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK,
- },
- .hdmi = {
- .regn = 15,
- .regm2 = 1,
- },
- },
.platform_enable = sdp4430_panel_enable_hdmi,
.platform_disable = sdp4430_panel_disable_hdmi,
.channel = OMAP_DSS_CHANNEL_DIGIT,
+ .data = &sdp4430_hdmi_data,
};
static struct omap_dss_device *sdp4430_dss_devices[] = {
@@ -645,6 +638,10 @@ void omap_4430sdp_display_init(void)
{
sdp4430_hdmi_mux_init();
omap_display_init(&sdp4430_dss_data);
+
+ omap_mux_init_gpio(HDMI_GPIO_LS_OE, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(HDMI_GPIO_CT_CP_HPD, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT_PULLDOWN);
}
#ifdef CONFIG_OMAP_MUX
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 0cfe2005cb50..107dfc377a8a 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -52,8 +52,9 @@
#define GPIO_HUB_NRESET 62
#define GPIO_WIFI_PMENA 43
#define GPIO_WIFI_IRQ 53
-#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
+#define HDMI_GPIO_CT_CP_HPD 60 /* HPD mode enable/disable */
#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
+#define HDMI_GPIO_HPD 63 /* Hotplug detect */
/* wl127x BT, FM, GPS connectivity chip */
static int wl1271_gpios[] = {46, -1, -1};
@@ -614,12 +615,8 @@ int __init omap4_panda_dvi_init(void)
static void omap4_panda_hdmi_mux_init(void)
{
- /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
- omap_mux_init_signal("hdmi_hpd",
- OMAP_PIN_INPUT_PULLUP);
omap_mux_init_signal("hdmi_cec",
OMAP_PIN_INPUT_PULLUP);
- /* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
omap_mux_init_signal("hdmi_ddc_scl",
OMAP_PIN_INPUT_PULLUP);
omap_mux_init_signal("hdmi_ddc_sda",
@@ -627,8 +624,9 @@ static void omap4_panda_hdmi_mux_init(void)
}
static struct gpio panda_hdmi_gpios[] = {
- { HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd" },
+ { HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ct_cp_hpd" },
{ HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" },
+ { HDMI_GPIO_HPD, GPIOF_DIR_IN, "hdmi_gpio_hpd" },
};
static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev)
@@ -645,10 +643,13 @@ static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev)
static void omap4_panda_panel_disable_hdmi(struct omap_dss_device *dssdev)
{
- gpio_free(HDMI_GPIO_LS_OE);
- gpio_free(HDMI_GPIO_HPD);
+ gpio_free_array(panda_hdmi_gpios, ARRAY_SIZE(panda_hdmi_gpios));
}
+static struct omap_dss_hdmi_data omap4_panda_hdmi_data = {
+ .hpd_gpio = HDMI_GPIO_HPD,
+};
+
static struct omap_dss_device omap4_panda_hdmi_device = {
.name = "hdmi",
.driver_name = "hdmi_panel",
@@ -656,6 +657,7 @@ static struct omap_dss_device omap4_panda_hdmi_device = {
.platform_enable = omap4_panda_panel_enable_hdmi,
.platform_disable = omap4_panda_panel_disable_hdmi,
.channel = OMAP_DSS_CHANNEL_DIGIT,
+ .data = &omap4_panda_hdmi_data,
};
static struct omap_dss_device *omap4_panda_dss_devices[] = {
@@ -679,6 +681,10 @@ void omap4_panda_display_init(void)
omap4_panda_hdmi_mux_init();
omap_display_init(&omap4_panda_dss_data);
+
+ omap_mux_init_gpio(HDMI_GPIO_LS_OE, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(HDMI_GPIO_CT_CP_HPD, OMAP_PIN_OUTPUT);
+ omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT_PULLDOWN);
}
static void __init omap4_panda_init(void)
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
index 88bd6f7705f0..c56597172bfc 100644
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -133,7 +133,7 @@ static struct platform_device rx51_charger_device = {
static void __init rx51_charger_init(void)
{
WARN_ON(gpio_request_one(RX51_USB_TRANSCEIVER_RST_GPIO,
- GPIOF_OUT_INIT_LOW, "isp1704_reset"));
+ GPIOF_OUT_INIT_HIGH, "isp1704_reset"));
platform_device_register(&rx51_charger_device);
}
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 130034bf01d5..dfffbbf4c009 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -528,7 +528,13 @@ int gpmc_cs_configure(int cs, int cmd, int wval)
case GPMC_CONFIG_DEV_SIZE:
regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+ /* clear 2 target bits */
+ regval &= ~GPMC_CONFIG1_DEVICESIZE(3);
+
+ /* set the proper value */
regval |= GPMC_CONFIG1_DEVICESIZE(wval);
+
gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
break;
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
index 0ab531d047fc..8a98da0b3f8e 100644
--- a/arch/arm/mach-orion5x/common.c
+++ b/arch/arm/mach-orion5x/common.c
@@ -29,6 +29,7 @@
#include <mach/hardware.h>
#include <mach/orion5x.h>
#include <plat/orion_nand.h>
+#include <plat/ehci-orion.h>
#include <plat/time.h>
#include <plat/common.h>
#include "common.h"
@@ -72,7 +73,8 @@ void __init orion5x_map_io(void)
void __init orion5x_ehci0_init(void)
{
orion_ehci_init(&orion5x_mbus_dram_info,
- ORION5X_USB0_PHYS_BASE, IRQ_ORION5X_USB0_CTRL);
+ ORION5X_USB0_PHYS_BASE, IRQ_ORION5X_USB0_CTRL,
+ EHCI_PHY_ORION);
}
diff --git a/arch/arm/mach-orion5x/mpp.h b/arch/arm/mach-orion5x/mpp.h
index eac68978a2c2..db70e79a1198 100644
--- a/arch/arm/mach-orion5x/mpp.h
+++ b/arch/arm/mach-orion5x/mpp.h
@@ -65,8 +65,8 @@
#define MPP8_GIGE MPP(8, 0x1, 0, 0, 1, 1, 1)
#define MPP9_UNUSED MPP(9, 0x0, 0, 0, 1, 1, 1)
-#define MPP9_GPIO MPP(9, 0x0, 0, 0, 1, 1, 1)
-#define MPP9_GIGE MPP(9, 0x1, 1, 1, 1, 1, 1)
+#define MPP9_GPIO MPP(9, 0x0, 1, 1, 1, 1, 1)
+#define MPP9_GIGE MPP(9, 0x1, 0, 0, 1, 1, 1)
#define MPP10_UNUSED MPP(10, 0x0, 0, 0, 1, 1, 1)
#define MPP10_GPIO MPP(10, 0x0, 1, 1, 1, 1, 1)
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index 9a9706cf1496..6ebdb0d03828 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -7,6 +7,7 @@ config UX500_SOC_COMMON
select HAS_MTU
select ARM_ERRATA_753970
select ARM_ERRATA_754322
+ select ARM_ERRATA_764369
menu "Ux500 SoC"
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 03da5fba8656..e830a9cfaa91 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -386,6 +386,22 @@ dma_alloc_writethrough(struct device *dev, size_t size, dma_addr_t *handle, gfp_
}
EXPORT_SYMBOL(dma_alloc_writethrough);
+
+#ifdef CONFIG_FSL_UTP
+/*
+ * Allocate noncacheable memory space and return both the kernel remapped
+ * virtual and bus address for that space.
+ */
+void *
+dma_alloc_noncacheable(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
+{
+ return __dma_alloc(dev, size, handle, gfp,
+ /*pgprot_writethrough(pgprot_kernel));*/
+ pgprot_noncached(pgprot_kernel));
+}
+EXPORT_SYMBOL(dma_alloc_noncacheable);
+#endif
+
static int dma_mmap(struct device *dev, struct vm_area_struct *vma,
void *cpu_addr, dma_addr_t dma_addr, size_t size)
{
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index bc0e1d88fd3b..8799eae5da9b 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -266,7 +266,9 @@ good_area:
return fault;
check_stack:
- if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr))
+ /* Don't allow expansion below FIRST_USER_ADDRESS */
+ if (vma->vm_flags & VM_GROWSDOWN &&
+ addr >= FIRST_USER_ADDRESS && !expand_stack(vma, addr))
goto good_area;
out:
return fault;
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index b6ba1032a988..21cd29834076 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -344,9 +344,7 @@ __v7_setup:
mcreq p15, 0, r10, c15, c0, 1 @ write diagnostic register
#endif
#ifdef CONFIG_ARM_ERRATA_743622
- teq r6, #0x20 @ present in r2p0
- teqne r6, #0x21 @ present in r2p1
- teqne r6, #0x22 @ present in r2p2
+ teq r5, #0x00200000 @ only present in r2p*
mrceq p15, 0, r10, c15, c0, 1 @ read diagnostic register
orreq r10, r10, #1 << 6 @ set bit #6
mcreq p15, 0, r10, c15, c0, 1 @ write diagnostic register
@@ -374,6 +372,18 @@ __v7_setup:
mcr p15, 0, r5, c10, c2, 0 @ write PRRR
mcr p15, 0, r6, c10, c2, 1 @ write NMRR
#endif
+#ifndef CONFIG_ARM_THUMBEE
+ mrc p15, 0, r0, c0, c1, 0 @ read ID_PFR0 for ThumbEE
+ and r0, r0, #(0xf << 12) @ ThumbEE enabled field
+ teq r0, #(1 << 12) @ check if ThumbEE is present
+ bne 1f
+ mov r5, #0
+ mcr p14, 6, r5, c1, c0, 0 @ Initialize TEEHBR to 0
+ mrc p14, 6, r0, c0, c0, 0 @ load TEECR
+ orr r0, r0, #1 @ set the 1st bit in order to
+ mcr p14, 6, r0, c0, c0, 0 @ stop userspace TEEHBR access
+1:
+#endif
adr r5, v7_crval
ldmia r5, {r5, r6}
#ifdef CONFIG_CPU_ENDIAN_BE8
diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c
index c074e66ad224..4e0a371630b3 100644
--- a/arch/arm/oprofile/common.c
+++ b/arch/arm/oprofile/common.c
@@ -116,7 +116,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
return oprofile_perf_init(ops);
}
-void __exit oprofile_arch_exit(void)
+void oprofile_arch_exit(void)
{
oprofile_perf_exit();
}
diff --git a/arch/arm/plat-mxc/devices/Makefile b/arch/arm/plat-mxc/devices/Makefile
index 386b9cb4e29c..41287783cb80 100755
--- a/arch/arm/plat-mxc/devices/Makefile
+++ b/arch/arm/plat-mxc/devices/Makefile
@@ -66,3 +66,4 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_MIPI_DSI) += platform-imx-mipi_dsi.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_MIPI_CSI2) += platform-imx-mipi_csi2.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_VDOA) += platform-imx-vdoa.o
obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_PCIE) += platform-imx-pcie.o
+obj-y += platform-imx-pmu.o
diff --git a/arch/arm/plat-mxc/devices/platform-imx-dcp.c b/arch/arm/plat-mxc/devices/platform-imx-dcp.c
index 3a36de55254b..a77840b93fe9 100755
--- a/arch/arm/plat-mxc/devices/platform-imx-dcp.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-dcp.c
@@ -1,28 +1,50 @@
/*
* Copyright (C) 2010 Pengutronix
* Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
- * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2011-2012 Freescale Semiconductor, Inc.
*
- * 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.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <asm/sizes.h>
#include <mach/hardware.h>
#include <mach/devices-common.h>
-#define imx_ocp_data_entry_single(soc) \
+#ifdef CONFIG_SOC_IMX50
+#define imx_dcp_data_entry_single(soc) \
{ \
.iobase = soc ## _DCP_BASE_ADDR, \
.irq1 = soc ## _INT_DCP_CHAN0, \
.irq2 = soc ## _INT_DCP_CHAN1_3, \
}
-#ifdef CONFIG_SOC_IMX50
const struct imx_dcp_data imx50_dcp_data __initconst =
- imx_ocp_data_entry_single(MX50);
+ imx_dcp_data_entry_single(MX50);
#endif /* ifdef CONFIG_SOC_IMX50 */
+#ifdef CONFIG_SOC_IMX6SL
+#define imx_dcp_data_entry_single(soc) \
+{ \
+ .iobase = soc ## _DCP_BASE_ADDR, \
+ .irq1 = soc ## _INT_DCP_CH0, \
+ .irq2 = soc ## _INT_DCP_GEN, \
+}
+
+const struct imx_dcp_data imx6sl_dcp_data __initconst =
+ imx_dcp_data_entry_single(MX6SL);
+#endif /* ifdef CONFIG_SOC_IMX6SL */
+
struct platform_device *__init imx_add_dcp(
const struct imx_dcp_data *data)
{
@@ -31,17 +53,19 @@ struct platform_device *__init imx_add_dcp(
.start = data->iobase,
.end = data->iobase + SZ_8K - 1,
.flags = IORESOURCE_MEM,
- }, {
+ },
+ {
.start = data->irq1,
.end = data->irq1,
.flags = IORESOURCE_IRQ,
- }, {
+ },
+ {
.start = data->irq2,
.end = data->irq2,
.flags = IORESOURCE_IRQ,
},
};
- return imx_add_platform_device("dcp", 0,
- res, ARRAY_SIZE(res), NULL, 0);
+ return imx_add_platform_device_dmamask("dcp", 0,
+ res, ARRAY_SIZE(res), NULL, 0, DMA_BIT_MASK(32));
}
diff --git a/arch/arm/plat-mxc/devices/platform-imx-ocotp.c b/arch/arm/plat-mxc/devices/platform-imx-ocotp.c
index 2279aa7b8f91..055fe337e143 100755
--- a/arch/arm/plat-mxc/devices/platform-imx-ocotp.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-ocotp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. 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 version 2 as published by the
@@ -53,7 +53,7 @@ const struct imx_otp_data imx50_otp_data = {
static const char *bank_reg_desc[BANKS][BANK_ITEMS] = {
BANK(LOCK, CFG0, CFG1, CFG2, CFG3, CFG4, CFG5, CFG6),
BANK(MEM0, MEM1, MEM2, MEM3, MEM4, ANA0, ANA1, ANA2),
- BANK(OTPMK0, SOTPMK1, OTPMK2, OTPMK3, OTPMK4, OTPMK5, OTPMK6, OTPMK7),
+ BANK(OTPMK0, OTPMK1, OTPMK2, OTPMK3, OTPMK4, OTPMK5, OTPMK6, OTPMK7),
BANK(SRK0, SRK1, SRK2, SRK3, SRK4, SRK5, SRK6, SRK7),
BANK(RESP0, HSJC_RESP1, MAC0, MAC1, HDCP_KSV0, HDCP_KSV1, GP1, GP2),
BANK(DTCP_KEY0, DTCP_KEY1, DTCP_KEY2, DTCP_KEY3, DTCP_KEY4, MISC_CONF, FIELD_RETURN, SRK_REVOKE),
diff --git a/arch/arm/plat-mxc/devices/platform-imx-pmu.c b/arch/arm/plat-mxc/devices/platform-imx-pmu.c
new file mode 100644
index 000000000000..cf29415d679e
--- /dev/null
+++ b/arch/arm/plat-mxc/devices/platform-imx-pmu.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, Inc. 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; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <asm/sizes.h>
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+#include <asm/pmu.h>
+
+static struct resource mx6_pmu_resources[] = {
+ [0] = {
+ .start = MXC_INT_CHEETAH_PERFORM,
+ .end = MXC_INT_CHEETAH_PERFORM,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device mx6_pmu_device = {
+ .name = "arm-pmu",
+ .id = ARM_PMU_DEVICE_CPU,
+ .num_resources = ARRAY_SIZE(mx6_pmu_resources),
+ .resource = mx6_pmu_resources,
+};
+
+void __init imx_add_imx_armpmu()
+{
+ platform_device_register(&mx6_pmu_device);
+}
diff --git a/arch/arm/plat-mxc/devices/platform-imx-rngb.c b/arch/arm/plat-mxc/devices/platform-imx-rngb.c
index 3407ea04ea53..9a0a652de82e 100755
--- a/arch/arm/plat-mxc/devices/platform-imx-rngb.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-rngb.c
@@ -1,8 +1,6 @@
/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
+ * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. 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; either version 2 of the License, or
@@ -33,6 +31,11 @@ const struct imx_rngb_data imx50_rngb_data __initconst =
imx_rngb_data_entry_single(MX50);
#endif /* ifdef CONFIG_SOC_IMX50 */
+#ifdef CONFIG_SOC_IMX6SL
+const struct imx_rngb_data imx6sl_rngb_data __initconst =
+ imx_rngb_data_entry_single(MX6SL);
+#endif /* ifdef CONFIG_SOC_IMX6SL */
+
struct platform_device *__init imx_add_rngb(
const struct imx_rngb_data *data)
{
diff --git a/arch/arm/plat-mxc/devices/platform-imx2-wdt.c b/arch/arm/plat-mxc/devices/platform-imx2-wdt.c
index 872515a04099..53cfb8dde927 100644
--- a/arch/arm/plat-mxc/devices/platform-imx2-wdt.c
+++ b/arch/arm/plat-mxc/devices/platform-imx2-wdt.c
@@ -15,6 +15,7 @@
.id = _id, \
.iobase = soc ## _WDOG ## _hwid ## _BASE_ADDR, \
.iosize = _size, \
+ .irq = soc ## _INT_WDOG ## _hwid, \
}
#define imx_imx2_wdt_data_entry(soc, _id, _hwid, _size) \
[_id] = imx_imx2_wdt_data_entry_single(soc, _id, _hwid, _size)
@@ -79,6 +80,10 @@ struct platform_device *__init imx_add_imx2_wdt(
.start = data->iobase,
.end = data->iobase + data->iosize - 1,
.flags = IORESOURCE_MEM,
+ }, {
+ .start = data->irq,
+ .end = data->irq,
+ .flags = IORESOURCE_IRQ,
},
};
return imx_add_platform_device("imx2-wdt", data->id,
diff --git a/arch/arm/plat-mxc/devices/platform-mxc_hdmi.c b/arch/arm/plat-mxc/devices/platform-mxc_hdmi.c
index c0545705e8c0..d4952620e223 100644
--- a/arch/arm/plat-mxc/devices/platform-mxc_hdmi.c
+++ b/arch/arm/plat-mxc/devices/platform-mxc_hdmi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -43,7 +43,8 @@ struct platform_device *__init imx_add_mxc_hdmi(
.flags = IORESOURCE_IRQ,
},
};
-
+ imx_add_platform_device("mxc_hdmi_cec", 0,
+ res, ARRAY_SIZE(res), NULL, 0);
return imx_add_platform_device_dmamask("mxc_hdmi", -1,
res, ARRAY_SIZE(res), pdata, sizeof(*pdata), DMA_BIT_MASK(32));
}
diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h
index 369ec0f6bd4a..4b6110712d1b 100755
--- a/arch/arm/plat-mxc/include/mach/devices-common.h
+++ b/arch/arm/plat-mxc/include/mach/devices-common.h
@@ -80,6 +80,7 @@ struct imx_imx2_wdt_data {
int id;
resource_size_t iobase;
resource_size_t iosize;
+ resource_size_t irq;
};
struct platform_device *__init imx_add_imx2_wdt(
const struct imx_imx2_wdt_data *data);
@@ -685,3 +686,5 @@ struct imx_pcie_data {
struct platform_device *__init imx_add_pcie(
const struct imx_pcie_data *data,
const struct imx_pcie_platform_data *pdata);
+
+void __init imx_add_imx_armpmu(void);
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx6dl.h b/arch/arm/plat-mxc/include/mach/iomux-mx6dl.h
index 1fa0e82b6a7e..4d0fa922c742 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx6dl.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx6dl.h
@@ -2665,11 +2665,13 @@
#define MX6DL_PAD_KEY_COL3__ENET_CRS \
IOMUX_PAD(0x0638, 0x0250, 1, 0x0000, 0, NO_PAD_CTRL)
#define MX6DL_PAD_KEY_COL3__HDMI_TX_DDC_SCL \
- IOMUX_PAD(0x0638, 0x0250, 2, 0x0860, 1, NO_PAD_CTRL)
+ IOMUX_PAD(0x0638, 0x0250, 2 | IOMUX_CONFIG_SION, 0x0860, 1, \
+ MX6DL_I2C_PAD_CTRL)
#define MX6DL_PAD_KEY_COL3__KPP_COL_3 \
IOMUX_PAD(0x0638, 0x0250, 3, 0x0000, 0, NO_PAD_CTRL)
#define MX6DL_PAD_KEY_COL3__I2C2_SCL \
- IOMUX_PAD(0x0638, 0x0250, 4 | IOMUX_CONFIG_SION, 0x0870, 1, MX6DL_I2C_PAD_CTRL)
+ IOMUX_PAD(0x0638, 0x0250, 4 | IOMUX_CONFIG_SION, 0x0870, 1, \
+ MX6DL_I2C_PAD_CTRL)
#define MX6DL_PAD_KEY_COL3__GPIO_4_12 \
IOMUX_PAD(0x0638, 0x0250, 5, 0x0000, 0, NO_PAD_CTRL)
#define MX6DL_PAD_KEY_COL3__SPDIF_IN1 \
@@ -2756,11 +2758,13 @@
#define MX6DL_PAD_KEY_ROW3__ASRC_ASRC_EXT_CLK \
IOMUX_PAD(0x064C, 0x0264, 1, 0x0794, 2, NO_PAD_CTRL)
#define MX6DL_PAD_KEY_ROW3__HDMI_TX_DDC_SDA \
- IOMUX_PAD(0x064C, 0x0264, 2, 0x0864, 1, NO_PAD_CTRL)
+ IOMUX_PAD(0x064C, 0x0264, 2 | IOMUX_CONFIG_SION, 0x0864, 1, \
+ MX6DL_I2C_PAD_CTRL)
#define MX6DL_PAD_KEY_ROW3__KPP_ROW_3 \
IOMUX_PAD(0x064C, 0x0264, 3, 0x0000, 0, NO_PAD_CTRL)
#define MX6DL_PAD_KEY_ROW3__I2C2_SDA \
- IOMUX_PAD(0x064C, 0x0264, 4 | IOMUX_CONFIG_SION, 0x0874, 1, MX6DL_I2C_PAD_CTRL)
+ IOMUX_PAD(0x064C, 0x0264, 4 | IOMUX_CONFIG_SION, 0x0874, 1, \
+ MX6DL_I2C_PAD_CTRL)
#define MX6DL_PAD_KEY_ROW3__GPIO_4_13 \
IOMUX_PAD(0x064C, 0x0264, 5, 0x0000, 0, NO_PAD_CTRL)
#define MX6DL_PAD_KEY_ROW3__USDHC1_VSELECT \
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx6q.h b/arch/arm/plat-mxc/include/mach/iomux-mx6q.h
index b56f2fe1ff1b..7618975d38a3 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx6q.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx6q.h
@@ -80,9 +80,10 @@
#define MX6Q_ECSPI_PAD_CTRL (PAD_CTL_SRE_FAST | PAD_CTL_SPEED_MED | \
PAD_CTL_DSE_40ohm | PAD_CTL_HYS)
-#define MX6Q_I2S_OUT_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_DSE_40ohm | \
- PAD_CTL_PUS_100K_DOWN | PAD_CTL_HYS | PAD_CTL_SPEED_MED)
+#define MX6Q_HDMICEC_PAD_CTRL (PAD_CTL_HYS | PAD_CTL_PUS_22K_UP | \
+ PAD_CTL_PUE | PAD_CTL_PKE | PAD_CTL_ODE | PAD_CTL_SPEED_MED | \
+ PAD_CTL_DSE_40ohm | PAD_CTL_SRE_SLOW)
#define _MX6Q_PAD_SD2_DAT1__USDHC2_DAT1 \
IOMUX_PAD(0x0360, 0x004C, 0, 0x0000, 0, 0)
@@ -2183,7 +2184,7 @@
#define _MX6Q_PAD_KEY_COL3__ENET_CRS \
IOMUX_PAD(0x05E0, 0x0210, 1, 0x0000, 0, 0)
#define _MX6Q_PAD_KEY_COL3__HDMI_TX_DDC_SCL \
- IOMUX_PAD(0x05E0, 0x0210, 2, 0x0890, 1, 0)
+ IOMUX_PAD(0x05E0, 0x0210, 2 | IOMUX_CONFIG_SION, 0x0890, 1, 0)
#define _MX6Q_PAD_KEY_COL3__KPP_COL_3 \
IOMUX_PAD(0x05E0, 0x0210, 3, 0x0000, 0, 0)
#define _MX6Q_PAD_KEY_COL3__I2C2_SCL \
@@ -2200,7 +2201,7 @@
#define _MX6Q_PAD_KEY_ROW3__ASRC_ASRC_EXT_CLK \
IOMUX_PAD(0x05E4, 0x0214, 1, 0x07B0, 0, 0)
#define _MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA \
- IOMUX_PAD(0x05E4, 0x0214, 2, 0x0894, 1, 0)
+ IOMUX_PAD(0x05E4, 0x0214, 2 | IOMUX_CONFIG_SION, 0x0894, 1, 0)
#define _MX6Q_PAD_KEY_ROW3__KPP_ROW_3 \
IOMUX_PAD(0x05E4, 0x0214, 3, 0x0000, 0, 0)
#define _MX6Q_PAD_KEY_ROW3__I2C2_SDA \
@@ -3871,7 +3872,7 @@
#define MX6Q_PAD_EIM_A25__GPIO_5_2 \
(_MX6Q_PAD_EIM_A25__GPIO_5_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
#define MX6Q_PAD_EIM_A25__HDMI_TX_CEC_LINE \
- (_MX6Q_PAD_EIM_A25__HDMI_TX_CEC_LINE | MUX_PAD_CTRL(NO_PAD_CTRL))
+ (_MX6Q_PAD_EIM_A25__HDMI_TX_CEC_LINE | MUX_PAD_CTRL(MX6Q_HDMICEC_PAD_CTRL))
#define MX6Q_PAD_EIM_A25__PL301_MX6QPER1_HBURST_0 \
(_MX6Q_PAD_EIM_A25__PL301_MX6QPER1_HBURST_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -5781,7 +5782,7 @@
#define MX6Q_PAD_KEY_ROW2__GPIO_4_11 \
(_MX6Q_PAD_KEY_ROW2__GPIO_4_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
#define MX6Q_PAD_KEY_ROW2__HDMI_TX_CEC_LINE \
- (_MX6Q_PAD_KEY_ROW2__HDMI_TX_CEC_LINE | MUX_PAD_CTRL(NO_PAD_CTRL))
+ (_MX6Q_PAD_KEY_ROW2__HDMI_TX_CEC_LINE | MUX_PAD_CTRL(MX6Q_HDMICEC_PAD_CTRL))
#define MX6Q_PAD_KEY_ROW2__PL301_MX6QPER1_HADDR_4 \
(_MX6Q_PAD_KEY_ROW2__PL301_MX6QPER1_HADDR_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -5790,7 +5791,7 @@
#define MX6Q_PAD_KEY_COL3__ENET_CRS \
(_MX6Q_PAD_KEY_COL3__ENET_CRS | MUX_PAD_CTRL(NO_PAD_CTRL))
#define MX6Q_PAD_KEY_COL3__HDMI_TX_DDC_SCL \
- (_MX6Q_PAD_KEY_COL3__HDMI_TX_DDC_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+ (_MX6Q_PAD_KEY_COL3__HDMI_TX_DDC_SCL | MUX_PAD_CTRL(MX6Q_I2C_PAD_CTRL))
#define MX6Q_PAD_KEY_COL3__KPP_COL_3 \
(_MX6Q_PAD_KEY_COL3__KPP_COL_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
#define MX6Q_PAD_KEY_COL3__I2C2_SCL \
@@ -5807,7 +5808,7 @@
#define MX6Q_PAD_KEY_ROW3__ASRC_ASRC_EXT_CLK \
(_MX6Q_PAD_KEY_ROW3__ASRC_ASRC_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
#define MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA \
- (_MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+ (_MX6Q_PAD_KEY_ROW3__HDMI_TX_DDC_SDA | MUX_PAD_CTRL(MX6Q_I2C_PAD_CTRL))
#define MX6Q_PAD_KEY_ROW3__KPP_ROW_3 \
(_MX6Q_PAD_KEY_ROW3__KPP_ROW_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
#define MX6Q_PAD_KEY_ROW3__I2C2_SDA \
@@ -6176,7 +6177,7 @@
#define MX6Q_PAD_CSI0_DAT5__KPP_ROW_5 \
(_MX6Q_PAD_CSI0_DAT5__KPP_ROW_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
#define MX6Q_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD \
- (_MX6Q_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD | MUX_PAD_CTRL(MX6Q_I2S_OUT_PAD_CTRL))
+ (_MX6Q_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
#define MX6Q_PAD_CSI0_DAT5__GPIO_5_23 \
(_MX6Q_PAD_CSI0_DAT5__GPIO_5_23 | MUX_PAD_CTRL(MX6Q_HIGH_DRV))
#define MX6Q_PAD_CSI0_DAT5__MMDC_MMDC_DEBUG_44 \
diff --git a/arch/arm/plat-mxc/include/mach/mx6.h b/arch/arm/plat-mxc/include/mach/mx6.h
index bb4423e20063..aaf8b998ca63 100644
--- a/arch/arm/plat-mxc/include/mach/mx6.h
+++ b/arch/arm/plat-mxc/include/mach/mx6.h
@@ -308,7 +308,7 @@
(((((x) >= (unsigned long)AIPS1_ARB_BASE_ADDR) && \
((x) <= (unsigned long)AIPS2_ARB_END_ADDR)) || \
((x) >= (unsigned long)ARM_PERIPHBASE && \
- ((x) <= (unsigned long)(ARM_PERIPHBASE + ARM_PERIPHBASE)))) ? \
+ ((x) <= (unsigned long)(ARM_PERIPHBASE + ARM_PERIPHBASE_SIZE)))) ? \
MX6_IO_ADDRESS(x) : (void __force __iomem *)0xDEADBEEF)
/*
@@ -322,7 +322,7 @@
#define MX6DL_INT_MSHC 35
#define MXC_INT_INTERRUPT_36_NUM 36
#define MX6Q_INT_IPU1_ERR 37
-#define MX6DL_INT_RNGB 37
+#define MX6SL_INT_RNGB 37
#define MX6Q_INT_IPU1_SYN 38
#define MX6SL_INT_SPDC 38
#define MX6Q_INT_IPU2_ERR 39
@@ -415,8 +415,8 @@
#define MXC_INT_GPIO6_INT31_16_NUM 109
#define MXC_INT_GPIO7_INT15_0_NUM 110
#define MXC_INT_GPIO7_INT31_16_NUM 111
-#define MXC_INT_WDOG1 112
-#define MXC_INT_WDOG2 113
+#define MX6Q_INT_WDOG1 112
+#define MX6Q_INT_WDOG2 113
#define MXC_INT_KPP 114
#define MX6SL_INT_KPP 114
#define MX6Q_INT_PWM1 115
@@ -436,9 +436,9 @@
#define MX6DL_INT_EPDC 129
#define MX6DL_INT_EPXP 130
#define MXC_INT_INTERRUPT_131_NUM 131
-#define MX6DL_INT_DCP_GEN 131
-#define MX6DL_INT_DCP_CH0 132
-#define MX6DL_INT_DCP_SEC 133
+#define MX6SL_INT_DCP_GEN 131
+#define MX6SL_INT_DCP_CH0 132
+#define MX6SL_INT_DCP_SEC 133
#define MXC_INT_CSI_INTR1 132
#define MXC_INT_CSI_INTR2 133
#define MXC_INT_DSI 134
diff --git a/arch/arm/plat-mxc/include/mach/mxc_edid.h b/arch/arm/plat-mxc/include/mach/mxc_edid.h
index 7385c2710db8..38bad6b7a67e 100755
--- a/arch/arm/plat-mxc/include/mach/mxc_edid.h
+++ b/arch/arm/plat-mxc/include/mach/mxc_edid.h
@@ -51,6 +51,13 @@ enum cea_audio_coding_types {
AUDIO_CODING_TYPE_RESERVED = 15,
};
+struct mxc_hdmi_3d_format {
+ unsigned char vic_order_2d;
+ unsigned char struct_3d;
+ unsigned char detail_3d;
+ unsigned char reserved;
+};
+
struct mxc_edid_cfg {
bool cea_underscan;
bool cea_basicaudio;
@@ -59,12 +66,30 @@ struct mxc_edid_cfg {
bool hdmi_cap;
/*VSD*/
+ bool vsd_support_ai;
bool vsd_dc_48bit;
bool vsd_dc_36bit;
bool vsd_dc_30bit;
bool vsd_dc_y444;
bool vsd_dvi_dual;
+ bool vsd_cnc0;
+ bool vsd_cnc1;
+ bool vsd_cnc2;
+ bool vsd_cnc3;
+
+ u8 vsd_video_latency;
+ u8 vsd_audio_latency;
+ u8 vsd_I_video_latency;
+ u8 vsd_I_audio_latency;
+
+ u8 physical_address[4];
+ u8 hdmi_vic[64];
+ struct mxc_hdmi_3d_format hdmi_3d_format[64];
+ u16 hdmi_3d_mask_all;
+ u16 hdmi_3d_struct_all;
+ u32 vsd_max_tmdsclk_rate;
+
u8 max_channels;
u8 sample_sizes;
u8 sample_rates;
@@ -75,5 +100,6 @@ int mxc_edid_var_to_vic(struct fb_var_screeninfo *var);
int mxc_edid_mode_to_vic(const struct fb_videomode *mode);
int mxc_edid_read(struct i2c_adapter *adp, unsigned short addr,
unsigned char *edid, struct mxc_edid_cfg *cfg, struct fb_info *fbi);
-
+int mxc_edid_parse_ext_blk(unsigned char *edid, struct mxc_edid_cfg *cfg,
+ struct fb_monspecs *specs);
#endif
diff --git a/arch/arm/plat-mxc/include/mach/mxc_hdmi.h b/arch/arm/plat-mxc/include/mach/mxc_hdmi.h
index bc1ed6c48ecd..60946cadc441 100644
--- a/arch/arm/plat-mxc/include/mach/mxc_hdmi.h
+++ b/arch/arm/plat-mxc/include/mach/mxc_hdmi.h
@@ -538,7 +538,7 @@
/* I2C Master Registers (E-DDC) */
#define HDMI_I2CM_SLAVE 0x7E00
-#define HDMI_I2CMESS 0x7E01
+#define HDMI_I2CM_ADDRESS 0x7E01
#define HDMI_I2CM_DATAO 0x7E02
#define HDMI_I2CM_DATAI 0x7E03
#define HDMI_I2CM_OPERATION 0x7E04
@@ -583,6 +583,16 @@ enum {
HDMI_IH_PHY_STAT0_TX_PHY_LOCK = 0x2,
HDMI_IH_PHY_STAT0_HPD = 0x1,
+/* IH_CEC_STAT0 field values */
+ HDMI_IH_CEC_STAT0_WAKEUP = 0x40,
+ HDMI_IH_CEC_STAT0_ERROR_FOLL = 0x20,
+ HDMI_IH_CEC_STAT0_ERROR_INIT = 0x10,
+ HDMI_IH_CEC_STAT0_ARB_LOST = 0x8,
+ HDMI_IH_CEC_STAT0_NACK = 0x4,
+ HDMI_IH_CEC_STAT0_EOM = 0x2,
+ HDMI_IH_CEC_STAT0_DONE = 0x1,
+
+
/* IH_MUTE_I2CMPHY_STAT0 field values */
HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYDONE = 0x2,
HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYERROR = 0x1,
@@ -1056,6 +1066,23 @@ enum {
HDMI_A_VIDPOLCFG_HSYNCPOL_MASK = 0x2,
HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_HIGH = 0x2,
HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_LOW = 0x0,
+
+
+/* I2CM_OPERATION field values */
+ HDMI_I2CM_OPERATION_WRITE = 0x10,
+ HDMI_I2CM_OPERATION_READ_EXT = 0x2,
+ HDMI_I2CM_OPERATION_READ = 0x1,
+
+/* HDMI_I2CM_INT */
+ HDMI_I2CM_INT_DONE_POL = 0x08,
+ HDMI_I2CM_INT_DONE_MASK = 0x04,
+
+/* HDMI_I2CM_CTLINT */
+ HDMI_I2CM_CTLINT_NAC_POL = 0x80,
+ HDMI_I2CM_CTLINT_NAC_MASK = 0x40,
+ HDMI_I2CM_CTLINT_ARBITRATION_POL = 0x08,
+ HDMI_I2CM_CTLINT_ARBITRATION_MASK = 0x04,
+
};
#endif /* __MXC_HDMI_H__ */
diff --git a/arch/arm/plat-mxc/pwm.c b/arch/arm/plat-mxc/pwm.c
index 4a67f4de0e4d..c663acf65c3f 100755
--- a/arch/arm/plat-mxc/pwm.c
+++ b/arch/arm/plat-mxc/pwm.c
@@ -34,6 +34,9 @@
#define MX3_PWMSAR 0x0C /* PWM Sample Register */
#define MX3_PWMPR 0x10 /* PWM Period Register */
#define MX3_PWMCR_PRESCALER(x) (((x - 1) & 0xFFF) << 4)
+#define MX3_PWMCR_DOZEEN (1 << 24)
+#define MX3_PWMCR_WAITEN (1 << 23)
+#define MX3_PWMCR_DBGEN (1 << 22)
#define MX3_PWMCR_CLKSRC_IPG_HIGH (2 << 16)
#define MX3_PWMCR_CLKSRC_IPG (1 << 16)
#define MX3_PWMCR_EN (1 << 0)
@@ -91,6 +94,15 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
do_div(c, period_ns);
duty_cycles = c;
+ /*
+ * according to imx pwm RM, the real period value should be
+ * PERIOD value in PWMPR plus 2.
+ */
+ if (period_cycles > 2)
+ period_cycles -= 2;
+ else
+ period_cycles = 0;
+
writel(duty_cycles, pwm->mmio_base + MX3_PWMSAR);
writel(period_cycles, pwm->mmio_base + MX3_PWMPR);
diff --git a/arch/arm/plat-mxc/system.c b/arch/arm/plat-mxc/system.c
index 5a022321802f..d2a999bdcf5b 100644
--- a/arch/arm/plat-mxc/system.c
+++ b/arch/arm/plat-mxc/system.c
@@ -34,6 +34,7 @@
static void __iomem *wdog_base;
+
static void arch_reset_special_mode(char mode, const char *cmd)
{
if (strcmp(cmd, "download") == 0)
diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
index 9e5451b3c8e3..11dce87c2487 100644
--- a/arch/arm/plat-orion/common.c
+++ b/arch/arm/plat-orion/common.c
@@ -806,10 +806,7 @@ void __init orion_xor1_init(unsigned long mapbase_low,
/*****************************************************************************
* EHCI
****************************************************************************/
-static struct orion_ehci_data orion_ehci_data = {
- .phy_version = EHCI_PHY_NA,
-};
-
+static struct orion_ehci_data orion_ehci_data;
static u64 ehci_dmamask = DMA_BIT_MASK(32);
@@ -830,9 +827,11 @@ static struct platform_device orion_ehci = {
void __init orion_ehci_init(struct mbus_dram_target_info *mbus_dram_info,
unsigned long mapbase,
- unsigned long irq)
+ unsigned long irq,
+ enum orion_ehci_phy_ver phy_version)
{
orion_ehci_data.dram = mbus_dram_info;
+ orion_ehci_data.phy_version = phy_version;
fill_resources(&orion_ehci, orion_ehci_resources, mapbase, SZ_4K - 1,
irq);
diff --git a/arch/arm/plat-orion/include/plat/common.h b/arch/arm/plat-orion/include/plat/common.h
index a63c357e2ab1..a2c0e31ce0dc 100644
--- a/arch/arm/plat-orion/include/plat/common.h
+++ b/arch/arm/plat-orion/include/plat/common.h
@@ -95,7 +95,8 @@ void __init orion_xor1_init(unsigned long mapbase_low,
void __init orion_ehci_init(struct mbus_dram_target_info *mbus_dram_info,
unsigned long mapbase,
- unsigned long irq);
+ unsigned long irq,
+ enum orion_ehci_phy_ver phy_version);
void __init orion_ehci_1_init(struct mbus_dram_target_info *mbus_dram_info,
unsigned long mapbase,
diff --git a/arch/arm/plat-orion/mpp.c b/arch/arm/plat-orion/mpp.c
index 91553432711d..3b1e17bd3d17 100644
--- a/arch/arm/plat-orion/mpp.c
+++ b/arch/arm/plat-orion/mpp.c
@@ -64,8 +64,7 @@ void __init orion_mpp_conf(unsigned int *mpp_list, unsigned int variant_mask,
gpio_mode |= GPIO_INPUT_OK;
if (*mpp_list & MPP_OUTPUT_MASK)
gpio_mode |= GPIO_OUTPUT_OK;
- if (sel != 0)
- gpio_mode = 0;
+
orion_gpio_set_valid(num, gpio_mode);
}
diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c
index 539bd0e3defd..0719f49defb2 100644
--- a/arch/arm/plat-s3c24xx/dma.c
+++ b/arch/arm/plat-s3c24xx/dma.c
@@ -1249,7 +1249,7 @@ static void s3c2410_dma_resume(void)
struct s3c2410_dma_chan *cp = s3c2410_chans + dma_channels - 1;
int channel;
- for (channel = dma_channels - 1; channel >= 0; cp++, channel--)
+ for (channel = dma_channels - 1; channel >= 0; cp--, channel--)
s3c2410_dma_resume_chan(cp);
}
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig
index e9d689b7c833..c614484f0fca 100644
--- a/arch/avr32/Kconfig
+++ b/arch/avr32/Kconfig
@@ -8,6 +8,7 @@ config AVR32
select HAVE_KPROBES
select HAVE_GENERIC_HARDIRQS
select GENERIC_IRQ_PROBE
+ select GENERIC_ATOMIC64
select HARDIRQS_SW_RESEND
select GENERIC_IRQ_SHOW
help
diff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h
index 8428525ddb22..21ab376465d5 100644
--- a/arch/ia64/include/asm/futex.h
+++ b/arch/ia64/include/asm/futex.h
@@ -107,15 +107,16 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
return -EFAULT;
{
- register unsigned long r8 __asm ("r8") = 0;
+ register unsigned long r8 __asm ("r8");
unsigned long prev;
__asm__ __volatile__(
" mf;; \n"
- " mov ar.ccv=%3;; \n"
- "[1:] cmpxchg4.acq %0=[%1],%2,ar.ccv \n"
+ " mov %0=r0 \n"
+ " mov ar.ccv=%4;; \n"
+ "[1:] cmpxchg4.acq %1=[%2],%3,ar.ccv \n"
" .xdata4 \"__ex_table\", 1b-., 2f-. \n"
"[2:]"
- : "=r" (prev)
+ : "=r" (r8), "=r" (prev)
: "r" (uaddr), "r" (newval),
"rO" ((long) (unsigned) oldval)
: "memory");
diff --git a/arch/ia64/include/asm/unistd.h b/arch/ia64/include/asm/unistd.h
index 7c928da35b17..d8de1825b736 100644
--- a/arch/ia64/include/asm/unistd.h
+++ b/arch/ia64/include/asm/unistd.h
@@ -321,11 +321,12 @@
#define __NR_syncfs 1329
#define __NR_setns 1330
#define __NR_sendmmsg 1331
+#define __NR_accept4 1334
#ifdef __KERNEL__
-#define NR_syscalls 308 /* length of syscall table */
+#define NR_syscalls 311 /* length of syscall table */
/*
* The following defines stop scripts/checksyscalls.sh from complaining about
diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c
index 3be485a300b1..f19de9f7f5f5 100644
--- a/arch/ia64/kernel/acpi.c
+++ b/arch/ia64/kernel/acpi.c
@@ -429,22 +429,24 @@ static u32 __devinitdata pxm_flag[PXM_FLAG_LEN];
static struct acpi_table_slit __initdata *slit_table;
cpumask_t early_cpu_possible_map = CPU_MASK_NONE;
-static int get_processor_proximity_domain(struct acpi_srat_cpu_affinity *pa)
+static int __init
+get_processor_proximity_domain(struct acpi_srat_cpu_affinity *pa)
{
int pxm;
pxm = pa->proximity_domain_lo;
- if (ia64_platform_is("sn2"))
+ if (ia64_platform_is("sn2") || acpi_srat_revision >= 2)
pxm += pa->proximity_domain_hi[0] << 8;
return pxm;
}
-static int get_memory_proximity_domain(struct acpi_srat_mem_affinity *ma)
+static int __init
+get_memory_proximity_domain(struct acpi_srat_mem_affinity *ma)
{
int pxm;
pxm = ma->proximity_domain;
- if (!ia64_platform_is("sn2"))
+ if (!ia64_platform_is("sn2") && acpi_srat_revision <= 1)
pxm &= 0xff;
return pxm;
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index 97dd2abdeb1a..df477f8c9d82 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1777,6 +1777,9 @@ sys_call_table:
data8 sys_syncfs
data8 sys_setns // 1330
data8 sys_sendmmsg
+ data8 sys_ni_syscall /* process_vm_readv */
+ data8 sys_ni_syscall /* process_vm_writev */
+ data8 sys_accept4
.org sys_call_table + 8*NR_syscalls // guard against failures to increase NR_syscalls
#endif /* __IA64_ASM_PARAVIRTUALIZED_NATIVE */
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index c247de02bc7e..1918d76aa06b 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -950,6 +950,9 @@ int __init mac_platform_init(void)
{
u8 *swim_base;
+ if (!MACH_IS_MAC)
+ return -ENODEV;
+
/*
* Serial devices
*/
diff --git a/arch/parisc/include/asm/prefetch.h b/arch/parisc/include/asm/prefetch.h
index c5edc60c059f..1ee7c82672c1 100644
--- a/arch/parisc/include/asm/prefetch.h
+++ b/arch/parisc/include/asm/prefetch.h
@@ -21,7 +21,12 @@
#define ARCH_HAS_PREFETCH
static inline void prefetch(const void *addr)
{
- __asm__("ldw 0(%0), %%r0" : : "r" (addr));
+ __asm__(
+#ifndef CONFIG_PA20
+ /* Need to avoid prefetch of NULL on PA7300LC */
+ " extrw,u,= %0,31,32,%%r0\n"
+#endif
+ " ldw 0(%0), %%r0" : : "r" (addr));
}
/* LDD is a PA2.0 addition. */
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index 6f0594439143..07ef351edd57 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -552,7 +552,7 @@
* entry (identifying the physical page) and %r23 up with
* the from tlb entry (or nothing if only a to entry---for
* clear_user_page_asm) */
- .macro do_alias spc,tmp,tmp1,va,pte,prot,fault
+ .macro do_alias spc,tmp,tmp1,va,pte,prot,fault,patype
cmpib,COND(<>),n 0,\spc,\fault
ldil L%(TMPALIAS_MAP_START),\tmp
#if defined(CONFIG_64BIT) && (TMPALIAS_MAP_START >= 0x80000000)
@@ -581,7 +581,15 @@
*/
cmpiclr,= 0x01,\tmp,%r0
ldi (_PAGE_DIRTY|_PAGE_READ|_PAGE_WRITE),\prot
+.ifc \patype,20
depd,z \prot,8,7,\prot
+.else
+.ifc \patype,11
+ depw,z \prot,8,7,\prot
+.else
+ .error "undefined PA type to do_alias"
+.endif
+.endif
/*
* OK, it is in the temp alias region, check whether "from" or "to".
* Check "subtle" note in pacache.S re: r23/r26.
@@ -1185,7 +1193,7 @@ dtlb_miss_20w:
nop
dtlb_check_alias_20w:
- do_alias spc,t0,t1,va,pte,prot,dtlb_fault
+ do_alias spc,t0,t1,va,pte,prot,dtlb_fault,20
idtlbt pte,prot
@@ -1209,7 +1217,7 @@ nadtlb_miss_20w:
nop
nadtlb_check_alias_20w:
- do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate
+ do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate,20
idtlbt pte,prot
@@ -1241,7 +1249,7 @@ dtlb_miss_11:
nop
dtlb_check_alias_11:
- do_alias spc,t0,t1,va,pte,prot,dtlb_fault
+ do_alias spc,t0,t1,va,pte,prot,dtlb_fault,11
idtlba pte,(va)
idtlbp prot,(va)
@@ -1273,7 +1281,7 @@ nadtlb_miss_11:
nop
nadtlb_check_alias_11:
- do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate
+ do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate,11
idtlba pte,(va)
idtlbp prot,(va)
@@ -1300,7 +1308,7 @@ dtlb_miss_20:
nop
dtlb_check_alias_20:
- do_alias spc,t0,t1,va,pte,prot,dtlb_fault
+ do_alias spc,t0,t1,va,pte,prot,dtlb_fault,20
idtlbt pte,prot
@@ -1326,7 +1334,7 @@ nadtlb_miss_20:
nop
nadtlb_check_alias_20:
- do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate
+ do_alias spc,t0,t1,va,pte,prot,nadtlb_emulate,20
idtlbt pte,prot
@@ -1453,7 +1461,7 @@ naitlb_miss_20w:
nop
naitlb_check_alias_20w:
- do_alias spc,t0,t1,va,pte,prot,naitlb_fault
+ do_alias spc,t0,t1,va,pte,prot,naitlb_fault,20
iitlbt pte,prot
@@ -1507,7 +1515,7 @@ naitlb_miss_11:
nop
naitlb_check_alias_11:
- do_alias spc,t0,t1,va,pte,prot,itlb_fault
+ do_alias spc,t0,t1,va,pte,prot,itlb_fault,11
iitlba pte,(%sr0, va)
iitlbp prot,(%sr0, va)
@@ -1553,7 +1561,7 @@ naitlb_miss_20:
nop
naitlb_check_alias_20:
- do_alias spc,t0,t1,va,pte,prot,naitlb_fault
+ do_alias spc,t0,t1,va,pte,prot,naitlb_fault,20
iitlbt pte,prot
diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S
index 93ff3d90edd1..5d7218ad885c 100644
--- a/arch/parisc/kernel/pacache.S
+++ b/arch/parisc/kernel/pacache.S
@@ -692,7 +692,7 @@ ENTRY(flush_icache_page_asm)
/* Purge any old translation */
- pitlb (%sr0,%r28)
+ pitlb (%sr4,%r28)
ldil L%icache_stride, %r1
ldw R%icache_stride(%r1), %r1
@@ -706,27 +706,29 @@ ENTRY(flush_icache_page_asm)
sub %r25, %r1, %r25
-1: fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
- fic,m %r1(%r28)
+ /* fic only has the type 26 form on PA1.1, requiring an
+ * explicit space specification, so use %sr4 */
+1: fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
+ fic,m %r1(%sr4,%r28)
cmpb,COND(<<) %r28, %r25,1b
- fic,m %r1(%r28)
+ fic,m %r1(%sr4,%r28)
sync
bv %r0(%r2)
- pitlb (%sr0,%r25)
+ pitlb (%sr4,%r25)
.exit
.procend
diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
index fa6f2b8163e0..64a999882e4f 100644
--- a/arch/parisc/kernel/vmlinux.lds.S
+++ b/arch/parisc/kernel/vmlinux.lds.S
@@ -50,8 +50,10 @@ SECTIONS
. = KERNEL_BINARY_TEXT_START;
_text = .; /* Text and read-only data */
- .text ALIGN(16) : {
+ .head ALIGN(16) : {
HEAD_TEXT
+ } = 0
+ .text ALIGN(16) : {
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
@@ -65,7 +67,7 @@ SECTIONS
*(.fixup)
*(.lock.text) /* out-of-line lock text */
*(.gnu.warning)
- } = 0
+ }
/* End of text section */
_etext = .;
diff --git a/arch/powerpc/include/asm/time.h b/arch/powerpc/include/asm/time.h
index fe6f7c2c9c68..bc3c745cb906 100644
--- a/arch/powerpc/include/asm/time.h
+++ b/arch/powerpc/include/asm/time.h
@@ -219,5 +219,7 @@ DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array);
extern void secondary_cpu_time_init(void);
extern void iSeries_time_init_early(void);
+extern void decrementer_check_overflow(void);
+
#endif /* __KERNEL__ */
#endif /* __POWERPC_TIME_H */
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index 5b428e308666..ca2987d939f5 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -170,16 +170,13 @@ notrace void arch_local_irq_restore(unsigned long en)
*/
local_paca->hard_enabled = en;
-#ifndef CONFIG_BOOKE
- /* On server, re-trigger the decrementer if it went negative since
- * some processors only trigger on edge transitions of the sign bit.
- *
- * BookE has a level sensitive decrementer (latches in TSR) so we
- * don't need that
+ /*
+ * Trigger the decrementer if we have a pending event. Some processors
+ * only trigger on edge transitions of the sign bit. We might also
+ * have disabled interrupts long enough that the decrementer wrapped
+ * to positive.
*/
- if ((int)mfspr(SPRN_DEC) < 0)
- mtspr(SPRN_DEC, 1);
-#endif /* CONFIG_BOOKE */
+ decrementer_check_overflow();
/*
* Force the delivery of pending soft-disabled interrupts on PS3.
diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c
index f832773fc28e..449a7e053e67 100644
--- a/arch/powerpc/kernel/module_32.c
+++ b/arch/powerpc/kernel/module_32.c
@@ -187,8 +187,8 @@ int apply_relocate(Elf32_Shdr *sechdrs,
static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val)
{
- if (entry->jump[0] == 0x3d600000 + ((val + 0x8000) >> 16)
- && entry->jump[1] == 0x396b0000 + (val & 0xffff))
+ if (entry->jump[0] == 0x3d800000 + ((val + 0x8000) >> 16)
+ && entry->jump[1] == 0x398c0000 + (val & 0xffff))
return 1;
return 0;
}
@@ -215,10 +215,9 @@ static uint32_t do_plt_call(void *location,
entry++;
}
- /* Stolen from Paul Mackerras as well... */
- entry->jump[0] = 0x3d600000+((val+0x8000)>>16); /* lis r11,sym@ha */
- entry->jump[1] = 0x396b0000 + (val&0xffff); /* addi r11,r11,sym@l*/
- entry->jump[2] = 0x7d6903a6; /* mtctr r11 */
+ entry->jump[0] = 0x3d800000+((val+0x8000)>>16); /* lis r12,sym@ha */
+ entry->jump[1] = 0x398c0000 + (val&0xffff); /* addi r12,r12,sym@l*/
+ entry->jump[2] = 0x7d8903a6; /* mtctr r12 */
entry->jump[3] = 0x4e800420; /* bctr */
DEBUGP("Initialized plt for 0x%x at %p\n", val, entry);
diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c
index 822f63008ae1..5793c4ba5a03 100644
--- a/arch/powerpc/kernel/perf_event.c
+++ b/arch/powerpc/kernel/perf_event.c
@@ -865,6 +865,7 @@ static void power_pmu_start(struct perf_event *event, int ef_flags)
{
unsigned long flags;
s64 left;
+ unsigned long val;
if (!event->hw.idx || !event->hw.sample_period)
return;
@@ -880,7 +881,12 @@ static void power_pmu_start(struct perf_event *event, int ef_flags)
event->hw.state = 0;
left = local64_read(&event->hw.period_left);
- write_pmc(event->hw.idx, left);
+
+ val = 0;
+ if (left < 0x80000000L)
+ val = 0x80000000L - left;
+
+ write_pmc(event->hw.idx, val);
perf_event_update_userpage(event);
perf_pmu_enable(event->pmu);
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 03b29a6759ab..2de304af07ab 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -889,6 +889,15 @@ static void __init clocksource_init(void)
clock->name, clock->mult, clock->shift);
}
+void decrementer_check_overflow(void)
+{
+ u64 now = get_tb_or_rtc();
+ struct decrementer_clock *decrementer = &__get_cpu_var(decrementers);
+
+ if (now >= decrementer->next_tb)
+ set_dec(1);
+}
+
static int decrementer_set_next_event(unsigned long evt,
struct clock_event_device *dev)
{
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index db092d7c4c5b..53a6be7ebe3c 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -414,7 +414,7 @@ static struct irqaction psurge_irqaction = {
static void __init smp_psurge_setup_cpu(int cpu_nr)
{
- if (cpu_nr != 0)
+ if (cpu_nr != 0 || !psurge_start)
return;
/* reset the entry point so if we get another intr we won't
diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c
index f106662f4381..c9311cfdfcac 100644
--- a/arch/powerpc/platforms/pseries/hvCall_inst.c
+++ b/arch/powerpc/platforms/pseries/hvCall_inst.c
@@ -109,7 +109,7 @@ static void probe_hcall_entry(void *ignored, unsigned long opcode, unsigned long
if (opcode > MAX_HCALL_OPCODE)
return;
- h = &get_cpu_var(hcall_stats)[opcode / 4];
+ h = &__get_cpu_var(hcall_stats)[opcode / 4];
h->tb_start = mftb();
h->purr_start = mfspr(SPRN_PURR);
}
@@ -126,8 +126,6 @@ static void probe_hcall_exit(void *ignored, unsigned long opcode, unsigned long
h->num_calls++;
h->tb_total += mftb() - h->tb_start;
h->purr_total += mfspr(SPRN_PURR) - h->purr_start;
-
- put_cpu_var(hcall_stats);
}
static int __init hcall_inst_init(void)
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c
index ed96b3765377..81e30d96f83f 100644
--- a/arch/powerpc/platforms/pseries/lpar.c
+++ b/arch/powerpc/platforms/pseries/lpar.c
@@ -745,6 +745,7 @@ void __trace_hcall_entry(unsigned long opcode, unsigned long *args)
goto out;
(*depth)++;
+ preempt_disable();
trace_hcall_entry(opcode, args);
(*depth)--;
@@ -767,6 +768,7 @@ void __trace_hcall_exit(long opcode, unsigned long retval,
(*depth)++;
trace_hcall_exit(opcode, retval, retbuf);
+ preempt_enable();
(*depth)--;
out:
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index c03fef7a9c22..c395f713ce31 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -89,7 +89,6 @@ config S390
select HAVE_GET_USER_PAGES_FAST
select HAVE_ARCH_MUTEX_CPU_RELAX
select HAVE_ARCH_JUMP_LABEL if !MARCH_G5
- select HAVE_RCU_TABLE_FREE if SMP
select ARCH_INLINE_SPIN_TRYLOCK
select ARCH_INLINE_SPIN_TRYLOCK_BH
select ARCH_INLINE_SPIN_LOCK
@@ -228,6 +227,9 @@ config COMPAT
config SYSVIPC_COMPAT
def_bool y if COMPAT && SYSVIPC
+config KEYS_COMPAT
+ def_bool y if COMPAT && KEYS
+
config AUDIT_ARCH
def_bool y
diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h
index da359ca6fe55..f7b74bcce10c 100644
--- a/arch/s390/include/asm/compat.h
+++ b/arch/s390/include/asm/compat.h
@@ -172,13 +172,6 @@ static inline int is_compat_task(void)
return is_32bit_task();
}
-#else
-
-static inline int is_compat_task(void)
-{
- return 0;
-}
-
#endif
static inline void __user *arch_compat_alloc_user_space(long len)
diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h
index 38e71ebcd3c2..e4b6609fe92a 100644
--- a/arch/s390/include/asm/pgalloc.h
+++ b/arch/s390/include/asm/pgalloc.h
@@ -22,10 +22,7 @@ void crst_table_free(struct mm_struct *, unsigned long *);
unsigned long *page_table_alloc(struct mm_struct *);
void page_table_free(struct mm_struct *, unsigned long *);
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
void page_table_free_rcu(struct mmu_gather *, unsigned long *);
-void __tlb_remove_table(void *_table);
-#endif
static inline void clear_table(unsigned long *s, unsigned long val, size_t n)
{
diff --git a/arch/s390/include/asm/tlb.h b/arch/s390/include/asm/tlb.h
index c687a2c83462..775a5eea8f9e 100644
--- a/arch/s390/include/asm/tlb.h
+++ b/arch/s390/include/asm/tlb.h
@@ -30,14 +30,10 @@
struct mmu_gather {
struct mm_struct *mm;
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
struct mmu_table_batch *batch;
-#endif
unsigned int fullmm;
- unsigned int need_flush;
};
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
struct mmu_table_batch {
struct rcu_head rcu;
unsigned int nr;
@@ -49,7 +45,6 @@ struct mmu_table_batch {
extern void tlb_table_flush(struct mmu_gather *tlb);
extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
-#endif
static inline void tlb_gather_mmu(struct mmu_gather *tlb,
struct mm_struct *mm,
@@ -57,29 +52,20 @@ static inline void tlb_gather_mmu(struct mmu_gather *tlb,
{
tlb->mm = mm;
tlb->fullmm = full_mm_flush;
- tlb->need_flush = 0;
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
tlb->batch = NULL;
-#endif
if (tlb->fullmm)
__tlb_flush_mm(mm);
}
static inline void tlb_flush_mmu(struct mmu_gather *tlb)
{
- if (!tlb->need_flush)
- return;
- tlb->need_flush = 0;
- __tlb_flush_mm(tlb->mm);
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
tlb_table_flush(tlb);
-#endif
}
static inline void tlb_finish_mmu(struct mmu_gather *tlb,
unsigned long start, unsigned long end)
{
- tlb_flush_mmu(tlb);
+ tlb_table_flush(tlb);
}
/*
@@ -105,10 +91,8 @@ static inline void tlb_remove_page(struct mmu_gather *tlb, struct page *page)
static inline void pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
unsigned long address)
{
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
if (!tlb->fullmm)
return page_table_free_rcu(tlb, (unsigned long *) pte);
-#endif
page_table_free(tlb->mm, (unsigned long *) pte);
}
@@ -125,10 +109,8 @@ static inline void pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd,
#ifdef __s390x__
if (tlb->mm->context.asce_limit <= (1UL << 31))
return;
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
if (!tlb->fullmm)
return tlb_remove_table(tlb, pmd);
-#endif
crst_table_free(tlb->mm, (unsigned long *) pmd);
#endif
}
@@ -146,10 +128,8 @@ static inline void pud_free_tlb(struct mmu_gather *tlb, pud_t *pud,
#ifdef __s390x__
if (tlb->mm->context.asce_limit <= (1UL << 42))
return;
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
if (!tlb->fullmm)
return tlb_remove_table(tlb, pud);
-#endif
crst_table_free(tlb->mm, (unsigned long *) pud);
#endif
}
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 541a7509faeb..abdc2b1063ed 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -28,7 +28,6 @@
#include <asm/irq.h>
#include <asm/timer.h>
#include <asm/nmi.h>
-#include <asm/compat.h>
#include <asm/smp.h>
#include "entry.h"
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c
index 5804cfa7cba7..5c55466e78e6 100644
--- a/arch/s390/kernel/ptrace.c
+++ b/arch/s390/kernel/ptrace.c
@@ -20,8 +20,8 @@
#include <linux/regset.h>
#include <linux/tracehook.h>
#include <linux/seccomp.h>
+#include <linux/compat.h>
#include <trace/syscall.h>
-#include <asm/compat.h>
#include <asm/segment.h>
#include <asm/page.h>
#include <asm/pgtable.h>
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 0c35dee10b00..0260051c08f2 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -42,6 +42,7 @@
#include <linux/reboot.h>
#include <linux/topology.h>
#include <linux/ftrace.h>
+#include <linux/compat.h>
#include <asm/ipl.h>
#include <asm/uaccess.h>
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index fe103e891e7a..6903d441068e 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -36,7 +36,6 @@
#include <asm/pgtable.h>
#include <asm/irq.h>
#include <asm/mmu_context.h>
-#include <asm/compat.h>
#include "../kernel/entry.h"
#ifndef CONFIG_64BIT
@@ -568,6 +567,7 @@ static void pfault_interrupt(unsigned int ext_int_code,
tsk->thread.pfault_wait = 0;
list_del(&tsk->thread.list);
wake_up_process(tsk);
+ put_task_struct(tsk);
} else {
/* Completion interrupt was faster than initial
* interrupt. Set pfault_wait to -1 so the initial
@@ -577,14 +577,22 @@ static void pfault_interrupt(unsigned int ext_int_code,
put_task_struct(tsk);
} else {
/* signal bit not set -> a real page is missing. */
- if (tsk->thread.pfault_wait == -1) {
+ if (tsk->thread.pfault_wait == 1) {
+ /* Already on the list with a reference: put to sleep */
+ set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+ set_tsk_need_resched(tsk);
+ } else if (tsk->thread.pfault_wait == -1) {
/* Completion interrupt was faster than the initial
* interrupt (pfault_wait == -1). Set pfault_wait
* back to zero and exit. */
tsk->thread.pfault_wait = 0;
} else {
/* Initial interrupt arrived before completion
- * interrupt. Let the task sleep. */
+ * interrupt. Let the task sleep.
+ * An extra task reference is needed since a different
+ * cpu may set the task state to TASK_RUNNING again
+ * before the scheduler is reached. */
+ get_task_struct(tsk);
tsk->thread.pfault_wait = 1;
list_add(&tsk->thread.list, &pfault_list);
set_task_state(tsk, TASK_UNINTERRUPTIBLE);
@@ -609,6 +617,7 @@ static int __cpuinit pfault_cpu_notify(struct notifier_block *self,
list_del(&thread->list);
tsk = container_of(thread, struct task_struct, thread);
wake_up_process(tsk);
+ put_task_struct(tsk);
}
spin_unlock_irq(&pfault_lock);
break;
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c
index c9a9f7f18188..c0cf9ceb3833 100644
--- a/arch/s390/mm/mmap.c
+++ b/arch/s390/mm/mmap.c
@@ -28,8 +28,8 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/random.h>
+#include <linux/compat.h>
#include <asm/pgalloc.h>
-#include <asm/compat.h>
static unsigned long stack_maxrandom_size(void)
{
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 458893f5f6b8..51b80b9d1f6a 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -243,8 +243,6 @@ void page_table_free(struct mm_struct *mm, unsigned long *table)
}
}
-#ifdef CONFIG_HAVE_RCU_TABLE_FREE
-
static void __page_table_free_rcu(void *table, unsigned bit)
{
struct page *page;
@@ -301,7 +299,66 @@ void __tlb_remove_table(void *_table)
free_pages((unsigned long) table, ALLOC_ORDER);
}
-#endif
+static void tlb_remove_table_smp_sync(void *arg)
+{
+ /* Simply deliver the interrupt */
+}
+
+static void tlb_remove_table_one(void *table)
+{
+ /*
+ * This isn't an RCU grace period and hence the page-tables cannot be
+ * assumed to be actually RCU-freed.
+ *
+ * It is however sufficient for software page-table walkers that rely
+ * on IRQ disabling. See the comment near struct mmu_table_batch.
+ */
+ smp_call_function(tlb_remove_table_smp_sync, NULL, 1);
+ __tlb_remove_table(table);
+}
+
+static void tlb_remove_table_rcu(struct rcu_head *head)
+{
+ struct mmu_table_batch *batch;
+ int i;
+
+ batch = container_of(head, struct mmu_table_batch, rcu);
+
+ for (i = 0; i < batch->nr; i++)
+ __tlb_remove_table(batch->tables[i]);
+
+ free_page((unsigned long)batch);
+}
+
+void tlb_table_flush(struct mmu_gather *tlb)
+{
+ struct mmu_table_batch **batch = &tlb->batch;
+
+ if (*batch) {
+ __tlb_flush_mm(tlb->mm);
+ call_rcu_sched(&(*batch)->rcu, tlb_remove_table_rcu);
+ *batch = NULL;
+ }
+}
+
+void tlb_remove_table(struct mmu_gather *tlb, void *table)
+{
+ struct mmu_table_batch **batch = &tlb->batch;
+
+ if (*batch == NULL) {
+ *batch = (struct mmu_table_batch *)
+ __get_free_page(GFP_NOWAIT | __GFP_NOWARN);
+ if (*batch == NULL) {
+ __tlb_flush_mm(tlb->mm);
+ tlb_remove_table_one(table);
+ return;
+ }
+ (*batch)->nr = 0;
+ }
+ (*batch)->tables[(*batch)->nr++] = table;
+ if ((*batch)->nr == MAX_TABLE_BATCH)
+ tlb_table_flush(tlb);
+}
/*
* switch on pgstes for its userspace process (for kvm)
diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c
index 0e358c2cffeb..422110a4385b 100644
--- a/arch/s390/oprofile/init.c
+++ b/arch/s390/oprofile/init.c
@@ -90,7 +90,7 @@ static ssize_t hwsampler_write(struct file *file, char const __user *buf,
return -EINVAL;
retval = oprofilefs_ulong_from_user(&val, buf, count);
- if (retval)
+ if (retval <= 0)
return retval;
if (oprofile_started)
diff --git a/arch/score/kernel/entry.S b/arch/score/kernel/entry.S
index 577abba3fac6..83bb96079c43 100644
--- a/arch/score/kernel/entry.S
+++ b/arch/score/kernel/entry.S
@@ -408,7 +408,7 @@ ENTRY(handle_sys)
sw r9, [r0, PT_EPC]
cmpi.c r27, __NR_syscalls # check syscall number
- bgtu illegal_syscall
+ bgeu illegal_syscall
slli r8, r27, 2 # get syscall routine
la r11, sys_call_table
diff --git a/arch/sh/oprofile/common.c b/arch/sh/oprofile/common.c
index b4c2d2b946dd..e4dd5d5a1115 100644
--- a/arch/sh/oprofile/common.c
+++ b/arch/sh/oprofile/common.c
@@ -49,7 +49,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
return oprofile_perf_init(ops);
}
-void __exit oprofile_arch_exit(void)
+void oprofile_arch_exit(void)
{
oprofile_perf_exit();
kfree(sh_pmu_op_name);
@@ -60,5 +60,5 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
ops->backtrace = sh_backtrace;
return -ENODEV;
}
-void __exit oprofile_arch_exit(void) {}
+void oprofile_arch_exit(void) {}
#endif /* CONFIG_HW_PERF_EVENTS */
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 2e794193cd9b..9e702570001d 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -590,6 +590,9 @@ config SYSVIPC_COMPAT
depends on COMPAT && SYSVIPC
default y
+config KEYS_COMPAT
+ def_bool y if COMPAT && KEYS
+
endmenu
source "net/Kconfig"
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index ad1fb5d969f3..eddcfb36aafb 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -31,7 +31,7 @@ UTS_MACHINE := sparc
#KBUILD_CFLAGS += -g -pipe -fcall-used-g5 -fcall-used-g7
KBUILD_CFLAGS += -m32 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
-KBUILD_AFLAGS += -m32
+KBUILD_AFLAGS += -m32 -Wa,-Av8
#LDFLAGS_vmlinux = -N -Ttext 0xf0004000
# Since 2.5.40, the first stage is left not btfix-ed.
diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h
index 5b31a8e89823..a790cc657476 100644
--- a/arch/sparc/include/asm/pgtable_32.h
+++ b/arch/sparc/include/asm/pgtable_32.h
@@ -431,10 +431,6 @@ extern unsigned long *sparc_valid_addr_bitmap;
#define kern_addr_valid(addr) \
(test_bit(__pa((unsigned long)(addr))>>20, sparc_valid_addr_bitmap))
-extern int io_remap_pfn_range(struct vm_area_struct *vma,
- unsigned long from, unsigned long pfn,
- unsigned long size, pgprot_t prot);
-
/*
* For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
* its high 4 bits. These macros/functions put it there or get it from there.
@@ -443,6 +439,22 @@ extern int io_remap_pfn_range(struct vm_area_struct *vma,
#define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4))
#define GET_PFN(pfn) (pfn & 0x0fffffffUL)
+extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
+ unsigned long, pgprot_t);
+
+static inline int io_remap_pfn_range(struct vm_area_struct *vma,
+ unsigned long from, unsigned long pfn,
+ unsigned long size, pgprot_t prot)
+{
+ unsigned long long offset, space, phys_base;
+
+ offset = ((unsigned long long) GET_PFN(pfn)) << PAGE_SHIFT;
+ space = GET_IOSPACE(pfn);
+ phys_base = offset | (space << 32ULL);
+
+ return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
+}
+
#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
({ \
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 1e03c5a6b4f7..982262804237 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -750,10 +750,6 @@ static inline bool kern_addr_valid(unsigned long addr)
extern int page_in_phys_avail(unsigned long paddr);
-extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
- unsigned long pfn,
- unsigned long size, pgprot_t prot);
-
/*
* For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
* its high 4 bits. These macros/functions put it there or get it from there.
@@ -762,6 +758,22 @@ extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
#define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4))
#define GET_PFN(pfn) (pfn & 0x0fffffffffffffffUL)
+extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
+ unsigned long, pgprot_t);
+
+static inline int io_remap_pfn_range(struct vm_area_struct *vma,
+ unsigned long from, unsigned long pfn,
+ unsigned long size, pgprot_t prot)
+{
+ unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
+ int space = GET_IOSPACE(pfn);
+ unsigned long phys_base;
+
+ phys_base = offset | (((unsigned long) space) << 32UL);
+
+ return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
+}
+
#include <asm-generic/pgtable.h>
/* We provide our own get_unmapped_area to cope with VA holes and
diff --git a/arch/sparc/kernel/central.c b/arch/sparc/kernel/central.c
index 7eef3f741963..f5ddc0bae38d 100644
--- a/arch/sparc/kernel/central.c
+++ b/arch/sparc/kernel/central.c
@@ -268,4 +268,4 @@ static int __init sunfire_init(void)
return 0;
}
-subsys_initcall(sunfire_init);
+fs_initcall(sunfire_init);
diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c
index 7429b47c3aca..dcae702fc1f3 100644
--- a/arch/sparc/kernel/ds.c
+++ b/arch/sparc/kernel/ds.c
@@ -1269,4 +1269,4 @@ static int __init ds_init(void)
return vio_register_driver(&ds_driver);
}
-subsys_initcall(ds_init);
+fs_initcall(ds_init);
diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h
index e27f8ea8656e..0c218e4c0881 100644
--- a/arch/sparc/kernel/entry.h
+++ b/arch/sparc/kernel/entry.h
@@ -42,6 +42,9 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
extern void fpload(unsigned long *fpregs, unsigned long *fsr);
#else /* CONFIG_SPARC32 */
+
+#include <asm/trap_block.h>
+
struct popc_3insn_patch_entry {
unsigned int addr;
unsigned int insns[3];
@@ -57,6 +60,10 @@ extern struct popc_6insn_patch_entry __popc_6insn_patch,
__popc_6insn_patch_end;
extern void __init per_cpu_patch(void);
+extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
+ struct sun4v_1insn_patch_entry *);
+extern void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *,
+ struct sun4v_2insn_patch_entry *);
extern void __init sun4v_patch(void);
extern void __init boot_cpu_id_too_large(int cpu);
extern unsigned int dcache_parity_tl1_occurred;
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c
index 99ba5baa9497..8172c18d844f 100644
--- a/arch/sparc/kernel/module.c
+++ b/arch/sparc/kernel/module.c
@@ -17,6 +17,8 @@
#include <asm/processor.h>
#include <asm/spitfire.h>
+#include "entry.h"
+
#ifdef CONFIG_SPARC64
#include <linux/jump_label.h>
@@ -220,6 +222,29 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
}
#ifdef CONFIG_SPARC64
+static void do_patch_sections(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs)
+{
+ const Elf_Shdr *s, *sun4v_1insn = NULL, *sun4v_2insn = NULL;
+ char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+ for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
+ if (!strcmp(".sun4v_1insn_patch", secstrings + s->sh_name))
+ sun4v_1insn = s;
+ if (!strcmp(".sun4v_2insn_patch", secstrings + s->sh_name))
+ sun4v_2insn = s;
+ }
+
+ if (sun4v_1insn && tlb_type == hypervisor) {
+ void *p = (void *) sun4v_1insn->sh_addr;
+ sun4v_patch_1insn_range(p, p + sun4v_1insn->sh_size);
+ }
+ if (sun4v_2insn && tlb_type == hypervisor) {
+ void *p = (void *) sun4v_2insn->sh_addr;
+ sun4v_patch_2insn_range(p, p + sun4v_2insn->sh_size);
+ }
+}
+
int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *me)
@@ -227,6 +252,8 @@ int module_finalize(const Elf_Ehdr *hdr,
/* make jump label nops */
jump_label_apply_nops(me);
+ do_patch_sections(hdr, sechdrs);
+
/* Cheetah's I-cache is fully coherent. */
if (tlb_type == spitfire) {
unsigned long va;
diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c
index b01a06e9ae4e..9e73c4a37ae9 100644
--- a/arch/sparc/kernel/pci_sun4v.c
+++ b/arch/sparc/kernel/pci_sun4v.c
@@ -848,10 +848,10 @@ static int pci_sun4v_msiq_build_irq(struct pci_pbm_info *pbm,
if (!irq)
return -ENOMEM;
- if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE))
- return -EINVAL;
if (pci_sun4v_msiq_setvalid(pbm->devhandle, msiqid, HV_MSIQ_VALID))
return -EINVAL;
+ if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE))
+ return -EINVAL;
return irq;
}
diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S
index 77f1b95e0806..9171fc238def 100644
--- a/arch/sparc/kernel/rtrap_64.S
+++ b/arch/sparc/kernel/rtrap_64.S
@@ -20,11 +20,6 @@
.text
.align 32
-__handle_softirq:
- call do_softirq
- nop
- ba,a,pt %xcc, __handle_softirq_continue
- nop
__handle_preemption:
call schedule
wrpr %g0, RTRAP_PSTATE, %pstate
@@ -89,9 +84,7 @@ rtrap:
cmp %l1, 0
/* mm/ultra.S:xcall_report_regs KNOWS about this load. */
- bne,pn %icc, __handle_softirq
ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
-__handle_softirq_continue:
rtrap_xcall:
sethi %hi(0xf << 20), %l4
and %l1, %l4, %l4
diff --git a/arch/sparc/kernel/setup_64.c b/arch/sparc/kernel/setup_64.c
index 3c5bb784214f..4e7d3ff0ccb4 100644
--- a/arch/sparc/kernel/setup_64.c
+++ b/arch/sparc/kernel/setup_64.c
@@ -234,40 +234,50 @@ void __init per_cpu_patch(void)
}
}
-void __init sun4v_patch(void)
+void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *start,
+ struct sun4v_1insn_patch_entry *end)
{
- extern void sun4v_hvapi_init(void);
- struct sun4v_1insn_patch_entry *p1;
- struct sun4v_2insn_patch_entry *p2;
-
- if (tlb_type != hypervisor)
- return;
+ while (start < end) {
+ unsigned long addr = start->addr;
- p1 = &__sun4v_1insn_patch;
- while (p1 < &__sun4v_1insn_patch_end) {
- unsigned long addr = p1->addr;
-
- *(unsigned int *) (addr + 0) = p1->insn;
+ *(unsigned int *) (addr + 0) = start->insn;
wmb();
__asm__ __volatile__("flush %0" : : "r" (addr + 0));
- p1++;
+ start++;
}
+}
- p2 = &__sun4v_2insn_patch;
- while (p2 < &__sun4v_2insn_patch_end) {
- unsigned long addr = p2->addr;
+void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
+ struct sun4v_2insn_patch_entry *end)
+{
+ while (start < end) {
+ unsigned long addr = start->addr;
- *(unsigned int *) (addr + 0) = p2->insns[0];
+ *(unsigned int *) (addr + 0) = start->insns[0];
wmb();
__asm__ __volatile__("flush %0" : : "r" (addr + 0));
- *(unsigned int *) (addr + 4) = p2->insns[1];
+ *(unsigned int *) (addr + 4) = start->insns[1];
wmb();
__asm__ __volatile__("flush %0" : : "r" (addr + 4));
- p2++;
+ start++;
}
+}
+
+void __init sun4v_patch(void)
+{
+ extern void sun4v_hvapi_init(void);
+
+ if (tlb_type != hypervisor)
+ return;
+
+ sun4v_patch_1insn_range(&__sun4v_1insn_patch,
+ &__sun4v_1insn_patch_end);
+
+ sun4v_patch_2insn_range(&__sun4v_2insn_patch,
+ &__sun4v_2insn_patch_end);
sun4v_hvapi_init();
}
diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c
index 5d92488fc167..2e58328c30e0 100644
--- a/arch/sparc/kernel/signal32.c
+++ b/arch/sparc/kernel/signal32.c
@@ -829,21 +829,23 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs
* want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake.
*/
-void do_signal32(sigset_t *oldset, struct pt_regs * regs,
- int restart_syscall, unsigned long orig_i0)
+void do_signal32(sigset_t *oldset, struct pt_regs * regs)
{
struct k_sigaction ka;
+ unsigned long orig_i0;
+ int restart_syscall;
siginfo_t info;
int signr;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- /* If the debugger messes with the program counter, it clears
- * the "in syscall" bit, directing us to not perform a syscall
- * restart.
- */
- if (restart_syscall && !pt_regs_is_syscall(regs))
- restart_syscall = 0;
+ restart_syscall = 0;
+ orig_i0 = 0;
+ if (pt_regs_is_syscall(regs) &&
+ (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
+ restart_syscall = 1;
+ orig_i0 = regs->u_regs[UREG_G6];
+ }
if (signr > 0) {
if (restart_syscall)
diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c
index 04ede8f04add..2302567578ba 100644
--- a/arch/sparc/kernel/signal_32.c
+++ b/arch/sparc/kernel/signal_32.c
@@ -525,10 +525,26 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
siginfo_t info;
int signr;
+ /* It's a lot of work and synchronization to add a new ptrace
+ * register for GDB to save and restore in order to get
+ * orig_i0 correct for syscall restarts when debugging.
+ *
+ * Although it should be the case that most of the global
+ * registers are volatile across a system call, glibc already
+ * depends upon that fact that we preserve them. So we can't
+ * just use any global register to save away the orig_i0 value.
+ *
+ * In particular %g2, %g3, %g4, and %g5 are all assumed to be
+ * preserved across a system call trap by various pieces of
+ * code in glibc.
+ *
+ * %g7 is used as the "thread register". %g6 is not used in
+ * any fixed manner. %g6 is used as a scratch register and
+ * a compiler temporary, but it's value is never used across
+ * a system call. Therefore %g6 is usable for orig_i0 storage.
+ */
if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C))
- restart_syscall = 1;
- else
- restart_syscall = 0;
+ regs->u_regs[UREG_G6] = orig_i0;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
@@ -541,8 +557,12 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
* the software "in syscall" bit, directing us to not perform
* a syscall restart.
*/
- if (restart_syscall && !pt_regs_is_syscall(regs))
- restart_syscall = 0;
+ restart_syscall = 0;
+ if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) {
+ restart_syscall = 1;
+ orig_i0 = regs->u_regs[UREG_G6];
+ }
+
if (signr > 0) {
if (restart_syscall)
diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c
index 47509df3b893..d58260bff2df 100644
--- a/arch/sparc/kernel/signal_64.c
+++ b/arch/sparc/kernel/signal_64.c
@@ -535,11 +535,27 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
siginfo_t info;
int signr;
+ /* It's a lot of work and synchronization to add a new ptrace
+ * register for GDB to save and restore in order to get
+ * orig_i0 correct for syscall restarts when debugging.
+ *
+ * Although it should be the case that most of the global
+ * registers are volatile across a system call, glibc already
+ * depends upon that fact that we preserve them. So we can't
+ * just use any global register to save away the orig_i0 value.
+ *
+ * In particular %g2, %g3, %g4, and %g5 are all assumed to be
+ * preserved across a system call trap by various pieces of
+ * code in glibc.
+ *
+ * %g7 is used as the "thread register". %g6 is not used in
+ * any fixed manner. %g6 is used as a scratch register and
+ * a compiler temporary, but it's value is never used across
+ * a system call. Therefore %g6 is usable for orig_i0 storage.
+ */
if (pt_regs_is_syscall(regs) &&
- (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
- restart_syscall = 1;
- } else
- restart_syscall = 0;
+ (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
+ regs->u_regs[UREG_G6] = orig_i0;
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
oldset = &current->saved_sigmask;
@@ -548,22 +564,20 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
#ifdef CONFIG_COMPAT
if (test_thread_flag(TIF_32BIT)) {
- extern void do_signal32(sigset_t *, struct pt_regs *,
- int restart_syscall,
- unsigned long orig_i0);
- do_signal32(oldset, regs, restart_syscall, orig_i0);
+ extern void do_signal32(sigset_t *, struct pt_regs *);
+ do_signal32(oldset, regs);
return;
}
#endif
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
- /* If the debugger messes with the program counter, it clears
- * the software "in syscall" bit, directing us to not perform
- * a syscall restart.
- */
- if (restart_syscall && !pt_regs_is_syscall(regs))
- restart_syscall = 0;
+ restart_syscall = 0;
+ if (pt_regs_is_syscall(regs) &&
+ (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
+ restart_syscall = 1;
+ orig_i0 = regs->u_regs[UREG_G6];
+ }
if (signr > 0) {
if (restart_syscall)
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index f566518483b5..248fb6763362 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -74,7 +74,7 @@ sys_call_table32:
.word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
/*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
.word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
-/*280*/ .word sys32_tee, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat
+/*280*/ .word sys32_tee, sys_add_key, sys_request_key, compat_sys_keyctl, compat_sys_openat
.word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_fstatat64
/*290*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
.word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare
diff --git a/arch/sparc/kernel/visemul.c b/arch/sparc/kernel/visemul.c
index 36357717d691..9384a0cbeba4 100644
--- a/arch/sparc/kernel/visemul.c
+++ b/arch/sparc/kernel/visemul.c
@@ -713,17 +713,17 @@ static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf)
s16 b = (rs2 >> (i * 16)) & 0xffff;
if (a > b)
- rd_val |= 1 << i;
+ rd_val |= 8 >> i;
}
break;
case FCMPGT32_OPF:
for (i = 0; i < 2; i++) {
- s32 a = (rs1 >> (i * 32)) & 0xffff;
- s32 b = (rs2 >> (i * 32)) & 0xffff;
+ s32 a = (rs1 >> (i * 32)) & 0xffffffff;
+ s32 b = (rs2 >> (i * 32)) & 0xffffffff;
if (a > b)
- rd_val |= 1 << i;
+ rd_val |= 2 >> i;
}
break;
@@ -733,17 +733,17 @@ static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf)
s16 b = (rs2 >> (i * 16)) & 0xffff;
if (a <= b)
- rd_val |= 1 << i;
+ rd_val |= 8 >> i;
}
break;
case FCMPLE32_OPF:
for (i = 0; i < 2; i++) {
- s32 a = (rs1 >> (i * 32)) & 0xffff;
- s32 b = (rs2 >> (i * 32)) & 0xffff;
+ s32 a = (rs1 >> (i * 32)) & 0xffffffff;
+ s32 b = (rs2 >> (i * 32)) & 0xffffffff;
if (a <= b)
- rd_val |= 1 << i;
+ rd_val |= 2 >> i;
}
break;
@@ -753,17 +753,17 @@ static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf)
s16 b = (rs2 >> (i * 16)) & 0xffff;
if (a != b)
- rd_val |= 1 << i;
+ rd_val |= 8 >> i;
}
break;
case FCMPNE32_OPF:
for (i = 0; i < 2; i++) {
- s32 a = (rs1 >> (i * 32)) & 0xffff;
- s32 b = (rs2 >> (i * 32)) & 0xffff;
+ s32 a = (rs1 >> (i * 32)) & 0xffffffff;
+ s32 b = (rs2 >> (i * 32)) & 0xffffffff;
if (a != b)
- rd_val |= 1 << i;
+ rd_val |= 2 >> i;
}
break;
@@ -773,17 +773,17 @@ static void pcmp(struct pt_regs *regs, unsigned int insn, unsigned int opf)
s16 b = (rs2 >> (i * 16)) & 0xffff;
if (a == b)
- rd_val |= 1 << i;
+ rd_val |= 8 >> i;
}
break;
case FCMPEQ32_OPF:
for (i = 0; i < 2; i++) {
- s32 a = (rs1 >> (i * 32)) & 0xffff;
- s32 b = (rs2 >> (i * 32)) & 0xffff;
+ s32 a = (rs1 >> (i * 32)) & 0xffffffff;
+ s32 b = (rs2 >> (i * 32)) & 0xffffffff;
if (a == b)
- rd_val |= 1 << i;
+ rd_val |= 2 >> i;
}
break;
}
diff --git a/arch/sparc/lib/memcpy.S b/arch/sparc/lib/memcpy.S
index 34fe65751737..4d8c497517bd 100644
--- a/arch/sparc/lib/memcpy.S
+++ b/arch/sparc/lib/memcpy.S
@@ -7,40 +7,12 @@
* Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/
-#ifdef __KERNEL__
-
-#define FUNC(x) \
+#define FUNC(x) \
.globl x; \
.type x,@function; \
- .align 4; \
+ .align 4; \
x:
-#undef FASTER_REVERSE
-#undef FASTER_NONALIGNED
-#define FASTER_ALIGNED
-
-/* In kernel these functions don't return a value.
- * One should use macros in asm/string.h for that purpose.
- * We return 0, so that bugs are more apparent.
- */
-#define SETUP_RETL
-#define RETL_INSN clr %o0
-
-#else
-
-/* libc */
-
-#include "DEFS.h"
-
-#define FASTER_REVERSE
-#define FASTER_NONALIGNED
-#define FASTER_ALIGNED
-
-#define SETUP_RETL mov %o0, %g6
-#define RETL_INSN mov %g6, %o0
-
-#endif
-
/* Both these macros have to start with exactly the same insn */
#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
ldd [%src + (offset) + 0x00], %t0; \
@@ -164,30 +136,6 @@ x:
.text
.align 4
-#ifdef FASTER_REVERSE
-
-70: /* rdword_align */
-
- andcc %o1, 1, %g0
- be 4f
- andcc %o1, 2, %g0
-
- ldub [%o1 - 1], %g2
- sub %o1, 1, %o1
- stb %g2, [%o0 - 1]
- sub %o2, 1, %o2
- be 3f
- sub %o0, 1, %o0
-4:
- lduh [%o1 - 2], %g2
- sub %o1, 2, %o1
- sth %g2, [%o0 - 2]
- sub %o2, 2, %o2
- b 3f
- sub %o0, 2, %o0
-
-#endif /* FASTER_REVERSE */
-
0:
retl
nop ! Only bcopy returns here and it retuns void...
@@ -198,7 +146,7 @@ FUNC(__memmove)
#endif
FUNC(memmove)
cmp %o0, %o1
- SETUP_RETL
+ mov %o0, %g7
bleu 9f
sub %o0, %o1, %o4
@@ -207,8 +155,6 @@ FUNC(memmove)
bleu 0f
andcc %o4, 3, %o5
-#ifndef FASTER_REVERSE
-
add %o1, %o2, %o1
add %o0, %o2, %o0
sub %o1, 1, %o1
@@ -224,295 +170,7 @@ FUNC(memmove)
sub %o0, 1, %o0
retl
- RETL_INSN
-
-#else /* FASTER_REVERSE */
-
- add %o1, %o2, %o1
- add %o0, %o2, %o0
- bne 77f
- cmp %o2, 15
- bleu 91f
- andcc %o1, 3, %g0
- bne 70b
-3:
- andcc %o1, 4, %g0
-
- be 2f
- mov %o2, %g1
-
- ld [%o1 - 4], %o4
- sub %g1, 4, %g1
- st %o4, [%o0 - 4]
- sub %o1, 4, %o1
- sub %o0, 4, %o0
-2:
- andcc %g1, 0xffffff80, %g7
- be 3f
- andcc %o0, 4, %g0
-
- be 74f + 4
-5:
- RMOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
- RMOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
- RMOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
- RMOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
- subcc %g7, 128, %g7
- sub %o1, 128, %o1
- bne 5b
- sub %o0, 128, %o0
-3:
- andcc %g1, 0x70, %g7
- be 72f
- andcc %g1, 8, %g0
-
- sethi %hi(72f), %o5
- srl %g7, 1, %o4
- add %g7, %o4, %o4
- sub %o1, %g7, %o1
- sub %o5, %o4, %o5
- jmpl %o5 + %lo(72f), %g0
- sub %o0, %g7, %o0
-
-71: /* rmemcpy_table */
- RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
- RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
- RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
- RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5)
- RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5)
- RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
- RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
-
-72: /* rmemcpy_table_end */
-
- be 73f
- andcc %g1, 4, %g0
-
- ldd [%o1 - 0x08], %g2
- sub %o0, 8, %o0
- sub %o1, 8, %o1
- st %g2, [%o0]
- st %g3, [%o0 + 0x04]
-
-73: /* rmemcpy_last7 */
-
- be 1f
- andcc %g1, 2, %g0
-
- ld [%o1 - 4], %g2
- sub %o1, 4, %o1
- st %g2, [%o0 - 4]
- sub %o0, 4, %o0
-1:
- be 1f
- andcc %g1, 1, %g0
-
- lduh [%o1 - 2], %g2
- sub %o1, 2, %o1
- sth %g2, [%o0 - 2]
- sub %o0, 2, %o0
-1:
- be 1f
- nop
-
- ldub [%o1 - 1], %g2
- stb %g2, [%o0 - 1]
-1:
- retl
- RETL_INSN
-
-74: /* rldd_std */
- RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
- RMOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
- RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
- RMOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
- subcc %g7, 128, %g7
- sub %o1, 128, %o1
- bne 74b
- sub %o0, 128, %o0
-
- andcc %g1, 0x70, %g7
- be 72b
- andcc %g1, 8, %g0
-
- sethi %hi(72b), %o5
- srl %g7, 1, %o4
- add %g7, %o4, %o4
- sub %o1, %g7, %o1
- sub %o5, %o4, %o5
- jmpl %o5 + %lo(72b), %g0
- sub %o0, %g7, %o0
-
-75: /* rshort_end */
-
- and %o2, 0xe, %o3
-2:
- sethi %hi(76f), %o5
- sll %o3, 3, %o4
- sub %o0, %o3, %o0
- sub %o5, %o4, %o5
- sub %o1, %o3, %o1
- jmpl %o5 + %lo(76f), %g0
- andcc %o2, 1, %g0
-
- RMOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3)
- RMOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3)
- RMOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3)
- RMOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3)
- RMOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3)
- RMOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3)
- RMOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3)
-
-76: /* rshort_table_end */
-
- be 1f
- nop
- ldub [%o1 - 1], %g2
- stb %g2, [%o0 - 1]
-1:
- retl
- RETL_INSN
-
-91: /* rshort_aligned_end */
-
- bne 75b
- andcc %o2, 8, %g0
-
- be 1f
- andcc %o2, 4, %g0
-
- ld [%o1 - 0x08], %g2
- ld [%o1 - 0x04], %g3
- sub %o1, 8, %o1
- st %g2, [%o0 - 0x08]
- st %g3, [%o0 - 0x04]
- sub %o0, 8, %o0
-1:
- b 73b
- mov %o2, %g1
-
-77: /* rnon_aligned */
- cmp %o2, 15
- bleu 75b
- andcc %o0, 3, %g0
- be 64f
- andcc %o0, 1, %g0
- be 63f
- andcc %o0, 2, %g0
- ldub [%o1 - 1], %g5
- sub %o1, 1, %o1
- stb %g5, [%o0 - 1]
- sub %o0, 1, %o0
- be 64f
- sub %o2, 1, %o2
-63:
- ldub [%o1 - 1], %g5
- sub %o1, 2, %o1
- stb %g5, [%o0 - 1]
- sub %o0, 2, %o0
- ldub [%o1], %g5
- sub %o2, 2, %o2
- stb %g5, [%o0]
-64:
- and %o1, 3, %g2
- and %o1, -4, %o1
- and %o2, 0xc, %g3
- add %o1, 4, %o1
- cmp %g3, 4
- sll %g2, 3, %g4
- mov 32, %g2
- be 4f
- sub %g2, %g4, %g7
-
- blu 3f
- cmp %g3, 8
-
- be 2f
- srl %o2, 2, %g3
-
- ld [%o1 - 4], %o3
- add %o0, -8, %o0
- ld [%o1 - 8], %o4
- add %o1, -16, %o1
- b 7f
- add %g3, 1, %g3
-2:
- ld [%o1 - 4], %o4
- add %o0, -4, %o0
- ld [%o1 - 8], %g1
- add %o1, -12, %o1
- b 8f
- add %g3, 2, %g3
-3:
- ld [%o1 - 4], %o5
- add %o0, -12, %o0
- ld [%o1 - 8], %o3
- add %o1, -20, %o1
- b 6f
- srl %o2, 2, %g3
-4:
- ld [%o1 - 4], %g1
- srl %o2, 2, %g3
- ld [%o1 - 8], %o5
- add %o1, -24, %o1
- add %o0, -16, %o0
- add %g3, -1, %g3
-
- ld [%o1 + 12], %o3
-5:
- sll %o5, %g4, %g2
- srl %g1, %g7, %g5
- or %g2, %g5, %g2
- st %g2, [%o0 + 12]
-6:
- ld [%o1 + 8], %o4
- sll %o3, %g4, %g2
- srl %o5, %g7, %g5
- or %g2, %g5, %g2
- st %g2, [%o0 + 8]
-7:
- ld [%o1 + 4], %g1
- sll %o4, %g4, %g2
- srl %o3, %g7, %g5
- or %g2, %g5, %g2
- st %g2, [%o0 + 4]
-8:
- ld [%o1], %o5
- sll %g1, %g4, %g2
- srl %o4, %g7, %g5
- addcc %g3, -4, %g3
- or %g2, %g5, %g2
- add %o1, -16, %o1
- st %g2, [%o0]
- add %o0, -16, %o0
- bne,a 5b
- ld [%o1 + 12], %o3
- sll %o5, %g4, %g2
- srl %g1, %g7, %g5
- srl %g4, 3, %g3
- or %g2, %g5, %g2
- add %o1, %g3, %o1
- andcc %o2, 2, %g0
- st %g2, [%o0 + 12]
- be 1f
- andcc %o2, 1, %g0
-
- ldub [%o1 + 15], %g5
- add %o1, -2, %o1
- stb %g5, [%o0 + 11]
- add %o0, -2, %o0
- ldub [%o1 + 16], %g5
- stb %g5, [%o0 + 12]
-1:
- be 1f
- nop
- ldub [%o1 + 15], %g5
- stb %g5, [%o0 + 11]
-1:
- retl
- RETL_INSN
-
-#endif /* FASTER_REVERSE */
+ mov %g7, %o0
/* NOTE: This code is executed just for the cases,
where %src (=%o1) & 3 is != 0.
@@ -546,7 +204,7 @@ FUNC(memmove)
FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
sub %o0, %o1, %o4
- SETUP_RETL
+ mov %o0, %g7
9:
andcc %o4, 3, %o5
0:
@@ -569,7 +227,7 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
add %o1, 4, %o1
add %o0, 4, %o0
2:
- andcc %g1, 0xffffff80, %g7
+ andcc %g1, 0xffffff80, %g0
be 3f
andcc %o0, 4, %g0
@@ -579,22 +237,23 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
- subcc %g7, 128, %g7
+ sub %g1, 128, %g1
add %o1, 128, %o1
- bne 5b
+ cmp %g1, 128
+ bge 5b
add %o0, 128, %o0
3:
- andcc %g1, 0x70, %g7
+ andcc %g1, 0x70, %g4
be 80f
andcc %g1, 8, %g0
sethi %hi(80f), %o5
- srl %g7, 1, %o4
- add %g7, %o4, %o4
- add %o1, %g7, %o1
+ srl %g4, 1, %o4
+ add %g4, %o4, %o4
+ add %o1, %g4, %o1
sub %o5, %o4, %o5
jmpl %o5 + %lo(80f), %g0
- add %o0, %g7, %o0
+ add %o0, %g4, %o0
79: /* memcpy_table */
@@ -641,43 +300,28 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
stb %g2, [%o0]
1:
retl
- RETL_INSN
+ mov %g7, %o0
82: /* ldd_std */
MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
- subcc %g7, 128, %g7
+ subcc %g1, 128, %g1
add %o1, 128, %o1
- bne 82b
+ cmp %g1, 128
+ bge 82b
add %o0, 128, %o0
-#ifndef FASTER_ALIGNED
-
- andcc %g1, 0x70, %g7
- be 80b
- andcc %g1, 8, %g0
-
- sethi %hi(80b), %o5
- srl %g7, 1, %o4
- add %g7, %o4, %o4
- add %o1, %g7, %o1
- sub %o5, %o4, %o5
- jmpl %o5 + %lo(80b), %g0
- add %o0, %g7, %o0
-
-#else /* FASTER_ALIGNED */
-
- andcc %g1, 0x70, %g7
+ andcc %g1, 0x70, %g4
be 84f
andcc %g1, 8, %g0
sethi %hi(84f), %o5
- add %o1, %g7, %o1
- sub %o5, %g7, %o5
+ add %o1, %g4, %o1
+ sub %o5, %g4, %o5
jmpl %o5 + %lo(84f), %g0
- add %o0, %g7, %o0
+ add %o0, %g4, %o0
83: /* amemcpy_table */
@@ -721,382 +365,132 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
stb %g2, [%o0]
1:
retl
- RETL_INSN
-
-#endif /* FASTER_ALIGNED */
+ mov %g7, %o0
86: /* non_aligned */
cmp %o2, 6
bleu 88f
+ nop
-#ifdef FASTER_NONALIGNED
-
- cmp %o2, 256
- bcc 87f
-
-#endif /* FASTER_NONALIGNED */
-
- andcc %o0, 3, %g0
+ save %sp, -96, %sp
+ andcc %i0, 3, %g0
be 61f
- andcc %o0, 1, %g0
+ andcc %i0, 1, %g0
be 60f
- andcc %o0, 2, %g0
+ andcc %i0, 2, %g0
- ldub [%o1], %g5
- add %o1, 1, %o1
- stb %g5, [%o0]
- sub %o2, 1, %o2
+ ldub [%i1], %g5
+ add %i1, 1, %i1
+ stb %g5, [%i0]
+ sub %i2, 1, %i2
bne 61f
- add %o0, 1, %o0
+ add %i0, 1, %i0
60:
- ldub [%o1], %g3
- add %o1, 2, %o1
- stb %g3, [%o0]
- sub %o2, 2, %o2
- ldub [%o1 - 1], %g3
- add %o0, 2, %o0
- stb %g3, [%o0 - 1]
+ ldub [%i1], %g3
+ add %i1, 2, %i1
+ stb %g3, [%i0]
+ sub %i2, 2, %i2
+ ldub [%i1 - 1], %g3
+ add %i0, 2, %i0
+ stb %g3, [%i0 - 1]
61:
- and %o1, 3, %g2
- and %o2, 0xc, %g3
- and %o1, -4, %o1
+ and %i1, 3, %g2
+ and %i2, 0xc, %g3
+ and %i1, -4, %i1
cmp %g3, 4
sll %g2, 3, %g4
mov 32, %g2
be 4f
- sub %g2, %g4, %g7
+ sub %g2, %g4, %l0
blu 3f
cmp %g3, 0x8
be 2f
- srl %o2, 2, %g3
+ srl %i2, 2, %g3
- ld [%o1], %o3
- add %o0, -8, %o0
- ld [%o1 + 4], %o4
+ ld [%i1], %i3
+ add %i0, -8, %i0
+ ld [%i1 + 4], %i4
b 8f
add %g3, 1, %g3
2:
- ld [%o1], %o4
- add %o0, -12, %o0
- ld [%o1 + 4], %o5
+ ld [%i1], %i4
+ add %i0, -12, %i0
+ ld [%i1 + 4], %i5
add %g3, 2, %g3
b 9f
- add %o1, -4, %o1
+ add %i1, -4, %i1
3:
- ld [%o1], %g1
- add %o0, -4, %o0
- ld [%o1 + 4], %o3
- srl %o2, 2, %g3
+ ld [%i1], %g1
+ add %i0, -4, %i0
+ ld [%i1 + 4], %i3
+ srl %i2, 2, %g3
b 7f
- add %o1, 4, %o1
+ add %i1, 4, %i1
4:
- ld [%o1], %o5
- cmp %o2, 7
- ld [%o1 + 4], %g1
- srl %o2, 2, %g3
+ ld [%i1], %i5
+ cmp %i2, 7
+ ld [%i1 + 4], %g1
+ srl %i2, 2, %g3
bleu 10f
- add %o1, 8, %o1
+ add %i1, 8, %i1
- ld [%o1], %o3
+ ld [%i1], %i3
add %g3, -1, %g3
5:
- sll %o5, %g4, %g2
- srl %g1, %g7, %g5
+ sll %i5, %g4, %g2
+ srl %g1, %l0, %g5
or %g2, %g5, %g2
- st %g2, [%o0]
+ st %g2, [%i0]
7:
- ld [%o1 + 4], %o4
+ ld [%i1 + 4], %i4
sll %g1, %g4, %g2
- srl %o3, %g7, %g5
+ srl %i3, %l0, %g5
or %g2, %g5, %g2
- st %g2, [%o0 + 4]
+ st %g2, [%i0 + 4]
8:
- ld [%o1 + 8], %o5
- sll %o3, %g4, %g2
- srl %o4, %g7, %g5
+ ld [%i1 + 8], %i5
+ sll %i3, %g4, %g2
+ srl %i4, %l0, %g5
or %g2, %g5, %g2
- st %g2, [%o0 + 8]
+ st %g2, [%i0 + 8]
9:
- ld [%o1 + 12], %g1
- sll %o4, %g4, %g2
- srl %o5, %g7, %g5
+ ld [%i1 + 12], %g1
+ sll %i4, %g4, %g2
+ srl %i5, %l0, %g5
addcc %g3, -4, %g3
or %g2, %g5, %g2
- add %o1, 16, %o1
- st %g2, [%o0 + 12]
- add %o0, 16, %o0
+ add %i1, 16, %i1
+ st %g2, [%i0 + 12]
+ add %i0, 16, %i0
bne,a 5b
- ld [%o1], %o3
+ ld [%i1], %i3
10:
- sll %o5, %g4, %g2
- srl %g1, %g7, %g5
- srl %g7, 3, %g3
+ sll %i5, %g4, %g2
+ srl %g1, %l0, %g5
+ srl %l0, 3, %g3
or %g2, %g5, %g2
- sub %o1, %g3, %o1
- andcc %o2, 2, %g0
- st %g2, [%o0]
+ sub %i1, %g3, %i1
+ andcc %i2, 2, %g0
+ st %g2, [%i0]
be 1f
- andcc %o2, 1, %g0
-
- ldub [%o1], %g2
- add %o1, 2, %o1
- stb %g2, [%o0 + 4]
- add %o0, 2, %o0
- ldub [%o1 - 1], %g2
- stb %g2, [%o0 + 3]
+ andcc %i2, 1, %g0
+
+ ldub [%i1], %g2
+ add %i1, 2, %i1
+ stb %g2, [%i0 + 4]
+ add %i0, 2, %i0
+ ldub [%i1 - 1], %g2
+ stb %g2, [%i0 + 3]
1:
be 1f
nop
- ldub [%o1], %g2
- stb %g2, [%o0 + 4]
-1:
- retl
- RETL_INSN
-
-#ifdef FASTER_NONALIGNED
-
-87: /* faster_nonaligned */
-
- andcc %o1, 3, %g0
- be 3f
- andcc %o1, 1, %g0
-
- be 4f
- andcc %o1, 2, %g0
-
- ldub [%o1], %g2
- add %o1, 1, %o1
- stb %g2, [%o0]
- sub %o2, 1, %o2
- bne 3f
- add %o0, 1, %o0
-4:
- lduh [%o1], %g2
- add %o1, 2, %o1
- srl %g2, 8, %g3
- sub %o2, 2, %o2
- stb %g3, [%o0]
- add %o0, 2, %o0
- stb %g2, [%o0 - 1]
-3:
- andcc %o1, 4, %g0
-
- bne 2f
- cmp %o5, 1
-
- ld [%o1], %o4
- srl %o4, 24, %g2
- stb %g2, [%o0]
- srl %o4, 16, %g3
- stb %g3, [%o0 + 1]
- srl %o4, 8, %g2
- stb %g2, [%o0 + 2]
- sub %o2, 4, %o2
- stb %o4, [%o0 + 3]
- add %o1, 4, %o1
- add %o0, 4, %o0
-2:
- be 33f
- cmp %o5, 2
- be 32f
- sub %o2, 4, %o2
-31:
- ld [%o1], %g2
- add %o1, 4, %o1
- srl %g2, 24, %g3
- and %o0, 7, %g5
- stb %g3, [%o0]
- cmp %g5, 7
- sll %g2, 8, %g1
- add %o0, 4, %o0
- be 41f
- and %o2, 0xffffffc0, %o3
- ld [%o0 - 7], %o4
-4:
- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- subcc %o3, 64, %o3
- add %o1, 64, %o1
- bne 4b
- add %o0, 64, %o0
-
- andcc %o2, 0x30, %o3
- be,a 1f
- srl %g1, 16, %g2
-4:
- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- subcc %o3, 16, %o3
- add %o1, 16, %o1
- bne 4b
- add %o0, 16, %o0
-
- srl %g1, 16, %g2
-1:
- st %o4, [%o0 - 7]
- sth %g2, [%o0 - 3]
- srl %g1, 8, %g4
- b 88f
- stb %g4, [%o0 - 1]
-32:
- ld [%o1], %g2
- add %o1, 4, %o1
- srl %g2, 16, %g3
- and %o0, 7, %g5
- sth %g3, [%o0]
- cmp %g5, 6
- sll %g2, 16, %g1
- add %o0, 4, %o0
- be 42f
- and %o2, 0xffffffc0, %o3
- ld [%o0 - 6], %o4
-4:
- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- subcc %o3, 64, %o3
- add %o1, 64, %o1
- bne 4b
- add %o0, 64, %o0
-
- andcc %o2, 0x30, %o3
- be,a 1f
- srl %g1, 16, %g2
-4:
- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- subcc %o3, 16, %o3
- add %o1, 16, %o1
- bne 4b
- add %o0, 16, %o0
-
- srl %g1, 16, %g2
-1:
- st %o4, [%o0 - 6]
- b 88f
- sth %g2, [%o0 - 2]
-33:
- ld [%o1], %g2
- sub %o2, 4, %o2
- srl %g2, 24, %g3
- and %o0, 7, %g5
- stb %g3, [%o0]
- cmp %g5, 5
- srl %g2, 8, %g4
- sll %g2, 24, %g1
- sth %g4, [%o0 + 1]
- add %o1, 4, %o1
- be 43f
- and %o2, 0xffffffc0, %o3
-
- ld [%o0 - 1], %o4
- add %o0, 4, %o0
-4:
- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
- SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
- SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
- SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
- subcc %o3, 64, %o3
- add %o1, 64, %o1
- bne 4b
- add %o0, 64, %o0
-
- andcc %o2, 0x30, %o3
- be,a 1f
- srl %g1, 24, %g2
-4:
- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
- subcc %o3, 16, %o3
- add %o1, 16, %o1
- bne 4b
- add %o0, 16, %o0
-
- srl %g1, 24, %g2
-1:
- st %o4, [%o0 - 5]
- b 88f
- stb %g2, [%o0 - 1]
-41:
- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- subcc %o3, 64, %o3
- add %o1, 64, %o1
- bne 41b
- add %o0, 64, %o0
-
- andcc %o2, 0x30, %o3
- be,a 1f
- srl %g1, 16, %g2
-4:
- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
- subcc %o3, 16, %o3
- add %o1, 16, %o1
- bne 4b
- add %o0, 16, %o0
-
- srl %g1, 16, %g2
+ ldub [%i1], %g2
+ stb %g2, [%i0 + 4]
1:
- sth %g2, [%o0 - 3]
- srl %g1, 8, %g4
- b 88f
- stb %g4, [%o0 - 1]
-43:
- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
- SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
- SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
- SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
- subcc %o3, 64, %o3
- add %o1, 64, %o1
- bne 43b
- add %o0, 64, %o0
-
- andcc %o2, 0x30, %o3
- be,a 1f
- srl %g1, 24, %g2
-4:
- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
- subcc %o3, 16, %o3
- add %o1, 16, %o1
- bne 4b
- add %o0, 16, %o0
-
- srl %g1, 24, %g2
-1:
- stb %g2, [%o0 + 3]
- b 88f
- add %o0, 4, %o0
-42:
- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- subcc %o3, 64, %o3
- add %o1, 64, %o1
- bne 42b
- add %o0, 64, %o0
-
- andcc %o2, 0x30, %o3
- be,a 1f
- srl %g1, 16, %g2
-4:
- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
- subcc %o3, 16, %o3
- add %o1, 16, %o1
- bne 4b
- add %o0, 16, %o0
-
- srl %g1, 16, %g2
-1:
- sth %g2, [%o0 - 2]
-
- /* Fall through */
-
-#endif /* FASTER_NONALIGNED */
+ ret
+ restore %g7, %g0, %o0
88: /* short_end */
@@ -1127,7 +521,7 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
stb %g2, [%o0]
1:
retl
- RETL_INSN
+ mov %g7, %o0
90: /* short_aligned_end */
bne 88b
diff --git a/arch/sparc/mm/Makefile b/arch/sparc/mm/Makefile
index 79836a7dd00c..3b6e248650d4 100644
--- a/arch/sparc/mm/Makefile
+++ b/arch/sparc/mm/Makefile
@@ -8,7 +8,6 @@ obj-$(CONFIG_SPARC64) += ultra.o tlb.o tsb.o
obj-y += fault_$(BITS).o
obj-y += init_$(BITS).o
obj-$(CONFIG_SPARC32) += loadmmu.o
-obj-y += generic_$(BITS).o
obj-$(CONFIG_SPARC32) += extable.o btfixup.o srmmu.o iommu.o io-unit.o
obj-$(CONFIG_SPARC32) += hypersparc.o viking.o tsunami.o swift.o
obj-$(CONFIG_SPARC_LEON)+= leon_mm.o
diff --git a/arch/sparc/mm/btfixup.c b/arch/sparc/mm/btfixup.c
index 5175ac2f4820..8a7f81743c12 100644
--- a/arch/sparc/mm/btfixup.c
+++ b/arch/sparc/mm/btfixup.c
@@ -302,8 +302,7 @@ void __init btfixup(void)
case 'i': /* INT */
if ((insn & 0xc1c00000) == 0x01000000) /* %HI */
set_addr(addr, q[1], fmangled, (insn & 0xffc00000) | (p[1] >> 10));
- else if ((insn & 0x80002000) == 0x80002000 &&
- (insn & 0x01800000) != 0x01800000) /* %LO */
+ else if ((insn & 0x80002000) == 0x80002000) /* %LO */
set_addr(addr, q[1], fmangled, (insn & 0xffffe000) | (p[1] & 0x3ff));
else {
prom_printf(insn_i, p, addr, insn);
diff --git a/arch/sparc/mm/generic_32.c b/arch/sparc/mm/generic_32.c
deleted file mode 100644
index e6067b75f11c..000000000000
--- a/arch/sparc/mm/generic_32.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * generic.c: Generic Sparc mm routines that are not dependent upon
- * MMU type but are Sparc specific.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/pagemap.h>
-
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-
-/* Remap IO memory, the same way as remap_pfn_range(), but use
- * the obio memory space.
- *
- * They use a pgprot that sets PAGE_IO and does not check the
- * mem_map table as this is independent of normal memory.
- */
-static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, unsigned long address, unsigned long size,
- unsigned long offset, pgprot_t prot, int space)
-{
- unsigned long end;
-
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- do {
- set_pte_at(mm, address, pte, mk_pte_io(offset, prot, space));
- address += PAGE_SIZE;
- offset += PAGE_SIZE;
- pte++;
- } while (address < end);
-}
-
-static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long offset, pgprot_t prot, int space)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- offset -= address;
- do {
- pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
- if (!pte)
- return -ENOMEM;
- io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address < end);
- return 0;
-}
-
-int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
- unsigned long pfn, unsigned long size, pgprot_t prot)
-{
- int error = 0;
- pgd_t * dir;
- unsigned long beg = from;
- unsigned long end = from + size;
- struct mm_struct *mm = vma->vm_mm;
- int space = GET_IOSPACE(pfn);
- unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
-
- /* See comment in mm/memory.c remap_pfn_range */
- vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
- vma->vm_pgoff = (offset >> PAGE_SHIFT) |
- ((unsigned long)space << 28UL);
-
- offset -= from;
- dir = pgd_offset(mm, from);
- flush_cache_range(vma, beg, end);
-
- while (from < end) {
- pmd_t *pmd = pmd_alloc(mm, dir, from);
- error = -ENOMEM;
- if (!pmd)
- break;
- error = io_remap_pmd_range(mm, pmd, from, end - from, offset + from, prot, space);
- if (error)
- break;
- from = (from + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- }
-
- flush_tlb_range(vma, beg, end);
- return error;
-}
-EXPORT_SYMBOL(io_remap_pfn_range);
diff --git a/arch/sparc/mm/generic_64.c b/arch/sparc/mm/generic_64.c
deleted file mode 100644
index 3cb00dfd4bd6..000000000000
--- a/arch/sparc/mm/generic_64.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * generic.c: Generic Sparc mm routines that are not dependent upon
- * MMU type but are Sparc specific.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/pagemap.h>
-
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/tlbflush.h>
-
-/* Remap IO memory, the same way as remap_pfn_range(), but use
- * the obio memory space.
- *
- * They use a pgprot that sets PAGE_IO and does not check the
- * mem_map table as this is independent of normal memory.
- */
-static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte,
- unsigned long address,
- unsigned long size,
- unsigned long offset, pgprot_t prot,
- int space)
-{
- unsigned long end;
-
- /* clear hack bit that was used as a write_combine side-effect flag */
- offset &= ~0x1UL;
- address &= ~PMD_MASK;
- end = address + size;
- if (end > PMD_SIZE)
- end = PMD_SIZE;
- do {
- pte_t entry;
- unsigned long curend = address + PAGE_SIZE;
-
- entry = mk_pte_io(offset, prot, space, PAGE_SIZE);
- if (!(address & 0xffff)) {
- if (PAGE_SIZE < (4 * 1024 * 1024) &&
- !(address & 0x3fffff) &&
- !(offset & 0x3ffffe) &&
- end >= address + 0x400000) {
- entry = mk_pte_io(offset, prot, space,
- 4 * 1024 * 1024);
- curend = address + 0x400000;
- offset += 0x400000;
- } else if (PAGE_SIZE < (512 * 1024) &&
- !(address & 0x7ffff) &&
- !(offset & 0x7fffe) &&
- end >= address + 0x80000) {
- entry = mk_pte_io(offset, prot, space,
- 512 * 1024 * 1024);
- curend = address + 0x80000;
- offset += 0x80000;
- } else if (PAGE_SIZE < (64 * 1024) &&
- !(offset & 0xfffe) &&
- end >= address + 0x10000) {
- entry = mk_pte_io(offset, prot, space,
- 64 * 1024);
- curend = address + 0x10000;
- offset += 0x10000;
- } else
- offset += PAGE_SIZE;
- } else
- offset += PAGE_SIZE;
-
- if (pte_write(entry))
- entry = pte_mkdirty(entry);
- do {
- BUG_ON(!pte_none(*pte));
- set_pte_at(mm, address, pte, entry);
- address += PAGE_SIZE;
- pte_val(entry) += PAGE_SIZE;
- pte++;
- } while (address < curend);
- } while (address < end);
-}
-
-static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
- unsigned long offset, pgprot_t prot, int space)
-{
- unsigned long end;
-
- address &= ~PGDIR_MASK;
- end = address + size;
- if (end > PGDIR_SIZE)
- end = PGDIR_SIZE;
- offset -= address;
- do {
- pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
- if (!pte)
- return -ENOMEM;
- io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
- pte_unmap(pte);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address < end);
- return 0;
-}
-
-static inline int io_remap_pud_range(struct mm_struct *mm, pud_t * pud, unsigned long address, unsigned long size,
- unsigned long offset, pgprot_t prot, int space)
-{
- unsigned long end;
-
- address &= ~PUD_MASK;
- end = address + size;
- if (end > PUD_SIZE)
- end = PUD_SIZE;
- offset -= address;
- do {
- pmd_t *pmd = pmd_alloc(mm, pud, address);
- if (!pud)
- return -ENOMEM;
- io_remap_pmd_range(mm, pmd, address, end - address, address + offset, prot, space);
- address = (address + PUD_SIZE) & PUD_MASK;
- pud++;
- } while (address < end);
- return 0;
-}
-
-int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
- unsigned long pfn, unsigned long size, pgprot_t prot)
-{
- int error = 0;
- pgd_t * dir;
- unsigned long beg = from;
- unsigned long end = from + size;
- struct mm_struct *mm = vma->vm_mm;
- int space = GET_IOSPACE(pfn);
- unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
- unsigned long phys_base;
-
- phys_base = offset | (((unsigned long) space) << 32UL);
-
- /* See comment in mm/memory.c remap_pfn_range */
- vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
- vma->vm_pgoff = phys_base >> PAGE_SHIFT;
-
- offset -= from;
- dir = pgd_offset(mm, from);
- flush_cache_range(vma, beg, end);
-
- while (from < end) {
- pud_t *pud = pud_alloc(mm, dir, from);
- error = -ENOMEM;
- if (!pud)
- break;
- error = io_remap_pud_range(mm, pud, from, end - from, offset + from, prot, space);
- if (error)
- break;
- from = (from + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- }
-
- flush_tlb_range(vma, beg, end);
- return error;
-}
-EXPORT_SYMBOL(io_remap_pfn_range);
diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S
index b57a5942ba64..874162a11ceb 100644
--- a/arch/sparc/mm/ultra.S
+++ b/arch/sparc/mm/ultra.S
@@ -495,11 +495,11 @@ xcall_fetch_glob_regs:
stx %o7, [%g1 + GR_SNAP_O7]
stx %i7, [%g1 + GR_SNAP_I7]
/* Don't try this at home kids... */
- rdpr %cwp, %g2
- sub %g2, 1, %g7
+ rdpr %cwp, %g3
+ sub %g3, 1, %g7
wrpr %g7, %cwp
mov %i7, %g7
- wrpr %g2, %cwp
+ wrpr %g3, %cwp
stx %g7, [%g1 + GR_SNAP_RPC]
sethi %hi(trap_block), %g7
or %g7, %lo(trap_block), %g7
diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 0249b8b4db54..532a2a42ab7e 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -11,6 +11,7 @@ config TILE
select GENERIC_IRQ_PROBE
select GENERIC_PENDING_IRQ if SMP
select GENERIC_IRQ_SHOW
+ select HAVE_SYSCALL_WRAPPERS if TILEGX
select SYS_HYPERVISOR
# FIXME: investigate whether we need/want these options.
diff --git a/arch/tile/include/asm/bitops.h b/arch/tile/include/asm/bitops.h
index 16f1fa51fea1..bd186c4eaa50 100644
--- a/arch/tile/include/asm/bitops.h
+++ b/arch/tile/include/asm/bitops.h
@@ -77,6 +77,11 @@ static inline int ffs(int x)
return __builtin_ffs(x);
}
+static inline int fls64(__u64 w)
+{
+ return (sizeof(__u64) * 8) - __builtin_clzll(w);
+}
+
/**
* fls - find last set bit in word
* @x: the word to search
@@ -90,12 +95,7 @@ static inline int ffs(int x)
*/
static inline int fls(int x)
{
- return (sizeof(int) * 8) - __builtin_clz(x);
-}
-
-static inline int fls64(__u64 w)
-{
- return (sizeof(__u64) * 8) - __builtin_clzll(w);
+ return fls64((unsigned int) x);
}
static inline unsigned int __arch_hweight32(unsigned int w)
diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c
index a7869ad62776..41459d80b6bf 100644
--- a/arch/tile/kernel/compat_signal.c
+++ b/arch/tile/kernel/compat_signal.c
@@ -406,19 +406,17 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
* Set up registers for signal handler.
* Registers that we don't modify keep the value they had from
* user-space at the time we took the signal.
+ * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
+ * since some things rely on this (e.g. glibc's debug/segfault.c).
*/
regs->pc = ptr_to_compat_reg(ka->sa.sa_handler);
regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
regs->sp = ptr_to_compat_reg(frame);
regs->lr = restorer;
regs->regs[0] = (unsigned long) usig;
-
- if (ka->sa.sa_flags & SA_SIGINFO) {
- /* Need extra arguments, so mark to restore caller-saves. */
- regs->regs[1] = ptr_to_compat_reg(&frame->info);
- regs->regs[2] = ptr_to_compat_reg(&frame->uc);
- regs->flags |= PT_FLAGS_CALLER_SAVES;
- }
+ regs->regs[1] = ptr_to_compat_reg(&frame->info);
+ regs->regs[2] = ptr_to_compat_reg(&frame->uc);
+ regs->flags |= PT_FLAGS_CALLER_SAVES;
/*
* Notify any tracer that was single-stepping it.
diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h
index 41474fb5eee7..aa365c55ecf9 100644
--- a/arch/um/include/asm/pgtable.h
+++ b/arch/um/include/asm/pgtable.h
@@ -271,6 +271,12 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval)
}
#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+#define __HAVE_ARCH_PTE_SAME
+static inline int pte_same(pte_t pte_a, pte_t pte_b)
+{
+ return !((pte_val(pte_a) ^ pte_val(pte_b)) & ~_PAGE_NEWPAGE);
+}
+
/*
* Conversion functions: convert a page and protection to a page entry,
* and a page entry and page directory to the page they refer to.
@@ -346,11 +352,11 @@ extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr);
#define update_mmu_cache(vma,address,ptep) do ; while (0)
/* Encode and de-code a swap entry */
-#define __swp_type(x) (((x).val >> 4) & 0x3f)
+#define __swp_type(x) (((x).val >> 5) & 0x1f)
#define __swp_offset(x) ((x).val >> 11)
#define __swp_entry(type, offset) \
- ((swp_entry_t) { ((type) << 4) | ((offset) << 11) })
+ ((swp_entry_t) { ((type) << 5) | ((offset) << 11) })
#define __pte_to_swp_entry(pte) \
((swp_entry_t) { pte_val(pte_mkuptodate(pte)) })
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S
index be6d9e365a80..3470624d7835 100644
--- a/arch/x86/crypto/aesni-intel_asm.S
+++ b/arch/x86/crypto/aesni-intel_asm.S
@@ -2460,10 +2460,12 @@ ENTRY(aesni_cbc_dec)
pxor IN3, STATE4
movaps IN4, IV
#else
- pxor (INP), STATE2
- pxor 0x10(INP), STATE3
pxor IN1, STATE4
movaps IN2, IV
+ movups (INP), IN1
+ pxor IN1, STATE2
+ movups 0x10(INP), IN2
+ pxor IN2, STATE3
#endif
movups STATE1, (OUTP)
movups STATE2, 0x10(OUTP)
diff --git a/arch/x86/include/asm/amd_nb.h b/arch/x86/include/asm/amd_nb.h
index 67f87f257611..78a1eff74223 100644
--- a/arch/x86/include/asm/amd_nb.h
+++ b/arch/x86/include/asm/amd_nb.h
@@ -1,6 +1,7 @@
#ifndef _ASM_X86_AMD_NB_H
#define _ASM_X86_AMD_NB_H
+#include <linux/ioport.h>
#include <linux/pci.h>
struct amd_nb_bus_dev_range {
@@ -13,6 +14,7 @@ extern const struct pci_device_id amd_nb_misc_ids[];
extern const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[];
extern bool early_is_amd_nb(u32 value);
+extern struct resource *amd_get_mmconfig_range(struct resource *res);
extern int amd_cache_northbridges(void);
extern void amd_flush_garts(void);
extern int amd_numa_init(void);
diff --git a/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h
index c9e09ea05644..a850b4d8d14d 100644
--- a/arch/x86/include/asm/i387.h
+++ b/arch/x86/include/asm/i387.h
@@ -29,8 +29,8 @@ extern unsigned int sig_xstate_size;
extern void fpu_init(void);
extern void mxcsr_feature_mask_init(void);
extern int init_fpu(struct task_struct *child);
-extern asmlinkage void math_state_restore(void);
-extern void __math_state_restore(void);
+extern void __math_state_restore(struct task_struct *);
+extern void math_state_restore(void);
extern int dump_fpu(struct pt_regs *, struct user_i387_struct *);
extern user_regset_active_fn fpregs_active, xfpregs_active;
@@ -212,19 +212,11 @@ static inline void fpu_fxsave(struct fpu *fpu)
#endif /* CONFIG_X86_64 */
-/* We need a safe address that is cheap to find and that is already
- in L1 during context switch. The best choices are unfortunately
- different for UP and SMP */
-#ifdef CONFIG_SMP
-#define safe_address (__per_cpu_offset[0])
-#else
-#define safe_address (kstat_cpu(0).cpustat.user)
-#endif
-
/*
- * These must be called with preempt disabled
+ * These must be called with preempt disabled. Returns
+ * 'true' if the FPU state is still intact.
*/
-static inline void fpu_save_init(struct fpu *fpu)
+static inline int fpu_save_init(struct fpu *fpu)
{
if (use_xsave()) {
fpu_xsave(fpu);
@@ -233,33 +225,33 @@ static inline void fpu_save_init(struct fpu *fpu)
* xsave header may indicate the init state of the FP.
*/
if (!(fpu->state->xsave.xsave_hdr.xstate_bv & XSTATE_FP))
- return;
+ return 1;
} else if (use_fxsr()) {
fpu_fxsave(fpu);
} else {
asm volatile("fnsave %[fx]; fwait"
: [fx] "=m" (fpu->state->fsave));
- return;
+ return 0;
}
- if (unlikely(fpu->state->fxsave.swd & X87_FSW_ES))
+ /*
+ * If exceptions are pending, we need to clear them so
+ * that we don't randomly get exceptions later.
+ *
+ * FIXME! Is this perhaps only true for the old-style
+ * irq13 case? Maybe we could leave the x87 state
+ * intact otherwise?
+ */
+ if (unlikely(fpu->state->fxsave.swd & X87_FSW_ES)) {
asm volatile("fnclex");
-
- /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
- is pending. Clear the x87 state here by setting it to fixed
- values. safe_address is a random variable that should be in L1 */
- alternative_input(
- ASM_NOP8 ASM_NOP2,
- "emms\n\t" /* clear stack tags */
- "fildl %P[addr]", /* set F?P to defined value */
- X86_FEATURE_FXSAVE_LEAK,
- [addr] "m" (safe_address));
+ return 0;
+ }
+ return 1;
}
-static inline void __save_init_fpu(struct task_struct *tsk)
+static inline int __save_init_fpu(struct task_struct *tsk)
{
- fpu_save_init(&tsk->thread.fpu);
- task_thread_info(tsk)->status &= ~TS_USEDFPU;
+ return fpu_save_init(&tsk->thread.fpu);
}
static inline int fpu_fxrstor_checking(struct fpu *fpu)
@@ -281,39 +273,185 @@ static inline int restore_fpu_checking(struct task_struct *tsk)
}
/*
- * Signal frame handlers...
+ * Software FPU state helpers. Careful: these need to
+ * be preemption protection *and* they need to be
+ * properly paired with the CR0.TS changes!
*/
-extern int save_i387_xstate(void __user *buf);
-extern int restore_i387_xstate(void __user *buf);
+static inline int __thread_has_fpu(struct task_struct *tsk)
+{
+ return tsk->thread.has_fpu;
+}
-static inline void __unlazy_fpu(struct task_struct *tsk)
+/* Must be paired with an 'stts' after! */
+static inline void __thread_clear_has_fpu(struct task_struct *tsk)
{
- if (task_thread_info(tsk)->status & TS_USEDFPU) {
- __save_init_fpu(tsk);
- stts();
- } else
- tsk->fpu_counter = 0;
+ tsk->thread.has_fpu = 0;
+}
+
+/* Must be paired with a 'clts' before! */
+static inline void __thread_set_has_fpu(struct task_struct *tsk)
+{
+ tsk->thread.has_fpu = 1;
}
+/*
+ * Encapsulate the CR0.TS handling together with the
+ * software flag.
+ *
+ * These generally need preemption protection to work,
+ * do try to avoid using these on their own.
+ */
+static inline void __thread_fpu_end(struct task_struct *tsk)
+{
+ __thread_clear_has_fpu(tsk);
+ stts();
+}
+
+static inline void __thread_fpu_begin(struct task_struct *tsk)
+{
+ clts();
+ __thread_set_has_fpu(tsk);
+}
+
+/*
+ * FPU state switching for scheduling.
+ *
+ * This is a two-stage process:
+ *
+ * - switch_fpu_prepare() saves the old state and
+ * sets the new state of the CR0.TS bit. This is
+ * done within the context of the old process.
+ *
+ * - switch_fpu_finish() restores the new state as
+ * necessary.
+ */
+typedef struct { int preload; } fpu_switch_t;
+
+/*
+ * FIXME! We could do a totally lazy restore, but we need to
+ * add a per-cpu "this was the task that last touched the FPU
+ * on this CPU" variable, and the task needs to have a "I last
+ * touched the FPU on this CPU" and check them.
+ *
+ * We don't do that yet, so "fpu_lazy_restore()" always returns
+ * false, but some day..
+ */
+#define fpu_lazy_restore(tsk) (0)
+#define fpu_lazy_state_intact(tsk) do { } while (0)
+
+static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct task_struct *new)
+{
+ fpu_switch_t fpu;
+
+ fpu.preload = tsk_used_math(new) && new->fpu_counter > 5;
+ if (__thread_has_fpu(old)) {
+ if (__save_init_fpu(old))
+ fpu_lazy_state_intact(old);
+ __thread_clear_has_fpu(old);
+ old->fpu_counter++;
+
+ /* Don't change CR0.TS if we just switch! */
+ if (fpu.preload) {
+ __thread_set_has_fpu(new);
+ prefetch(new->thread.fpu.state);
+ } else
+ stts();
+ } else {
+ old->fpu_counter = 0;
+ if (fpu.preload) {
+ if (fpu_lazy_restore(new))
+ fpu.preload = 0;
+ else
+ prefetch(new->thread.fpu.state);
+ __thread_fpu_begin(new);
+ }
+ }
+ return fpu;
+}
+
+/*
+ * By the time this gets called, we've already cleared CR0.TS and
+ * given the process the FPU if we are going to preload the FPU
+ * state - all we need to do is to conditionally restore the register
+ * state itself.
+ */
+static inline void switch_fpu_finish(struct task_struct *new, fpu_switch_t fpu)
+{
+ if (fpu.preload)
+ __math_state_restore(new);
+}
+
+/*
+ * Signal frame handlers...
+ */
+extern int save_i387_xstate(void __user *buf);
+extern int restore_i387_xstate(void __user *buf);
+
static inline void __clear_fpu(struct task_struct *tsk)
{
- if (task_thread_info(tsk)->status & TS_USEDFPU) {
+ if (__thread_has_fpu(tsk)) {
/* Ignore delayed exceptions from user space */
asm volatile("1: fwait\n"
"2:\n"
_ASM_EXTABLE(1b, 2b));
- task_thread_info(tsk)->status &= ~TS_USEDFPU;
- stts();
+ __thread_fpu_end(tsk);
}
}
+/*
+ * Were we in an interrupt that interrupted kernel mode?
+ *
+ * We can do a kernel_fpu_begin/end() pair *ONLY* if that
+ * pair does nothing at all: the thread must not have fpu (so
+ * that we don't try to save the FPU state), and TS must
+ * be set (so that the clts/stts pair does nothing that is
+ * visible in the interrupted kernel thread).
+ */
+static inline bool interrupted_kernel_fpu_idle(void)
+{
+ return !__thread_has_fpu(current) &&
+ (read_cr0() & X86_CR0_TS);
+}
+
+/*
+ * Were we in user mode (or vm86 mode) when we were
+ * interrupted?
+ *
+ * Doing kernel_fpu_begin/end() is ok if we are running
+ * in an interrupt context from user mode - we'll just
+ * save the FPU state as required.
+ */
+static inline bool interrupted_user_mode(void)
+{
+ struct pt_regs *regs = get_irq_regs();
+ return regs && user_mode_vm(regs);
+}
+
+/*
+ * Can we use the FPU in kernel mode with the
+ * whole "kernel_fpu_begin/end()" sequence?
+ *
+ * It's always ok in process context (ie "not interrupt")
+ * but it is sometimes ok even from an irq.
+ */
+static inline bool irq_fpu_usable(void)
+{
+ return !in_interrupt() ||
+ interrupted_user_mode() ||
+ interrupted_kernel_fpu_idle();
+}
+
static inline void kernel_fpu_begin(void)
{
- struct thread_info *me = current_thread_info();
+ struct task_struct *me = current;
+
+ WARN_ON_ONCE(!irq_fpu_usable());
preempt_disable();
- if (me->status & TS_USEDFPU)
- __save_init_fpu(me->task);
- else
+ if (__thread_has_fpu(me)) {
+ __save_init_fpu(me);
+ __thread_clear_has_fpu(me);
+ /* We do 'stts()' in kernel_fpu_end() */
+ } else
clts();
}
@@ -323,14 +461,6 @@ static inline void kernel_fpu_end(void)
preempt_enable();
}
-static inline bool irq_fpu_usable(void)
-{
- struct pt_regs *regs;
-
- return !in_interrupt() || !(regs = get_irq_regs()) || \
- user_mode(regs) || (read_cr0() & X86_CR0_TS);
-}
-
/*
* Some instructions like VIA's padlock instructions generate a spurious
* DNA fault but don't modify SSE registers. And these instructions
@@ -363,20 +493,64 @@ static inline void irq_ts_restore(int TS_state)
}
/*
+ * The question "does this thread have fpu access?"
+ * is slightly racy, since preemption could come in
+ * and revoke it immediately after the test.
+ *
+ * However, even in that very unlikely scenario,
+ * we can just assume we have FPU access - typically
+ * to save the FP state - we'll just take a #NM
+ * fault and get the FPU access back.
+ *
+ * The actual user_fpu_begin/end() functions
+ * need to be preemption-safe, though.
+ *
+ * NOTE! user_fpu_end() must be used only after you
+ * have saved the FP state, and user_fpu_begin() must
+ * be used only immediately before restoring it.
+ * These functions do not do any save/restore on
+ * their own.
+ */
+static inline int user_has_fpu(void)
+{
+ return __thread_has_fpu(current);
+}
+
+static inline void user_fpu_end(void)
+{
+ preempt_disable();
+ __thread_fpu_end(current);
+ preempt_enable();
+}
+
+static inline void user_fpu_begin(void)
+{
+ preempt_disable();
+ if (!user_has_fpu())
+ __thread_fpu_begin(current);
+ preempt_enable();
+}
+
+/*
* These disable preemption on their own and are safe
*/
static inline void save_init_fpu(struct task_struct *tsk)
{
+ WARN_ON_ONCE(!__thread_has_fpu(tsk));
preempt_disable();
__save_init_fpu(tsk);
- stts();
+ __thread_fpu_end(tsk);
preempt_enable();
}
static inline void unlazy_fpu(struct task_struct *tsk)
{
preempt_disable();
- __unlazy_fpu(tsk);
+ if (__thread_has_fpu(tsk)) {
+ __save_init_fpu(tsk);
+ __thread_fpu_end(tsk);
+ } else
+ tsk->fpu_counter = 0;
preempt_enable();
}
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index 0049211959c0..0ab6a4dcb911 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -189,6 +189,9 @@ struct x86_emulate_ops {
int (*intercept)(struct x86_emulate_ctxt *ctxt,
struct x86_instruction_info *info,
enum x86_intercept_stage stage);
+
+ bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt,
+ u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
};
typedef u32 __attribute__((vector_size(16))) sse128_t;
@@ -298,6 +301,19 @@ struct x86_emulate_ctxt {
#define X86EMUL_MODE_PROT (X86EMUL_MODE_PROT16|X86EMUL_MODE_PROT32| \
X86EMUL_MODE_PROT64)
+/* CPUID vendors */
+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx 0x68747541
+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx 0x444d4163
+#define X86EMUL_CPUID_VENDOR_AuthenticAMD_edx 0x69746e65
+
+#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx 0x69444d41
+#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx 0x21726574
+#define X86EMUL_CPUID_VENDOR_AMDisbetterI_edx 0x74656273
+
+#define X86EMUL_CPUID_VENDOR_GenuineIntel_ebx 0x756e6547
+#define X86EMUL_CPUID_VENDOR_GenuineIntel_ecx 0x6c65746e
+#define X86EMUL_CPUID_VENDOR_GenuineIntel_edx 0x49656e69
+
enum x86_intercept_stage {
X86_ICTP_NONE = 0, /* Allow zero-init to not match anything */
X86_ICPT_PRE_EXCEPT,
diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h
index effff47a3c82..43876f16caf1 100644
--- a/arch/x86/include/asm/pgtable-3level.h
+++ b/arch/x86/include/asm/pgtable-3level.h
@@ -31,6 +31,56 @@ static inline void native_set_pte(pte_t *ptep, pte_t pte)
ptep->pte_low = pte.pte_low;
}
+#define pmd_read_atomic pmd_read_atomic
+/*
+ * pte_offset_map_lock on 32bit PAE kernels was reading the pmd_t with
+ * a "*pmdp" dereference done by gcc. Problem is, in certain places
+ * where pte_offset_map_lock is called, concurrent page faults are
+ * allowed, if the mmap_sem is hold for reading. An example is mincore
+ * vs page faults vs MADV_DONTNEED. On the page fault side
+ * pmd_populate rightfully does a set_64bit, but if we're reading the
+ * pmd_t with a "*pmdp" on the mincore side, a SMP race can happen
+ * because gcc will not read the 64bit of the pmd atomically. To fix
+ * this all places running pmd_offset_map_lock() while holding the
+ * mmap_sem in read mode, shall read the pmdp pointer using this
+ * function to know if the pmd is null nor not, and in turn to know if
+ * they can run pmd_offset_map_lock or pmd_trans_huge or other pmd
+ * operations.
+ *
+ * Without THP if the mmap_sem is hold for reading, the
+ * pmd can only transition from null to not null while pmd_read_atomic runs.
+ * So there's no need of literally reading it atomically.
+ *
+ * With THP if the mmap_sem is hold for reading, the pmd can become
+ * THP or null or point to a pte (and in turn become "stable") at any
+ * time under pmd_read_atomic, so it's mandatory to read it atomically
+ * with cmpxchg8b.
+ */
+#ifndef CONFIG_TRANSPARENT_HUGEPAGE
+static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
+{
+ pmdval_t ret;
+ u32 *tmp = (u32 *)pmdp;
+
+ ret = (pmdval_t) (*tmp);
+ if (ret) {
+ /*
+ * If the low part is null, we must not read the high part
+ * or we can end up with a partial pmd.
+ */
+ smp_rmb();
+ ret |= ((pmdval_t)*(tmp + 1)) << 32;
+ }
+
+ return (pmd_t) { ret };
+}
+#else /* CONFIG_TRANSPARENT_HUGEPAGE */
+static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
+{
+ return (pmd_t) { atomic64_read((atomic64_t *)pmdp) };
+}
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+
static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte)
{
set_64bit((unsigned long long *)(ptep), native_pte_val(pte));
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 219371546afd..5d9c61d0b270 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -454,6 +454,7 @@ struct thread_struct {
unsigned long trap_no;
unsigned long error_code;
/* floating point and extended processor state */
+ unsigned long has_fpu;
struct fpu fpu;
#ifdef CONFIG_X86_32
/* Virtual 86 mode info */
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index 1f2e61e28981..278d3d5f9062 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -242,8 +242,6 @@ static inline struct thread_info *current_thread_info(void)
* ever touches our thread-synchronous status, so we don't
* have to worry about atomic accesses.
*/
-#define TS_USEDFPU 0x0001 /* FPU was used by this task
- this quantum (SMP) */
#define TS_COMPAT 0x0002 /* 32bit syscall active (64BIT)*/
#define TS_POLLING 0x0004 /* idle task polling need_resched,
skip sending interrupt */
diff --git a/arch/x86/include/asm/timer.h b/arch/x86/include/asm/timer.h
index 431793e5d484..34baa0eb5d0c 100644
--- a/arch/x86/include/asm/timer.h
+++ b/arch/x86/include/asm/timer.h
@@ -57,14 +57,10 @@ DECLARE_PER_CPU(unsigned long long, cyc2ns_offset);
static inline unsigned long long __cycles_2_ns(unsigned long long cyc)
{
- unsigned long long quot;
- unsigned long long rem;
int cpu = smp_processor_id();
unsigned long long ns = per_cpu(cyc2ns_offset, cpu);
- quot = (cyc >> CYC2NS_SCALE_FACTOR);
- rem = cyc & ((1ULL << CYC2NS_SCALE_FACTOR) - 1);
- ns += quot * per_cpu(cyc2ns, cpu) +
- ((rem * per_cpu(cyc2ns, cpu)) >> CYC2NS_SCALE_FACTOR);
+ ns += mult_frac(cyc, per_cpu(cyc2ns, cpu),
+ (1UL << CYC2NS_SCALE_FACTOR));
return ns;
}
diff --git a/arch/x86/include/asm/uv/uv_hub.h b/arch/x86/include/asm/uv/uv_hub.h
index 54a13aaebc40..21f7385badb8 100644
--- a/arch/x86/include/asm/uv/uv_hub.h
+++ b/arch/x86/include/asm/uv/uv_hub.h
@@ -318,13 +318,13 @@ uv_gpa_in_mmr_space(unsigned long gpa)
/* UV global physical address --> socket phys RAM */
static inline unsigned long uv_gpa_to_soc_phys_ram(unsigned long gpa)
{
- unsigned long paddr = gpa & uv_hub_info->gpa_mask;
+ unsigned long paddr;
unsigned long remap_base = uv_hub_info->lowmem_remap_base;
unsigned long remap_top = uv_hub_info->lowmem_remap_top;
gpa = ((gpa << uv_hub_info->m_shift) >> uv_hub_info->m_shift) |
((gpa >> uv_hub_info->n_lshift) << uv_hub_info->m_val);
- gpa = gpa & uv_hub_info->gpa_mask;
+ paddr = gpa & uv_hub_info->gpa_mask;
if (paddr >= remap_base && paddr < remap_base + remap_top)
paddr -= remap_base;
return paddr;
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
index bfc8453bd98d..33df6e82f653 100644
--- a/arch/x86/kernel/amd_iommu_init.c
+++ b/arch/x86/kernel/amd_iommu_init.c
@@ -1031,8 +1031,9 @@ static int iommu_setup_msi(struct amd_iommu *iommu)
{
int r;
- if (pci_enable_msi(iommu->dev))
- return 1;
+ r = pci_enable_msi(iommu->dev);
+ if (r)
+ return r;
r = request_threaded_irq(iommu->dev->irq,
amd_iommu_int_handler,
@@ -1042,24 +1043,33 @@ static int iommu_setup_msi(struct amd_iommu *iommu)
if (r) {
pci_disable_msi(iommu->dev);
- return 1;
+ return r;
}
iommu->int_enabled = true;
- iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
return 0;
}
static int iommu_init_msi(struct amd_iommu *iommu)
{
+ int ret;
+
if (iommu->int_enabled)
- return 0;
+ goto enable_faults;
if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSI))
- return iommu_setup_msi(iommu);
+ ret = iommu_setup_msi(iommu);
+ else
+ ret = -ENODEV;
- return 1;
+ if (ret)
+ return ret;
+
+enable_faults:
+ iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
+
+ return 0;
}
/****************************************************************************
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
index 4c39baa8facc..bae1efe6d515 100644
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -119,6 +119,37 @@ bool __init early_is_amd_nb(u32 device)
return false;
}
+struct resource *amd_get_mmconfig_range(struct resource *res)
+{
+ u32 address;
+ u64 base, msr;
+ unsigned segn_busn_bits;
+
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+ return NULL;
+
+ /* assume all cpus from fam10h have mmconfig */
+ if (boot_cpu_data.x86 < 0x10)
+ return NULL;
+
+ address = MSR_FAM10H_MMIO_CONF_BASE;
+ rdmsrl(address, msr);
+
+ /* mmconfig is not enabled */
+ if (!(msr & FAM10H_MMIO_CONF_ENABLE))
+ return NULL;
+
+ base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT);
+
+ segn_busn_bits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) &
+ FAM10H_MMIO_CONF_BUSRANGE_MASK;
+
+ res->flags = IORESOURCE_MEM;
+ res->start = base;
+ res->end = base + (1ULL<<(segn_busn_bits + 20)) - 1;
+ return res;
+}
+
int amd_get_subcaches(int cpu)
{
struct pci_dev *link = node_to_amd_nb(amd_get_nb_id(cpu))->link;
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index b9338b8cf420..147169569274 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1558,9 +1558,11 @@ static int __init apic_verify(void)
mp_lapic_addr = APIC_DEFAULT_PHYS_BASE;
/* The BIOS may have set up the APIC at some other address */
- rdmsr(MSR_IA32_APICBASE, l, h);
- if (l & MSR_IA32_APICBASE_ENABLE)
- mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
+ if (boot_cpu_data.x86 >= 6) {
+ rdmsr(MSR_IA32_APICBASE, l, h);
+ if (l & MSR_IA32_APICBASE_ENABLE)
+ mp_lapic_addr = l & MSR_IA32_APICBASE_BASE;
+ }
pr_info("Found and enabled local APIC!\n");
return 0;
@@ -1578,13 +1580,15 @@ int __init apic_force_enable(unsigned long addr)
* MSR. This can only be done in software for Intel P6 or later
* and AMD K7 (Model > 1) or later.
*/
- rdmsr(MSR_IA32_APICBASE, l, h);
- if (!(l & MSR_IA32_APICBASE_ENABLE)) {
- pr_info("Local APIC disabled by BIOS -- reenabling.\n");
- l &= ~MSR_IA32_APICBASE_BASE;
- l |= MSR_IA32_APICBASE_ENABLE | addr;
- wrmsr(MSR_IA32_APICBASE, l, h);
- enabled_via_apicbase = 1;
+ if (boot_cpu_data.x86 >= 6) {
+ rdmsr(MSR_IA32_APICBASE, l, h);
+ if (!(l & MSR_IA32_APICBASE_ENABLE)) {
+ pr_info("Local APIC disabled by BIOS -- reenabling.\n");
+ l &= ~MSR_IA32_APICBASE_BASE;
+ l |= MSR_IA32_APICBASE_ENABLE | addr;
+ wrmsr(MSR_IA32_APICBASE, l, h);
+ enabled_via_apicbase = 1;
+ }
}
return apic_verify();
}
@@ -2112,10 +2116,12 @@ static void lapic_resume(void)
* FIXME! This will be wrong if we ever support suspend on
* SMP! We'll need to do this as part of the CPU restore!
*/
- rdmsr(MSR_IA32_APICBASE, l, h);
- l &= ~MSR_IA32_APICBASE_BASE;
- l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
- wrmsr(MSR_IA32_APICBASE, l, h);
+ if (boot_cpu_data.x86 >= 6) {
+ rdmsr(MSR_IA32_APICBASE, l, h);
+ l &= ~MSR_IA32_APICBASE_BASE;
+ l |= MSR_IA32_APICBASE_ENABLE | mp_lapic_addr;
+ wrmsr(MSR_IA32_APICBASE, l, h);
+ }
}
maxlvt = lapic_get_maxlvt();
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index cfeb978f49fd..874c20877140 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -779,7 +779,12 @@ void __init uv_system_init(void)
for(i = 0; i < UVH_NODE_PRESENT_TABLE_DEPTH; i++)
uv_possible_blades +=
hweight64(uv_read_local_mmr( UVH_NODE_PRESENT_TABLE + i * 8));
- printk(KERN_DEBUG "UV: Found %d blades\n", uv_num_possible_blades());
+
+ /* uv_num_possible_blades() is really the hub count */
+ printk(KERN_INFO "UV: Found %d blades, %d hubs\n",
+ is_uv1_hub() ? uv_num_possible_blades() :
+ (uv_num_possible_blades() + 1) / 2,
+ uv_num_possible_blades());
bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades();
uv_blade_info = kzalloc(bytes, GFP_KERNEL);
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index c105c533ed94..fde44284cf21 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -330,8 +330,7 @@ static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3)
l3->indices = (max(max3(sc0, sc1, sc2), sc3) << 10) - 1;
}
-static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf,
- int index)
+static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf, int index)
{
static struct amd_l3_cache *__cpuinitdata l3_caches;
int node;
@@ -748,14 +747,16 @@ static DEFINE_PER_CPU(struct _cpuid4_info *, ici_cpuid4_info);
#define CPUID4_INFO_IDX(x, y) (&((per_cpu(ici_cpuid4_info, x))[y]))
#ifdef CONFIG_SMP
-static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
+
+static int __cpuinit cache_shared_amd_cpu_map_setup(unsigned int cpu, int index)
{
- struct _cpuid4_info *this_leaf, *sibling_leaf;
- unsigned long num_threads_sharing;
- int index_msb, i, sibling;
+ struct _cpuid4_info *this_leaf;
+ int ret, i, sibling;
struct cpuinfo_x86 *c = &cpu_data(cpu);
- if ((index == 3) && (c->x86_vendor == X86_VENDOR_AMD)) {
+ ret = 0;
+ if (index == 3) {
+ ret = 1;
for_each_cpu(i, cpu_llc_shared_mask(cpu)) {
if (!per_cpu(ici_cpuid4_info, i))
continue;
@@ -766,8 +767,35 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
set_bit(sibling, this_leaf->shared_cpu_map);
}
}
- return;
+ } else if ((c->x86 == 0x15) && ((index == 1) || (index == 2))) {
+ ret = 1;
+ for_each_cpu(i, cpu_sibling_mask(cpu)) {
+ if (!per_cpu(ici_cpuid4_info, i))
+ continue;
+ this_leaf = CPUID4_INFO_IDX(i, index);
+ for_each_cpu(sibling, cpu_sibling_mask(cpu)) {
+ if (!cpu_online(sibling))
+ continue;
+ set_bit(sibling, this_leaf->shared_cpu_map);
+ }
+ }
}
+
+ return ret;
+}
+
+static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index)
+{
+ struct _cpuid4_info *this_leaf, *sibling_leaf;
+ unsigned long num_threads_sharing;
+ int index_msb, i;
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
+
+ if (c->x86_vendor == X86_VENDOR_AMD) {
+ if (cache_shared_amd_cpu_map_setup(cpu, index))
+ return;
+ }
+
this_leaf = CPUID4_INFO_IDX(cpu, index);
num_threads_sharing = 1 + this_leaf->eax.split.num_threads_sharing;
diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c
index 1e8d66c1336a..362190bd9e1e 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-severity.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c
@@ -101,15 +101,19 @@ static struct severity {
};
/*
- * If the EIPV bit is set, it means the saved IP is the
- * instruction which caused the MCE.
+ * If mcgstatus indicated that ip/cs on the stack were
+ * no good, then "m->cs" will be zero and we will have
+ * to assume the worst case (IN_KERNEL) as we actually
+ * have no idea what we were executing when the machine
+ * check hit.
+ * If we do have a good "m->cs" (or a faked one in the
+ * case we were executing in VM86 mode) we can use it to
+ * distinguish an exception taken in user from from one
+ * taken in the kernel.
*/
static int error_context(struct mce *m)
{
- if (m->mcgstatus & MCG_STATUS_EIPV)
- return (m->ip && (m->cs & 3) == 3) ? IN_USER : IN_KERNEL;
- /* Unknown, assume kernel */
- return IN_KERNEL;
+ return ((m->cs & 3) == 3) ? IN_USER : IN_KERNEL;
}
int mce_severity(struct mce *a, int tolerant, char **msg)
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index bb0adad35143..dc4fb779a724 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -52,6 +52,7 @@ struct threshold_block {
unsigned int cpu;
u32 address;
u16 interrupt_enable;
+ bool interrupt_capable;
u16 threshold_limit;
struct kobject kobj;
struct list_head miscj;
@@ -86,6 +87,21 @@ struct thresh_restart {
u16 old_limit;
};
+static bool lvt_interrupt_supported(unsigned int bank, u32 msr_high_bits)
+{
+ /*
+ * bank 4 supports APIC LVT interrupts implicitly since forever.
+ */
+ if (bank == 4)
+ return true;
+
+ /*
+ * IntP: interrupt present; if this bit is set, the thresholding
+ * bank can generate APIC LVT interrupts
+ */
+ return msr_high_bits & BIT(28);
+}
+
static int lvt_off_valid(struct threshold_block *b, int apic, u32 lo, u32 hi)
{
int msr = (hi & MASK_LVTOFF_HI) >> 20;
@@ -107,8 +123,10 @@ static int lvt_off_valid(struct threshold_block *b, int apic, u32 lo, u32 hi)
return 1;
};
-/* must be called with correct cpu affinity */
-/* Called via smp_call_function_single() */
+/*
+ * Called via smp_call_function_single(), must be called with correct
+ * cpu affinity.
+ */
static void threshold_restart_bank(void *_tr)
{
struct thresh_restart *tr = _tr;
@@ -131,6 +149,12 @@ static void threshold_restart_bank(void *_tr)
(new_count & THRESHOLD_MAX);
}
+ /* clear IntType */
+ hi &= ~MASK_INT_TYPE_HI;
+
+ if (!tr->b->interrupt_capable)
+ goto done;
+
if (tr->set_lvt_off) {
if (lvt_off_valid(tr->b, tr->lvt_off, lo, hi)) {
/* set new lvt offset */
@@ -139,9 +163,10 @@ static void threshold_restart_bank(void *_tr)
}
}
- tr->b->interrupt_enable ?
- (hi = (hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) :
- (hi &= ~MASK_INT_TYPE_HI);
+ if (tr->b->interrupt_enable)
+ hi |= INT_TYPE_APIC;
+
+ done:
hi |= MASK_COUNT_EN_HI;
wrmsr(tr->b->address, lo, hi);
@@ -206,14 +231,18 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
if (shared_bank[bank] && c->cpu_core_id)
break;
#endif
- offset = setup_APIC_mce(offset,
- (high & MASK_LVTOFF_HI) >> 20);
memset(&b, 0, sizeof(b));
- b.cpu = cpu;
- b.bank = bank;
- b.block = block;
- b.address = address;
+ b.cpu = cpu;
+ b.bank = bank;
+ b.block = block;
+ b.address = address;
+ b.interrupt_capable = lvt_interrupt_supported(bank, high);
+
+ if (b.interrupt_capable) {
+ int new = (high & MASK_LVTOFF_HI) >> 20;
+ offset = setup_APIC_mce(offset, new);
+ }
mce_threshold_block_init(&b, offset);
mce_threshold_vector = amd_threshold_interrupt;
@@ -313,6 +342,9 @@ store_interrupt_enable(struct threshold_block *b, const char *buf, size_t size)
struct thresh_restart tr;
unsigned long new;
+ if (!b->interrupt_capable)
+ return -EINVAL;
+
if (strict_strtoul(buf, 0, &new) < 0)
return -EINVAL;
@@ -471,6 +503,7 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu,
b->cpu = cpu;
b->address = address;
b->interrupt_enable = 0;
+ b->interrupt_capable = lvt_interrupt_supported(bank, high);
b->threshold_limit = THRESHOLD_MAX;
INIT_LIST_HEAD(&b->miscj);
diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c
index fe29c1d2219e..4b50c965f0e6 100644
--- a/arch/x86/kernel/cpu/perf_event_amd.c
+++ b/arch/x86/kernel/cpu/perf_event_amd.c
@@ -437,6 +437,7 @@ static __initconst const struct x86_pmu amd_pmu = {
* 0x023 DE PERF_CTL[2:0]
* 0x02D LS PERF_CTL[3]
* 0x02E LS PERF_CTL[3,0]
+ * 0x031 LS PERF_CTL[2:0] (**)
* 0x043 CU PERF_CTL[2:0]
* 0x045 CU PERF_CTL[2:0]
* 0x046 CU PERF_CTL[2:0]
@@ -450,10 +451,12 @@ static __initconst const struct x86_pmu amd_pmu = {
* 0x0DD LS PERF_CTL[5:0]
* 0x0DE LS PERF_CTL[5:0]
* 0x0DF LS PERF_CTL[5:0]
+ * 0x1C0 EX PERF_CTL[5:3]
* 0x1D6 EX PERF_CTL[5:0]
* 0x1D8 EX PERF_CTL[5:0]
*
- * (*) depending on the umask all FPU counters may be used
+ * (*) depending on the umask all FPU counters may be used
+ * (**) only one unitmask enabled at a time
*/
static struct event_constraint amd_f15_PMC0 = EVENT_CONSTRAINT(0, 0x01, 0);
@@ -503,6 +506,12 @@ amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *ev
return &amd_f15_PMC3;
case 0x02E:
return &amd_f15_PMC30;
+ case 0x031:
+ if (hweight_long(hwc->config & ARCH_PERFMON_EVENTSEL_UMASK) <= 1)
+ return &amd_f15_PMC20;
+ return &emptyconstraint;
+ case 0x1C0:
+ return &amd_f15_PMC53;
default:
return &amd_f15_PMC50;
}
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 5c1a91974918..edb3d46c16db 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -98,12 +98,6 @@
#endif
.endm
-#ifdef CONFIG_VM86
-#define resume_userspace_sig check_userspace
-#else
-#define resume_userspace_sig resume_userspace
-#endif
-
/*
* User gs save/restore
*
@@ -327,10 +321,19 @@ ret_from_exception:
preempt_stop(CLBR_ANY)
ret_from_intr:
GET_THREAD_INFO(%ebp)
-check_userspace:
+resume_userspace_sig:
+#ifdef CONFIG_VM86
movl PT_EFLAGS(%esp), %eax # mix EFLAGS and CS
movb PT_CS(%esp), %al
andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
+#else
+ /*
+ * We can be coming here from a syscall done in the kernel space,
+ * e.g. a failed kernel_execve().
+ */
+ movl PT_CS(%esp), %eax
+ andl $SEGMENT_RPL_MASK, %eax
+#endif
cmpl $USER_RPL, %eax
jb resume_kernel # not returning to v8086 or userspace
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index 5f9ecff328b5..fc1f48dc9989 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -43,6 +43,8 @@
#include <linux/smp.h>
#include <linux/nmi.h>
#include <linux/hw_breakpoint.h>
+#include <linux/uaccess.h>
+#include <linux/memory.h>
#include <asm/debugreg.h>
#include <asm/apicdef.h>
@@ -710,6 +712,64 @@ void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long ip)
regs->ip = ip;
}
+int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
+{
+ int err;
+ char opc[BREAK_INSTR_SIZE];
+
+ bpt->type = BP_BREAKPOINT;
+ err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
+ BREAK_INSTR_SIZE);
+ if (err)
+ return err;
+ err = probe_kernel_write((char *)bpt->bpt_addr,
+ arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
+#ifdef CONFIG_DEBUG_RODATA
+ if (!err)
+ return err;
+ /*
+ * It is safe to call text_poke() because normal kernel execution
+ * is stopped on all cores, so long as the text_mutex is not locked.
+ */
+ if (mutex_is_locked(&text_mutex))
+ return -EBUSY;
+ text_poke((void *)bpt->bpt_addr, arch_kgdb_ops.gdb_bpt_instr,
+ BREAK_INSTR_SIZE);
+ err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE);
+ if (err)
+ return err;
+ if (memcmp(opc, arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE))
+ return -EINVAL;
+ bpt->type = BP_POKE_BREAKPOINT;
+#endif /* CONFIG_DEBUG_RODATA */
+ return err;
+}
+
+int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
+{
+#ifdef CONFIG_DEBUG_RODATA
+ int err;
+ char opc[BREAK_INSTR_SIZE];
+
+ if (bpt->type != BP_POKE_BREAKPOINT)
+ goto knl_write;
+ /*
+ * It is safe to call text_poke() because normal kernel execution
+ * is stopped on all cores, so long as the text_mutex is not locked.
+ */
+ if (mutex_is_locked(&text_mutex))
+ goto knl_write;
+ text_poke((void *)bpt->bpt_addr, bpt->saved_instr, BREAK_INSTR_SIZE);
+ err = probe_kernel_read(opc, (char *)bpt->bpt_addr, BREAK_INSTR_SIZE);
+ if (err || memcmp(opc, bpt->saved_instr, BREAK_INSTR_SIZE))
+ goto knl_write;
+ return err;
+knl_write:
+#endif /* CONFIG_DEBUG_RODATA */
+ return probe_kernel_write((char *)bpt->bpt_addr,
+ (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
+}
+
struct kgdb_arch arch_kgdb_ops = {
/* Breakpoint instruction: */
.gdb_bpt_instr = { 0xcc },
diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c
index c5610384ab16..b727450f5d78 100644
--- a/arch/x86/kernel/microcode_amd.c
+++ b/arch/x86/kernel/microcode_amd.c
@@ -298,13 +298,33 @@ free_table:
return state;
}
+/*
+ * AMD microcode firmware naming convention, up to family 15h they are in
+ * the legacy file:
+ *
+ * amd-ucode/microcode_amd.bin
+ *
+ * This legacy file is always smaller than 2K in size.
+ *
+ * Starting at family 15h they are in family specific firmware files:
+ *
+ * amd-ucode/microcode_amd_fam15h.bin
+ * amd-ucode/microcode_amd_fam16h.bin
+ * ...
+ *
+ * These might be larger than 2K.
+ */
static enum ucode_state request_microcode_amd(int cpu, struct device *device)
{
- const char *fw_name = "amd-ucode/microcode_amd.bin";
+ char fw_name[36] = "amd-ucode/microcode_amd.bin";
const struct firmware *fw;
enum ucode_state ret = UCODE_NFOUND;
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
+
+ if (c->x86 >= 0x15)
+ snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86);
- if (request_firmware(&fw, fw_name, device)) {
+ if (request_firmware(&fw, (const char *)fw_name, device)) {
pr_err("failed to load file %s\n", fw_name);
goto out;
}
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index a3d0dc59067b..fcdb1b34aa1c 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -293,22 +293,11 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
*next = &next_p->thread;
int cpu = smp_processor_id();
struct tss_struct *tss = &per_cpu(init_tss, cpu);
- bool preload_fpu;
+ fpu_switch_t fpu;
/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
- /*
- * If the task has used fpu the last 5 timeslices, just do a full
- * restore of the math state immediately to avoid the trap; the
- * chances of needing FPU soon are obviously high now
- */
- preload_fpu = tsk_used_math(next_p) && next_p->fpu_counter > 5;
-
- __unlazy_fpu(prev_p);
-
- /* we're going to use this soon, after a few expensive things */
- if (preload_fpu)
- prefetch(next->fpu.state);
+ fpu = switch_fpu_prepare(prev_p, next_p);
/*
* Reload esp0.
@@ -348,11 +337,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT))
__switch_to_xtra(prev_p, next_p, tss);
- /* If we're going to preload the fpu context, make sure clts
- is run while we're batching the cpu state updates. */
- if (preload_fpu)
- clts();
-
/*
* Leave lazy mode, flushing any hypercalls made here.
* This must be done before restoring TLS segments so
@@ -362,15 +346,14 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
*/
arch_end_context_switch(next_p);
- if (preload_fpu)
- __math_state_restore();
-
/*
* Restore %gs if needed (which is common)
*/
if (prev->gs | next->gs)
lazy_load_gs(next->gs);
+ switch_fpu_finish(next_p, fpu);
+
percpu_write(current_task, next_p);
return prev_p;
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 63c8aedbe5b3..eeb50045bfd3 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -363,18 +363,9 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
int cpu = smp_processor_id();
struct tss_struct *tss = &per_cpu(init_tss, cpu);
unsigned fsindex, gsindex;
- bool preload_fpu;
+ fpu_switch_t fpu;
- /*
- * If the task has used fpu the last 5 timeslices, just do a full
- * restore of the math state immediately to avoid the trap; the
- * chances of needing FPU soon are obviously high now
- */
- preload_fpu = tsk_used_math(next_p) && next_p->fpu_counter > 5;
-
- /* we're going to use this soon, after a few expensive things */
- if (preload_fpu)
- prefetch(next->fpu.state);
+ fpu = switch_fpu_prepare(prev_p, next_p);
/*
* Reload esp0, LDT and the page table pointer:
@@ -404,13 +395,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
load_TLS(next, cpu);
- /* Must be after DS reload */
- __unlazy_fpu(prev_p);
-
- /* Make sure cpu is ready for new context */
- if (preload_fpu)
- clts();
-
/*
* Leave lazy mode, flushing any hypercalls made here.
* This must be done before restoring TLS segments so
@@ -451,6 +435,8 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
wrmsrl(MSR_KERNEL_GS_BASE, next->gs);
prev->gsindex = gsindex;
+ switch_fpu_finish(next_p, fpu);
+
/*
* Switch the PDA and FPU contexts.
*/
@@ -469,13 +455,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
__switch_to_xtra(prev_p, next_p, tss);
- /*
- * Preload the FPU context, now that we've determined that the
- * task is likely to be using it.
- */
- if (preload_fpu)
- __math_state_restore();
-
return prev_p;
}
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index 71f4727da373..5a98aa272184 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -185,10 +185,22 @@ void __init setup_per_cpu_areas(void)
#endif
rc = -EINVAL;
if (pcpu_chosen_fc != PCPU_FC_PAGE) {
- const size_t atom_size = cpu_has_pse ? PMD_SIZE : PAGE_SIZE;
const size_t dyn_size = PERCPU_MODULE_RESERVE +
PERCPU_DYNAMIC_RESERVE - PERCPU_FIRST_CHUNK_RESERVE;
+ size_t atom_size;
+ /*
+ * On 64bit, use PMD_SIZE for atom_size so that embedded
+ * percpu areas are aligned to PMD. This, in the future,
+ * can also allow using PMD mappings in vmalloc area. Use
+ * PAGE_SIZE on 32bit as vmalloc space is highly contended
+ * and large vmalloc area allocs can easily fail.
+ */
+#ifdef CONFIG_X86_64
+ atom_size = PMD_SIZE;
+#else
+ atom_size = PAGE_SIZE;
+#endif
rc = pcpu_embed_first_chunk(PERCPU_FIRST_CHUNK_RESERVE,
dyn_size, atom_size,
pcpu_cpu_distance,
diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c
index 6bb7b8579e70..bcfec2d23769 100644
--- a/arch/x86/kernel/tls.c
+++ b/arch/x86/kernel/tls.c
@@ -163,7 +163,7 @@ int regset_tls_get(struct task_struct *target, const struct user_regset *regset,
{
const struct desc_struct *tls;
- if (pos > GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) ||
+ if (pos >= GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) ||
(pos % sizeof(struct user_desc)) != 0 ||
(count % sizeof(struct user_desc)) != 0)
return -EINVAL;
@@ -198,7 +198,7 @@ int regset_tls_set(struct task_struct *target, const struct user_regset *regset,
struct user_desc infobuf[GDT_ENTRY_TLS_ENTRIES];
const struct user_desc *info;
- if (pos > GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) ||
+ if (pos >= GDT_ENTRY_TLS_ENTRIES * sizeof(struct user_desc) ||
(pos % sizeof(struct user_desc)) != 0 ||
(count % sizeof(struct user_desc)) != 0)
return -EINVAL;
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index b9b67166f9de..1b26e01047b5 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -717,25 +717,34 @@ asmlinkage void __attribute__((weak)) smp_threshold_interrupt(void)
}
/*
- * __math_state_restore assumes that cr0.TS is already clear and the
- * fpu state is all ready for use. Used during context switch.
+ * This gets called with the process already owning the
+ * FPU state, and with CR0.TS cleared. It just needs to
+ * restore the FPU register state.
*/
-void __math_state_restore(void)
+void __math_state_restore(struct task_struct *tsk)
{
- struct thread_info *thread = current_thread_info();
- struct task_struct *tsk = thread->task;
+ /* We need a safe address that is cheap to find and that is already
+ in L1. We've just brought in "tsk->thread.has_fpu", so use that */
+#define safe_address (tsk->thread.has_fpu)
+
+ /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception
+ is pending. Clear the x87 state here by setting it to fixed
+ values. safe_address is a random variable that should be in L1 */
+ alternative_input(
+ ASM_NOP8 ASM_NOP2,
+ "emms\n\t" /* clear stack tags */
+ "fildl %P[addr]", /* set F?P to defined value */
+ X86_FEATURE_FXSAVE_LEAK,
+ [addr] "m" (safe_address));
/*
* Paranoid restore. send a SIGSEGV if we fail to restore the state.
*/
if (unlikely(restore_fpu_checking(tsk))) {
- stts();
+ __thread_fpu_end(tsk);
force_sig(SIGSEGV, tsk);
return;
}
-
- thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */
- tsk->fpu_counter++;
}
/*
@@ -745,13 +754,12 @@ void __math_state_restore(void)
* Careful.. There are problems with IBM-designed IRQ13 behaviour.
* Don't touch unless you *really* know how it works.
*
- * Must be called with kernel preemption disabled (in this case,
- * local interrupts are disabled at the call-site in entry.S).
+ * Must be called with kernel preemption disabled (eg with local
+ * local interrupts as in the case of do_device_not_available).
*/
-asmlinkage void math_state_restore(void)
+void math_state_restore(void)
{
- struct thread_info *thread = current_thread_info();
- struct task_struct *tsk = thread->task;
+ struct task_struct *tsk = current;
if (!tsk_used_math(tsk)) {
local_irq_enable();
@@ -768,9 +776,10 @@ asmlinkage void math_state_restore(void)
local_irq_disable();
}
- clts(); /* Allow maths ops (or we recurse) */
+ __thread_fpu_begin(tsk);
+ __math_state_restore(tsk);
- __math_state_restore();
+ tsk->fpu_counter++;
}
EXPORT_SYMBOL_GPL(math_state_restore);
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 6cc6922262af..4406c038a0a8 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -623,7 +623,8 @@ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
if (cpu_khz) {
*scale = (NSEC_PER_MSEC << CYC2NS_SCALE_FACTOR)/cpu_khz;
- *offset = ns_now - (tsc_now * *scale >> CYC2NS_SCALE_FACTOR);
+ *offset = ns_now - mult_frac(tsc_now, *scale,
+ (1UL << CYC2NS_SCALE_FACTOR));
}
sched_clock_idle_wakeup_event(0);
@@ -956,6 +957,16 @@ static int __init init_tsc_clocksource(void)
clocksource_tsc.rating = 0;
clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS;
}
+
+ /*
+ * Trust the results of the earlier calibration on systems
+ * exporting a reliable TSC.
+ */
+ if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE)) {
+ clocksource_register_khz(&clocksource_tsc, tsc_khz);
+ return 0;
+ }
+
schedule_delayed_work(&tsc_irqwork, 0);
return 0;
}
diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c
index 863f8753ab0a..04b87269edfb 100644
--- a/arch/x86/kernel/vm86_32.c
+++ b/arch/x86/kernel/vm86_32.c
@@ -172,6 +172,7 @@ static void mark_screen_rdonly(struct mm_struct *mm)
spinlock_t *ptl;
int i;
+ down_write(&mm->mmap_sem);
pgd = pgd_offset(mm, 0xA0000);
if (pgd_none_or_clear_bad(pgd))
goto out;
@@ -190,6 +191,7 @@ static void mark_screen_rdonly(struct mm_struct *mm)
}
pte_unmap_unlock(pte, ptl);
out:
+ up_write(&mm->mmap_sem);
flush_tlb();
}
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
index a3911343976b..711091114119 100644
--- a/arch/x86/kernel/xsave.c
+++ b/arch/x86/kernel/xsave.c
@@ -47,7 +47,7 @@ void __sanitize_i387_state(struct task_struct *tsk)
if (!fx)
return;
- BUG_ON(task_thread_info(tsk)->status & TS_USEDFPU);
+ BUG_ON(__thread_has_fpu(tsk));
xstate_bv = tsk->thread.fpu.state->xsave.xsave_hdr.xstate_bv;
@@ -168,7 +168,7 @@ int save_i387_xstate(void __user *buf)
if (!used_math())
return 0;
- if (task_thread_info(tsk)->status & TS_USEDFPU) {
+ if (user_has_fpu()) {
if (use_xsave())
err = xsave_user(buf);
else
@@ -176,8 +176,7 @@ int save_i387_xstate(void __user *buf)
if (err)
return err;
- task_thread_info(tsk)->status &= ~TS_USEDFPU;
- stts();
+ user_fpu_end();
} else {
sanitize_i387_state(tsk);
if (__copy_to_user(buf, &tsk->thread.fpu.state->fxsave,
@@ -292,10 +291,7 @@ int restore_i387_xstate(void __user *buf)
return err;
}
- if (!(task_thread_info(current)->status & TS_USEDFPU)) {
- clts();
- task_thread_info(current)->status |= TS_USEDFPU;
- }
+ user_fpu_begin();
if (use_xsave())
err = restore_user_xstate(buf);
else
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index adc98675cda0..3e7d9138dd2e 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -1901,6 +1901,51 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
ss->p = 1;
}
+static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt)
+{
+ struct x86_emulate_ops *ops = ctxt->ops;
+ u32 eax, ebx, ecx, edx;
+
+ /*
+ * syscall should always be enabled in longmode - so only become
+ * vendor specific (cpuid) if other modes are active...
+ */
+ if (ctxt->mode == X86EMUL_MODE_PROT64)
+ return true;
+
+ eax = 0x00000000;
+ ecx = 0x00000000;
+ if (ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)) {
+ /*
+ * Intel ("GenuineIntel")
+ * remark: Intel CPUs only support "syscall" in 64bit
+ * longmode. Also an 64bit guest with a
+ * 32bit compat-app running will #UD !! While this
+ * behaviour can be fixed (by emulating) into AMD
+ * response - CPUs of AMD can't behave like Intel.
+ */
+ if (ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx &&
+ ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx &&
+ edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx)
+ return false;
+
+ /* AMD ("AuthenticAMD") */
+ if (ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx &&
+ ecx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx &&
+ edx == X86EMUL_CPUID_VENDOR_AuthenticAMD_edx)
+ return true;
+
+ /* AMD ("AMDisbetter!") */
+ if (ebx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx &&
+ ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx &&
+ edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx)
+ return true;
+ }
+
+ /* default: (not Intel, not AMD), apply Intel's stricter rules... */
+ return false;
+}
+
static int
emulate_syscall(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
{
@@ -1915,9 +1960,15 @@ emulate_syscall(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
ctxt->mode == X86EMUL_MODE_VM86)
return emulate_ud(ctxt);
+ if (!(em_syscall_is_enabled(ctxt)))
+ return emulate_ud(ctxt);
+
ops->get_msr(ctxt, MSR_EFER, &efer);
setup_syscalls_segments(ctxt, ops, &cs, &ss);
+ if (!(efer & EFER_SCE))
+ return emulate_ud(ctxt);
+
ops->get_msr(ctxt, MSR_STAR, &msr_data);
msr_data >>= 32;
cs_sel = (u16)(msr_data & 0xfffc);
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index d48ec60ea421..2ad060acc445 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -948,7 +948,7 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx)
#ifdef CONFIG_X86_64
wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base);
#endif
- if (current_thread_info()->status & TS_USEDFPU)
+ if (__thread_has_fpu(current))
clts();
load_gdt(&__get_cpu_var(host_gdt));
}
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 77c9d8673dc4..fbb093601b5a 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4407,6 +4407,28 @@ static int emulator_intercept(struct x86_emulate_ctxt *ctxt,
return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage);
}
+static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt,
+ u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
+{
+ struct kvm_cpuid_entry2 *cpuid = NULL;
+
+ if (eax && ecx)
+ cpuid = kvm_find_cpuid_entry(emul_to_vcpu(ctxt),
+ *eax, *ecx);
+
+ if (cpuid) {
+ *eax = cpuid->eax;
+ *ecx = cpuid->ecx;
+ if (ebx)
+ *ebx = cpuid->ebx;
+ if (edx)
+ *edx = cpuid->edx;
+ return true;
+ }
+
+ return false;
+}
+
static struct x86_emulate_ops emulate_ops = {
.read_std = kvm_read_guest_virt_system,
.write_std = kvm_write_guest_virt_system,
@@ -4437,6 +4459,7 @@ static struct x86_emulate_ops emulate_ops = {
.get_fpu = emulator_get_fpu,
.put_fpu = emulator_put_fpu,
.intercept = emulator_intercept,
+ .get_cpuid = emulator_get_cpuid,
};
static void cache_all_regs(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/lib/delay.c b/arch/x86/lib/delay.c
index fc45ba887d05..e395693abdb1 100644
--- a/arch/x86/lib/delay.c
+++ b/arch/x86/lib/delay.c
@@ -48,9 +48,9 @@ static void delay_loop(unsigned long loops)
}
/* TSC based delay: */
-static void delay_tsc(unsigned long loops)
+static void delay_tsc(unsigned long __loops)
{
- unsigned long bclock, now;
+ u32 bclock, now, loops = __loops;
int cpu;
preempt_disable();
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 1dab5194fd9d..f927429d07ca 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -87,9 +87,9 @@ static unsigned long mmap_rnd(void)
*/
if (current->flags & PF_RANDOMIZE) {
if (mmap_is_ia32())
- rnd = (long)get_random_int() % (1<<8);
+ rnd = get_random_int() % (1<<8);
else
- rnd = (long)(get_random_int() % (1<<28));
+ rnd = get_random_int() % (1<<28);
}
return rnd << PAGE_SHIFT;
}
diff --git a/arch/x86/mm/srat.c b/arch/x86/mm/srat.c
index 81dbfdeb080d..7efd0c615d58 100644
--- a/arch/x86/mm/srat.c
+++ b/arch/x86/mm/srat.c
@@ -104,6 +104,8 @@ acpi_numa_processor_affinity_init(struct acpi_srat_cpu_affinity *pa)
if ((pa->flags & ACPI_SRAT_CPU_ENABLED) == 0)
return;
pxm = pa->proximity_domain_lo;
+ if (acpi_srat_revision >= 2)
+ pxm |= *((unsigned int*)pa->proximity_domain_hi) << 8;
node = setup_node(pxm);
if (node < 0) {
printk(KERN_ERR "SRAT: Too many proximity domains %x\n", pxm);
@@ -155,6 +157,8 @@ acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
start = ma->base_address;
end = start + ma->length;
pxm = ma->proximity_domain;
+ if (acpi_srat_revision <= 1)
+ pxm &= 0xff;
node = setup_node(pxm);
if (node < 0) {
printk(KERN_ERR "SRAT: Too many proximity domains.\n");
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index bfab3fa10edc..5a5b6e4dd738 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -151,17 +151,18 @@ void bpf_jit_compile(struct sk_filter *fp)
cleanup_addr = proglen; /* epilogue address */
for (pass = 0; pass < 10; pass++) {
+ u8 seen_or_pass0 = (pass == 0) ? (SEEN_XREG | SEEN_DATAREF | SEEN_MEM) : seen;
/* no prologue/epilogue for trivial filters (RET something) */
proglen = 0;
prog = temp;
- if (seen) {
+ if (seen_or_pass0) {
EMIT4(0x55, 0x48, 0x89, 0xe5); /* push %rbp; mov %rsp,%rbp */
EMIT4(0x48, 0x83, 0xec, 96); /* subq $96,%rsp */
/* note : must save %rbx in case bpf_error is hit */
- if (seen & (SEEN_XREG | SEEN_DATAREF))
+ if (seen_or_pass0 & (SEEN_XREG | SEEN_DATAREF))
EMIT4(0x48, 0x89, 0x5d, 0xf8); /* mov %rbx, -8(%rbp) */
- if (seen & SEEN_XREG)
+ if (seen_or_pass0 & SEEN_XREG)
CLEAR_X(); /* make sure we dont leek kernel memory */
/*
@@ -170,7 +171,7 @@ void bpf_jit_compile(struct sk_filter *fp)
* r9 = skb->len - skb->data_len
* r8 = skb->data
*/
- if (seen & SEEN_DATAREF) {
+ if (seen_or_pass0 & SEEN_DATAREF) {
if (offsetof(struct sk_buff, len) <= 127)
/* mov off8(%rdi),%r9d */
EMIT4(0x44, 0x8b, 0x4f, offsetof(struct sk_buff, len));
@@ -260,9 +261,14 @@ void bpf_jit_compile(struct sk_filter *fp)
case BPF_S_ALU_DIV_X: /* A /= X; */
seen |= SEEN_XREG;
EMIT2(0x85, 0xdb); /* test %ebx,%ebx */
- if (pc_ret0 != -1)
- EMIT_COND_JMP(X86_JE, addrs[pc_ret0] - (addrs[i] - 4));
- else {
+ if (pc_ret0 > 0) {
+ /* addrs[pc_ret0 - 1] is start address of target
+ * (addrs[i] - 4) is the address following this jmp
+ * ("xor %edx,%edx; div %ebx" being 4 bytes long)
+ */
+ EMIT_COND_JMP(X86_JE, addrs[pc_ret0 - 1] -
+ (addrs[i] - 4));
+ } else {
EMIT_COND_JMP(X86_JNE, 2 + 5);
CLEAR_A();
EMIT1_off32(0xe9, cleanup_addr - (addrs[i] - 4)); /* jmp .+off32 */
@@ -283,7 +289,7 @@ void bpf_jit_compile(struct sk_filter *fp)
EMIT2(0x24, K & 0xFF); /* and imm8,%al */
} else if (K >= 0xFFFF0000) {
EMIT2(0x66, 0x25); /* and imm16,%ax */
- EMIT2(K, 2);
+ EMIT(K, 2);
} else {
EMIT1_off32(0x25, K); /* and imm32,%eax */
}
@@ -335,12 +341,12 @@ void bpf_jit_compile(struct sk_filter *fp)
}
/* fallinto */
case BPF_S_RET_A:
- if (seen) {
+ if (seen_or_pass0) {
if (i != flen - 1) {
EMIT_JMP(cleanup_addr - addrs[i]);
break;
}
- if (seen & SEEN_XREG)
+ if (seen_or_pass0 & SEEN_XREG)
EMIT4(0x48, 0x8b, 0x5d, 0xf8); /* mov -8(%rbp),%rbx */
EMIT1(0xc9); /* leaveq */
}
@@ -469,8 +475,10 @@ void bpf_jit_compile(struct sk_filter *fp)
case BPF_S_LD_W_ABS:
func = sk_load_word;
common_load: seen |= SEEN_DATAREF;
- if ((int)K < 0)
+ if ((int)K < 0) {
+ /* Abort the JIT because __load_pointer() is needed. */
goto out;
+ }
t_offset = func - (image + addrs[i]);
EMIT1_off32(0xbe, K); /* mov imm32,%esi */
EMIT1_off32(0xe8, t_offset); /* call */
@@ -483,13 +491,8 @@ common_load: seen |= SEEN_DATAREF;
goto common_load;
case BPF_S_LDX_B_MSH:
if ((int)K < 0) {
- if (pc_ret0 != -1) {
- EMIT_JMP(addrs[pc_ret0] - addrs[i]);
- break;
- }
- CLEAR_A();
- EMIT_JMP(cleanup_addr - addrs[i]);
- break;
+ /* Abort the JIT because __load_pointer() is needed. */
+ goto out;
}
seen |= SEEN_DATAREF | SEEN_XREG;
t_offset = sk_load_byte_msh - (image + addrs[i]);
@@ -568,8 +571,8 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i];
break;
}
if (filter[i].jt != 0) {
- if (filter[i].jf)
- t_offset += is_near(f_offset) ? 2 : 6;
+ if (filter[i].jf && f_offset)
+ t_offset += is_near(f_offset) ? 2 : 5;
EMIT_COND_JMP(t_op, t_offset);
if (filter[i].jf)
EMIT_JMP(f_offset);
@@ -599,13 +602,14 @@ cond_branch: f_offset = addrs[i + filter[i].jf] - addrs[i];
* use it to give the cleanup instruction(s) addr
*/
cleanup_addr = proglen - 1; /* ret */
- if (seen)
+ if (seen_or_pass0)
cleanup_addr -= 1; /* leaveq */
- if (seen & SEEN_XREG)
+ if (seen_or_pass0 & SEEN_XREG)
cleanup_addr -= 4; /* mov -8(%rbp),%rbx */
if (image) {
- WARN_ON(proglen != oldproglen);
+ if (proglen != oldproglen)
+ pr_err("bpb_jit_compile proglen=%u != oldproglen=%u\n", proglen, oldproglen);
break;
}
if (proglen == oldproglen) {
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile
index 6b8759f7634e..d24d3da72926 100644
--- a/arch/x86/pci/Makefile
+++ b/arch/x86/pci/Makefile
@@ -18,8 +18,9 @@ obj-$(CONFIG_X86_NUMAQ) += numaq_32.o
obj-$(CONFIG_X86_MRST) += mrst.o
obj-y += common.o early.o
-obj-y += amd_bus.o bus_numa.o
+obj-y += bus_numa.o
+obj-$(CONFIG_AMD_NB) += amd_bus.o
obj-$(CONFIG_PCI_CNB20LE_QUIRK) += broadcom_bus.o
ifeq ($(CONFIG_PCI_DEBUG),y)
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 50b3f14c59a1..0473a8f93501 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -54,6 +54,16 @@ static const struct dmi_system_id pci_use_crs_table[] __initconst = {
DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
},
},
+ /* https://bugzilla.kernel.org/show_bug.cgi?id=42619 */
+ {
+ .callback = set_use_crs,
+ .ident = "MSI MS-7253",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
+ DMI_MATCH(DMI_BOARD_NAME, "MS-7253"),
+ DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies, LTD"),
+ },
+ },
{}
};
@@ -149,7 +159,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
struct acpi_resource_address64 addr;
acpi_status status;
unsigned long flags;
- u64 start, end;
+ u64 start, orig_end, end;
status = resource_to_addr(acpi_res, &addr);
if (!ACPI_SUCCESS(status))
@@ -165,7 +175,21 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
return AE_OK;
start = addr.minimum + addr.translation_offset;
- end = addr.maximum + addr.translation_offset;
+ orig_end = end = addr.maximum + addr.translation_offset;
+
+ /* Exclude non-addressable range or non-addressable portion of range */
+ end = min(end, (u64)iomem_resource.end);
+ if (end <= start) {
+ dev_info(&info->bridge->dev,
+ "host bridge window [%#llx-%#llx] "
+ "(ignored, not CPU addressable)\n", start, orig_end);
+ return AE_OK;
+ } else if (orig_end != end) {
+ dev_info(&info->bridge->dev,
+ "host bridge window [%#llx-%#llx] "
+ "([%#llx-%#llx] ignored, not CPU addressable)\n",
+ start, orig_end, end + 1, orig_end);
+ }
res = &info->res[info->res_num];
res->name = info->name;
diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c
index 026e4931d162..385a940b5422 100644
--- a/arch/x86/pci/amd_bus.c
+++ b/arch/x86/pci/amd_bus.c
@@ -30,34 +30,6 @@ static struct pci_hostbridge_probe pci_probes[] __initdata = {
{ 0, 0x18, PCI_VENDOR_ID_AMD, 0x1300 },
};
-static u64 __initdata fam10h_mmconf_start;
-static u64 __initdata fam10h_mmconf_end;
-static void __init get_pci_mmcfg_amd_fam10h_range(void)
-{
- u32 address;
- u64 base, msr;
- unsigned segn_busn_bits;
-
- /* assume all cpus from fam10h have mmconf */
- if (boot_cpu_data.x86 < 0x10)
- return;
-
- address = MSR_FAM10H_MMIO_CONF_BASE;
- rdmsrl(address, msr);
-
- /* mmconfig is not enable */
- if (!(msr & FAM10H_MMIO_CONF_ENABLE))
- return;
-
- base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT);
-
- segn_busn_bits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) &
- FAM10H_MMIO_CONF_BUSRANGE_MASK;
-
- fam10h_mmconf_start = base;
- fam10h_mmconf_end = base + (1ULL<<(segn_busn_bits + 20)) - 1;
-}
-
#define RANGE_NUM 16
/**
@@ -85,6 +57,9 @@ static int __init early_fill_mp_bus_info(void)
u64 val;
u32 address;
bool found;
+ struct resource fam10h_mmconf_res, *fam10h_mmconf;
+ u64 fam10h_mmconf_start;
+ u64 fam10h_mmconf_end;
if (!early_pci_allowed())
return -1;
@@ -211,12 +186,17 @@ static int __init early_fill_mp_bus_info(void)
subtract_range(range, RANGE_NUM, 0, end);
/* get mmconfig */
- get_pci_mmcfg_amd_fam10h_range();
+ fam10h_mmconf = amd_get_mmconfig_range(&fam10h_mmconf_res);
/* need to take out mmconf range */
- if (fam10h_mmconf_end) {
- printk(KERN_DEBUG "Fam 10h mmconf [%llx, %llx]\n", fam10h_mmconf_start, fam10h_mmconf_end);
+ if (fam10h_mmconf) {
+ printk(KERN_DEBUG "Fam 10h mmconf %pR\n", fam10h_mmconf);
+ fam10h_mmconf_start = fam10h_mmconf->start;
+ fam10h_mmconf_end = fam10h_mmconf->end;
subtract_range(range, RANGE_NUM, fam10h_mmconf_start,
fam10h_mmconf_end + 1);
+ } else {
+ fam10h_mmconf_start = 0;
+ fam10h_mmconf_end = 0;
}
/* mmio resource */
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index f567965c0620..6e96e65e7caa 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -308,7 +308,7 @@ int __init pci_xen_init(void)
int __init pci_xen_hvm_init(void)
{
- if (!xen_feature(XENFEAT_hvm_pirqs))
+ if (!xen_have_vector_callback || !xen_feature(XENFEAT_hvm_pirqs))
return 0;
#ifdef CONFIG_ACPI
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
index 82cff4a25f44..edf435b74e85 100644
--- a/arch/x86/platform/uv/tlb_uv.c
+++ b/arch/x86/platform/uv/tlb_uv.c
@@ -1575,14 +1575,14 @@ static int calculate_destination_timeout(void)
ts_ns = base * mult1 * mult2;
ret = ts_ns / 1000;
} else {
- /* 4 bits 0/1 for 10/80us, 3 bits of multiplier */
- mmr_image = uv_read_local_mmr(UVH_AGING_PRESCALE_SEL);
+ /* 4 bits 0/1 for 10/80us base, 3 bits of multiplier */
+ mmr_image = uv_read_local_mmr(UVH_LB_BAU_MISC_CONTROL);
mmr_image = (mmr_image & UV_SA_MASK) >> UV_SA_SHFT;
if (mmr_image & (1L << UV2_ACK_UNITS_SHFT))
- mult1 = 80;
+ base = 80;
else
- mult1 = 10;
- base = mmr_image & UV2_ACK_MASK;
+ base = 10;
+ mult1 = mmr_image & UV2_ACK_MASK;
ret = mult1 * base;
}
return ret;
@@ -1820,6 +1820,8 @@ static int __init uv_bau_init(void)
uv_base_pnode = uv_blade_to_pnode(uvhub);
}
+ enable_timeouts();
+
if (init_per_cpu(nuvhubs, uv_base_pnode)) {
nobau = 1;
return 0;
@@ -1830,7 +1832,6 @@ static int __init uv_bau_init(void)
if (uv_blade_nr_possible_cpus(uvhub))
init_uvhub(uvhub, vector, uv_base_pnode);
- enable_timeouts();
alloc_intr_gate(vector, uv_bau_message_intr1);
for_each_possible_blade(uvhub) {
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 0fb662abcebc..b50c5931f40b 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -62,6 +62,7 @@
#include <asm/reboot.h>
#include <asm/stackprotector.h>
#include <asm/hypervisor.h>
+#include <asm/pci_x86.h>
#include "xen-ops.h"
#include "mmu.h"
@@ -1259,8 +1260,10 @@ asmlinkage void __init xen_start_kernel(void)
/* Make sure ACS will be enabled */
pci_request_acs();
}
-
-
+#ifdef CONFIG_PCI
+ /* PCI BIOS service won't work from a PV guest. */
+ pci_probe &= ~PCI_PROBE_BIOS;
+#endif
xen_raw_console_write("about to get started...\n");
xen_setup_runstate_info(0);
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 5f76c0acb2c7..d957dce61ede 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -320,8 +320,13 @@ static pteval_t pte_mfn_to_pfn(pteval_t val)
{
if (val & _PAGE_PRESENT) {
unsigned long mfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT;
+ unsigned long pfn = mfn_to_pfn(mfn);
+
pteval_t flags = val & PTE_FLAGS_MASK;
- val = ((pteval_t)mfn_to_pfn(mfn) << PAGE_SHIFT) | flags;
+ if (unlikely(pfn == ~0))
+ val = flags & ~_PAGE_PRESENT;
+ else
+ val = ((pteval_t)pfn << PAGE_SHIFT) | flags;
}
return val;
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index d4fc6d454f8d..2843b5e7cf07 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -172,6 +172,7 @@ static void __init xen_fill_possible_map(void)
static void __init xen_filter_cpu_maps(void)
{
int i, rc;
+ unsigned int subtract = 0;
if (!xen_initial_domain())
return;
@@ -186,8 +187,22 @@ static void __init xen_filter_cpu_maps(void)
} else {
set_cpu_possible(i, false);
set_cpu_present(i, false);
+ subtract++;
}
}
+#ifdef CONFIG_HOTPLUG_CPU
+ /* This is akin to using 'nr_cpus' on the Linux command line.
+ * Which is OK as when we use 'dom0_max_vcpus=X' we can only
+ * have up to X, while nr_cpu_ids is greater than X. This
+ * normally is not a problem, except when CPU hotplugging
+ * is involved and then there might be more than X CPUs
+ * in the guest - which will not work as there is no
+ * hypercall to expand the max number of VCPUs an already
+ * running guest has. So cap it up to X. */
+ if (subtract)
+ nr_cpu_ids = nr_cpu_ids - subtract;
+#endif
+
}
static void __init xen_smp_prepare_boot_cpu(void)
diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S
index 79d7362ad6d1..3e45aa000718 100644
--- a/arch/x86/xen/xen-asm.S
+++ b/arch/x86/xen/xen-asm.S
@@ -96,7 +96,7 @@ ENTRY(xen_restore_fl_direct)
/* check for unmasked and pending */
cmpw $0x0001, PER_CPU_VAR(xen_vcpu_info) + XEN_vcpu_info_pending
- jz 1f
+ jnz 1f
2: call check_events
1:
ENDPATCH(xen_restore_fl_direct)
diff --git a/block/blk-core.c b/block/blk-core.c
index 847d04ef9f19..35ae52df6b6d 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -418,6 +418,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
q->backing_dev_info.state = 0;
q->backing_dev_info.capabilities = BDI_CAP_MAP_COPY;
q->backing_dev_info.name = "block";
+ q->node = node_id;
err = bdi_init(&q->backing_dev_info);
if (err) {
@@ -502,7 +503,7 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
if (!uninit_q)
return NULL;
- q = blk_init_allocated_queue_node(uninit_q, rfn, lock, node_id);
+ q = blk_init_allocated_queue(uninit_q, rfn, lock);
if (!q)
blk_cleanup_queue(uninit_q);
@@ -514,18 +515,9 @@ struct request_queue *
blk_init_allocated_queue(struct request_queue *q, request_fn_proc *rfn,
spinlock_t *lock)
{
- return blk_init_allocated_queue_node(q, rfn, lock, -1);
-}
-EXPORT_SYMBOL(blk_init_allocated_queue);
-
-struct request_queue *
-blk_init_allocated_queue_node(struct request_queue *q, request_fn_proc *rfn,
- spinlock_t *lock, int node_id)
-{
if (!q)
return NULL;
- q->node = node_id;
if (blk_init_free_list(q))
return NULL;
@@ -555,7 +547,7 @@ blk_init_allocated_queue_node(struct request_queue *q, request_fn_proc *rfn,
return NULL;
}
-EXPORT_SYMBOL(blk_init_allocated_queue_node);
+EXPORT_SYMBOL(blk_init_allocated_queue);
int blk_get_queue(struct request_queue *q)
{
diff --git a/block/bsg.c b/block/bsg.c
index 0c8b64a16484..792ead666757 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -985,7 +985,8 @@ void bsg_unregister_queue(struct request_queue *q)
mutex_lock(&bsg_mutex);
idr_remove(&bsg_minor_idr, bcd->minor);
- sysfs_remove_link(&q->kobj, "bsg");
+ if (q->kobj.sd)
+ sysfs_remove_link(&q->kobj, "bsg");
device_unregister(bcd->class_dev);
bcd->class_dev = NULL;
kref_put(&bcd->ref, bsg_kref_release_function);
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index ae21919f15e1..23500ac7f0f3 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -3169,7 +3169,7 @@ static int cfq_cic_link(struct cfq_data *cfqd, struct io_context *ioc,
}
}
- if (ret)
+ if (ret && ret != -EEXIST)
printk(KERN_ERR "cfq: cic link failed!\n");
return ret;
@@ -3185,6 +3185,7 @@ cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
{
struct io_context *ioc = NULL;
struct cfq_io_context *cic;
+ int ret;
might_sleep_if(gfp_mask & __GFP_WAIT);
@@ -3192,6 +3193,7 @@ cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
if (!ioc)
return NULL;
+retry:
cic = cfq_cic_lookup(cfqd, ioc);
if (cic)
goto out;
@@ -3200,7 +3202,12 @@ cfq_get_io_context(struct cfq_data *cfqd, gfp_t gfp_mask)
if (cic == NULL)
goto err;
- if (cfq_cic_link(cfqd, ioc, cic, gfp_mask))
+ ret = cfq_cic_link(cfqd, ioc, cic, gfp_mask);
+ if (ret == -EEXIST) {
+ /* someone has linked cic to ioc already */
+ cfq_cic_free(cic);
+ goto retry;
+ } else if (ret)
goto err_free;
out:
@@ -4015,6 +4022,11 @@ static void *cfq_init_queue(struct request_queue *q)
if (blkio_alloc_blkg_stats(&cfqg->blkg)) {
kfree(cfqg);
+
+ spin_lock(&cic_index_lock);
+ ida_remove(&cic_index_ida, cfqd->cic_index);
+ spin_unlock(&cic_index_lock);
+
kfree(cfqd);
return NULL;
}
diff --git a/block/genhd.c b/block/genhd.c
index b65f565c0277..a1b0b9012cd4 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -36,6 +36,7 @@ static DEFINE_IDR(ext_devt_idr);
static struct device_type disk_type;
+static void disk_alloc_events(struct gendisk *disk);
static void disk_add_events(struct gendisk *disk);
static void disk_del_events(struct gendisk *disk);
static void disk_release_events(struct gendisk *disk);
@@ -602,6 +603,8 @@ void add_disk(struct gendisk *disk)
disk->major = MAJOR(devt);
disk->first_minor = MINOR(devt);
+ disk_alloc_events(disk);
+
/* Register BDI before referencing it from bdev */
bdi = &disk->queue->backing_dev_info;
bdi_register_dev(bdi, disk_devt(disk));
@@ -741,7 +744,7 @@ void __init printk_all_partitions(void)
struct hd_struct *part;
char name_buf[BDEVNAME_SIZE];
char devt_buf[BDEVT_SIZE];
- u8 uuid[PARTITION_META_INFO_UUIDLTH * 2 + 1];
+ char uuid_buf[PARTITION_META_INFO_UUIDLTH * 2 + 5];
/*
* Don't show empty devices or things that have been
@@ -760,14 +763,16 @@ void __init printk_all_partitions(void)
while ((part = disk_part_iter_next(&piter))) {
bool is_part0 = part == &disk->part0;
- uuid[0] = 0;
+ uuid_buf[0] = '\0';
if (part->info)
- part_unpack_uuid(part->info->uuid, uuid);
+ snprintf(uuid_buf, sizeof(uuid_buf), "%pU",
+ part->info->uuid);
printk("%s%s %10llu %s %s", is_part0 ? "" : " ",
bdevt_str(part_devt(part), devt_buf),
(unsigned long long)part->nr_sects >> 1,
- disk_name(disk, part->partno, name_buf), uuid);
+ disk_name(disk, part->partno, name_buf),
+ uuid_buf);
if (is_part0) {
if (disk->driverfs_dev != NULL &&
disk->driverfs_dev->driver != NULL)
@@ -1501,9 +1506,9 @@ static void __disk_unblock_events(struct gendisk *disk, bool check_now)
intv = disk_events_poll_jiffies(disk);
set_timer_slack(&ev->dwork.timer, intv / 4);
if (check_now)
- queue_delayed_work(system_nrt_wq, &ev->dwork, 0);
+ queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, 0);
else if (intv)
- queue_delayed_work(system_nrt_wq, &ev->dwork, intv);
+ queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, intv);
out_unlock:
spin_unlock_irqrestore(&ev->lock, flags);
}
@@ -1544,7 +1549,7 @@ void disk_check_events(struct gendisk *disk)
spin_lock_irqsave(&ev->lock, flags);
if (!ev->block) {
cancel_delayed_work(&ev->dwork);
- queue_delayed_work(system_nrt_wq, &ev->dwork, 0);
+ queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, 0);
}
spin_unlock_irqrestore(&ev->lock, flags);
}
@@ -1582,7 +1587,7 @@ unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask)
/* uncondtionally schedule event check and wait for it to finish */
disk_block_events(disk);
- queue_delayed_work(system_nrt_wq, &ev->dwork, 0);
+ queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, 0);
flush_delayed_work(&ev->dwork);
__disk_unblock_events(disk, false);
@@ -1619,7 +1624,7 @@ static void disk_events_workfn(struct work_struct *work)
intv = disk_events_poll_jiffies(disk);
if (!ev->block && intv)
- queue_delayed_work(system_nrt_wq, &ev->dwork, intv);
+ queue_delayed_work(system_nrt_freezable_wq, &ev->dwork, intv);
spin_unlock_irq(&ev->lock);
@@ -1757,9 +1762,9 @@ module_param_cb(events_dfl_poll_msecs, &disk_events_dfl_poll_msecs_param_ops,
&disk_events_dfl_poll_msecs, 0644);
/*
- * disk_{add|del|release}_events - initialize and destroy disk_events.
+ * disk_{alloc|add|del|release}_events - initialize and destroy disk_events.
*/
-static void disk_add_events(struct gendisk *disk)
+static void disk_alloc_events(struct gendisk *disk)
{
struct disk_events *ev;
@@ -1772,16 +1777,6 @@ static void disk_add_events(struct gendisk *disk)
return;
}
- if (sysfs_create_files(&disk_to_dev(disk)->kobj,
- disk_events_attrs) < 0) {
- pr_warn("%s: failed to create sysfs files for events\n",
- disk->disk_name);
- kfree(ev);
- return;
- }
-
- disk->ev = ev;
-
INIT_LIST_HEAD(&ev->node);
ev->disk = disk;
spin_lock_init(&ev->lock);
@@ -1790,8 +1785,21 @@ static void disk_add_events(struct gendisk *disk)
ev->poll_msecs = -1;
INIT_DELAYED_WORK(&ev->dwork, disk_events_workfn);
+ disk->ev = ev;
+}
+
+static void disk_add_events(struct gendisk *disk)
+{
+ if (!disk->ev)
+ return;
+
+ /* FIXME: error handling */
+ if (sysfs_create_files(&disk_to_dev(disk)->kobj, disk_events_attrs) < 0)
+ pr_warn("%s: failed to create sysfs files for events\n",
+ disk->disk_name);
+
mutex_lock(&disk_events_mutex);
- list_add_tail(&ev->node, &disk_events);
+ list_add_tail(&disk->ev->node, &disk_events);
mutex_unlock(&disk_events_mutex);
/*
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index 4f4230b79bb6..5ef1f4c17e69 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -24,6 +24,7 @@
#include <linux/capability.h>
#include <linux/completion.h>
#include <linux/cdrom.h>
+#include <linux/ratelimit.h>
#include <linux/slab.h>
#include <linux/times.h>
#include <asm/uaccess.h>
@@ -691,6 +692,57 @@ int scsi_cmd_ioctl(struct request_queue *q, struct gendisk *bd_disk, fmode_t mod
}
EXPORT_SYMBOL(scsi_cmd_ioctl);
+int scsi_verify_blk_ioctl(struct block_device *bd, unsigned int cmd)
+{
+ if (bd && bd == bd->bd_contains)
+ return 0;
+
+ /* Actually none of these is particularly useful on a partition,
+ * but they are safe.
+ */
+ switch (cmd) {
+ case SCSI_IOCTL_GET_IDLUN:
+ case SCSI_IOCTL_GET_BUS_NUMBER:
+ case SCSI_IOCTL_GET_PCI:
+ case SCSI_IOCTL_PROBE_HOST:
+ case SG_GET_VERSION_NUM:
+ case SG_SET_TIMEOUT:
+ case SG_GET_TIMEOUT:
+ case SG_GET_RESERVED_SIZE:
+ case SG_SET_RESERVED_SIZE:
+ case SG_EMULATED_HOST:
+ return 0;
+ case CDROM_GET_CAPABILITY:
+ /* Keep this until we remove the printk below. udev sends it
+ * and we do not want to spam dmesg about it. CD-ROMs do
+ * not have partitions, so we get here only for disks.
+ */
+ return -ENOTTY;
+ default:
+ break;
+ }
+
+ /* In particular, rule out all resets and host-specific ioctls. */
+ printk_ratelimited(KERN_WARNING
+ "%s: sending ioctl %x to a partition!\n", current->comm, cmd);
+
+ return capable(CAP_SYS_RAWIO) ? 0 : -ENOTTY;
+}
+EXPORT_SYMBOL(scsi_verify_blk_ioctl);
+
+int scsi_cmd_blk_ioctl(struct block_device *bd, fmode_t mode,
+ unsigned int cmd, void __user *arg)
+{
+ int ret;
+
+ ret = scsi_verify_blk_ioctl(bd, cmd);
+ if (ret < 0)
+ return ret;
+
+ return scsi_cmd_ioctl(bd->bd_disk->queue, bd->bd_disk, mode, cmd, arg);
+}
+EXPORT_SYMBOL(scsi_cmd_blk_ioctl);
+
static int __init blk_scsi_ioctl_init(void)
{
blk_set_cmd_filter_defaults(&blk_default_cmd_filter);
diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c
index 9ed9f60316e5..dd30f40af9f5 100644
--- a/crypto/sha512_generic.c
+++ b/crypto/sha512_generic.c
@@ -21,8 +21,6 @@
#include <linux/percpu.h>
#include <asm/byteorder.h>
-static DEFINE_PER_CPU(u64[80], msg_schedule);
-
static inline u64 Ch(u64 x, u64 y, u64 z)
{
return z ^ (x & (y ^ z));
@@ -33,11 +31,6 @@ static inline u64 Maj(u64 x, u64 y, u64 z)
return (x & y) | (z & (x | y));
}
-static inline u64 RORu64(u64 x, u64 y)
-{
- return (x >> y) | (x << (64 - y));
-}
-
static const u64 sha512_K[80] = {
0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL,
0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
@@ -68,10 +61,10 @@ static const u64 sha512_K[80] = {
0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL,
};
-#define e0(x) (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39))
-#define e1(x) (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41))
-#define s0(x) (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7))
-#define s1(x) (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6))
+#define e0(x) (ror64(x,28) ^ ror64(x,34) ^ ror64(x,39))
+#define e1(x) (ror64(x,14) ^ ror64(x,18) ^ ror64(x,41))
+#define s0(x) (ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7))
+#define s1(x) (ror64(x,19) ^ ror64(x,61) ^ (x >> 6))
static inline void LOAD_OP(int I, u64 *W, const u8 *input)
{
@@ -80,7 +73,7 @@ static inline void LOAD_OP(int I, u64 *W, const u8 *input)
static inline void BLEND_OP(int I, u64 *W)
{
- W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
+ W[I & 15] += s1(W[(I-2) & 15]) + W[(I-7) & 15] + s0(W[(I-15) & 15]);
}
static void
@@ -89,15 +82,7 @@ sha512_transform(u64 *state, const u8 *input)
u64 a, b, c, d, e, f, g, h, t1, t2;
int i;
- u64 *W = get_cpu_var(msg_schedule);
-
- /* load the input */
- for (i = 0; i < 16; i++)
- LOAD_OP(i, W, input);
-
- for (i = 16; i < 80; i++) {
- BLEND_OP(i, W);
- }
+ u64 W[16];
/* load the state into our registers */
a=state[0]; b=state[1]; c=state[2]; d=state[3];
@@ -105,21 +90,35 @@ sha512_transform(u64 *state, const u8 *input)
/* now iterate */
for (i=0; i<80; i+=8) {
- t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i ] + W[i ];
+ if (!(i & 8)) {
+ int j;
+
+ if (i < 16) {
+ /* load the input */
+ for (j = 0; j < 16; j++)
+ LOAD_OP(i + j, W, input);
+ } else {
+ for (j = 0; j < 16; j++) {
+ BLEND_OP(i + j, W);
+ }
+ }
+ }
+
+ t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i ] + W[(i & 15)];
t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2;
- t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[i+1];
+ t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[(i & 15) + 1];
t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2;
- t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[i+2];
+ t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[(i & 15) + 2];
t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2;
- t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[i+3];
+ t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[(i & 15) + 3];
t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2;
- t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[i+4];
+ t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[(i & 15) + 4];
t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2;
- t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[i+5];
+ t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[(i & 15) + 5];
t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2;
- t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[i+6];
+ t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[(i & 15) + 6];
t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2;
- t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[i+7];
+ t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[(i & 15) + 7];
t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2;
}
@@ -128,8 +127,6 @@ sha512_transform(u64 *state, const u8 *input)
/* erase our data */
a = b = c = d = e = f = g = h = t1 = t2 = 0;
- memset(W, 0, sizeof(__get_cpu_var(msg_schedule)));
- put_cpu_var(msg_schedule);
}
static int
@@ -177,7 +174,7 @@ sha512_update(struct shash_desc *desc, const u8 *data, unsigned int len)
index = sctx->count[0] & 0x7f;
/* Update number of bytes */
- if (!(sctx->count[0] += len))
+ if ((sctx->count[0] += len) < len)
sctx->count[1]++;
part_len = 128 - index;
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h
index 1055769f2f01..6d276c20b57b 100644
--- a/drivers/acpi/acpica/acobject.h
+++ b/drivers/acpi/acpica/acobject.h
@@ -358,6 +358,7 @@ typedef enum {
*/
struct acpi_object_extra {
ACPI_OBJECT_COMMON_HEADER struct acpi_namespace_node *method_REG; /* _REG method for this region (if any) */
+ struct acpi_namespace_node *scope_node;
void *region_context; /* Region-specific data */
u8 *aml_start;
u32 aml_length;
diff --git a/drivers/acpi/acpica/dsargs.c b/drivers/acpi/acpica/dsargs.c
index 8c7b99728aa2..d69e4a53175b 100644
--- a/drivers/acpi/acpica/dsargs.c
+++ b/drivers/acpi/acpica/dsargs.c
@@ -384,8 +384,32 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
/* Execute the argument AML */
- status = acpi_ds_execute_arguments(node, node->parent,
+ status = acpi_ds_execute_arguments(node, extra_desc->extra.scope_node,
extra_desc->extra.aml_length,
extra_desc->extra.aml_start);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /* Validate the region address/length via the host OS */
+
+ status = acpi_os_validate_address(obj_desc->region.space_id,
+ obj_desc->region.address,
+ (acpi_size) obj_desc->region.length,
+ acpi_ut_get_node_name(node));
+
+ if (ACPI_FAILURE(status)) {
+ /*
+ * Invalid address/length. We will emit an error message and mark
+ * the region as invalid, so that it will cause an additional error if
+ * it is ever used. Then return AE_OK.
+ */
+ ACPI_EXCEPTION((AE_INFO, status,
+ "During address validation of OpRegion [%4.4s]",
+ node->name.ascii));
+ obj_desc->common.flags |= AOPOBJ_INVALID;
+ status = AE_OK;
+ }
+
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/excreate.c b/drivers/acpi/acpica/excreate.c
index 110711afada8..8a06dc523af7 100644
--- a/drivers/acpi/acpica/excreate.c
+++ b/drivers/acpi/acpica/excreate.c
@@ -330,6 +330,12 @@ acpi_ex_create_region(u8 * aml_start,
region_obj2 = obj_desc->common.next_object;
region_obj2->extra.aml_start = aml_start;
region_obj2->extra.aml_length = aml_length;
+ if (walk_state->scope_info) {
+ region_obj2->extra.scope_node =
+ walk_state->scope_info->scope.node;
+ } else {
+ region_obj2->extra.scope_node = node;
+ }
/* Init the region from the operands */
diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c
index 6f5588e62c0a..4c531b4a9625 100644
--- a/drivers/acpi/acpica/tbfadt.c
+++ b/drivers/acpi/acpica/tbfadt.c
@@ -350,10 +350,6 @@ static void acpi_tb_convert_fadt(void)
u32 address32;
u32 i;
- /* Update the local FADT table header length */
-
- acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt);
-
/*
* Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary.
* Later code will always use the X 64-bit field. Also, check for an
@@ -395,6 +391,10 @@ static void acpi_tb_convert_fadt(void)
acpi_gbl_FADT.boot_flags = 0;
}
+ /* Update the local FADT table header length */
+
+ acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt);
+
/*
* Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X"
* generic address structures as necessary. Later code will always use
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index fcc13ac0aa18..d77c97de9e73 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -635,11 +635,19 @@ static int acpi_battery_update(struct acpi_battery *battery)
static void acpi_battery_refresh(struct acpi_battery *battery)
{
+ int power_unit;
+
if (!battery->bat.dev)
return;
+ power_unit = battery->power_unit;
+
acpi_battery_get_info(battery);
- /* The battery may have changed its reporting units. */
+
+ if (power_unit == battery->power_unit)
+ return;
+
+ /* The battery has changed its reporting units. */
sysfs_remove_battery(battery);
sysfs_add_battery(battery);
}
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 3b5c3189fd99..e56f3be7b07d 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -45,6 +45,8 @@ static int pxm_to_node_map[MAX_PXM_DOMAINS]
static int node_to_pxm_map[MAX_NUMNODES]
= { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
+unsigned char acpi_srat_revision __initdata;
+
int pxm_to_node(int pxm)
{
if (pxm < 0)
@@ -255,9 +257,13 @@ acpi_parse_memory_affinity(struct acpi_subtable_header * header,
static int __init acpi_parse_srat(struct acpi_table_header *table)
{
+ struct acpi_table_srat *srat;
if (!table)
return -EINVAL;
+ srat = (struct acpi_table_srat *)table;
+ acpi_srat_revision = srat->header.revision;
+
/* Real work done in acpi_table_parse_srat below. */
return 0;
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index d06078d660ad..dfafecbddb53 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -595,6 +595,13 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
if (ACPI_SUCCESS(status)) {
dev_info(root->bus->bridge,
"ACPI _OSC control (0x%02x) granted\n", flags);
+ if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
+ /*
+ * We have ASPM control, but the FADT indicates
+ * that it's unsupported. Clear it.
+ */
+ pcie_clear_aspm(root->bus);
+ }
} else {
dev_info(root->bus->bridge,
"ACPI _OSC request failed (%s), "
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 02d2a4c9084d..0c0669fb1cc4 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -172,8 +172,30 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id)
apic_id = map_mat_entry(handle, type, acpi_id);
if (apic_id == -1)
apic_id = map_madt_entry(type, acpi_id);
- if (apic_id == -1)
- return apic_id;
+ if (apic_id == -1) {
+ /*
+ * On UP processor, there is no _MAT or MADT table.
+ * So above apic_id is always set to -1.
+ *
+ * BIOS may define multiple CPU handles even for UP processor.
+ * For example,
+ *
+ * Scope (_PR)
+ * {
+ * Processor (CPU0, 0x00, 0x00000410, 0x06) {}
+ * Processor (CPU1, 0x01, 0x00000410, 0x06) {}
+ * Processor (CPU2, 0x02, 0x00000410, 0x06) {}
+ * Processor (CPU3, 0x03, 0x00000410, 0x06) {}
+ * }
+ *
+ * Ignores apic_id and always return 0 for CPU0's handle.
+ * Return -1 for other CPU's handle.
+ */
+ if (acpi_id == 0)
+ return acpi_id;
+ else
+ return apic_id;
+ }
#ifdef CONFIG_SMP
for_each_possible_cpu(i) {
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
index 79cb65332894..3854df25ac93 100644
--- a/drivers/acpi/processor_thermal.c
+++ b/drivers/acpi/processor_thermal.c
@@ -58,6 +58,27 @@ ACPI_MODULE_NAME("processor_thermal");
static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg);
static unsigned int acpi_thermal_cpufreq_is_init = 0;
+#define reduction_pctg(cpu) \
+ per_cpu(cpufreq_thermal_reduction_pctg, phys_package_first_cpu(cpu))
+
+/*
+ * Emulate "per package data" using per cpu data (which should really be
+ * provided elsewhere)
+ *
+ * Note we can lose a CPU on cpu hotunplug, in this case we forget the state
+ * temporarily. Fortunately that's not a big issue here (I hope)
+ */
+static int phys_package_first_cpu(int cpu)
+{
+ int i;
+ int id = topology_physical_package_id(cpu);
+
+ for_each_online_cpu(i)
+ if (topology_physical_package_id(i) == id)
+ return i;
+ return 0;
+}
+
static int cpu_has_cpufreq(unsigned int cpu)
{
struct cpufreq_policy policy;
@@ -77,7 +98,7 @@ static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb,
max_freq = (
policy->cpuinfo.max_freq *
- (100 - per_cpu(cpufreq_thermal_reduction_pctg, policy->cpu) * 20)
+ (100 - reduction_pctg(policy->cpu) * 20)
) / 100;
cpufreq_verify_within_limits(policy, 0, max_freq);
@@ -103,16 +124,28 @@ static int cpufreq_get_cur_state(unsigned int cpu)
if (!cpu_has_cpufreq(cpu))
return 0;
- return per_cpu(cpufreq_thermal_reduction_pctg, cpu);
+ return reduction_pctg(cpu);
}
static int cpufreq_set_cur_state(unsigned int cpu, int state)
{
+ int i;
+
if (!cpu_has_cpufreq(cpu))
return 0;
- per_cpu(cpufreq_thermal_reduction_pctg, cpu) = state;
- cpufreq_update_policy(cpu);
+ reduction_pctg(cpu) = state;
+
+ /*
+ * Update all the CPUs in the same package because they all
+ * contribute to the temperature and often share the same
+ * frequency.
+ */
+ for_each_online_cpu(i) {
+ if (topology_physical_package_id(i) ==
+ topology_physical_package_id(cpu))
+ cpufreq_update_policy(i);
+ }
return 0;
}
@@ -120,10 +153,6 @@ void acpi_thermal_cpufreq_init(void)
{
int i;
- for (i = 0; i < nr_cpu_ids; i++)
- if (cpu_present(i))
- per_cpu(cpufreq_thermal_reduction_pctg, i) = 0;
-
i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block,
CPUFREQ_POLICY_NOTIFIER);
if (!i)
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 6c949602cbd1..79ddcdee83ad 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -422,12 +422,36 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
},
{
.callback = init_nvs_nosave,
+ .ident = "Sony Vaio VPCCW29FX",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VPCCW29FX"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
.ident = "Averatec AV1020-ED2",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"),
DMI_MATCH(DMI_PRODUCT_NAME, "1000 Series"),
},
},
+ {
+ .callback = init_nvs_nosave,
+ .ident = "Asus K54C",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "K54C"),
+ },
+ },
+ {
+ .callback = init_nvs_nosave,
+ .ident = "Asus K54HR",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "K54HR"),
+ },
+ },
{},
};
#endif /* CONFIG_SUSPEND */
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
index db39e9e607d8..623a3357ce9b 100644
--- a/drivers/acpi/video.c
+++ b/drivers/acpi/video.c
@@ -1732,6 +1732,7 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type)
static int __init intel_opregion_present(void)
{
+ int i915 = 0;
#if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE)
struct pci_dev *dev = NULL;
u32 address;
@@ -1744,10 +1745,10 @@ static int __init intel_opregion_present(void)
pci_read_config_dword(dev, 0xfc, &address);
if (!address)
continue;
- return 1;
+ i915 = 1;
}
#endif
- return 0;
+ return i915;
}
int acpi_video_register(void)
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 1e9ab9bf8549..abf2f4e10fd6 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -392,6 +392,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
.driver_data = board_ahci_yes_fbs }, /* 88se9128 */
{ PCI_DEVICE(0x1b4b, 0x9125),
.driver_data = board_ahci_yes_fbs }, /* 88se9125 */
+ { PCI_DEVICE(0x1b4b, 0x917a),
+ .driver_data = board_ahci_yes_fbs }, /* 88se9172 */
{ PCI_DEVICE(0x1b4b, 0x91a3),
.driver_data = board_ahci_yes_fbs },
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 6fef1fa75c54..936babd0fb9e 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -171,12 +171,78 @@ static int __devexit ahci_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM
+static int ahci_device_suspend(struct platform_device *pdev, pm_message_t msg)
+{
+ struct device *dev = &pdev->dev;
+ struct ahci_platform_data *pdata = dev_get_platdata(dev);
+ struct ata_host *host = dev_get_drvdata(dev);
+ struct ahci_host_priv *hpriv = host->private_data;
+ void __iomem *mmio = hpriv->mmio;
+ u32 ctl;
+ int rc;
+
+ if (hpriv->flags & AHCI_HFLAG_NO_SUSPEND) {
+ dev_err(dev, "firmware update required for suspend/resume\n");
+ return -EIO;
+ }
+
+ /*
+ * AHCI spec rev1.1 section 8.3.3:
+ * Software must disable interrupts prior to requesting a
+ * transition of the HBA to D3 state.
+ */
+ ctl = readl(mmio + HOST_CTL);
+ ctl &= ~HOST_IRQ_EN;
+ writel(ctl, mmio + HOST_CTL);
+ readl(mmio + HOST_CTL); /* flush */
+
+ rc = ata_host_suspend(host, msg);
+ if (rc)
+ return rc;
+
+ if (pdata && pdata->suspend)
+ return pdata->suspend(dev);
+ return 0;
+}
+
+static int ahci_device_resume(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct ahci_platform_data *pdata = dev_get_platdata(dev);
+ struct ata_host *host = dev_get_drvdata(dev);
+ int rc;
+
+ if (pdata && pdata->resume) {
+ rc = pdata->resume(dev);
+ if (rc)
+ return rc;
+ }
+
+ if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
+ rc = ahci_reset_controller(host);
+ if (rc)
+ return rc;
+
+ ahci_init_controller(host);
+ }
+
+ ata_host_resume(host);
+
+ return 0;
+}
+#endif /* CONFIG_PM */
+
static struct platform_driver ahci_driver = {
.remove = __devexit_p(ahci_remove),
.driver = {
.name = "ahci",
.owner = THIS_MODULE,
},
+#ifdef CONFIG_PM
+ .suspend = ahci_device_suspend,
+ .resume = ahci_device_resume,
+#endif
};
static int __init ahci_init(void)
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 7f099d6e4e0b..311c92d1db25 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -3487,7 +3487,8 @@ static int ata_count_probe_trials_cb(struct ata_ering_entry *ent, void *void_arg
u64 now = get_jiffies_64();
int *trials = void_arg;
- if (ent->timestamp < now - min(now, interval))
+ if ((ent->eflags & ATA_EFLAG_OLD_ER) ||
+ (ent->timestamp < now - min(now, interval)))
return -1;
(*trials)++;
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c
index 6bd9425ba5ab..d750962916b1 100644
--- a/drivers/ata/pata_legacy.c
+++ b/drivers/ata/pata_legacy.c
@@ -396,8 +396,7 @@ static void ht6560b_set_piomode(struct ata_port *ap, struct ata_device *adev)
ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000);
active = clamp_val(t.active, 2, 15);
- recover = clamp_val(t.recover, 2, 16);
- recover &= 0x15;
+ recover = clamp_val(t.recover, 2, 16) & 0x0F;
inb(0x3E6);
inb(0x3E6);
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index 5d1d07645132..d4525928fb7f 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -984,6 +984,7 @@ static uint32_t fpga_tx(struct solos_card *card)
} else if (skb && card->using_dma) {
SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data,
skb->len, PCI_DMA_TODEVICE);
+ card->tx_skb[port] = skb;
iowrite32(SKB_CB(skb)->dma_addr,
card->config_regs + TX_DMA_ADDR(port));
}
@@ -1152,7 +1153,8 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
db_fpga_upgrade = db_firmware_upgrade = 0;
}
- if (card->fpga_version >= DMA_SUPPORTED){
+ if (card->fpga_version >= DMA_SUPPORTED) {
+ pci_set_master(dev);
card->using_dma = 1;
} else {
card->using_dma = 0;
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 78445f40c430..d13851c5c684 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1743,8 +1743,10 @@ void device_shutdown(void)
*/
list_del_init(&dev->kobj.entry);
spin_unlock(&devices_kset->list_lock);
- /* Disable all device's runtime power management */
- pm_runtime_disable(dev);
+
+ /* Don't allow any more runtime suspends */
+ pm_runtime_get_noresume(dev);
+ pm_runtime_barrier(dev);
if (dev->bus && dev->bus->shutdown) {
dev_dbg(dev, "shutdown\n");
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 06ed6b4e7df5..3719c94be19c 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -226,13 +226,13 @@ static ssize_t firmware_loading_store(struct device *dev,
int loading = simple_strtol(buf, NULL, 10);
int i;
+ mutex_lock(&fw_lock);
+
+ if (!fw_priv->fw)
+ goto out;
+
switch (loading) {
case 1:
- mutex_lock(&fw_lock);
- if (!fw_priv->fw) {
- mutex_unlock(&fw_lock);
- break;
- }
firmware_free_data(fw_priv->fw);
memset(fw_priv->fw, 0, sizeof(struct firmware));
/* If the pages are not owned by 'struct firmware' */
@@ -243,7 +243,6 @@ static ssize_t firmware_loading_store(struct device *dev,
fw_priv->page_array_size = 0;
fw_priv->nr_pages = 0;
set_bit(FW_STATUS_LOADING, &fw_priv->status);
- mutex_unlock(&fw_lock);
break;
case 0:
if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) {
@@ -274,7 +273,8 @@ static ssize_t firmware_loading_store(struct device *dev,
fw_load_abort(fw_priv);
break;
}
-
+out:
+ mutex_unlock(&fw_lock);
return count;
}
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index c2f9b3e3dec7..1dab802d82b9 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -1716,7 +1716,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
case CCISS_BIG_PASSTHRU:
return cciss_bigpassthru(h, argp);
- /* scsi_cmd_ioctl handles these, below, though some are not */
+ /* scsi_cmd_blk_ioctl handles these, below, though some are not */
/* very meaningful for cciss. SG_IO is the main one people want. */
case SG_GET_VERSION_NUM:
@@ -1727,9 +1727,9 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
case SG_EMULATED_HOST:
case SG_IO:
case SCSI_IOCTL_SEND_COMMAND:
- return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
+ return scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
- /* scsi_cmd_ioctl would normally handle these, below, but */
+ /* scsi_cmd_blk_ioctl would normally handle these, below, but */
/* they aren't a good fit for cciss, as CD-ROMs are */
/* not supported, and we don't have any bus/target/lun */
/* which we present to the kernel. */
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 696100241a6f..a552cab85a21 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -866,6 +866,7 @@ cciss_scsi_detect(ctlr_info_t *h)
sh->can_queue = cciss_tape_cmds;
sh->sg_tablesize = h->maxsgentries;
sh->max_cmd_len = MAX_COMMAND_SIZE;
+ sh->max_sectors = h->cciss_max_sectors;
((struct cciss_scsi_adapter_data_t *)
h->scsi_ctlr)->scsi_host = sh;
@@ -1410,7 +1411,7 @@ static void cciss_scatter_gather(ctlr_info_t *h, CommandList_struct *c,
/* track how many SG entries we are using */
if (request_nsgs > h->maxSG)
h->maxSG = request_nsgs;
- c->Header.SGTotal = (__u8) request_nsgs + chained;
+ c->Header.SGTotal = (u16) request_nsgs + chained;
if (request_nsgs > h->max_cmd_sgentries)
c->Header.SGList = h->max_cmd_sgentries;
else
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index b70f0fca9a42..eec7b7a43cba 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -1116,7 +1116,7 @@ static inline void carm_handle_resp(struct carm_host *host,
break;
case MISC_GET_FW_VER: {
struct carm_fw_ver *ver = (struct carm_fw_ver *)
- mem + sizeof(struct carm_msg_get_fw_ver);
+ (mem + sizeof(struct carm_msg_get_fw_ver));
if (!error) {
host->fw_ver = le32_to_cpu(ver->version);
host->flags |= (ver->features & FL_FW_VER_MASK);
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index 0e376d46bdd1..7333b9e44411 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -1744,12 +1744,11 @@ static int ub_bd_release(struct gendisk *disk, fmode_t mode)
static int ub_bd_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
- struct gendisk *disk = bdev->bd_disk;
void __user *usermem = (void __user *) arg;
int ret;
mutex_lock(&ub_mutex);
- ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, usermem);
+ ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, usermem);
mutex_unlock(&ub_mutex);
return ret;
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 079c08808d8a..5d7a93403632 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -236,8 +236,8 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI))
return -ENOTTY;
- return scsi_cmd_ioctl(disk->queue, disk, mode, cmd,
- (void __user *)data);
+ return scsi_cmd_blk_ioctl(bdev, mode, cmd,
+ (void __user *)data);
}
/* We provide getgeo only to please some old bootloader/partitioning tools */
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index db7cb8111fbe..305e752678ed 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -64,16 +64,23 @@ static struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x0CF3, 0x3002) },
{ USB_DEVICE(0x13d3, 0x3304) },
{ USB_DEVICE(0x0930, 0x0215) },
+ { USB_DEVICE(0x0489, 0xE03D) },
/* Atheros AR9285 Malbec with sflash firmware */
{ USB_DEVICE(0x03F0, 0x311D) },
/* Atheros AR3012 with sflash firmware*/
{ USB_DEVICE(0x0CF3, 0x3004) },
+ { USB_DEVICE(0x0CF3, 0x311D) },
+ { USB_DEVICE(0x13d3, 0x3375) },
+ { USB_DEVICE(0x04CA, 0x3005) },
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE02C) },
+ /* Atheros AR5BBU22 with sflash firmware */
+ { USB_DEVICE(0x0489, 0xE03C) },
+
{ } /* Terminating entry */
};
@@ -86,6 +93,12 @@ static struct usb_device_id ath3k_blist_tbl[] = {
/* Atheros AR3012 with sflash firmware*/
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
+
+ /* Atheros AR5BBU22 with sflash firmware */
+ { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
{ } /* Terminating entry */
};
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index b9af6dbb46d8..f4585b90841d 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -61,7 +61,7 @@ static struct usb_device_id btusb_table[] = {
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
/* Broadcom SoftSailing reporting vendor specific */
- { USB_DEVICE(0x05ac, 0x21e1) },
+ { USB_DEVICE(0x0a5c, 0x21e1) },
/* Apple MacBookPro 7,1 */
{ USB_DEVICE(0x05ac, 0x8213) },
@@ -100,6 +100,17 @@ static struct usb_device_id btusb_table[] = {
/* Canyon CN-BTU1 with HID interfaces */
{ USB_DEVICE(0x0c10, 0x0000) },
+ /* Broadcom BCM20702A0 */
+ { USB_DEVICE(0x0489, 0xe042) },
+ { USB_DEVICE(0x0a5c, 0x21e3) },
+ { USB_DEVICE(0x0a5c, 0x21e6) },
+ { USB_DEVICE(0x0a5c, 0x21e8) },
+ { USB_DEVICE(0x0a5c, 0x21f3) },
+ { USB_DEVICE(0x413c, 0x8197) },
+
+ /* Foxconn - Hon Hai */
+ { USB_DEVICE(0x0489, 0xe033) },
+
{ } /* Terminating entry */
};
@@ -116,16 +127,23 @@ static struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
+ { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
/* Atheros AR9285 Malbec with sflash firmware */
{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
/* Atheros 3012 with sflash firmware */
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+ { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
+ /* Atheros AR5BBU12 with sflash firmware */
+ { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
+
/* Broadcom BCM2035 */
{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
@@ -497,15 +515,10 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress);
- urb->dev = data->udev;
- urb->pipe = pipe;
- urb->context = hdev;
- urb->complete = btusb_isoc_complete;
- urb->interval = data->isoc_rx_ep->bInterval;
+ usb_fill_int_urb(urb, data->udev, pipe, buf, size, btusb_isoc_complete,
+ hdev, data->isoc_rx_ep->bInterval);
urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP;
- urb->transfer_buffer = buf;
- urb->transfer_buffer_length = size;
__fill_isoc_descriptor(urb, size,
le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize));
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 48ad2a7ab080..8f3d6dbeb122 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -237,7 +237,6 @@ static void hci_uart_destruct(struct hci_dev *hdev)
return;
BT_DBG("%s", hdev->name);
- kfree(hdev->driver_data);
}
/* ------ LDISC part ------ */
@@ -310,12 +309,13 @@ static void hci_uart_tty_close(struct tty_struct *tty)
hci_uart_close(hdev);
if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
- hu->proto->close(hu);
if (hdev) {
hci_unregister_dev(hdev);
hci_free_dev(hdev);
}
+ hu->proto->close(hu);
}
+ kfree(hu);
}
}
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 75fb965b8f72..cc6471aa9f46 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -2114,11 +2114,6 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,
if (!nr)
return -ENOMEM;
- if (!access_ok(VERIFY_WRITE, ubuf, nframes * CD_FRAMESIZE_RAW)) {
- ret = -EFAULT;
- goto out;
- }
-
cgc.data_direction = CGC_DATA_READ;
while (nframes > 0) {
if (nr > nframes)
@@ -2127,7 +2122,7 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,
ret = cdrom_read_block(cdi, &cgc, lba, nr, 1, CD_FRAMESIZE_RAW);
if (ret)
break;
- if (__copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) {
+ if (copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) {
ret = -EFAULT;
break;
}
@@ -2135,7 +2130,6 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,
nframes -= nr;
lba += nr;
}
-out:
kfree(cgc.buffer);
return ret;
}
@@ -2741,12 +2735,11 @@ int cdrom_ioctl(struct cdrom_device_info *cdi, struct block_device *bdev,
{
void __user *argp = (void __user *)arg;
int ret;
- struct gendisk *disk = bdev->bd_disk;
/*
* Try the generic SCSI command ioctl's first.
*/
- ret = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
+ ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
if (ret != -ENOTTY)
return ret;
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index b427711be4be..58b49d1a283b 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -897,6 +897,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_B43_HB),
ID(PCI_DEVICE_ID_INTEL_B43_1_HB),
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB),
+ ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB),
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB),
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB),
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB),
diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h
index 5da67f165afa..6f246049d5b4 100644
--- a/drivers/char/agp/intel-agp.h
+++ b/drivers/char/agp/intel-agp.h
@@ -211,6 +211,7 @@
#define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30
#define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32
#define PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB 0x0040
+#define PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB 0x0069
#define PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG 0x0042
#define PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB 0x0044
#define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062
diff --git a/drivers/char/hw_random/fsl-rngc.c b/drivers/char/hw_random/fsl-rngc.c
index 58f0afb2dcdc..0ce3299639b1 100644
--- a/drivers/char/hw_random/fsl-rngc.c
+++ b/drivers/char/hw_random/fsl-rngc.c
@@ -1,7 +1,7 @@
/*
* RNG driver for Freescale RNGC
*
- * Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
*/
/*
@@ -123,7 +123,7 @@ static struct platform_device *rng_dev;
int irq_rng;
-static int fsl_rngc_data_present(struct hwrng *rng)
+static int fsl_rngc_data_present(struct hwrng *rng, int wait)
{
int level;
u32 rngc_base = (u32) rng->priv;
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index c044060a4b07..c371bb46d4c4 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -9,7 +9,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o
obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o
obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o
obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o
-obj-$(CONFIG_CPU_FREQ_GOV_INTERACTIVE) += cpufreq_interactive.o
+obj-$(CONFIG_CPU_FREQ_GOV_INTERACTIVE) += cpufreq_interactive.o
# CPUfreq cross-arch helpers
obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index 2fc2f5f49e54..2db752c1d346 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -30,9 +30,6 @@
#include <linux/mutex.h>
#include <linux/kernel_stat.h>
-#define CREATE_TRACE_POINTS
-#include <trace/events/cpufreq_interactive.h>
-
#include <asm/cputime.h>
static atomic_t active_count = ATOMIC_INIT(0);
@@ -44,8 +41,8 @@ struct cpufreq_interactive_cpuinfo {
u64 idle_exit_time;
u64 timer_run_time;
int idling;
- u64 target_set_time;
- u64 target_set_time_in_idle;
+ u64 freq_change_time;
+ u64 freq_change_time_in_idle;
struct cpufreq_policy *policy;
struct cpufreq_frequency_table *freq_table;
unsigned int target_freq;
@@ -136,7 +133,6 @@ static bool cpufreq_interactive_check_irq(void)
return val;
}
-
static void cpufreq_interactive_timer(unsigned long data)
{
unsigned int delta_idle;
@@ -192,9 +188,9 @@ static void cpufreq_interactive_timer(unsigned long data)
cpu_load = 100 * (delta_time - delta_idle) / delta_time;
delta_idle = (unsigned int) cputime64_sub(now_idle,
- pcpu->target_set_time_in_idle);
+ pcpu->freq_change_time_in_idle);
delta_time = (unsigned int) cputime64_sub(pcpu->timer_run_time,
- pcpu->target_set_time);
+ pcpu->freq_change_time);
if ((delta_time == 0) || (delta_idle > delta_time))
load_since_change = 0;
@@ -212,18 +208,14 @@ static void cpufreq_interactive_timer(unsigned long data)
irq_load = cpufreq_interactive_check_irq();
if (cpu_load >= go_hispeed_load || irq_load) {
- if (pcpu->policy->cur == pcpu->policy->min) {
+ if (pcpu->policy->cur == pcpu->policy->min)
new_freq = hispeed_freq;
- } else {
+ else
new_freq = pcpu->policy->max * cpu_load / 100;
-
- if (new_freq < hispeed_freq)
- new_freq = hispeed_freq;
- }
if (irq_load)
new_freq = hispeed_freq;
} else {
- new_freq = pcpu->policy->max * cpu_load / 100;
+ new_freq = pcpu->policy->cur * cpu_load / 100;
}
if (cpufreq_frequency_table_target(pcpu->policy, pcpu->freq_table,
@@ -235,32 +227,19 @@ static void cpufreq_interactive_timer(unsigned long data)
}
new_freq = pcpu->freq_table[index].frequency;
+ if (pcpu->target_freq == new_freq)
+ goto rearm_if_notmax;
/*
* Do not scale down unless we have been at this frequency for the
* minimum sample time.
*/
if (new_freq < pcpu->target_freq) {
- if (cputime64_sub(pcpu->timer_run_time, pcpu->target_set_time)
- < min_sample_time) {
- trace_cpufreq_interactive_notyet(data, cpu_load,
- pcpu->target_freq, new_freq);
+ if (cputime64_sub(pcpu->timer_run_time, pcpu->freq_change_time)
+ < min_sample_time)
goto rearm;
- }
- }
-
- pcpu->target_set_time_in_idle = now_idle;
- pcpu->target_set_time = pcpu->timer_run_time;
-
- if (pcpu->target_freq == new_freq) {
- trace_cpufreq_interactive_already(data, cpu_load,
- pcpu->target_freq, new_freq);
- goto rearm_if_notmax;
}
- trace_cpufreq_interactive_target(data, cpu_load, pcpu->target_freq,
- new_freq);
-
if (new_freq < pcpu->target_freq) {
pcpu->target_freq = new_freq;
spin_lock_irqsave(&down_cpumask_lock, flags);
@@ -315,11 +294,10 @@ static void cpufreq_interactive_idle_start(void)
&per_cpu(cpuinfo, smp_processor_id());
int pending;
- if (!pcpu->governor_enabled)
- return;
-
pcpu->idling = 1;
smp_wmb();
+ if (!pcpu->governor_enabled)
+ return;
pending = timer_pending(&pcpu->cpu_timer);
if (pcpu->target_freq != pcpu->policy->min) {
@@ -432,18 +410,18 @@ static int cpufreq_interactive_up_task(void *data)
for_each_online_cpu(j) {
struct cpufreq_interactive_cpuinfo *pjcpu =
&per_cpu(cpuinfo, j);
-
if (pjcpu->target_freq > max_freq)
max_freq = pjcpu->target_freq;
}
-
if (max_freq != pcpu->policy->cur)
__cpufreq_driver_target(pcpu->policy,
max_freq,
CPUFREQ_RELATION_H);
mutex_unlock(&set_speed_lock);
- trace_cpufreq_interactive_up(cpu, pcpu->target_freq,
- pcpu->policy->cur);
+
+ pcpu->freq_change_time_in_idle =
+ get_cpu_idle_time_us(cpu,
+ &pcpu->freq_change_time);
}
}
@@ -485,8 +463,9 @@ static void cpufreq_interactive_freq_down(struct work_struct *work)
CPUFREQ_RELATION_H);
mutex_unlock(&set_speed_lock);
- trace_cpufreq_interactive_down(cpu, pcpu->target_freq,
- pcpu->policy->cur);
+ pcpu->freq_change_time_in_idle =
+ get_cpu_idle_time_us(cpu,
+ &pcpu->freq_change_time);
}
}
@@ -580,6 +559,7 @@ static ssize_t store_timer_rate(struct kobject *kobj,
static struct global_attr timer_rate_attr = __ATTR(timer_rate, 0644,
show_timer_rate, store_timer_rate);
+
static ssize_t show_irq_param(struct kobject *kobj,
struct attribute *attr, char *buf)
{
@@ -656,11 +636,15 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy,
for_each_cpu(j, policy->cpus) {
pcpu = &per_cpu(cpuinfo, j);
pcpu->policy = policy;
- pcpu->target_freq = policy->cur;
+ if (pcpu->idling)
+ pcpu->target_freq = policy->min;
+ else
+ pcpu->target_freq = policy->cur;
+
pcpu->freq_table = freq_table;
- pcpu->target_set_time_in_idle =
+ pcpu->freq_change_time_in_idle =
get_cpu_idle_time_us(j,
- &pcpu->target_set_time);
+ &pcpu->freq_change_time);
pcpu->governor_enabled = 1;
smp_wmb();
}
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
index bce576d7478e..ad683ec2c57e 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -54,6 +54,9 @@ static DEFINE_PER_CPU(struct powernow_k8_data *, powernow_data);
static int cpu_family = CPU_OPTERON;
+/* array to map SW pstate number to acpi state */
+static u32 ps_to_as[8];
+
/* core performance boost */
static bool cpb_capable, cpb_enabled;
static struct msr __percpu *msrs;
@@ -80,9 +83,9 @@ static u32 find_khz_freq_from_fid(u32 fid)
}
static u32 find_khz_freq_from_pstate(struct cpufreq_frequency_table *data,
- u32 pstate)
+ u32 pstate)
{
- return data[pstate].frequency;
+ return data[ps_to_as[pstate]].frequency;
}
/* Return the vco fid for an input fid
@@ -926,23 +929,27 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data,
invalidate_entry(powernow_table, i);
continue;
}
- rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi);
- if (!(hi & HW_PSTATE_VALID_MASK)) {
- pr_debug("invalid pstate %d, ignoring\n", index);
- invalidate_entry(powernow_table, i);
- continue;
- }
- powernow_table[i].index = index;
+ ps_to_as[index] = i;
/* Frequency may be rounded for these */
if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10)
|| boot_cpu_data.x86 == 0x11) {
+
+ rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi);
+ if (!(hi & HW_PSTATE_VALID_MASK)) {
+ pr_debug("invalid pstate %d, ignoring\n", index);
+ invalidate_entry(powernow_table, i);
+ continue;
+ }
+
powernow_table[i].frequency =
freq_from_fid_did(lo & 0x3f, (lo >> 6) & 7);
} else
powernow_table[i].frequency =
data->acpi_data.states[i].core_frequency * 1000;
+
+ powernow_table[i].index = index;
}
return 0;
}
@@ -1189,7 +1196,8 @@ static int powernowk8_target(struct cpufreq_policy *pol,
powernow_k8_acpi_pst_values(data, newstate);
if (cpu_family == CPU_HW_PSTATE)
- ret = transition_frequency_pstate(data, newstate);
+ ret = transition_frequency_pstate(data,
+ data->powernow_table[newstate].index);
else
ret = transition_frequency_fidvid(data, newstate);
if (ret) {
@@ -1202,7 +1210,7 @@ static int powernowk8_target(struct cpufreq_policy *pol,
if (cpu_family == CPU_HW_PSTATE)
pol->cur = find_khz_freq_from_pstate(data->powernow_table,
- newstate);
+ data->powernow_table[newstate].index);
else
pol->cur = find_khz_freq_from_fid(data->currfid);
ret = 0;
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 13fdb2c3c465..ed37f0a758d8 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -173,6 +173,7 @@ config CRYPTO_DEV_MV_CESA
select CRYPTO_ALGAPI
select CRYPTO_AES
select CRYPTO_BLKCIPHER2
+ select CRYPTO_HASH
help
This driver allows you to utilize the Cryptographic Engines and
Security Accelerator (CESA) which can be found on the Marvell Orion
@@ -293,13 +294,13 @@ config CRYPTO_DEV_S5P
algorithms execution.
config CRYPTO_DEV_DCP
tristate "Support for the DCP engine"
- depends on SOC_IMX28 || SOC_IMX23 || SOC_IMX50
+ depends on SOC_IMX28 || SOC_IMX23 || SOC_IMX50 || SOC_IMX6SL
select CRYPTO_ALGAPI
select CRYPTO_BLKCIPHER
help
- Say 'Y' here to use the DCP AES and SHA
- engine for the CryptoAPI algorithms.
- To compile this driver as a module, choose M here: the module
- will be called geode-aes.
+ Say 'Y' here to use the DCP AES and SHA
+ engine for the CryptoAPI algorithms.
+ To compile this driver as a module, choose M here: the module
+ will be called geode-aes.
endif # CRYPTO_HW
diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index 82a1011978d8..a4637711e9bc 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -58,7 +58,9 @@ config CRYPTO_DEV_FSL_CAAM_INTC_TIME_THLD
threshold. Range is 1-65535.
config CRYPTO_DEV_FSL_CAAM_CRYPTO_API
- tristate "Register algorithm implementations with the Crypto API"
+# Forced to non-module for current ARM branch, until CONFIG_OF possible
+# tristate "Register algorithm implementations with the Crypto API"
+ boolean "Register algorithm implementations with the Crypto API"
depends on CRYPTO_DEV_FSL_CAAM
default y
select CRYPTO_ALGAPI
@@ -70,3 +72,40 @@ config CRYPTO_DEV_FSL_CAAM_CRYPTO_API
To compile this as a module, choose M here: the module
will be called caamalg.
+
+config CRYPTO_DEV_FSL_CAAM_AHASH_API
+# Forced to non-module for current ARM branch, until CONFIG_OF possible
+# tristate "Register hash algorithm implementations with Crypto API"
+ boolean "Register hash algorithm implementations with Crypto API"
+ depends on CRYPTO_DEV_FSL_CAAM
+ default y
+ select CRYPTO_AHASH
+ help
+ Selecting this will offload ahash for users of the
+ scatterlist crypto API to the SEC4 via job ring.
+
+ To compile this as a module, choose M here: the module
+ will be called caamhash.
+
+config CRYPTO_DEV_FSL_CAAM_RNG_API
+# Forced to non-module for current ARM branch, until CONFIG_OF possible
+# tristate "Register caam device for hwrng API"
+ boolean "Register caam device for hwrng API"
+ depends on CRYPTO_DEV_FSL_CAAM
+ default y
+ select CRYPTO_RNG
+ help
+ Selecting this will register the SEC4 hardware rng to
+ the hw_random API for suppying the kernel entropy pool.
+
+ To compile this as a module, choose M here: the module
+ will be called caamrng.
+
+config CRYPTO_DEV_FSL_CAAM_RNG_TEST
+ boolean "Test caam rng"
+ depends on CRYPTO_DEV_FSL_CAAM_RNG_API
+ default n
+ help
+ Selecting this will enable self-test for caam rng.
+
+
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
index ef39011b4505..deee4b3a44df 100644
--- a/drivers/crypto/caam/Makefile
+++ b/drivers/crypto/caam/Makefile
@@ -4,5 +4,8 @@
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o
+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
+
+caam-objs := ctrl.o jr.o error.o key_gen.o
-caam-objs := ctrl.o jr.o error.o
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index 549d52675786..87b365f8089f 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -37,9 +37,10 @@
* | ShareDesc Pointer |
* | SEQ_OUT_PTR |
* | (output buffer) |
+ * | (output length) |
* | SEQ_IN_PTR |
* | (input buffer) |
- * | LOAD (to DECO) |
+ * | (input length) |
* ---------------------
*/
@@ -50,6 +51,8 @@
#include "desc_constr.h"
#include "jr.h"
#include "error.h"
+#include "sg_sw_sec4.h"
+#include "key_gen.h"
/*
* crypto alg
@@ -62,7 +65,7 @@
#define CAAM_MAX_IV_LENGTH 16
/* length of descriptors text */
-#define DESC_JOB_IO_LEN (CAAM_CMD_SZ * 3 + CAAM_PTR_SZ * 3)
+#define DESC_JOB_IO_LEN (CAAM_CMD_SZ * 5 + CAAM_PTR_SZ * 3)
#define DESC_AEAD_BASE (4 * CAAM_CMD_SZ)
#define DESC_AEAD_ENC_LEN (DESC_AEAD_BASE + 16 * CAAM_CMD_SZ)
@@ -113,7 +116,7 @@ static inline void append_dec_shr_done(u32 *desc)
jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TEST_ALL);
set_jump_tgt_here(desc, jump_cmd);
- append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
}
/*
@@ -143,11 +146,11 @@ static inline void aead_append_ld_iv(u32 *desc, int ivsize)
*/
static inline void ablkcipher_append_src_dst(u32 *desc)
{
- append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ); \
- append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ); \
- append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | \
- KEY_VLF | FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1); \
- append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF); \
+ append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+ append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 |
+ KEY_VLF | FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1);
+ append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | KEY_VLF);
}
/*
@@ -202,7 +205,7 @@ static void init_sh_desc_key_aead(u32 *desc, struct caam_ctx *ctx,
{
u32 *key_jump_cmd;
- init_sh_desc(desc, HDR_SHARE_WAIT);
+ init_sh_desc(desc, HDR_SHARE_SERIAL);
/* Skip if already shared */
key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
@@ -213,7 +216,7 @@ static void init_sh_desc_key_aead(u32 *desc, struct caam_ctx *ctx,
set_jump_tgt_here(desc, key_jump_cmd);
/* Propagate errors from shared to job descriptor */
- append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
}
static int aead_set_sh_desc(struct crypto_aead *aead)
@@ -301,7 +304,7 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
desc = ctx->sh_desc_dec;
/* aead_decrypt shared descriptor */
- init_sh_desc(desc, HDR_SHARE_WAIT);
+ init_sh_desc(desc, HDR_SHARE_SERIAL);
/* Skip if already shared */
key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
@@ -312,7 +315,7 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
/* Only propagate error immediately if shared */
jump_cmd = append_jump(desc, JUMP_TEST_ALL);
set_jump_tgt_here(desc, key_jump_cmd);
- append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
set_jump_tgt_here(desc, jump_cmd);
/* Class 2 operation */
@@ -458,126 +461,12 @@ static int aead_setauthsize(struct crypto_aead *authenc,
return 0;
}
-struct split_key_result {
- struct completion completion;
- int err;
-};
-
-static void split_key_done(struct device *dev, u32 *desc, u32 err,
- void *context)
+static u32 gen_split_aead_key(struct caam_ctx *ctx, const u8 *key_in,
+ u32 authkeylen)
{
- struct split_key_result *res = context;
-
-#ifdef DEBUG
- dev_err(dev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
-#endif
-
- if (err) {
- char tmp[CAAM_ERROR_STR_MAX];
-
- dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
- }
-
- res->err = err;
-
- complete(&res->completion);
-}
-
-/*
-get a split ipad/opad key
-
-Split key generation-----------------------------------------------
-
-[00] 0xb0810008 jobdesc: stidx=1 share=never len=8
-[01] 0x04000014 key: class2->keyreg len=20
- @0xffe01000
-[03] 0x84410014 operation: cls2-op sha1 hmac init dec
-[04] 0x24940000 fifold: class2 msgdata-last2 len=0 imm
-[05] 0xa4000001 jump: class2 local all ->1 [06]
-[06] 0x64260028 fifostr: class2 mdsplit-jdk len=40
- @0xffe04000
-*/
-static u32 gen_split_key(struct caam_ctx *ctx, const u8 *key_in, u32 authkeylen)
-{
- struct device *jrdev = ctx->jrdev;
- u32 *desc;
- struct split_key_result result;
- dma_addr_t dma_addr_in, dma_addr_out;
- int ret = 0;
-
- desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
-
- init_job_desc(desc, 0);
-
- dma_addr_in = dma_map_single(jrdev, (void *)key_in, authkeylen,
- DMA_TO_DEVICE);
- if (dma_mapping_error(jrdev, dma_addr_in)) {
- dev_err(jrdev, "unable to map key input memory\n");
- kfree(desc);
- return -ENOMEM;
- }
- dma_sync_single_for_device(jrdev, dma_addr_in, authkeylen,
- DMA_TO_DEVICE);
-
- append_key(desc, dma_addr_in, authkeylen, CLASS_2 |
- KEY_DEST_CLASS_REG);
-
- /* Sets MDHA up into an HMAC-INIT */
- append_operation(desc, ctx->alg_op | OP_ALG_DECRYPT |
- OP_ALG_AS_INIT);
-
- /*
- * do a FIFO_LOAD of zero, this will trigger the internal key expansion
- into both pads inside MDHA
- */
- append_fifo_load_as_imm(desc, NULL, 0, LDST_CLASS_2_CCB |
- FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST2);
-
- /*
- * FIFO_STORE with the explicit split-key content store
- * (0x26 output type)
- */
- dma_addr_out = dma_map_single(jrdev, ctx->key, ctx->split_key_pad_len,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(jrdev, dma_addr_out)) {
- dev_err(jrdev, "unable to map key output memory\n");
- kfree(desc);
- return -ENOMEM;
- }
- append_fifo_store(desc, dma_addr_out, ctx->split_key_len,
- LDST_CLASS_2_CCB | FIFOST_TYPE_SPLIT_KEK);
-
-#ifdef DEBUG
- print_hex_dump(KERN_ERR, "ctx.key@"xstr(__LINE__)": ",
- DUMP_PREFIX_ADDRESS, 16, 4, key_in, authkeylen, 1);
- print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ",
- DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
-#endif
-
- result.err = 0;
- init_completion(&result.completion);
-
- ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result);
- if (!ret) {
- /* in progress */
- wait_for_completion_interruptible(&result.completion);
- ret = result.err;
-#ifdef DEBUG
- print_hex_dump(KERN_ERR, "ctx.key@"xstr(__LINE__)": ",
- DUMP_PREFIX_ADDRESS, 16, 4, ctx->key,
- ctx->split_key_pad_len, 1);
-#endif
- }
-
- dma_sync_single_for_cpu(jrdev, dma_addr_out, ctx->split_key_pad_len,
- DMA_FROM_DEVICE);
- dma_unmap_single(jrdev, dma_addr_out, ctx->split_key_pad_len,
- DMA_FROM_DEVICE);
- dma_unmap_single(jrdev, dma_addr_in, authkeylen, DMA_TO_DEVICE);
-
- kfree(desc);
-
- return ret;
+ return gen_split_key(ctx->jrdev, ctx->key, ctx->split_key_len,
+ ctx->split_key_pad_len, key_in, authkeylen,
+ ctx->alg_op);
}
static int aead_setkey(struct crypto_aead *aead,
@@ -621,7 +510,7 @@ static int aead_setkey(struct crypto_aead *aead,
DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
#endif
- ret = gen_split_key(ctx, key, authkeylen);
+ ret = gen_split_aead_key(ctx, key, authkeylen);
if (ret) {
goto badkey;
}
@@ -685,7 +574,7 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
/* ablkcipher_encrypt shared descriptor */
desc = ctx->sh_desc_enc;
- init_sh_desc(desc, HDR_SHARE_WAIT);
+ init_sh_desc(desc, HDR_SHARE_SERIAL);
/* Skip if already shared */
key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
JUMP_COND_SHRD);
@@ -698,7 +587,7 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
set_jump_tgt_here(desc, key_jump_cmd);
/* Propagate errors from shared to job descriptor */
- append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
/* Load iv */
append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
@@ -729,7 +618,7 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
/* ablkcipher_decrypt shared descriptor */
desc = ctx->sh_desc_dec;
- init_sh_desc(desc, HDR_SHARE_WAIT);
+ init_sh_desc(desc, HDR_SHARE_SERIAL);
/* Skip if already shared */
key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
JUMP_COND_SHRD);
@@ -742,7 +631,7 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
/* For aead, only propagate error immediately if shared */
jump_cmd = append_jump(desc, JUMP_TEST_ALL);
set_jump_tgt_here(desc, key_jump_cmd);
- append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
set_jump_tgt_here(desc, jump_cmd);
/* load IV */
@@ -778,91 +667,78 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
}
/*
- * 16-byte hardware scatter/gather table
- * An 8-byte table exists in the hardware spec, but has never been
- * implemented to date. The 8/16 option is selected at RTL-compile-time.
- * and this selection is visible in the Compile Time Parameters Register
- */
-
-#define LINKTBL_EXT 0x80000000 /* Entry points to table */
-#define LINKTBL_FINAL 0x40000000 /* Last ent in table */
-#define LINKTBL_BPID_MASK 0x000000ff
-#define LINKTBL_BPID_SHIFT 16
-#define LINKTBL_LEN_MASK 0x3fffffff /* Excludes EXT and FINAL */
-#define LINKTBL_OFFS_MASK 0x00001fff
-
-struct link_tbl_entry {
-#ifdef CONFIG_64BIT
- u64 ptr;
-#else
- u32 reserved;
- u32 ptr;
-#endif
- u32 len;
- u32 bpid_offset; /* BPID in high, offset in lowest bits */
-};
-
-/*
* aead_edesc - s/w-extended aead descriptor
* @assoc_nents: number of segments in associated data (SPI+Seq) scatterlist
+ * @assoc_chained: if source is chained
* @src_nents: number of segments in input scatterlist
+ * @src_chained: if source is chained
* @dst_nents: number of segments in output scatterlist
+ * @dst_chained: if destination is chained
* @iv_dma: dma address of iv for checking continuity and link table
* @desc: h/w descriptor (variable length; must not exceed MAX_CAAM_DESCSIZE)
- * @link_tbl_bytes: length of dma mapped link_tbl space
- * @link_tbl_dma: bus physical mapped address of h/w link table
+ * @sec4_sg_bytes: length of dma mapped sec4_sg space
+ * @sec4_sg_dma: bus physical mapped address of h/w link table
* @hw_desc: the h/w job descriptor followed by any referenced link tables
*/
struct aead_edesc {
int assoc_nents;
+ bool assoc_chained;
int src_nents;
+ bool src_chained;
int dst_nents;
+ bool dst_chained;
dma_addr_t iv_dma;
- int link_tbl_bytes;
- dma_addr_t link_tbl_dma;
- struct link_tbl_entry *link_tbl;
+ int sec4_sg_bytes;
+ dma_addr_t sec4_sg_dma;
+ struct sec4_sg_entry *sec4_sg;
u32 hw_desc[0];
};
/*
* ablkcipher_edesc - s/w-extended ablkcipher descriptor
* @src_nents: number of segments in input scatterlist
+ * @src_chained: if source is chained
* @dst_nents: number of segments in output scatterlist
+ * @dst_chained: if destination is chained
* @iv_dma: dma address of iv for checking continuity and link table
* @desc: h/w descriptor (variable length; must not exceed MAX_CAAM_DESCSIZE)
- * @link_tbl_bytes: length of dma mapped link_tbl space
- * @link_tbl_dma: bus physical mapped address of h/w link table
+ * @sec4_sg_bytes: length of dma mapped sec4_sg space
+ * @sec4_sg_dma: bus physical mapped address of h/w link table
* @hw_desc: the h/w job descriptor followed by any referenced link tables
*/
struct ablkcipher_edesc {
int src_nents;
+ bool src_chained;
int dst_nents;
+ bool dst_chained;
dma_addr_t iv_dma;
- int link_tbl_bytes;
- dma_addr_t link_tbl_dma;
- struct link_tbl_entry *link_tbl;
+ int sec4_sg_bytes;
+ dma_addr_t sec4_sg_dma;
+ struct sec4_sg_entry *sec4_sg;
u32 hw_desc[0];
};
static void caam_unmap(struct device *dev, struct scatterlist *src,
- struct scatterlist *dst, int src_nents, int dst_nents,
- dma_addr_t iv_dma, int ivsize, dma_addr_t link_tbl_dma,
- int link_tbl_bytes)
+ struct scatterlist *dst, int src_nents,
+ bool src_chained, int dst_nents, bool dst_chained,
+ dma_addr_t iv_dma, int ivsize, dma_addr_t sec4_sg_dma,
+ int sec4_sg_bytes)
{
- if (unlikely(dst != src)) {
- dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE);
- dma_sync_sg_for_cpu(dev, dst, dst_nents, DMA_FROM_DEVICE);
- dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE);
+ if (dst != src) {
+ dma_unmap_sg_chained(dev, src, src_nents ? : 1, DMA_TO_DEVICE,
+ src_chained);
+ dma_unmap_sg_chained(dev, dst, dst_nents ? : 1, DMA_FROM_DEVICE,
+ dst_chained);
} else {
- dma_sync_sg_for_cpu(dev, src, src_nents, DMA_BIDIRECTIONAL);
- dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL);
+ dma_unmap_sg_chained(dev, src, src_nents ? : 1,
+ DMA_BIDIRECTIONAL, src_chained);
}
if (iv_dma)
dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
- if (link_tbl_bytes)
- dma_unmap_single(dev, link_tbl_dma, link_tbl_bytes,
+ if (sec4_sg_bytes)
+ dma_unmap_single(dev, sec4_sg_dma, sec4_sg_bytes,
DMA_TO_DEVICE);
}
@@ -873,12 +749,13 @@ static void aead_unmap(struct device *dev,
struct crypto_aead *aead = crypto_aead_reqtfm(req);
int ivsize = crypto_aead_ivsize(aead);
- dma_unmap_sg(dev, req->assoc, edesc->assoc_nents, DMA_TO_DEVICE);
+ dma_unmap_sg_chained(dev, req->assoc, edesc->assoc_nents,
+ DMA_TO_DEVICE, edesc->assoc_chained);
caam_unmap(dev, req->src, req->dst,
- edesc->src_nents, edesc->dst_nents,
- edesc->iv_dma, ivsize, edesc->link_tbl_dma,
- edesc->link_tbl_bytes);
+ edesc->src_nents, edesc->src_chained, edesc->dst_nents,
+ edesc->dst_chained, edesc->iv_dma, ivsize,
+ edesc->sec4_sg_dma, edesc->sec4_sg_bytes);
}
static void ablkcipher_unmap(struct device *dev,
@@ -889,9 +766,9 @@ static void ablkcipher_unmap(struct device *dev,
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
caam_unmap(dev, req->src, req->dst,
- edesc->src_nents, edesc->dst_nents,
- edesc->iv_dma, ivsize, edesc->link_tbl_dma,
- edesc->link_tbl_bytes);
+ edesc->src_nents, edesc->src_chained, edesc->dst_nents,
+ edesc->dst_chained, edesc->iv_dma, ivsize,
+ edesc->sec4_sg_dma, edesc->sec4_sg_bytes);
}
static void aead_encrypt_done(struct device *jrdev, u32 *desc, u32 err,
@@ -982,7 +859,7 @@ static void aead_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
sizeof(struct iphdr) + req->assoclen +
((req->cryptlen > 1500) ? 1500 : req->cryptlen) +
ctx->authsize + 36, 1);
- if (!err && edesc->link_tbl_bytes) {
+ if (!err && edesc->sec4_sg_bytes) {
struct scatterlist *sg = sg_last(req->src, edesc->src_nents);
print_hex_dump(KERN_ERR, "sglastout@"xstr(__LINE__)": ",
DUMP_PREFIX_ADDRESS, 16, 4, sg_virt(sg),
@@ -1066,53 +943,6 @@ static void ablkcipher_decrypt_done(struct device *jrdev, u32 *desc, u32 err,
ablkcipher_request_complete(req, err);
}
-static void sg_to_link_tbl_one(struct link_tbl_entry *link_tbl_ptr,
- dma_addr_t dma, u32 len, u32 offset)
-{
-#ifndef CONFIG_64BIT
- link_tbl_ptr->reserved = 0; /* ensure high half is zero */
-#endif
- link_tbl_ptr->ptr = dma;
- link_tbl_ptr->len = (len & LINKTBL_LEN_MASK);
- /* Does not add in buffer pool ID's at this time */
- link_tbl_ptr->bpid_offset = (offset & LINKTBL_OFFS_MASK);
-
-#ifdef DEBUG
- print_hex_dump(KERN_ERR, "link_tbl_ptr@"xstr(__LINE__)": ",
- DUMP_PREFIX_ADDRESS, 16, 4, link_tbl_ptr,
- sizeof(struct link_tbl_entry), 1);
-#endif
-}
-
-/*
- * convert scatterlist to h/w link table format
- * but does not have final bit; instead, returns last entry
- */
-static struct link_tbl_entry *sg_to_link_tbl(struct scatterlist *sg,
- int sg_count, struct link_tbl_entry
- *link_tbl_ptr, u32 offset)
-{
- while (sg_count) {
- sg_to_link_tbl_one(link_tbl_ptr, sg_dma_address(sg),
- sg_dma_len(sg), offset);
- link_tbl_ptr++;
- sg = sg_next(sg);
- sg_count--;
- }
- return link_tbl_ptr - 1;
-}
-
-/*
- * convert scatterlist to h/w link table format
- * scatterlist must have been previously dma mapped
- */
-static void sg_to_link_tbl_last(struct scatterlist *sg, int sg_count,
- struct link_tbl_entry *link_tbl_ptr, u32 offset)
-{
- link_tbl_ptr = sg_to_link_tbl(sg, sg_count, link_tbl_ptr, offset);
- link_tbl_ptr->len |= LINKTBL_FINAL;
-}
-
/*
* Fill in aead job descriptor
*/
@@ -1128,7 +958,7 @@ static void init_aead_job(u32 *sh_desc, dma_addr_t ptr,
u32 *desc = edesc->hw_desc;
u32 out_options = 0, in_options;
dma_addr_t dst_dma, src_dma;
- int len, link_tbl_index = 0;
+ int len, sec4_sg_index = 0;
#ifdef DEBUG
debug("assoclen %d cryptlen %d authsize %d\n",
@@ -1154,9 +984,9 @@ static void init_aead_job(u32 *sh_desc, dma_addr_t ptr,
src_dma = sg_dma_address(req->assoc);
in_options = 0;
} else {
- src_dma = edesc->link_tbl_dma;
- link_tbl_index += (edesc->assoc_nents ? : 1) + 1 +
- (edesc->src_nents ? : 1);
+ src_dma = edesc->sec4_sg_dma;
+ sec4_sg_index += (edesc->assoc_nents ? : 1) + 1 +
+ (edesc->src_nents ? : 1);
in_options = LDST_SGF;
}
if (encrypt)
@@ -1170,7 +1000,7 @@ static void init_aead_job(u32 *sh_desc, dma_addr_t ptr,
if (all_contig) {
dst_dma = sg_dma_address(req->src);
} else {
- dst_dma = src_dma + sizeof(struct link_tbl_entry) *
+ dst_dma = src_dma + sizeof(struct sec4_sg_entry) *
((edesc->assoc_nents ? : 1) + 1);
out_options = LDST_SGF;
}
@@ -1178,9 +1008,9 @@ static void init_aead_job(u32 *sh_desc, dma_addr_t ptr,
if (!edesc->dst_nents) {
dst_dma = sg_dma_address(req->dst);
} else {
- dst_dma = edesc->link_tbl_dma +
- link_tbl_index *
- sizeof(struct link_tbl_entry);
+ dst_dma = edesc->sec4_sg_dma +
+ sec4_sg_index *
+ sizeof(struct sec4_sg_entry);
out_options = LDST_SGF;
}
}
@@ -1206,7 +1036,7 @@ static void init_aead_giv_job(u32 *sh_desc, dma_addr_t ptr,
u32 *desc = edesc->hw_desc;
u32 out_options = 0, in_options;
dma_addr_t dst_dma, src_dma;
- int len, link_tbl_index = 0;
+ int len, sec4_sg_index = 0;
#ifdef DEBUG
debug("assoclen %d cryptlen %d authsize %d\n",
@@ -1231,8 +1061,8 @@ static void init_aead_giv_job(u32 *sh_desc, dma_addr_t ptr,
src_dma = sg_dma_address(req->assoc);
in_options = 0;
} else {
- src_dma = edesc->link_tbl_dma;
- link_tbl_index += edesc->assoc_nents + 1 + edesc->src_nents;
+ src_dma = edesc->sec4_sg_dma;
+ sec4_sg_index += edesc->assoc_nents + 1 + edesc->src_nents;
in_options = LDST_SGF;
}
append_seq_in_ptr(desc, src_dma, req->assoclen + ivsize +
@@ -1242,13 +1072,13 @@ static void init_aead_giv_job(u32 *sh_desc, dma_addr_t ptr,
dst_dma = edesc->iv_dma;
} else {
if (likely(req->src == req->dst)) {
- dst_dma = src_dma + sizeof(struct link_tbl_entry) *
+ dst_dma = src_dma + sizeof(struct sec4_sg_entry) *
edesc->assoc_nents;
out_options = LDST_SGF;
} else {
- dst_dma = edesc->link_tbl_dma +
- link_tbl_index *
- sizeof(struct link_tbl_entry);
+ dst_dma = edesc->sec4_sg_dma +
+ sec4_sg_index *
+ sizeof(struct sec4_sg_entry);
out_options = LDST_SGF;
}
}
@@ -1269,7 +1099,7 @@ static void init_ablkcipher_job(u32 *sh_desc, dma_addr_t ptr,
u32 *desc = edesc->hw_desc;
u32 out_options = 0, in_options;
dma_addr_t dst_dma, src_dma;
- int len, link_tbl_index = 0;
+ int len, sec4_sg_index = 0;
#ifdef DEBUG
print_hex_dump(KERN_ERR, "presciv@"xstr(__LINE__)": ",
@@ -1287,8 +1117,8 @@ static void init_ablkcipher_job(u32 *sh_desc, dma_addr_t ptr,
src_dma = edesc->iv_dma;
in_options = 0;
} else {
- src_dma = edesc->link_tbl_dma;
- link_tbl_index += (iv_contig ? 0 : 1) + edesc->src_nents;
+ src_dma = edesc->sec4_sg_dma;
+ sec4_sg_index += (iv_contig ? 0 : 1) + edesc->src_nents;
in_options = LDST_SGF;
}
append_seq_in_ptr(desc, src_dma, req->nbytes + ivsize, in_options);
@@ -1297,16 +1127,16 @@ static void init_ablkcipher_job(u32 *sh_desc, dma_addr_t ptr,
if (!edesc->src_nents && iv_contig) {
dst_dma = sg_dma_address(req->src);
} else {
- dst_dma = edesc->link_tbl_dma +
- sizeof(struct link_tbl_entry);
+ dst_dma = edesc->sec4_sg_dma +
+ sizeof(struct sec4_sg_entry);
out_options = LDST_SGF;
}
} else {
if (!edesc->dst_nents) {
dst_dma = sg_dma_address(req->dst);
} else {
- dst_dma = edesc->link_tbl_dma +
- link_tbl_index * sizeof(struct link_tbl_entry);
+ dst_dma = edesc->sec4_sg_dma +
+ sec4_sg_index * sizeof(struct sec4_sg_entry);
out_options = LDST_SGF;
}
}
@@ -1314,28 +1144,6 @@ static void init_ablkcipher_job(u32 *sh_desc, dma_addr_t ptr,
}
/*
- * derive number of elements in scatterlist
- */
-static int sg_count(struct scatterlist *sg_list, int nbytes)
-{
- struct scatterlist *sg = sg_list;
- int sg_nents = 0;
-
- while (nbytes > 0) {
- sg_nents++;
- nbytes -= sg->length;
- if (!sg_is_last(sg) && (sg + 1)->length == 0)
- BUG(); /* Not support chaining */
- sg = scatterwalk_sg_next(sg);
- }
-
- if (likely(sg_nents == 1))
- return 0;
-
- return sg_nents;
-}
-
-/*
* allocate and map the aead extended descriptor
*/
static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
@@ -1351,31 +1159,26 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
dma_addr_t iv_dma = 0;
int sgc;
bool all_contig = true;
+ bool assoc_chained = false, src_chained = false, dst_chained = false;
int ivsize = crypto_aead_ivsize(aead);
- int link_tbl_index, link_tbl_len = 0, link_tbl_bytes;
+ int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes;
- assoc_nents = sg_count(req->assoc, req->assoclen);
- src_nents = sg_count(req->src, req->cryptlen);
+ assoc_nents = sg_count(req->assoc, req->assoclen, &assoc_chained);
+ src_nents = sg_count(req->src, req->cryptlen, &src_chained);
if (unlikely(req->dst != req->src))
- dst_nents = sg_count(req->dst, req->cryptlen);
+ dst_nents = sg_count(req->dst, req->cryptlen, &dst_chained);
- sgc = dma_map_sg(jrdev, req->assoc, assoc_nents ? : 1,
- DMA_BIDIRECTIONAL);
- dma_sync_sg_for_device(jrdev, req->assoc, sgc,
- DMA_BIDIRECTIONAL);
+ sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1,
+ DMA_BIDIRECTIONAL, assoc_chained);
if (likely(req->src == req->dst)) {
- sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
- DMA_BIDIRECTIONAL);
- dma_sync_sg_for_device(jrdev, req->src, sgc,
- DMA_BIDIRECTIONAL);
+ sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
+ DMA_BIDIRECTIONAL, src_chained);
} else {
- sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
- DMA_TO_DEVICE);
- dma_sync_sg_for_device(jrdev, req->src, sgc,
- DMA_TO_DEVICE);
- sgc = dma_map_sg(jrdev, req->dst, dst_nents ? : 1,
- DMA_FROM_DEVICE);
+ sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
+ DMA_TO_DEVICE, src_chained);
+ sgc = dma_map_sg_chained(jrdev, req->dst, dst_nents ? : 1,
+ DMA_FROM_DEVICE, dst_chained);
}
/* Check if data are contiguous */
@@ -1386,53 +1189,56 @@ static struct aead_edesc *aead_edesc_alloc(struct aead_request *req,
all_contig = false;
assoc_nents = assoc_nents ? : 1;
src_nents = src_nents ? : 1;
- link_tbl_len = assoc_nents + 1 + src_nents;
+ sec4_sg_len = assoc_nents + 1 + src_nents;
}
- link_tbl_len += dst_nents;
+ sec4_sg_len += dst_nents;
- link_tbl_bytes = link_tbl_len * sizeof(struct link_tbl_entry);
+ sec4_sg_bytes = sec4_sg_len * sizeof(struct sec4_sg_entry);
dma_sync_single_for_device(jrdev, iv_dma, ivsize, DMA_TO_DEVICE);
/* allocate space for base edesc and hw desc commands, link tables */
edesc = kmalloc(sizeof(struct aead_edesc) + desc_bytes +
- link_tbl_bytes, GFP_DMA | flags);
+ sec4_sg_bytes, GFP_DMA | flags);
if (!edesc) {
dev_err(jrdev, "could not allocate extended descriptor\n");
return ERR_PTR(-ENOMEM);
}
edesc->assoc_nents = assoc_nents;
+ edesc->assoc_chained = assoc_chained;
edesc->src_nents = src_nents;
+ edesc->src_chained = src_chained;
edesc->dst_nents = dst_nents;
+ edesc->dst_chained = dst_chained;
edesc->iv_dma = iv_dma;
- edesc->link_tbl_bytes = link_tbl_bytes;
- edesc->link_tbl = (void *)edesc + sizeof(struct aead_edesc) +
- desc_bytes;
- edesc->link_tbl_dma = dma_map_single(jrdev, edesc->link_tbl,
- link_tbl_bytes, DMA_TO_DEVICE);
+ edesc->sec4_sg_bytes = sec4_sg_bytes;
+ edesc->sec4_sg = (void *)edesc + sizeof(struct aead_edesc) +
+ desc_bytes;
+ edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+ sec4_sg_bytes, DMA_TO_DEVICE);
*all_contig_ptr = all_contig;
- link_tbl_index = 0;
+ sec4_sg_index = 0;
if (!all_contig) {
- sg_to_link_tbl(req->assoc,
- (assoc_nents ? : 1),
- edesc->link_tbl +
- link_tbl_index, 0);
- link_tbl_index += assoc_nents ? : 1;
- sg_to_link_tbl_one(edesc->link_tbl + link_tbl_index,
+ sg_to_sec4_sg(req->assoc,
+ (assoc_nents ? : 1),
+ edesc->sec4_sg +
+ sec4_sg_index, 0);
+ sec4_sg_index += assoc_nents ? : 1;
+ dma_to_sec4_sg_one(edesc->sec4_sg + sec4_sg_index,
iv_dma, ivsize, 0);
- link_tbl_index += 1;
- sg_to_link_tbl_last(req->src,
- (src_nents ? : 1),
- edesc->link_tbl +
- link_tbl_index, 0);
- link_tbl_index += src_nents ? : 1;
+ sec4_sg_index += 1;
+ sg_to_sec4_sg_last(req->src,
+ (src_nents ? : 1),
+ edesc->sec4_sg +
+ sec4_sg_index, 0);
+ sec4_sg_index += src_nents ? : 1;
}
if (dst_nents) {
- sg_to_link_tbl_last(req->dst, dst_nents,
- edesc->link_tbl + link_tbl_index, 0);
+ sg_to_sec4_sg_last(req->dst, dst_nents,
+ edesc->sec4_sg + sec4_sg_index, 0);
}
- dma_sync_single_for_device(jrdev, edesc->link_tbl_dma, link_tbl_bytes,
+ dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma, sec4_sg_bytes,
DMA_TO_DEVICE);
return edesc;
@@ -1539,30 +1345,25 @@ static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request
int sgc;
u32 contig = GIV_SRC_CONTIG | GIV_DST_CONTIG;
int ivsize = crypto_aead_ivsize(aead);
- int link_tbl_index, link_tbl_len = 0, link_tbl_bytes;
+ bool assoc_chained = false, src_chained = false, dst_chained = false;
+ int sec4_sg_index, sec4_sg_len = 0, sec4_sg_bytes;
- assoc_nents = sg_count(req->assoc, req->assoclen);
- src_nents = sg_count(req->src, req->cryptlen);
+ assoc_nents = sg_count(req->assoc, req->assoclen, &assoc_chained);
+ src_nents = sg_count(req->src, req->cryptlen, &src_chained);
if (unlikely(req->dst != req->src))
- dst_nents = sg_count(req->dst, req->cryptlen);
+ dst_nents = sg_count(req->dst, req->cryptlen, &dst_chained);
- sgc = dma_map_sg(jrdev, req->assoc, assoc_nents ? : 1,
- DMA_BIDIRECTIONAL);
- dma_sync_sg_for_device(jrdev, req->assoc, assoc_nents ? : 1,
- DMA_BIDIRECTIONAL);
+ sgc = dma_map_sg_chained(jrdev, req->assoc, assoc_nents ? : 1,
+ DMA_BIDIRECTIONAL, assoc_chained);
if (likely(req->src == req->dst)) {
- sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
- DMA_BIDIRECTIONAL);
- dma_sync_sg_for_device(jrdev, req->src, src_nents ? : 1,
- DMA_BIDIRECTIONAL);
+ sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
+ DMA_BIDIRECTIONAL, src_chained);
} else {
- sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
- DMA_TO_DEVICE);
- dma_sync_sg_for_device(jrdev, req->src, src_nents ? : 1,
- DMA_TO_DEVICE);
- sgc = dma_map_sg(jrdev, req->dst, dst_nents ? : 1,
- DMA_FROM_DEVICE);
+ sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
+ DMA_TO_DEVICE, src_chained);
+ sgc = dma_map_sg_chained(jrdev, req->dst, dst_nents ? : 1,
+ DMA_FROM_DEVICE, dst_chained);
}
/* Check if data are contiguous */
@@ -1574,62 +1375,65 @@ static struct aead_edesc *aead_giv_edesc_alloc(struct aead_givcrypt_request
contig &= ~GIV_DST_CONTIG;
if (unlikely(req->src != req->dst)) {
dst_nents = dst_nents ? : 1;
- link_tbl_len += 1;
+ sec4_sg_len += 1;
}
if (!(contig & GIV_SRC_CONTIG)) {
assoc_nents = assoc_nents ? : 1;
src_nents = src_nents ? : 1;
- link_tbl_len += assoc_nents + 1 + src_nents;
+ sec4_sg_len += assoc_nents + 1 + src_nents;
if (likely(req->src == req->dst))
contig &= ~GIV_DST_CONTIG;
}
- link_tbl_len += dst_nents;
+ sec4_sg_len += dst_nents;
- link_tbl_bytes = link_tbl_len * sizeof(struct link_tbl_entry);
+ sec4_sg_bytes = sec4_sg_len * sizeof(struct sec4_sg_entry);
dma_sync_single_for_device(jrdev, iv_dma, ivsize, DMA_TO_DEVICE);
/* allocate space for base edesc and hw desc commands, link tables */
- edesc = kmalloc(sizeof(struct aead_edesc) + desc_bytes +
- link_tbl_bytes, GFP_DMA | flags);
+ edesc = kzalloc(sizeof(struct aead_edesc) + desc_bytes +
+ sec4_sg_bytes, GFP_DMA | flags);
if (!edesc) {
dev_err(jrdev, "could not allocate extended descriptor\n");
return ERR_PTR(-ENOMEM);
}
edesc->assoc_nents = assoc_nents;
+ edesc->assoc_chained = assoc_chained;
edesc->src_nents = src_nents;
+ edesc->src_chained = src_chained;
edesc->dst_nents = dst_nents;
+ edesc->dst_chained = dst_chained;
edesc->iv_dma = iv_dma;
- edesc->link_tbl_bytes = link_tbl_bytes;
- edesc->link_tbl = (void *)edesc + sizeof(struct aead_edesc) +
- desc_bytes;
- edesc->link_tbl_dma = dma_map_single(jrdev, edesc->link_tbl,
- link_tbl_bytes, DMA_TO_DEVICE);
+ edesc->sec4_sg_bytes = sec4_sg_bytes;
+ edesc->sec4_sg = (void *)edesc + sizeof(struct aead_edesc) +
+ desc_bytes;
+ edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+ sec4_sg_bytes, DMA_TO_DEVICE);
*contig_ptr = contig;
- link_tbl_index = 0;
+ sec4_sg_index = 0;
if (!(contig & GIV_SRC_CONTIG)) {
- sg_to_link_tbl(req->assoc, assoc_nents,
- edesc->link_tbl +
- link_tbl_index, 0);
- link_tbl_index += assoc_nents;
- sg_to_link_tbl_one(edesc->link_tbl + link_tbl_index,
+ sg_to_sec4_sg(req->assoc, assoc_nents,
+ edesc->sec4_sg +
+ sec4_sg_index, 0);
+ sec4_sg_index += assoc_nents;
+ dma_to_sec4_sg_one(edesc->sec4_sg + sec4_sg_index,
iv_dma, ivsize, 0);
- link_tbl_index += 1;
- sg_to_link_tbl_last(req->src, src_nents,
- edesc->link_tbl +
- link_tbl_index, 0);
- link_tbl_index += src_nents;
+ sec4_sg_index += 1;
+ sg_to_sec4_sg_last(req->src, src_nents,
+ edesc->sec4_sg +
+ sec4_sg_index, 0);
+ sec4_sg_index += src_nents;
}
if (unlikely(req->src != req->dst && !(contig & GIV_DST_CONTIG))) {
- sg_to_link_tbl_one(edesc->link_tbl + link_tbl_index,
+ dma_to_sec4_sg_one(edesc->sec4_sg + sec4_sg_index,
iv_dma, ivsize, 0);
- link_tbl_index += 1;
- sg_to_link_tbl_last(req->dst, dst_nents,
- edesc->link_tbl + link_tbl_index, 0);
+ sec4_sg_index += 1;
+ sg_to_sec4_sg_last(req->dst, dst_nents,
+ edesc->sec4_sg + sec4_sg_index, 0);
}
- dma_sync_single_for_device(jrdev, edesc->link_tbl_dma, link_tbl_bytes,
+ dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma, sec4_sg_bytes,
DMA_TO_DEVICE);
return edesc;
@@ -1695,30 +1499,28 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
CRYPTO_TFM_REQ_MAY_SLEEP)) ?
GFP_KERNEL : GFP_ATOMIC;
- int src_nents, dst_nents = 0, link_tbl_bytes;
+ int src_nents, dst_nents = 0, sec4_sg_bytes;
struct ablkcipher_edesc *edesc;
dma_addr_t iv_dma = 0;
bool iv_contig = false;
int sgc;
int ivsize = crypto_ablkcipher_ivsize(ablkcipher);
- int link_tbl_index;
+ bool src_chained = false, dst_chained = false;
+ int sec4_sg_index;
- src_nents = sg_count(req->src, req->nbytes);
+ src_nents = sg_count(req->src, req->nbytes, &src_chained);
- if (unlikely(req->dst != req->src))
- dst_nents = sg_count(req->dst, req->nbytes);
+ if (req->dst != req->src)
+ dst_nents = sg_count(req->dst, req->nbytes, &dst_chained);
if (likely(req->src == req->dst)) {
- sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
- DMA_BIDIRECTIONAL);
- dma_sync_sg_for_device(jrdev, req->src, sgc,
- DMA_BIDIRECTIONAL);
+ sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
+ DMA_BIDIRECTIONAL, src_chained);
} else {
- sgc = dma_map_sg(jrdev, req->src, src_nents ? : 1,
- DMA_TO_DEVICE);
- dma_sync_sg_for_device(jrdev, req->src, sgc, DMA_TO_DEVICE);
- sgc = dma_map_sg(jrdev, req->dst, dst_nents ? : 1,
- DMA_FROM_DEVICE);
+ sgc = dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
+ DMA_TO_DEVICE, src_chained);
+ sgc = dma_map_sg_chained(jrdev, req->dst, dst_nents ? : 1,
+ DMA_FROM_DEVICE, dst_chained);
}
/* FIXME: no test for sgc values returned above... */
@@ -1732,47 +1534,49 @@ static struct ablkcipher_edesc *ablkcipher_edesc_alloc(struct ablkcipher_request
iv_contig = true;
else
src_nents = src_nents ? : 1;
- link_tbl_bytes = ((iv_contig ? 0 : 1) + src_nents + dst_nents) *
- sizeof(struct link_tbl_entry);
+ sec4_sg_bytes = ((iv_contig ? 0 : 1) + src_nents + dst_nents) *
+ sizeof(struct sec4_sg_entry);
/* allocate space for base edesc and hw desc commands, link tables */
- edesc = kmalloc(sizeof(struct ablkcipher_edesc) + desc_bytes +
- link_tbl_bytes, GFP_DMA | flags);
+ edesc = kzalloc(sizeof(struct ablkcipher_edesc) + desc_bytes +
+ sec4_sg_bytes, GFP_DMA | flags);
if (!edesc) {
dev_err(jrdev, "could not allocate extended descriptor\n");
return ERR_PTR(-ENOMEM);
}
edesc->src_nents = src_nents;
+ edesc->src_chained = src_chained;
edesc->dst_nents = dst_nents;
- edesc->link_tbl_bytes = link_tbl_bytes;
- edesc->link_tbl = (void *)edesc + sizeof(struct ablkcipher_edesc) +
- desc_bytes;
+ edesc->dst_chained = dst_chained;
+ edesc->sec4_sg_bytes = sec4_sg_bytes;
+ edesc->sec4_sg = (void *)edesc + sizeof(struct ablkcipher_edesc) +
+ desc_bytes;
- link_tbl_index = 0;
+ sec4_sg_index = 0;
if (!iv_contig) {
- sg_to_link_tbl_one(edesc->link_tbl, iv_dma, ivsize, 0);
- sg_to_link_tbl_last(req->src, src_nents,
- edesc->link_tbl + 1, 0);
- link_tbl_index += 1 + src_nents;
+ dma_to_sec4_sg_one(edesc->sec4_sg, iv_dma, ivsize, 0);
+ sg_to_sec4_sg_last(req->src, src_nents,
+ edesc->sec4_sg + 1, 0);
+ sec4_sg_index += 1 + src_nents;
}
- if (unlikely(dst_nents)) {
- sg_to_link_tbl_last(req->dst, dst_nents,
- edesc->link_tbl + link_tbl_index, 0);
+ if (dst_nents) {
+ sg_to_sec4_sg_last(req->dst, dst_nents,
+ edesc->sec4_sg + sec4_sg_index, 0);
}
- edesc->link_tbl_dma = dma_map_single(jrdev, edesc->link_tbl,
- link_tbl_bytes, DMA_TO_DEVICE);
+ edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+ sec4_sg_bytes, DMA_TO_DEVICE);
edesc->iv_dma = iv_dma;
- dma_sync_single_for_device(jrdev, edesc->link_tbl_dma, link_tbl_bytes,
+ dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma, sec4_sg_bytes,
DMA_TO_DEVICE);
#ifdef DEBUG
- print_hex_dump(KERN_ERR, "ablkcipher link_tbl@"xstr(__LINE__)": ",
- DUMP_PREFIX_ADDRESS, 16, 4, edesc->link_tbl,
- link_tbl_bytes, 1);
+ print_hex_dump(KERN_ERR, "ablkcipher sec4_sg@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, edesc->sec4_sg,
+ sec4_sg_bytes, 1);
#endif
*iv_contig_out = iv_contig;
@@ -1876,6 +1680,25 @@ struct caam_alg_template {
static struct caam_alg_template driver_algs[] = {
/* single-pass ipsec_esp descriptor */
{
+ .name = "authenc(hmac(md5),cbc(aes))",
+ .driver_name = "authenc-hmac-md5-cbc-aes-caam",
+ .blocksize = AES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = MD5_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+ },
+ {
.name = "authenc(hmac(sha1),cbc(aes))",
.driver_name = "authenc-hmac-sha1-cbc-aes-caam",
.blocksize = AES_BLOCK_SIZE,
@@ -1895,6 +1718,26 @@ static struct caam_alg_template driver_algs[] = {
.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
},
{
+ .name = "authenc(hmac(sha224),cbc(aes))",
+ .driver_name = "authenc-hmac-sha224-cbc-aes-caam",
+ .blocksize = AES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = SHA224_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+ },
+ {
.name = "authenc(hmac(sha256),cbc(aes))",
.driver_name = "authenc-hmac-sha256-cbc-aes-caam",
.blocksize = AES_BLOCK_SIZE,
@@ -1915,6 +1758,26 @@ static struct caam_alg_template driver_algs[] = {
.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
},
{
+ .name = "authenc(hmac(sha384),cbc(aes))",
+ .driver_name = "authenc-hmac-sha384-cbc-aes-caam",
+ .blocksize = AES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = SHA384_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+ },
+ {
.name = "authenc(hmac(sha512),cbc(aes))",
.driver_name = "authenc-hmac-sha512-cbc-aes-caam",
.blocksize = AES_BLOCK_SIZE,
@@ -1935,6 +1798,25 @@ static struct caam_alg_template driver_algs[] = {
.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
},
{
+ .name = "authenc(hmac(md5),cbc(des3_ede))",
+ .driver_name = "authenc-hmac-md5-cbc-des3_ede-caam",
+ .blocksize = DES3_EDE_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .maxauthsize = MD5_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+ },
+ {
.name = "authenc(hmac(sha1),cbc(des3_ede))",
.driver_name = "authenc-hmac-sha1-cbc-des3_ede-caam",
.blocksize = DES3_EDE_BLOCK_SIZE,
@@ -1954,6 +1836,26 @@ static struct caam_alg_template driver_algs[] = {
.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
},
{
+ .name = "authenc(hmac(sha224),cbc(des3_ede))",
+ .driver_name = "authenc-hmac-sha224-cbc-des3_ede-caam",
+ .blocksize = DES3_EDE_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .maxauthsize = SHA224_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+ },
+ {
.name = "authenc(hmac(sha256),cbc(des3_ede))",
.driver_name = "authenc-hmac-sha256-cbc-des3_ede-caam",
.blocksize = DES3_EDE_BLOCK_SIZE,
@@ -1974,6 +1876,26 @@ static struct caam_alg_template driver_algs[] = {
.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
},
{
+ .name = "authenc(hmac(sha384),cbc(des3_ede))",
+ .driver_name = "authenc-hmac-sha384-cbc-des3_ede-caam",
+ .blocksize = DES3_EDE_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .maxauthsize = SHA384_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+ },
+ {
.name = "authenc(hmac(sha512),cbc(des3_ede))",
.driver_name = "authenc-hmac-sha512-cbc-des3_ede-caam",
.blocksize = DES3_EDE_BLOCK_SIZE,
@@ -1994,6 +1916,25 @@ static struct caam_alg_template driver_algs[] = {
.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
},
{
+ .name = "authenc(hmac(md5),cbc(des))",
+ .driver_name = "authenc-hmac-md5-cbc-des-caam",
+ .blocksize = DES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES_BLOCK_SIZE,
+ .maxauthsize = MD5_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+ },
+ {
.name = "authenc(hmac(sha1),cbc(des))",
.driver_name = "authenc-hmac-sha1-cbc-des-caam",
.blocksize = DES_BLOCK_SIZE,
@@ -2013,6 +1954,26 @@ static struct caam_alg_template driver_algs[] = {
.alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
},
{
+ .name = "authenc(hmac(sha224),cbc(des))",
+ .driver_name = "authenc-hmac-sha224-cbc-des-caam",
+ .blocksize = DES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES_BLOCK_SIZE,
+ .maxauthsize = SHA224_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA224 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+ },
+ {
.name = "authenc(hmac(sha256),cbc(des))",
.driver_name = "authenc-hmac-sha256-cbc-des-caam",
.blocksize = DES_BLOCK_SIZE,
@@ -2033,6 +1994,26 @@ static struct caam_alg_template driver_algs[] = {
.alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
},
{
+ .name = "authenc(hmac(sha384),cbc(des))",
+ .driver_name = "authenc-hmac-sha384-cbc-des-caam",
+ .blocksize = DES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES_BLOCK_SIZE,
+ .maxauthsize = SHA384_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_SHA384 |
+ OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+ },
+ {
.name = "authenc(hmac(sha512),cbc(des))",
.driver_name = "authenc-hmac-sha512-cbc-des-caam",
.blocksize = DES_BLOCK_SIZE,
@@ -2231,7 +2212,9 @@ int caam_algapi_startup(struct platform_device *pdev)
{
struct device *ctrldev, **jrdev;
struct caam_drv_private *priv;
- int i = 0, err = 0;
+ int i = 0, err = 0, md_limit = 0;
+ int des_inst, aes_inst, md_inst;
+ u64 cha_inst;
ctrldev = &pdev->dev;
priv = dev_get_drvdata(ctrldev);
@@ -2257,11 +2240,47 @@ int caam_algapi_startup(struct platform_device *pdev)
priv->algapi_jr = jrdev;
atomic_set(&priv->tfm_count, -1);
- /* register crypto algorithms the device supports */
+ /*
+ * register crypto algorithms the device supports
+ * first, detect presence of DES, AES, and MD blocks. If MD present,
+ * determine limit of supported digest size
+ */
+ cha_inst = rd_reg64(&priv->ctrl->perfmon.cha_num);
+ des_inst = (cha_inst & CHA_ID_DES_MASK) >> CHA_ID_DES_SHIFT;
+ aes_inst = (cha_inst & CHA_ID_AES_MASK) >> CHA_ID_AES_SHIFT;
+ md_inst = (cha_inst & CHA_ID_MD_MASK) >> CHA_ID_MD_SHIFT;
+ if (md_inst) {
+ md_limit = SHA512_DIGEST_SIZE;
+ if ((rd_reg64(&priv->ctrl->perfmon.cha_id) & CHA_ID_MD_MASK)
+ == CHA_ID_MD_LP256) /* LP256 limits digest size */
+ md_limit = SHA256_DIGEST_SIZE;
+ }
+
for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
- /* TODO: check if h/w supports alg */
struct caam_crypto_alg *t_alg;
+ /*
+ * All registrable algs in this module require a blockcipher
+ * All aead algs require message digests, so check them for
+ * instantiation and size.
+ */
+ if (driver_algs[i].type == CRYPTO_ALG_TYPE_AEAD) {
+ /* If no MD instantiated, or MD too small, skip */
+ if ((!md_inst) ||
+ (driver_algs[i].template_aead.maxauthsize >
+ md_limit))
+ continue;
+ }
+ /* If DES alg, and CHA not instantiated, skip */
+ if ((driver_algs[i].class1_alg_type & OP_ALG_ALGSEL_3DES) ||
+ (driver_algs[i].class1_alg_type & OP_ALG_ALGSEL_DES))
+ if (!des_inst)
+ continue;
+ /* If AES alg, and CHA not instantiated, skip */
+ if (driver_algs[i].class1_alg_type & OP_ALG_ALGSEL_AES)
+ if (!aes_inst)
+ continue;
+
t_alg = caam_alg_alloc(ctrldev, &driver_algs[i]);
if (IS_ERR(t_alg)) {
err = PTR_ERR(t_alg);
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
new file mode 100644
index 000000000000..cdc3f3efef02
--- /dev/null
+++ b/drivers/crypto/caam/caamhash.c
@@ -0,0 +1,1962 @@
+/*
+ * caam - Freescale FSL CAAM support for ahash functions of crypto API
+ *
+ * Copyright (C) 2011-2012 Freescale Semiconductor, Inc.
+ *
+ * Based on caamalg.c crypto API driver.
+ *
+ * relationship of digest job descriptor or first job descriptor after init to
+ * shared descriptors:
+ *
+ * --------------- ---------------
+ * | JobDesc #1 |-------------------->| ShareDesc |
+ * | *(packet 1) | | (hashKey) |
+ * --------------- | (operation) |
+ * ---------------
+ *
+ * relationship of subsequent job descriptors to shared descriptors:
+ *
+ * --------------- ---------------
+ * | JobDesc #2 |-------------------->| ShareDesc |
+ * | *(packet 2) | |------------->| (hashKey) |
+ * --------------- | |-------->| (operation) |
+ * . | | | (load ctx2) |
+ * . | | ---------------
+ * --------------- | |
+ * | JobDesc #3 |------| |
+ * | *(packet 3) | |
+ * --------------- |
+ * . |
+ * . |
+ * --------------- |
+ * | JobDesc #4 |------------
+ * | *(packet 4) |
+ * ---------------
+ *
+ * The SharedDesc never changes for a connection unless rekeyed, but
+ * each packet will likely be in a different place. So all we need
+ * to know to process the packet is where the input is, where the
+ * output goes, and what context we want to process with. Context is
+ * in the SharedDesc, packet references in the JobDesc.
+ *
+ * So, a job desc looks like:
+ *
+ * ---------------------
+ * | Header |
+ * | ShareDesc Pointer |
+ * | SEQ_OUT_PTR |
+ * | (output buffer) |
+ * | (output length) |
+ * | SEQ_IN_PTR |
+ * | (input buffer) |
+ * | (input length) |
+ * ---------------------
+ */
+
+#include "compat.h"
+
+#include "regs.h"
+#include "intern.h"
+#include "desc_constr.h"
+#include "jr.h"
+#include "error.h"
+#include "sg_sw_sec4.h"
+#include "key_gen.h"
+
+#define CAAM_CRA_PRIORITY 3000
+
+/* max hash key is max split key size */
+#define CAAM_MAX_HASH_KEY_SIZE (SHA512_DIGEST_SIZE * 2)
+
+#define CAAM_MAX_HASH_BLOCK_SIZE SHA512_BLOCK_SIZE
+#define CAAM_MAX_HASH_DIGEST_SIZE SHA512_DIGEST_SIZE
+
+/* length of descriptors text */
+#define DESC_JOB_IO_LEN (CAAM_CMD_SZ * 5 + CAAM_PTR_SZ * 3)
+
+#define DESC_AHASH_BASE (4 * CAAM_CMD_SZ)
+#define DESC_AHASH_UPDATE_LEN (6 * CAAM_CMD_SZ)
+#define DESC_AHASH_UPDATE_FIRST_LEN (DESC_AHASH_BASE + 4 * CAAM_CMD_SZ)
+#define DESC_AHASH_FINAL_LEN (DESC_AHASH_BASE + 5 * CAAM_CMD_SZ)
+#define DESC_AHASH_FINUP_LEN (DESC_AHASH_BASE + 5 * CAAM_CMD_SZ)
+#define DESC_AHASH_DIGEST_LEN (DESC_AHASH_BASE + 4 * CAAM_CMD_SZ)
+
+#define DESC_HASH_MAX_USED_BYTES (DESC_AHASH_FINAL_LEN + \
+ CAAM_MAX_HASH_KEY_SIZE)
+#define DESC_HASH_MAX_USED_LEN (DESC_HASH_MAX_USED_BYTES / CAAM_CMD_SZ)
+
+/* caam context sizes for hashes: running digest + 8 */
+#define HASH_MSG_LEN 8
+#define MAX_CTX_LEN (HASH_MSG_LEN + SHA512_DIGEST_SIZE)
+
+#ifdef DEBUG
+/* for print_hex_dumps with line references */
+#define xstr(s) str(s)
+#define str(s) #s
+#define debug(format, arg...) printk(format, arg)
+#else
+#define debug(format, arg...)
+#endif
+
+/* ahash per-session context */
+struct caam_hash_ctx {
+ struct device *jrdev;
+ u32 sh_desc_update[DESC_HASH_MAX_USED_LEN];
+ u32 sh_desc_update_first[DESC_HASH_MAX_USED_LEN];
+ u32 sh_desc_fin[DESC_HASH_MAX_USED_LEN];
+ u32 sh_desc_digest[DESC_HASH_MAX_USED_LEN];
+ u32 sh_desc_finup[DESC_HASH_MAX_USED_LEN];
+ dma_addr_t sh_desc_update_dma;
+ dma_addr_t sh_desc_update_first_dma;
+ dma_addr_t sh_desc_fin_dma;
+ dma_addr_t sh_desc_digest_dma;
+ dma_addr_t sh_desc_finup_dma;
+ u32 alg_type;
+ u32 alg_op;
+ u8 key[CAAM_MAX_HASH_KEY_SIZE];
+ dma_addr_t key_dma;
+ int ctx_len;
+ unsigned int split_key_len;
+ unsigned int split_key_pad_len;
+};
+
+/* ahash state */
+struct caam_hash_state {
+ dma_addr_t buf_dma;
+ dma_addr_t ctx_dma;
+ u8 buf_0[CAAM_MAX_HASH_BLOCK_SIZE] ____cacheline_aligned;
+ int buflen_0;
+ u8 buf_1[CAAM_MAX_HASH_BLOCK_SIZE] ____cacheline_aligned;
+ int buflen_1;
+ u8 caam_ctx[MAX_CTX_LEN];
+ int (*update)(struct ahash_request *req);
+ int (*final)(struct ahash_request *req);
+ int (*finup)(struct ahash_request *req);
+ int current_buf;
+};
+
+/* Common job descriptor seq in/out ptr routines */
+
+/* Map state->caam_ctx, and append seq_out_ptr command that points to it */
+static inline void map_seq_out_ptr_ctx(u32 *desc, struct device *jrdev,
+ struct caam_hash_state *state,
+ int ctx_len)
+{
+ state->ctx_dma = dma_map_single(jrdev, state->caam_ctx,
+ ctx_len, DMA_FROM_DEVICE);
+ append_seq_out_ptr(desc, state->ctx_dma, ctx_len, 0);
+}
+
+/* Map req->result, and append seq_out_ptr command that points to it */
+static inline dma_addr_t map_seq_out_ptr_result(u32 *desc, struct device *jrdev,
+ u8 *result, int digestsize)
+{
+ dma_addr_t dst_dma;
+
+ dst_dma = dma_map_single(jrdev, result, digestsize, DMA_FROM_DEVICE);
+ append_seq_out_ptr(desc, dst_dma, digestsize, 0);
+
+ return dst_dma;
+}
+
+/* Map current buffer in state and put it in link table */
+static inline dma_addr_t buf_map_to_sec4_sg(struct device *jrdev,
+ struct sec4_sg_entry *sec4_sg,
+ u8 *buf, int buflen)
+{
+ dma_addr_t buf_dma;
+
+ buf_dma = dma_map_single(jrdev, buf, buflen, DMA_TO_DEVICE);
+ dma_sync_single_for_device(jrdev, buf_dma, buflen, DMA_TO_DEVICE);
+ dma_to_sec4_sg_one(sec4_sg, buf_dma, buflen, 0);
+
+ return buf_dma;
+}
+
+/* Map req->src and put it in link table */
+static inline void src_map_to_sec4_sg(struct device *jrdev,
+ struct scatterlist *src, int src_nents,
+ struct sec4_sg_entry *sec4_sg,
+ bool chained)
+{
+ dma_map_sg_chained(jrdev, src, src_nents, DMA_TO_DEVICE, chained);
+ sg_to_sec4_sg_last(src, src_nents, sec4_sg, 0);
+}
+
+/*
+ * Only put buffer in link table if it contains data, which is possible,
+ * since a buffer has previously been used, and needs to be unmapped,
+ */
+static inline dma_addr_t
+try_buf_map_to_sec4_sg(struct device *jrdev, struct sec4_sg_entry *sec4_sg,
+ u8 *buf, dma_addr_t buf_dma, int buflen,
+ int last_buflen)
+{
+ if (buf_dma && !dma_mapping_error(jrdev, buf_dma))
+ dma_unmap_single(jrdev, buf_dma, last_buflen, DMA_TO_DEVICE);
+ if (buflen)
+ buf_dma = buf_map_to_sec4_sg(jrdev, sec4_sg, buf, buflen);
+ else
+ buf_dma = 0;
+
+ return buf_dma;
+}
+
+/* Map state->caam_ctx, and add it to link table */
+static inline void ctx_map_to_sec4_sg(u32 *desc, struct device *jrdev,
+ struct caam_hash_state *state,
+ int ctx_len,
+ struct sec4_sg_entry *sec4_sg,
+ u32 flag)
+{
+ state->ctx_dma = dma_map_single(jrdev, state->caam_ctx, ctx_len, flag);
+ if ((flag == DMA_TO_DEVICE) || (flag == DMA_BIDIRECTIONAL))
+ dma_sync_single_for_device(jrdev, state->ctx_dma, ctx_len,
+ flag);
+ dma_to_sec4_sg_one(sec4_sg, state->ctx_dma, ctx_len, 0);
+}
+
+/* Common shared descriptor commands */
+static inline void append_key_ahash(u32 *desc, struct caam_hash_ctx *ctx)
+{
+ append_key_as_imm(desc, ctx->key, ctx->split_key_pad_len,
+ ctx->split_key_len, CLASS_2 |
+ KEY_DEST_MDHA_SPLIT | KEY_ENC);
+}
+
+/* Append key if it has been set */
+static inline void init_sh_desc_key_ahash(u32 *desc, struct caam_hash_ctx *ctx)
+{
+ u32 *key_jump_cmd;
+
+ init_sh_desc(desc, HDR_SHARE_SERIAL);
+
+ if (ctx->split_key_len) {
+ /* Skip if already shared */
+ key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL |
+ JUMP_COND_SHRD);
+
+ append_key_ahash(desc, ctx);
+
+ set_jump_tgt_here(desc, key_jump_cmd);
+ }
+
+ /* Propagate errors from shared to job descriptor */
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
+}
+
+/*
+ * For ahash read data from seqin following state->caam_ctx,
+ * and write resulting class2 context to seqout, which may be state->caam_ctx
+ * or req->result
+ */
+static inline void ahash_append_load_str(u32 *desc, int digestsize)
+{
+ /* Calculate remaining bytes to read */
+ append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ);
+
+ /* Read remaining bytes */
+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_LAST2 |
+ FIFOLD_TYPE_MSG | KEY_VLF);
+
+ /* Store class2 context bytes */
+ append_seq_store(desc, digestsize, LDST_CLASS_2_CCB |
+ LDST_SRCDST_BYTE_CONTEXT);
+}
+
+/*
+ * For ahash update, final and finup, import context, read and write to seqout
+ */
+static inline void ahash_ctx_data_to_out(u32 *desc, u32 op, u32 state,
+ int digestsize,
+ struct caam_hash_ctx *ctx)
+{
+ init_sh_desc_key_ahash(desc, ctx);
+
+ /* Import context from software */
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
+ LDST_CLASS_2_CCB | ctx->ctx_len);
+
+ /* Class 2 operation */
+ append_operation(desc, op | state | OP_ALG_ENCRYPT);
+
+ /*
+ * Load from buf and/or src and write to req->result or state->context
+ */
+ ahash_append_load_str(desc, digestsize);
+}
+
+/* For ahash firsts and digest, read and write to seqout */
+static inline void ahash_data_to_out(u32 *desc, u32 op, u32 state,
+ int digestsize, struct caam_hash_ctx *ctx)
+{
+ init_sh_desc_key_ahash(desc, ctx);
+
+ /* Class 2 operation */
+ append_operation(desc, op | state | OP_ALG_ENCRYPT);
+
+ /*
+ * Load from buf and/or src and write to req->result or state->context
+ */
+ ahash_append_load_str(desc, digestsize);
+}
+
+static int ahash_set_sh_desc(struct crypto_ahash *ahash)
+{
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ int digestsize = crypto_ahash_digestsize(ahash);
+ struct device *jrdev = ctx->jrdev;
+ u32 have_key = 0;
+ u32 *desc;
+
+ if (ctx->split_key_len)
+ have_key = OP_ALG_AAI_HMAC_PRECOMP;
+
+ /* ahash_update shared descriptor */
+ desc = ctx->sh_desc_update;
+
+ init_sh_desc(desc, HDR_SHARE_SERIAL);
+
+ /* Import context from software */
+ append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
+ LDST_CLASS_2_CCB | ctx->ctx_len);
+
+ /* Class 2 operation */
+ append_operation(desc, ctx->alg_type | OP_ALG_AS_UPDATE |
+ OP_ALG_ENCRYPT);
+
+ /* Load data and write to result or context */
+ ahash_append_load_str(desc, ctx->ctx_len);
+
+ ctx->sh_desc_update_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_update_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ahash update shdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+
+ /* ahash_update_first shared descriptor */
+ desc = ctx->sh_desc_update_first;
+
+ ahash_data_to_out(desc, have_key | ctx->alg_type, OP_ALG_AS_INIT,
+ ctx->ctx_len, ctx);
+
+ ctx->sh_desc_update_first_dma = dma_map_single(jrdev, desc,
+ desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_update_first_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ahash update first shdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+ dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma,
+ desc_bytes(desc), DMA_TO_DEVICE);
+
+ /* ahash_final shared descriptor */
+ desc = ctx->sh_desc_fin;
+
+ ahash_ctx_data_to_out(desc, have_key | ctx->alg_type,
+ OP_ALG_AS_FINALIZE, digestsize, ctx);
+
+ ctx->sh_desc_fin_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_fin_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ahash final shdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+ dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma,
+ desc_bytes(desc), DMA_TO_DEVICE);
+
+ /* ahash_finup shared descriptor */
+ desc = ctx->sh_desc_finup;
+
+ ahash_ctx_data_to_out(desc, have_key | ctx->alg_type,
+ OP_ALG_AS_FINALIZE, digestsize, ctx);
+
+ ctx->sh_desc_finup_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_finup_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ahash finup shdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+ dma_sync_single_for_device(jrdev, ctx->sh_desc_finup_dma,
+ desc_bytes(desc), DMA_TO_DEVICE);
+
+ /* ahash_digest shared descriptor */
+ desc = ctx->sh_desc_digest;
+
+ ahash_data_to_out(desc, have_key | ctx->alg_type, OP_ALG_AS_INITFINAL,
+ digestsize, ctx);
+
+ ctx->sh_desc_digest_dma = dma_map_single(jrdev, desc,
+ desc_bytes(desc),
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->sh_desc_digest_dma)) {
+ dev_err(jrdev, "unable to map shared descriptor\n");
+ return -ENOMEM;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ahash digest shdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+ dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma,
+ desc_bytes(desc), DMA_TO_DEVICE);
+
+ return 0;
+}
+
+static u32 gen_split_hash_key(struct caam_hash_ctx *ctx, const u8 *key_in,
+ u32 keylen)
+{
+ return gen_split_key(ctx->jrdev, ctx->key, ctx->split_key_len,
+ ctx->split_key_pad_len, key_in, keylen,
+ ctx->alg_op);
+}
+
+/* Digest hash size if it is too large */
+static u32 hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in,
+ u32 *keylen, u8 *key_out, u32 digestsize)
+{
+ struct device *jrdev = ctx->jrdev;
+ u32 *desc;
+ struct split_key_result result;
+ dma_addr_t src_dma, dst_dma;
+ int ret = 0;
+
+ desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
+
+ init_job_desc(desc, 0);
+
+ src_dma = dma_map_single(jrdev, (void *)key_in, *keylen,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, src_dma)) {
+ dev_err(jrdev, "unable to map key input memory\n");
+ kfree(desc);
+ return -ENOMEM;
+ }
+ dma_sync_single_for_device(jrdev, src_dma, *keylen, DMA_TO_DEVICE);
+
+ dst_dma = dma_map_single(jrdev, (void *)key_out, digestsize,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(jrdev, dst_dma)) {
+ dev_err(jrdev, "unable to map key output memory\n");
+ dma_unmap_single(jrdev, src_dma, *keylen, DMA_TO_DEVICE);
+ kfree(desc);
+ return -ENOMEM;
+ }
+
+ /* Job descriptor to perform unkeyed hash on key_in */
+ append_operation(desc, ctx->alg_type | OP_ALG_ENCRYPT |
+ OP_ALG_AS_INITFINAL);
+ append_seq_in_ptr(desc, src_dma, *keylen, 0);
+ append_seq_fifo_load(desc, *keylen, FIFOLD_CLASS_CLASS2 |
+ FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_MSG);
+ append_seq_out_ptr(desc, dst_dma, digestsize, 0);
+ append_seq_store(desc, digestsize, LDST_CLASS_2_CCB |
+ LDST_SRCDST_BYTE_CONTEXT);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "key_in@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, key_in, *keylen, 1);
+ print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+
+ result.err = 0;
+ init_completion(&result.completion);
+
+ ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result);
+ if (!ret) {
+ /* in progress */
+ wait_for_completion_interruptible(&result.completion);
+ ret = result.err;
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "digested key@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, key_in,
+ digestsize, 1);
+#endif
+ }
+ *keylen = digestsize;
+
+ dma_unmap_single(jrdev, src_dma, *keylen, DMA_TO_DEVICE);
+ dma_sync_single_for_cpu(jrdev, dst_dma, digestsize, DMA_FROM_DEVICE);
+ dma_unmap_single(jrdev, dst_dma, digestsize, DMA_FROM_DEVICE);
+
+ kfree(desc);
+
+ return ret;
+}
+
+static int ahash_setkey(struct crypto_ahash *ahash,
+ const u8 *key, unsigned int keylen)
+{
+ /* Sizes for MDHA pads (*not* keys): MD5, SHA1, 224, 256, 384, 512 */
+ static const u8 mdpadlen[] = { 16, 20, 32, 32, 64, 64 };
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ struct device *jrdev = ctx->jrdev;
+ int blocksize = crypto_tfm_alg_blocksize(&ahash->base);
+ int digestsize = crypto_ahash_digestsize(ahash);
+ int ret = 0;
+ u8 *hashed_key = NULL;
+
+#ifdef DEBUG
+ printk(KERN_ERR "keylen %d\n", keylen);
+#endif
+
+ if (keylen > blocksize) {
+ hashed_key = kmalloc(sizeof(u8) * digestsize, GFP_KERNEL |
+ GFP_DMA);
+ if (!hashed_key)
+ return -ENOMEM;
+ ret = hash_digest_key(ctx, key, &keylen, hashed_key,
+ digestsize);
+ if (ret)
+ goto badkey;
+ key = hashed_key;
+ }
+
+ /* Pick class 2 key length from algorithm submask */
+ ctx->split_key_len = mdpadlen[(ctx->alg_op & OP_ALG_ALGSEL_SUBMASK) >>
+ OP_ALG_ALGSEL_SHIFT] * 2;
+ ctx->split_key_pad_len = ALIGN(ctx->split_key_len, 16);
+
+#ifdef DEBUG
+ printk(KERN_ERR "split_key_len %d split_key_pad_len %d\n",
+ ctx->split_key_len, ctx->split_key_pad_len);
+ print_hex_dump(KERN_ERR, "key in @"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1);
+#endif
+
+ ret = gen_split_hash_key(ctx, key, keylen);
+ if (ret)
+ goto badkey;
+
+ ctx->key_dma = dma_map_single(jrdev, ctx->key, ctx->split_key_pad_len,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, ctx->key_dma)) {
+ dev_err(jrdev, "unable to map key i/o memory\n");
+ return -ENOMEM;
+ }
+
+ dma_sync_single_for_device(jrdev, ctx->key_dma, ctx->split_key_pad_len,
+ DMA_TO_DEVICE);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ctx.key@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, ctx->key,
+ ctx->split_key_pad_len, 1);
+#endif
+
+ ret = ahash_set_sh_desc(ahash);
+ if (ret) {
+ dma_unmap_single(jrdev, ctx->key_dma, ctx->split_key_pad_len,
+ DMA_TO_DEVICE);
+ }
+
+ kfree(hashed_key);
+ return ret;
+badkey:
+ kfree(hashed_key);
+ crypto_ahash_set_flags(ahash, CRYPTO_TFM_RES_BAD_KEY_LEN);
+ return -EINVAL;
+}
+
+/*
+ * ahash_edesc - s/w-extended ahash descriptor
+ * @dst_dma: physical mapped address of req->result
+ * @sec4_sg_dma: physical mapped address of h/w link table
+ * @chained: if source is chained
+ * @src_nents: number of segments in input scatterlist
+ * @sec4_sg_bytes: length of dma mapped sec4_sg space
+ * @sec4_sg: pointer to h/w link table
+ * @hw_desc: the h/w job descriptor followed by any referenced link tables
+ */
+struct ahash_edesc {
+ dma_addr_t dst_dma;
+ dma_addr_t sec4_sg_dma;
+ bool chained;
+ int src_nents;
+ int sec4_sg_bytes;
+ struct sec4_sg_entry *sec4_sg;
+ u32 hw_desc[0];
+};
+
+static inline void ahash_unmap(struct device *dev,
+ struct ahash_edesc *edesc,
+ struct ahash_request *req, int dst_len)
+{
+ if (edesc->src_nents)
+ dma_unmap_sg_chained(dev, req->src, edesc->src_nents,
+ DMA_TO_DEVICE, edesc->chained);
+ if (edesc->dst_dma) {
+ dma_sync_single_for_cpu(dev, edesc->dst_dma, dst_len,
+ DMA_FROM_DEVICE);
+ dma_unmap_single(dev, edesc->dst_dma, dst_len, DMA_FROM_DEVICE);
+ }
+
+ if (edesc->sec4_sg_bytes)
+ dma_unmap_single(dev, edesc->sec4_sg_dma,
+ edesc->sec4_sg_bytes, DMA_TO_DEVICE);
+}
+
+static inline void ahash_unmap_ctx(struct device *dev,
+ struct ahash_edesc *edesc,
+ struct ahash_request *req, int dst_len, u32 flag)
+{
+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ struct caam_hash_state *state = ahash_request_ctx(req);
+
+ if (state->ctx_dma) {
+ if ((flag == DMA_FROM_DEVICE) || (flag == DMA_BIDIRECTIONAL))
+ dma_sync_single_for_cpu(dev, state->ctx_dma,
+ ctx->ctx_len, flag);
+ dma_unmap_single(dev, state->ctx_dma, ctx->ctx_len, flag);
+ }
+ ahash_unmap(dev, edesc, req, dst_len);
+}
+
+static void ahash_done(struct device *jrdev, u32 *desc, u32 err,
+ void *context)
+{
+ struct ahash_request *req = context;
+ struct ahash_edesc *edesc;
+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ int digestsize = crypto_ahash_digestsize(ahash);
+#ifdef DEBUG
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ struct caam_hash_state *state = ahash_request_ctx(req);
+
+ dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
+#endif
+
+ edesc = (struct ahash_edesc *)((char *)desc -
+ offsetof(struct ahash_edesc, hw_desc));
+ if (err) {
+ char tmp[CAAM_ERROR_STR_MAX];
+
+ dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
+ }
+
+ ahash_unmap(jrdev, edesc, req, digestsize);
+ kfree(edesc);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ctx@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
+ ctx->ctx_len, 1);
+ if (req->result)
+ print_hex_dump(KERN_ERR, "result@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, req->result,
+ digestsize, 1);
+#endif
+
+ req->base.complete(&req->base, err);
+}
+
+static void ahash_done_bi(struct device *jrdev, u32 *desc, u32 err,
+ void *context)
+{
+ struct ahash_request *req = context;
+ struct ahash_edesc *edesc;
+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+#ifdef DEBUG
+ struct caam_hash_state *state = ahash_request_ctx(req);
+ int digestsize = crypto_ahash_digestsize(ahash);
+
+ dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
+#endif
+
+ edesc = (struct ahash_edesc *)((char *)desc -
+ offsetof(struct ahash_edesc, hw_desc));
+ if (err) {
+ char tmp[CAAM_ERROR_STR_MAX];
+
+ dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
+ }
+
+ ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_BIDIRECTIONAL);
+ kfree(edesc);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ctx@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
+ ctx->ctx_len, 1);
+ if (req->result)
+ print_hex_dump(KERN_ERR, "result@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, req->result,
+ digestsize, 1);
+#endif
+
+ req->base.complete(&req->base, err);
+}
+
+static void ahash_done_ctx_src(struct device *jrdev, u32 *desc, u32 err,
+ void *context)
+{
+ struct ahash_request *req = context;
+ struct ahash_edesc *edesc;
+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ int digestsize = crypto_ahash_digestsize(ahash);
+#ifdef DEBUG
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ struct caam_hash_state *state = ahash_request_ctx(req);
+
+ dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
+#endif
+
+ edesc = (struct ahash_edesc *)((char *)desc -
+ offsetof(struct ahash_edesc, hw_desc));
+ if (err) {
+ char tmp[CAAM_ERROR_STR_MAX];
+
+ dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
+ }
+
+ ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
+ kfree(edesc);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ctx@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
+ ctx->ctx_len, 1);
+ if (req->result)
+ print_hex_dump(KERN_ERR, "result@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, req->result,
+ digestsize, 1);
+#endif
+
+ req->base.complete(&req->base, err);
+}
+
+static void ahash_done_ctx_dst(struct device *jrdev, u32 *desc, u32 err,
+ void *context)
+{
+ struct ahash_request *req = context;
+ struct ahash_edesc *edesc;
+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+#ifdef DEBUG
+ struct caam_hash_state *state = ahash_request_ctx(req);
+ int digestsize = crypto_ahash_digestsize(ahash);
+
+ dev_err(jrdev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
+#endif
+
+ edesc = (struct ahash_edesc *)((char *)desc -
+ offsetof(struct ahash_edesc, hw_desc));
+ if (err) {
+ char tmp[CAAM_ERROR_STR_MAX];
+
+ dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
+ }
+
+ ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len, DMA_TO_DEVICE);
+ kfree(edesc);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ctx@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx,
+ ctx->ctx_len, 1);
+ if (req->result)
+ print_hex_dump(KERN_ERR, "result@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, req->result,
+ digestsize, 1);
+#endif
+
+ req->base.complete(&req->base, err);
+}
+
+/* submit update job descriptor */
+static int ahash_update_ctx(struct ahash_request *req)
+{
+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ struct caam_hash_state *state = ahash_request_ctx(req);
+ struct device *jrdev = ctx->jrdev;
+ gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
+ CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
+ u8 *buf = state->current_buf ? state->buf_1 : state->buf_0;
+ int *buflen = state->current_buf ? &state->buflen_1 : &state->buflen_0;
+ u8 *next_buf = state->current_buf ? state->buf_0 : state->buf_1;
+ int *next_buflen = state->current_buf ? &state->buflen_0 :
+ &state->buflen_1, last_buflen;
+ int in_len = *buflen + req->nbytes, to_hash;
+ u32 *sh_desc = ctx->sh_desc_update, *desc;
+ dma_addr_t ptr = ctx->sh_desc_update_dma;
+ int src_nents, sec4_sg_bytes, sec4_sg_src_index;
+ struct ahash_edesc *edesc;
+ bool chained = false;
+ int ret = 0;
+ int sh_len;
+
+ last_buflen = *next_buflen;
+ *next_buflen = in_len & (crypto_tfm_alg_blocksize(&ahash->base) - 1);
+ to_hash = in_len - *next_buflen;
+
+ if (to_hash) {
+ src_nents = __sg_count(req->src, req->nbytes - (*next_buflen),
+ &chained);
+ sec4_sg_src_index = 1 + (*buflen ? 1 : 0);
+ sec4_sg_bytes = (sec4_sg_src_index + src_nents) *
+ sizeof(struct sec4_sg_entry);
+
+ /*
+ * allocate space for base edesc and hw desc commands,
+ * link tables
+ */
+ edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
+ sec4_sg_bytes, GFP_DMA | flags);
+ if (!edesc) {
+ dev_err(jrdev,
+ "could not allocate extended descriptor\n");
+ return -ENOMEM;
+ }
+
+ edesc->src_nents = src_nents;
+ edesc->chained = chained;
+ edesc->sec4_sg_bytes = sec4_sg_bytes;
+ edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
+ DESC_JOB_IO_LEN;
+ edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+ sec4_sg_bytes,
+ DMA_TO_DEVICE);
+
+ ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len,
+ edesc->sec4_sg, DMA_BIDIRECTIONAL);
+
+ state->buf_dma = try_buf_map_to_sec4_sg(jrdev,
+ edesc->sec4_sg + 1,
+ buf, state->buf_dma,
+ *buflen, last_buflen);
+
+ if (src_nents) {
+ src_map_to_sec4_sg(jrdev, req->src, src_nents,
+ edesc->sec4_sg + sec4_sg_src_index,
+ chained);
+ if (*next_buflen) {
+ sg_copy_part(next_buf, req->src, to_hash -
+ *buflen, req->nbytes);
+ state->current_buf = !state->current_buf;
+ }
+ } else {
+ (edesc->sec4_sg + sec4_sg_src_index - 1)->len |=
+ SEC4_SG_LEN_FIN;
+ }
+
+ sh_len = desc_len(sh_desc);
+ desc = edesc->hw_desc;
+ init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER |
+ HDR_REVERSE);
+
+ append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len +
+ to_hash, LDST_SGF);
+
+ append_seq_out_ptr(desc, state->ctx_dma, ctx->ctx_len, 0);
+
+ dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma,
+ sec4_sg_bytes, DMA_TO_DEVICE);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+
+ ret = caam_jr_enqueue(jrdev, desc, ahash_done_bi, req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len,
+ DMA_BIDIRECTIONAL);
+ kfree(edesc);
+ }
+ } else if (*next_buflen) {
+ sg_copy(buf + *buflen, req->src, req->nbytes);
+ *buflen = *next_buflen;
+ *next_buflen = last_buflen;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "buf@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, buf, *buflen, 1);
+ print_hex_dump(KERN_ERR, "next buf@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, next_buf,
+ *next_buflen, 1);
+#endif
+
+ return ret;
+}
+
+static int ahash_final_ctx(struct ahash_request *req)
+{
+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ struct caam_hash_state *state = ahash_request_ctx(req);
+ struct device *jrdev = ctx->jrdev;
+ gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
+ CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
+ u8 *buf = state->current_buf ? state->buf_1 : state->buf_0;
+ int buflen = state->current_buf ? state->buflen_1 : state->buflen_0;
+ int last_buflen = state->current_buf ? state->buflen_0 :
+ state->buflen_1;
+ u32 *sh_desc = ctx->sh_desc_fin, *desc;
+ dma_addr_t ptr = ctx->sh_desc_fin_dma;
+ int sec4_sg_bytes;
+ int digestsize = crypto_ahash_digestsize(ahash);
+ struct ahash_edesc *edesc;
+ int ret = 0;
+ int sh_len;
+
+ sec4_sg_bytes = (1 + (buflen ? 1 : 0)) * sizeof(struct sec4_sg_entry);
+
+ /* allocate space for base edesc and hw desc commands, link tables */
+ edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
+ sec4_sg_bytes, GFP_DMA | flags);
+ if (!edesc) {
+ dev_err(jrdev, "could not allocate extended descriptor\n");
+ return -ENOMEM;
+ }
+
+ sh_len = desc_len(sh_desc);
+ desc = edesc->hw_desc;
+ init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE);
+
+ edesc->sec4_sg_bytes = sec4_sg_bytes;
+ edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
+ DESC_JOB_IO_LEN;
+ edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+ sec4_sg_bytes, DMA_TO_DEVICE);
+ edesc->src_nents = 0;
+
+ ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len, edesc->sec4_sg,
+ DMA_TO_DEVICE);
+
+ state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1,
+ buf, state->buf_dma, buflen,
+ last_buflen);
+ (edesc->sec4_sg + sec4_sg_bytes - 1)->len |= SEC4_SG_LEN_FIN;
+
+ append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len + buflen,
+ LDST_SGF);
+
+ edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
+ digestsize);
+
+ dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma, sec4_sg_bytes,
+ DMA_TO_DEVICE);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+
+ ret = caam_jr_enqueue(jrdev, desc, ahash_done_ctx_src, req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
+ kfree(edesc);
+ }
+
+ return ret;
+}
+
+static int ahash_finup_ctx(struct ahash_request *req)
+{
+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ struct caam_hash_state *state = ahash_request_ctx(req);
+ struct device *jrdev = ctx->jrdev;
+ gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
+ CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
+ u8 *buf = state->current_buf ? state->buf_1 : state->buf_0;
+ int buflen = state->current_buf ? state->buflen_1 : state->buflen_0;
+ int last_buflen = state->current_buf ? state->buflen_0 :
+ state->buflen_1;
+ u32 *sh_desc = ctx->sh_desc_finup, *desc;
+ dma_addr_t ptr = ctx->sh_desc_finup_dma;
+ int sec4_sg_bytes, sec4_sg_src_index;
+ int src_nents;
+ int digestsize = crypto_ahash_digestsize(ahash);
+ struct ahash_edesc *edesc;
+ bool chained = false;
+ int ret = 0;
+ int sh_len;
+
+ src_nents = __sg_count(req->src, req->nbytes, &chained);
+ sec4_sg_src_index = 1 + (buflen ? 1 : 0);
+ sec4_sg_bytes = (sec4_sg_src_index + src_nents) *
+ sizeof(struct sec4_sg_entry);
+
+ /* allocate space for base edesc and hw desc commands, link tables */
+ edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
+ sec4_sg_bytes, GFP_DMA | flags);
+ if (!edesc) {
+ dev_err(jrdev, "could not allocate extended descriptor\n");
+ return -ENOMEM;
+ }
+
+ sh_len = desc_len(sh_desc);
+ desc = edesc->hw_desc;
+ init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE);
+
+ edesc->src_nents = src_nents;
+ edesc->chained = chained;
+ edesc->sec4_sg_bytes = sec4_sg_bytes;
+ edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
+ DESC_JOB_IO_LEN;
+ edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+ sec4_sg_bytes, DMA_TO_DEVICE);
+
+ ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len, edesc->sec4_sg,
+ DMA_TO_DEVICE);
+
+ state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1,
+ buf, state->buf_dma, buflen,
+ last_buflen);
+
+ src_map_to_sec4_sg(jrdev, req->src, src_nents, edesc->sec4_sg +
+ sec4_sg_src_index, chained);
+
+ append_seq_in_ptr(desc, edesc->sec4_sg_dma, ctx->ctx_len +
+ buflen + req->nbytes, LDST_SGF);
+
+ edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
+ digestsize);
+
+ dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma, sec4_sg_bytes,
+ DMA_TO_DEVICE);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+
+ ret = caam_jr_enqueue(jrdev, desc, ahash_done_ctx_src, req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ ahash_unmap_ctx(jrdev, edesc, req, digestsize, DMA_FROM_DEVICE);
+ kfree(edesc);
+ }
+
+ return ret;
+}
+
+static int ahash_digest(struct ahash_request *req)
+{
+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ struct device *jrdev = ctx->jrdev;
+ gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
+ CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
+ u32 *sh_desc = ctx->sh_desc_digest, *desc;
+ dma_addr_t ptr = ctx->sh_desc_digest_dma;
+ int digestsize = crypto_ahash_digestsize(ahash);
+ int src_nents, sec4_sg_bytes;
+ dma_addr_t src_dma;
+ struct ahash_edesc *edesc;
+ bool chained = false;
+ int ret = 0;
+ u32 options;
+ int sh_len;
+
+ src_nents = sg_count(req->src, req->nbytes, &chained);
+ dma_map_sg_chained(jrdev, req->src, src_nents ? : 1, DMA_TO_DEVICE,
+ chained);
+ sec4_sg_bytes = src_nents * sizeof(struct sec4_sg_entry);
+
+ /* allocate space for base edesc and hw desc commands, link tables */
+ edesc = kzalloc(sizeof(struct ahash_edesc) + sec4_sg_bytes +
+ DESC_JOB_IO_LEN, GFP_DMA | flags);
+ if (!edesc) {
+ dev_err(jrdev, "could not allocate extended descriptor\n");
+ return -ENOMEM;
+ }
+ edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
+ DESC_JOB_IO_LEN;
+ edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+ sec4_sg_bytes, DMA_TO_DEVICE);
+ edesc->sec4_sg_bytes = sec4_sg_bytes;
+ edesc->src_nents = src_nents;
+ edesc->chained = chained;
+
+ sh_len = desc_len(sh_desc);
+ desc = edesc->hw_desc;
+ init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE);
+
+ if (src_nents) {
+ sg_to_sec4_sg_last(req->src, src_nents, edesc->sec4_sg, 0);
+ src_dma = edesc->sec4_sg_dma;
+ options = LDST_SGF;
+ } else {
+ src_dma = sg_dma_address(req->src);
+ options = 0;
+ }
+ append_seq_in_ptr(desc, src_dma, req->nbytes, options);
+
+ dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma,
+ edesc->sec4_sg_bytes, DMA_TO_DEVICE);
+
+ edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
+ digestsize);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+
+ ret = caam_jr_enqueue(jrdev, desc, ahash_done, req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ ahash_unmap(jrdev, edesc, req, digestsize);
+ kfree(edesc);
+ }
+
+ return ret;
+}
+
+/* submit ahash final if it the first job descriptor */
+static int ahash_final_no_ctx(struct ahash_request *req)
+{
+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ struct caam_hash_state *state = ahash_request_ctx(req);
+ struct device *jrdev = ctx->jrdev;
+ gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
+ CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
+ u8 *buf = state->current_buf ? state->buf_1 : state->buf_0;
+ int buflen = state->current_buf ? state->buflen_1 : state->buflen_0;
+ u32 *sh_desc = ctx->sh_desc_digest, *desc;
+ dma_addr_t ptr = ctx->sh_desc_digest_dma;
+ int digestsize = crypto_ahash_digestsize(ahash);
+ struct ahash_edesc *edesc;
+ int ret = 0;
+ int sh_len;
+
+ /* allocate space for base edesc and hw desc commands, link tables */
+ edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN,
+ GFP_DMA | flags);
+ if (!edesc) {
+ dev_err(jrdev, "could not allocate extended descriptor\n");
+ return -ENOMEM;
+ }
+
+ sh_len = desc_len(sh_desc);
+ desc = edesc->hw_desc;
+ init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE);
+
+ state->buf_dma = dma_map_single(jrdev, buf, buflen, DMA_TO_DEVICE);
+
+ append_seq_in_ptr(desc, state->buf_dma, buflen, 0);
+
+ edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
+ digestsize);
+ edesc->src_nents = 0;
+
+ dma_sync_single_for_device(jrdev, state->buf_dma, buflen,
+ DMA_TO_DEVICE);
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+
+ ret = caam_jr_enqueue(jrdev, desc, ahash_done, req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ ahash_unmap(jrdev, edesc, req, digestsize);
+ kfree(edesc);
+ }
+
+ return ret;
+}
+
+/* submit ahash update if it the first job descriptor after update */
+static int ahash_update_no_ctx(struct ahash_request *req)
+{
+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ struct caam_hash_state *state = ahash_request_ctx(req);
+ struct device *jrdev = ctx->jrdev;
+ gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
+ CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
+ u8 *buf = state->current_buf ? state->buf_1 : state->buf_0;
+ int *buflen = state->current_buf ? &state->buflen_1 : &state->buflen_0;
+ u8 *next_buf = state->current_buf ? state->buf_0 : state->buf_1;
+ int *next_buflen = state->current_buf ? &state->buflen_0 :
+ &state->buflen_1;
+ int in_len = *buflen + req->nbytes, to_hash;
+ int sec4_sg_bytes, src_nents;
+ struct ahash_edesc *edesc;
+ u32 *desc, *sh_desc = ctx->sh_desc_update_first;
+ dma_addr_t ptr = ctx->sh_desc_update_first_dma;
+ bool chained = false;
+ int ret = 0;
+ int sh_len;
+
+ *next_buflen = in_len & (crypto_tfm_alg_blocksize(&ahash->base) - 1);
+ to_hash = in_len - *next_buflen;
+
+ if (to_hash) {
+ src_nents = __sg_count(req->src, req->nbytes - (*next_buflen),
+ &chained);
+ sec4_sg_bytes = (1 + src_nents) *
+ sizeof(struct sec4_sg_entry);
+
+ /*
+ * allocate space for base edesc and hw desc commands,
+ * link tables
+ */
+ edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
+ sec4_sg_bytes, GFP_DMA | flags);
+ if (!edesc) {
+ dev_err(jrdev,
+ "could not allocate extended descriptor\n");
+ return -ENOMEM;
+ }
+
+ edesc->src_nents = src_nents;
+ edesc->chained = chained;
+ edesc->sec4_sg_bytes = sec4_sg_bytes;
+ edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
+ DESC_JOB_IO_LEN;
+ edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+ sec4_sg_bytes,
+ DMA_TO_DEVICE);
+
+ state->buf_dma = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg,
+ buf, *buflen);
+ src_map_to_sec4_sg(jrdev, req->src, src_nents,
+ edesc->sec4_sg + 1, chained);
+ if (*next_buflen) {
+ sg_copy_part(next_buf, req->src, to_hash - *buflen,
+ req->nbytes);
+ state->current_buf = !state->current_buf;
+ }
+
+ sh_len = desc_len(sh_desc);
+ desc = edesc->hw_desc;
+ init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER |
+ HDR_REVERSE);
+
+ append_seq_in_ptr(desc, edesc->sec4_sg_dma, to_hash, LDST_SGF);
+
+ map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
+
+ dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma,
+ sec4_sg_bytes, DMA_TO_DEVICE);
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+
+ ret = caam_jr_enqueue(jrdev, desc, ahash_done_ctx_dst, req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ state->update = ahash_update_ctx;
+ state->finup = ahash_finup_ctx;
+ state->final = ahash_final_ctx;
+ } else {
+ ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len,
+ DMA_TO_DEVICE);
+ kfree(edesc);
+ }
+ } else if (*next_buflen) {
+ sg_copy(buf + *buflen, req->src, req->nbytes);
+ *buflen = *next_buflen;
+ *next_buflen = 0;
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "buf@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, buf, *buflen, 1);
+ print_hex_dump(KERN_ERR, "next buf@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, next_buf,
+ *next_buflen, 1);
+#endif
+
+ return ret;
+}
+
+/* submit ahash finup if it the first job descriptor after update */
+static int ahash_finup_no_ctx(struct ahash_request *req)
+{
+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ struct caam_hash_state *state = ahash_request_ctx(req);
+ struct device *jrdev = ctx->jrdev;
+ gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
+ CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
+ u8 *buf = state->current_buf ? state->buf_1 : state->buf_0;
+ int buflen = state->current_buf ? state->buflen_1 : state->buflen_0;
+ int last_buflen = state->current_buf ? state->buflen_0 :
+ state->buflen_1;
+ u32 *sh_desc = ctx->sh_desc_digest, *desc;
+ dma_addr_t ptr = ctx->sh_desc_digest_dma;
+ int sec4_sg_bytes, sec4_sg_src_index, src_nents;
+ int digestsize = crypto_ahash_digestsize(ahash);
+ struct ahash_edesc *edesc;
+ bool chained = false;
+ int sh_len;
+ int ret = 0;
+
+ src_nents = __sg_count(req->src, req->nbytes, &chained);
+ sec4_sg_src_index = 2;
+ sec4_sg_bytes = (sec4_sg_src_index + src_nents) *
+ sizeof(struct sec4_sg_entry);
+
+ /* allocate space for base edesc and hw desc commands, link tables */
+ edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
+ sec4_sg_bytes, GFP_DMA | flags);
+ if (!edesc) {
+ dev_err(jrdev, "could not allocate extended descriptor\n");
+ return -ENOMEM;
+ }
+
+ sh_len = desc_len(sh_desc);
+ desc = edesc->hw_desc;
+ init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER | HDR_REVERSE);
+
+ edesc->src_nents = src_nents;
+ edesc->chained = chained;
+ edesc->sec4_sg_bytes = sec4_sg_bytes;
+ edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
+ DESC_JOB_IO_LEN;
+ edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+ sec4_sg_bytes, DMA_TO_DEVICE);
+
+ state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg, buf,
+ state->buf_dma, buflen,
+ last_buflen);
+
+ src_map_to_sec4_sg(jrdev, req->src, src_nents, edesc->sec4_sg + 1,
+ chained);
+
+ append_seq_in_ptr(desc, edesc->sec4_sg_dma, buflen +
+ req->nbytes, LDST_SGF);
+
+ edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
+ digestsize);
+
+ dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma, sec4_sg_bytes,
+ DMA_TO_DEVICE);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+
+ ret = caam_jr_enqueue(jrdev, desc, ahash_done, req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ } else {
+ ahash_unmap(jrdev, edesc, req, digestsize);
+ kfree(edesc);
+ }
+
+ return ret;
+}
+
+/* submit first update job descriptor after init */
+static int ahash_update_first(struct ahash_request *req)
+{
+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ struct caam_hash_state *state = ahash_request_ctx(req);
+ struct device *jrdev = ctx->jrdev;
+ gfp_t flags = (req->base.flags & (CRYPTO_TFM_REQ_MAY_BACKLOG |
+ CRYPTO_TFM_REQ_MAY_SLEEP)) ? GFP_KERNEL : GFP_ATOMIC;
+ u8 *next_buf = state->buf_0 + state->current_buf *
+ CAAM_MAX_HASH_BLOCK_SIZE;
+ int *next_buflen = &state->buflen_0 + state->current_buf;
+ int to_hash;
+ u32 *sh_desc = ctx->sh_desc_update_first, *desc;
+ dma_addr_t ptr = ctx->sh_desc_update_first_dma;
+ int sec4_sg_bytes, src_nents;
+ dma_addr_t src_dma;
+ u32 options;
+ struct ahash_edesc *edesc;
+ bool chained = false;
+ int ret = 0;
+ int sh_len;
+
+ *next_buflen = req->nbytes & (crypto_tfm_alg_blocksize(&ahash->base) -
+ 1);
+ to_hash = req->nbytes - *next_buflen;
+
+ if (to_hash) {
+ src_nents = sg_count(req->src, req->nbytes - (*next_buflen),
+ &chained);
+ dma_map_sg_chained(jrdev, req->src, src_nents ? : 1,
+ DMA_TO_DEVICE, chained);
+ sec4_sg_bytes = src_nents * sizeof(struct sec4_sg_entry);
+
+ /*
+ * allocate space for base edesc and hw desc commands,
+ * link tables
+ */
+ edesc = kzalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
+ sec4_sg_bytes, GFP_DMA | flags);
+ if (!edesc) {
+ dev_err(jrdev,
+ "could not allocate extended descriptor\n");
+ return -ENOMEM;
+ }
+
+ edesc->src_nents = src_nents;
+ edesc->chained = chained;
+ edesc->sec4_sg_bytes = sec4_sg_bytes;
+ edesc->sec4_sg = (void *)edesc + sizeof(struct ahash_edesc) +
+ DESC_JOB_IO_LEN;
+ edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
+ sec4_sg_bytes,
+ DMA_TO_DEVICE);
+
+ if (src_nents) {
+ sg_to_sec4_sg_last(req->src, src_nents,
+ edesc->sec4_sg, 0);
+ src_dma = edesc->sec4_sg_dma;
+ options = LDST_SGF;
+ } else {
+ src_dma = sg_dma_address(req->src);
+ options = 0;
+ }
+
+ if (*next_buflen)
+ sg_copy_part(next_buf, req->src, to_hash, req->nbytes);
+
+ sh_len = desc_len(sh_desc);
+ desc = edesc->hw_desc;
+ init_job_desc_shared(desc, ptr, sh_len, HDR_SHARE_DEFER |
+ HDR_REVERSE);
+
+ append_seq_in_ptr(desc, src_dma, to_hash, options);
+
+ map_seq_out_ptr_ctx(desc, jrdev, state, ctx->ctx_len);
+
+ dma_sync_single_for_device(jrdev, edesc->sec4_sg_dma,
+ sec4_sg_bytes, DMA_TO_DEVICE);
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc,
+ desc_bytes(desc), 1);
+#endif
+
+ ret = caam_jr_enqueue(jrdev, desc, ahash_done_ctx_dst,
+ req);
+ if (!ret) {
+ ret = -EINPROGRESS;
+ state->update = ahash_update_ctx;
+ state->finup = ahash_finup_ctx;
+ state->final = ahash_final_ctx;
+ } else {
+ ahash_unmap_ctx(jrdev, edesc, req, ctx->ctx_len,
+ DMA_TO_DEVICE);
+ kfree(edesc);
+ }
+ } else if (*next_buflen) {
+ state->update = ahash_update_no_ctx;
+ state->finup = ahash_finup_no_ctx;
+ state->final = ahash_final_no_ctx;
+ sg_copy(next_buf, req->src, req->nbytes);
+ }
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "next buf@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, next_buf,
+ *next_buflen, 1);
+#endif
+
+ return ret;
+}
+
+static int ahash_finup_first(struct ahash_request *req)
+{
+ return ahash_digest(req);
+}
+
+static int ahash_init(struct ahash_request *req)
+{
+ struct caam_hash_state *state = ahash_request_ctx(req);
+
+ state->update = ahash_update_first;
+ state->finup = ahash_finup_first;
+ state->final = ahash_final_no_ctx;
+
+ state->current_buf = 0;
+
+ return 0;
+}
+
+static int ahash_update(struct ahash_request *req)
+{
+ struct caam_hash_state *state = ahash_request_ctx(req);
+
+ return state->update(req);
+}
+
+static int ahash_finup(struct ahash_request *req)
+{
+ struct caam_hash_state *state = ahash_request_ctx(req);
+
+ return state->finup(req);
+}
+
+static int ahash_final(struct ahash_request *req)
+{
+ struct caam_hash_state *state = ahash_request_ctx(req);
+
+ return state->final(req);
+}
+
+static int ahash_export(struct ahash_request *req, void *out)
+{
+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ struct caam_hash_state *state = ahash_request_ctx(req);
+
+ memcpy(out, ctx, sizeof(struct caam_hash_ctx));
+ memcpy(out + sizeof(struct caam_hash_ctx), state,
+ sizeof(struct caam_hash_state));
+ return 0;
+}
+
+static int ahash_import(struct ahash_request *req, const void *in)
+{
+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash);
+ struct caam_hash_state *state = ahash_request_ctx(req);
+
+ memcpy(ctx, in, sizeof(struct caam_hash_ctx));
+ memcpy(state, in + sizeof(struct caam_hash_ctx),
+ sizeof(struct caam_hash_state));
+ return 0;
+}
+
+struct caam_hash_template {
+ char name[CRYPTO_MAX_ALG_NAME];
+ char driver_name[CRYPTO_MAX_ALG_NAME];
+ char hmac_name[CRYPTO_MAX_ALG_NAME];
+ char hmac_driver_name[CRYPTO_MAX_ALG_NAME];
+ unsigned int blocksize;
+ struct ahash_alg template_ahash;
+ u32 alg_type;
+ u32 alg_op;
+};
+
+/* ahash descriptors */
+static struct caam_hash_template driver_hash[] = {
+ {
+ .name = "sha1",
+ .driver_name = "sha1-caam",
+ .hmac_name = "hmac(sha1)",
+ .hmac_driver_name = "hmac-sha1-caam",
+ .blocksize = SHA1_BLOCK_SIZE,
+ .template_ahash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .export = ahash_export,
+ .import = ahash_import,
+ .setkey = ahash_setkey,
+ .halg = {
+ .digestsize = SHA1_DIGEST_SIZE,
+ },
+ },
+ .alg_type = OP_ALG_ALGSEL_SHA1,
+ .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC,
+ }, {
+ .name = "sha224",
+ .driver_name = "sha224-caam",
+ .hmac_name = "hmac(sha224)",
+ .hmac_driver_name = "hmac-sha224-caam",
+ .blocksize = SHA224_BLOCK_SIZE,
+ .template_ahash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .export = ahash_export,
+ .import = ahash_import,
+ .setkey = ahash_setkey,
+ .halg = {
+ .digestsize = SHA224_DIGEST_SIZE,
+ },
+ },
+ .alg_type = OP_ALG_ALGSEL_SHA224,
+ .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC,
+ }, {
+ .name = "sha256",
+ .driver_name = "sha256-caam",
+ .hmac_name = "hmac(sha256)",
+ .hmac_driver_name = "hmac-sha256-caam",
+ .blocksize = SHA256_BLOCK_SIZE,
+ .template_ahash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .export = ahash_export,
+ .import = ahash_import,
+ .setkey = ahash_setkey,
+ .halg = {
+ .digestsize = SHA256_DIGEST_SIZE,
+ },
+ },
+ .alg_type = OP_ALG_ALGSEL_SHA256,
+ .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC,
+ }, {
+ .name = "sha384",
+ .driver_name = "sha384-caam",
+ .hmac_name = "hmac(sha384)",
+ .hmac_driver_name = "hmac-sha384-caam",
+ .blocksize = SHA384_BLOCK_SIZE,
+ .template_ahash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .export = ahash_export,
+ .import = ahash_import,
+ .setkey = ahash_setkey,
+ .halg = {
+ .digestsize = SHA384_DIGEST_SIZE,
+ },
+ },
+ .alg_type = OP_ALG_ALGSEL_SHA384,
+ .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC,
+ }, {
+ .name = "sha512",
+ .driver_name = "sha512-caam",
+ .hmac_name = "hmac(sha512)",
+ .hmac_driver_name = "hmac-sha512-caam",
+ .blocksize = SHA512_BLOCK_SIZE,
+ .template_ahash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .export = ahash_export,
+ .import = ahash_import,
+ .setkey = ahash_setkey,
+ .halg = {
+ .digestsize = SHA512_DIGEST_SIZE,
+ },
+ },
+ .alg_type = OP_ALG_ALGSEL_SHA512,
+ .alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
+ }, {
+ .name = "md5",
+ .driver_name = "md5-caam",
+ .hmac_name = "hmac(md5)",
+ .hmac_driver_name = "hmac-md5-caam",
+ .blocksize = MD5_BLOCK_WORDS * 4,
+ .template_ahash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .export = ahash_export,
+ .import = ahash_import,
+ .setkey = ahash_setkey,
+ .halg = {
+ .digestsize = MD5_DIGEST_SIZE,
+ },
+ },
+ .alg_type = OP_ALG_ALGSEL_MD5,
+ .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+ },
+};
+
+struct caam_hash_alg {
+ struct list_head entry;
+ struct device *ctrldev;
+ int alg_type;
+ int alg_op;
+ struct ahash_alg ahash_alg;
+};
+
+static int caam_hash_cra_init(struct crypto_tfm *tfm)
+{
+ struct crypto_ahash *ahash = __crypto_ahash_cast(tfm);
+ struct crypto_alg *base = tfm->__crt_alg;
+ struct hash_alg_common *halg =
+ container_of(base, struct hash_alg_common, base);
+ struct ahash_alg *alg =
+ container_of(halg, struct ahash_alg, halg);
+ struct caam_hash_alg *caam_hash =
+ container_of(alg, struct caam_hash_alg, ahash_alg);
+ struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct caam_drv_private *priv = dev_get_drvdata(caam_hash->ctrldev);
+ /* Sizes for MDHA running digests: MD5, SHA1, 224, 256, 384, 512 */
+ static const u8 runninglen[] = { HASH_MSG_LEN + MD5_DIGEST_SIZE,
+ HASH_MSG_LEN + SHA1_DIGEST_SIZE,
+ HASH_MSG_LEN + 32,
+ HASH_MSG_LEN + SHA256_DIGEST_SIZE,
+ HASH_MSG_LEN + 64,
+ HASH_MSG_LEN + SHA512_DIGEST_SIZE };
+ int tgt_jr = atomic_inc_return(&priv->tfm_count);
+ int ret = 0;
+
+ /*
+ * distribute tfms across job rings to ensure in-order
+ * crypto request processing per tfm
+ */
+ ctx->jrdev = priv->jrdev[tgt_jr % priv->total_jobrs];
+
+ /* copy descriptor header template value */
+ ctx->alg_type = OP_TYPE_CLASS2_ALG | caam_hash->alg_type;
+ ctx->alg_op = OP_TYPE_CLASS2_ALG | caam_hash->alg_op;
+
+ ctx->ctx_len = runninglen[(ctx->alg_op & OP_ALG_ALGSEL_SUBMASK) >>
+ OP_ALG_ALGSEL_SHIFT];
+
+ crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
+ sizeof(struct caam_hash_state));
+
+ ret = ahash_set_sh_desc(ahash);
+
+ return ret;
+}
+
+static void caam_hash_cra_exit(struct crypto_tfm *tfm)
+{
+ struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ if (ctx->sh_desc_update_dma &&
+ !dma_mapping_error(ctx->jrdev, ctx->sh_desc_update_dma))
+ dma_unmap_single(ctx->jrdev, ctx->sh_desc_update_dma,
+ desc_bytes(ctx->sh_desc_update),
+ DMA_TO_DEVICE);
+ if (ctx->sh_desc_update_first_dma &&
+ !dma_mapping_error(ctx->jrdev, ctx->sh_desc_update_first_dma))
+ dma_unmap_single(ctx->jrdev, ctx->sh_desc_update_first_dma,
+ desc_bytes(ctx->sh_desc_update_first),
+ DMA_TO_DEVICE);
+ if (ctx->sh_desc_fin_dma &&
+ !dma_mapping_error(ctx->jrdev, ctx->sh_desc_fin_dma))
+ dma_unmap_single(ctx->jrdev, ctx->sh_desc_fin_dma,
+ desc_bytes(ctx->sh_desc_fin), DMA_TO_DEVICE);
+ if (ctx->sh_desc_digest_dma &&
+ !dma_mapping_error(ctx->jrdev, ctx->sh_desc_digest_dma))
+ dma_unmap_single(ctx->jrdev, ctx->sh_desc_digest_dma,
+ desc_bytes(ctx->sh_desc_digest),
+ DMA_TO_DEVICE);
+ if (ctx->sh_desc_finup_dma &&
+ !dma_mapping_error(ctx->jrdev, ctx->sh_desc_finup_dma))
+ dma_unmap_single(ctx->jrdev, ctx->sh_desc_finup_dma,
+ desc_bytes(ctx->sh_desc_finup), DMA_TO_DEVICE);
+}
+
+static struct caam_hash_alg *
+caam_hash_alloc(struct device *ctrldev, struct caam_hash_template *template,
+ bool keyed)
+{
+ struct caam_hash_alg *t_alg;
+ struct ahash_alg *halg;
+ struct crypto_alg *alg;
+
+ t_alg = kzalloc(sizeof(struct caam_hash_alg), GFP_KERNEL);
+ if (!t_alg) {
+ dev_err(ctrldev, "failed to allocate t_alg\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ t_alg->ahash_alg = template->template_ahash;
+ halg = &t_alg->ahash_alg;
+ alg = &halg->halg.base;
+
+ if (keyed) {
+ snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
+ template->hmac_name);
+ snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+ template->hmac_driver_name);
+ } else {
+ snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
+ template->name);
+ snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
+ template->driver_name);
+ }
+ alg->cra_module = THIS_MODULE;
+ alg->cra_init = caam_hash_cra_init;
+ alg->cra_exit = caam_hash_cra_exit;
+ alg->cra_ctxsize = sizeof(struct caam_hash_ctx);
+ alg->cra_priority = CAAM_CRA_PRIORITY;
+ alg->cra_blocksize = template->blocksize;
+ alg->cra_alignmask = 0;
+ alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_TYPE_AHASH;
+ alg->cra_type = &crypto_ahash_type;
+
+ t_alg->alg_type = template->alg_type;
+ t_alg->alg_op = template->alg_op;
+ t_alg->ctrldev = ctrldev;
+
+ return t_alg;
+}
+
+int caam_algapi_hash_startup(struct platform_device *pdev)
+{
+ struct device *ctrldev;
+ struct caam_drv_private *priv;
+ int i = 0, err = 0, md_limit = 0, md_inst;
+ u64 cha_inst;
+
+ ctrldev = &pdev->dev;
+ priv = dev_get_drvdata(ctrldev);
+
+ INIT_LIST_HEAD(&priv->hash_list);
+
+ atomic_set(&priv->tfm_count, -1);
+
+ /* register algorithms the device supports */
+ cha_inst = rd_reg64(&priv->ctrl->perfmon.cha_num);
+ md_inst = (cha_inst & CHA_ID_MD_MASK) >> CHA_ID_MD_SHIFT;
+ if (md_inst) {
+ md_limit = SHA512_DIGEST_SIZE;
+ if ((rd_reg64(&priv->ctrl->perfmon.cha_id) & CHA_ID_MD_MASK)
+ == CHA_ID_MD_LP256) /* LP256 limits digest size */
+ md_limit = SHA256_DIGEST_SIZE;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(driver_hash); i++) {
+ struct caam_hash_alg *t_alg;
+
+ /* If no MD instantiated, or MD too small, skip */
+ if ((!md_inst) ||
+ (driver_hash[i].template_ahash.halg.digestsize >
+ md_limit))
+ continue;
+
+ /* register hmac version */
+ t_alg = caam_hash_alloc(ctrldev, &driver_hash[i], true);
+ if (IS_ERR(t_alg)) {
+ err = PTR_ERR(t_alg);
+ dev_warn(ctrldev, "%s alg allocation failed\n",
+ driver_hash[i].driver_name);
+ continue;
+ }
+
+ err = crypto_register_ahash(&t_alg->ahash_alg);
+ if (err) {
+ dev_warn(ctrldev, "%s alg registration failed\n",
+ t_alg->ahash_alg.halg.base.cra_driver_name);
+ kfree(t_alg);
+ } else
+ list_add_tail(&t_alg->entry, &priv->hash_list);
+
+ /* register unkeyed version */
+ t_alg = caam_hash_alloc(ctrldev, &driver_hash[i], false);
+ if (IS_ERR(t_alg)) {
+ err = PTR_ERR(t_alg);
+ dev_warn(ctrldev, "%s alg allocation failed\n",
+ driver_hash[i].driver_name);
+ continue;
+ }
+
+ err = crypto_register_ahash(&t_alg->ahash_alg);
+ if (err) {
+ dev_warn(ctrldev, "%s alg registration failed\n",
+ t_alg->ahash_alg.halg.base.cra_driver_name);
+ kfree(t_alg);
+ } else
+ list_add_tail(&t_alg->entry, &priv->hash_list);
+ }
+
+ return err;
+}
+
+void caam_algapi_hash_shutdown(struct platform_device *pdev)
+{
+ struct device *ctrldev;
+ struct caam_drv_private *priv;
+ struct caam_hash_alg *t_alg, *n;
+
+ ctrldev = &pdev->dev;
+ priv = dev_get_drvdata(ctrldev);
+
+ if (!priv->hash_list.next)
+ return;
+
+ list_for_each_entry_safe(t_alg, n, &priv->hash_list, entry) {
+ crypto_unregister_ahash(&t_alg->ahash_alg);
+ list_del(&t_alg->entry);
+ kfree(t_alg);
+ }
+}
+
+#ifdef CONFIG_OF
+static void __exit caam_algapi_hash_exit(void)
+{
+ struct device_node *dev_node;
+ struct platform_device *pdev;
+
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+ if (!dev_node) {
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+ if (!dev_node)
+ return;
+ }
+
+ pdev = of_find_device_by_node(dev_node);
+ if (!pdev)
+ return;
+
+ of_node_put(dev_node);
+}
+
+static int __init caam_algapi_hash_init(void)
+{
+ struct device_node *dev_node;
+ struct platform_device *pdev;
+ int err = 0;
+
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+ if (!dev_node) {
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+ if (!dev_node)
+ return -ENODEV;
+ }
+
+ pdev = of_find_device_by_node(dev_node);
+ if (!pdev)
+ return -ENODEV;
+
+ of_node_put(dev_node);
+
+ return caam_algapi_hash_startup(pdev);
+}
+
+module_init(caam_algapi_hash_init);
+module_exit(caam_algapi_hash_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("FSL CAAM support for ahash functions of crypto API");
+MODULE_AUTHOR("Freescale Semiconductor - NMG");
+#endif
diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c
new file mode 100644
index 000000000000..a4b4a3871bdf
--- /dev/null
+++ b/drivers/crypto/caam/caamrng.c
@@ -0,0 +1,381 @@
+/*
+ * caam - Freescale FSL CAAM support for hw_random
+ *
+ * Copyright (C) 2011-2012 Freescale Semiconductor, Inc.
+ *
+ * Based on caamalg.c crypto API driver.
+ *
+ * relationship between job descriptors to shared descriptors:
+ *
+ * --------------- --------------
+ * | JobDesc #0 |-------------------->| ShareDesc |
+ * | *(buffer 0) | |------------->| (generate) |
+ * --------------- | | (move) |
+ * | | (store) |
+ * --------------- | --------------
+ * | JobDesc #1 |------|
+ * | *(buffer 1) |
+ * ---------------
+ *
+ * A job desc looks like this:
+ *
+ * ---------------------
+ * | Header |
+ * | ShareDesc Pointer |
+ * | SEQ_OUT_PTR |
+ * | (output buffer) |
+ * ---------------------
+ *
+ * The SharedDesc never changes, and each job descriptor points to one of two
+ * buffers for each device, from which the data will be copied into the
+ * requested destination
+ */
+
+#include <linux/hw_random.h>
+#include <linux/completion.h>
+#include <linux/atomic.h>
+
+#include "compat.h"
+
+#include "regs.h"
+#include "intern.h"
+#include "desc_constr.h"
+#include "jr.h"
+#include "error.h"
+
+/*
+ * Maximum buffer size: maximum number of random, cache-aligned bytes that
+ * will be generated and moved to seq out ptr (extlen not allowed)
+ */
+#define RN_BUF_SIZE (0xffff / L1_CACHE_BYTES * \
+ L1_CACHE_BYTES)
+
+/* length of descriptors */
+#define DESC_JOB_O_LEN (CAAM_CMD_SZ * 2 + CAAM_PTR_SZ * 2)
+#define DESC_RNG_LEN (10 * CAAM_CMD_SZ)
+
+/* Buffer, its dma address and lock */
+struct buf_data {
+ u8 buf[RN_BUF_SIZE];
+ dma_addr_t addr;
+ struct completion filled;
+ u32 hw_desc[DESC_JOB_O_LEN];
+#define BUF_NOT_EMPTY 0
+#define BUF_EMPTY 1
+#define BUF_PENDING 2 /* Empty, but with job pending --don't submit another */
+ atomic_t empty;
+};
+
+/* rng per-device context */
+struct caam_rng_ctx {
+ struct device *jrdev;
+ dma_addr_t sh_desc_dma;
+ u32 sh_desc[DESC_RNG_LEN];
+ unsigned int cur_buf_idx;
+ int current_buf;
+ struct buf_data bufs[2];
+};
+
+static struct caam_rng_ctx rng_ctx;
+
+static inline void rng_unmap_buf(struct device *jrdev, struct buf_data *bd)
+{
+ if (bd->addr) {
+ dma_sync_single_for_cpu(jrdev, bd->addr, RN_BUF_SIZE,
+ DMA_FROM_DEVICE);
+ dma_unmap_single(jrdev, bd->addr, RN_BUF_SIZE,
+ DMA_FROM_DEVICE);
+ }
+}
+
+static inline void rng_unmap_ctx(struct caam_rng_ctx *ctx)
+{
+ struct device *jrdev = ctx->jrdev;
+
+ if (ctx->sh_desc_dma)
+ dma_unmap_single(jrdev, ctx->sh_desc_dma, DESC_RNG_LEN,
+ DMA_TO_DEVICE);
+ rng_unmap_buf(jrdev, &ctx->bufs[0]);
+ rng_unmap_buf(jrdev, &ctx->bufs[1]);
+}
+
+static void rng_done(struct device *jrdev, u32 *desc, u32 err, void *context)
+{
+ struct buf_data *bd;
+
+ bd = (struct buf_data *)((char *)desc -
+ offsetof(struct buf_data, hw_desc));
+
+ if (err) {
+ char tmp[CAAM_ERROR_STR_MAX];
+
+ dev_err(jrdev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
+ }
+
+ atomic_set(&bd->empty, BUF_NOT_EMPTY);
+ complete(&bd->filled);
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "rng refreshed buf@: ",
+ DUMP_PREFIX_ADDRESS, 16, 4, bd->buf, RN_BUF_SIZE, 1);
+#endif
+}
+
+static inline int submit_job(struct caam_rng_ctx *ctx, int to_current)
+{
+ struct buf_data *bd = &ctx->bufs[!(to_current ^ ctx->current_buf)];
+ struct device *jrdev = ctx->jrdev;
+ u32 *desc = bd->hw_desc;
+ int err;
+
+ dev_dbg(jrdev, "submitting job %d\n", !(to_current ^ ctx->current_buf));
+ init_completion(&bd->filled);
+ err = caam_jr_enqueue(jrdev, desc, rng_done, ctx);
+ if (err)
+ complete(&bd->filled); /* don't wait on failed job*/
+ else
+ atomic_inc(&bd->empty); /* note if pending */
+
+ return err;
+}
+
+static int caam_read(struct hwrng *rng, void *data, size_t max, bool wait)
+{
+ struct caam_rng_ctx *ctx = &rng_ctx;
+ struct buf_data *bd = &ctx->bufs[ctx->current_buf];
+ int next_buf_idx, copied_idx;
+ int err;
+
+ if (atomic_read(&bd->empty)) {
+ /* try to submit job if there wasn't one */
+ if (atomic_read(&bd->empty) == BUF_EMPTY) {
+ err = submit_job(ctx, 1);
+ /* if can't submit job, can't even wait */
+ if (err)
+ return 0;
+ }
+ /* no immediate data, so exit if not waiting */
+ if (!wait)
+ return 0;
+
+ /* waiting for pending job */
+ if (atomic_read(&bd->empty))
+ wait_for_completion(&bd->filled);
+ }
+
+ next_buf_idx = ctx->cur_buf_idx + max;
+ dev_dbg(ctx->jrdev, "%s: start reading at buffer %d, idx %d\n",
+ __func__, ctx->current_buf, ctx->cur_buf_idx);
+
+ /* if enough data in current buffer */
+ if (next_buf_idx < RN_BUF_SIZE) {
+ memcpy(data, bd->buf + ctx->cur_buf_idx, max);
+ ctx->cur_buf_idx = next_buf_idx;
+ return max;
+ }
+
+ /* else, copy what's left... */
+ copied_idx = RN_BUF_SIZE - ctx->cur_buf_idx;
+ memcpy(data, bd->buf + ctx->cur_buf_idx, copied_idx);
+ ctx->cur_buf_idx = 0;
+ atomic_set(&bd->empty, BUF_EMPTY);
+
+ /* ...refill... */
+ submit_job(ctx, 1);
+
+ /* and use next buffer */
+ ctx->current_buf = !ctx->current_buf;
+ dev_dbg(ctx->jrdev, "switched to buffer %d\n", ctx->current_buf);
+
+ /* since there already is some data read, don't wait */
+ return copied_idx + caam_read(rng, data + copied_idx,
+ max - copied_idx, false);
+}
+
+static inline void rng_create_sh_desc(struct caam_rng_ctx *ctx)
+{
+ struct device *jrdev = ctx->jrdev;
+ u32 *desc = ctx->sh_desc;
+
+ init_sh_desc(desc, HDR_SHARE_SERIAL);
+
+ /* Propagate errors from shared to job descriptor */
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
+
+ /* Generate random bytes */
+ append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG);
+
+ /* Store bytes */
+ append_seq_fifo_store(desc, RN_BUF_SIZE, FIFOST_TYPE_RNGSTORE);
+
+ ctx->sh_desc_dma = dma_map_single(jrdev, desc, desc_bytes(desc),
+ DMA_TO_DEVICE);
+ dma_sync_single_for_cpu(jrdev, ctx->sh_desc_dma, desc_bytes(desc),
+ DMA_TO_DEVICE);
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "rng shdesc@: ", DUMP_PREFIX_ADDRESS, 16, 4,
+ desc, desc_bytes(desc), 1);
+#endif
+}
+
+static inline void rng_create_job_desc(struct caam_rng_ctx *ctx, int buf_id)
+{
+ struct device *jrdev = ctx->jrdev;
+ struct buf_data *bd = &ctx->bufs[buf_id];
+ u32 *desc = bd->hw_desc;
+ int sh_len = desc_len(ctx->sh_desc);
+
+ init_job_desc_shared(desc, ctx->sh_desc_dma, sh_len, HDR_SHARE_DEFER |
+ HDR_REVERSE);
+
+ bd->addr = dma_map_single(jrdev, bd->buf, RN_BUF_SIZE, DMA_FROM_DEVICE);
+
+ append_seq_out_ptr_intlen(desc, bd->addr, RN_BUF_SIZE, 0);
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "rng job desc@: ", DUMP_PREFIX_ADDRESS, 16, 4,
+ desc, desc_bytes(desc), 1);
+#endif
+}
+
+static void caam_cleanup(struct hwrng *rng)
+{
+ int i;
+ struct buf_data *bd;
+
+ for (i = 0; i < 2; i++) {
+ bd = &rng_ctx.bufs[i];
+ if (atomic_read(&bd->empty) == BUF_PENDING)
+ wait_for_completion(&bd->filled);
+ }
+
+ rng_unmap_ctx(&rng_ctx);
+}
+
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST
+static inline void test_len(struct hwrng *rng, size_t len, bool wait)
+{
+ u8 *buf;
+ int real_len;
+
+ buf = kzalloc(sizeof(u8) * len, GFP_KERNEL);
+ real_len = rng->read(rng, buf, len, wait);
+ if (real_len == 0 && wait)
+ pr_err("WAITING FAILED\n");
+ pr_info("wanted %d bytes, got %d\n", len, real_len);
+ print_hex_dump(KERN_INFO, "random bytes@: ", DUMP_PREFIX_ADDRESS,
+ 16, 4, buf, real_len, 1);
+ kfree(buf);
+}
+
+static inline void test_mode_once(struct hwrng *rng, bool wait)
+{
+#define TEST_CHUNK (RN_BUF_SIZE / 4)
+
+ test_len(rng, TEST_CHUNK, wait);
+ test_len(rng, RN_BUF_SIZE * 2, wait);
+ test_len(rng, RN_BUF_SIZE * 2 - TEST_CHUNK, wait);
+}
+
+static inline void test_mode(struct hwrng *rng, bool wait)
+{
+#define TEST_PASS 1
+ int i;
+
+ for (i = 0; i < TEST_PASS; i++)
+ test_mode_once(rng, wait);
+}
+
+static void self_test(struct hwrng *rng)
+{
+ pr_info("testing without waiting\n");
+ test_mode(rng, false);
+ pr_info("testing with waiting\n");
+ test_mode(rng, true);
+}
+#endif
+
+static void caam_init_buf(struct caam_rng_ctx *ctx, int buf_id)
+{
+ struct buf_data *bd = &ctx->bufs[buf_id];
+
+ rng_create_job_desc(ctx, buf_id);
+ atomic_set(&bd->empty, BUF_EMPTY);
+ submit_job(ctx, buf_id == ctx->current_buf);
+ wait_for_completion(&bd->filled);
+}
+
+static void caam_init_rng(struct caam_rng_ctx *ctx, struct device *jrdev)
+{
+ ctx->jrdev = jrdev;
+ rng_create_sh_desc(ctx);
+ ctx->current_buf = 0;
+ ctx->cur_buf_idx = 0;
+ caam_init_buf(ctx, 0);
+ caam_init_buf(ctx, 1);
+}
+
+static struct hwrng caam_rng = {
+ .name = "rng-caam",
+ .cleanup = caam_cleanup,
+ .read = caam_read,
+};
+
+int caam_rng_startup(struct platform_device *pdev)
+{
+ struct device *ctrldev;
+ struct caam_drv_private *priv;
+
+ ctrldev = &pdev->dev;
+ priv = dev_get_drvdata(ctrldev);
+
+ /* Check RNG present in hardware before registration */
+ if (!(rd_reg64(&priv->ctrl->perfmon.cha_num) & CHA_ID_RNG_MASK))
+ return -ENODEV;
+
+ caam_init_rng(&rng_ctx, priv->jrdev[0]);
+
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_TEST
+ self_test(&caam_rng);
+#endif
+
+ dev_info(priv->jrdev[0], "registering rng-caam\n");
+ return hwrng_register(&caam_rng);
+}
+
+void caam_rng_shutdown(void)
+{
+ hwrng_unregister(&caam_rng);
+}
+
+#ifdef CONFIG_OF
+static void __exit caam_rng_exit(void)
+{
+ hwrng_unregister(&caam_rng);
+}
+
+static int __init caam_rng_init(void)
+{
+ struct device_node *dev_node;
+ struct platform_device *pdev;
+
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+ if (!dev_node) {
+ dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0");
+ if (!dev_node)
+ return -ENODEV;
+ }
+
+ pdev = of_find_device_by_node(dev_node);
+ if (!pdev)
+ return -ENODEV;
+
+ of_node_put(dev_node);
+
+}
+
+module_init(caam_rng_init);
+module_exit(caam_rng_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("FSL CAAM support for hw_random API");
+MODULE_AUTHOR("Freescale Semiconductor - NMG");
+#endif
diff --git a/drivers/crypto/caam/compat.h b/drivers/crypto/caam/compat.h
index 9ad93d4156c2..28d9670ff834 100644
--- a/drivers/crypto/caam/compat.h
+++ b/drivers/crypto/caam/compat.h
@@ -39,9 +39,11 @@
#include <crypto/aes.h>
#include <crypto/des.h>
#include <crypto/sha.h>
+#include <crypto/md5.h>
#include <crypto/aead.h>
#include <crypto/authenc.h>
#include <crypto/scatterwalk.h>
#include <crypto/internal/skcipher.h>
+#include <crypto/internal/hash.h>
#endif /* !defined(CAAM_COMPAT_H) */
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 7c1132097c0f..28828b9e559c 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -9,6 +9,8 @@
#include "regs.h"
#include "intern.h"
#include "jr.h"
+#include "desc_constr.h"
+#include "error.h"
static int caam_remove(struct platform_device *pdev)
{
@@ -23,8 +25,19 @@ static int caam_remove(struct platform_device *pdev)
topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
#ifndef CONFIG_OF
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API
+ if (ctrlpriv->rng_inst)
+ caam_rng_shutdown();
+#endif
+
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API
+ caam_algapi_hash_shutdown(pdev);
+#endif
+
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API
caam_algapi_shutdown(pdev);
#endif
+#endif
/* shut down JobRs */
for (ring = 0; ring < ctrlpriv->total_jobrs; ring++) {
ret |= caam_jr_shutdown(ctrlpriv->jrdev[ring]);
@@ -49,6 +62,119 @@ static int caam_remove(struct platform_device *pdev)
return ret;
}
+/*
+ * Descriptor to instantiate RNG State Handle 0 in normal mode and
+ * load the JDKEK, TDKEK and TDSK registers
+ */
+static void build_instantiation_desc(u32 *desc)
+{
+ u32 *jump_cmd;
+
+ init_job_desc(desc, 0);
+
+ /* INIT RNG in non-test mode */
+ append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+ OP_ALG_AS_INIT);
+
+ /* wait for done */
+ jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1);
+ set_jump_tgt_here(desc, jump_cmd);
+
+ /*
+ * load 1 to clear written reg:
+ * resets the done interrrupt and returns the RNG to idle.
+ */
+ append_load_imm_u32(desc, 1, LDST_SRCDST_WORD_CLRW);
+
+ /* generate secure keys (non-test) */
+ append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG |
+ OP_ALG_RNG4_SK);
+}
+
+struct instantiate_result {
+ struct completion completion;
+ int err;
+};
+
+static void rng4_init_done(struct device *dev, u32 *desc, u32 err,
+ void *context)
+{
+ struct instantiate_result *instantiation = context;
+
+ if (err) {
+ char tmp[CAAM_ERROR_STR_MAX];
+
+ dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
+ }
+
+ instantiation->err = err;
+ complete(&instantiation->completion);
+}
+
+static int instantiate_rng(struct device *jrdev)
+{
+ struct instantiate_result instantiation;
+
+ dma_addr_t desc_dma;
+ u32 *desc;
+ int ret;
+
+ desc = kmalloc(CAAM_CMD_SZ * 6, GFP_KERNEL | GFP_DMA);
+ if (!desc) {
+ dev_err(jrdev, "cannot allocate RNG init descriptor memory\n");
+ return -ENOMEM;
+ }
+
+ build_instantiation_desc(desc);
+ desc_dma = dma_map_single(jrdev, desc, desc_bytes(desc), DMA_TO_DEVICE);
+ dma_sync_single_for_device(jrdev, desc_dma, desc_bytes(desc),
+ DMA_TO_DEVICE);
+ init_completion(&instantiation.completion);
+
+ ret = caam_jr_enqueue(jrdev, desc, rng4_init_done, &instantiation);
+ if (!ret) {
+ wait_for_completion_interruptible(&instantiation.completion);
+ ret = instantiation.err;
+ if (ret)
+ dev_err(jrdev, "unable to instantiate RNG\n");
+ }
+
+ dma_unmap_single(jrdev, desc_dma, desc_bytes(desc), DMA_TO_DEVICE);
+
+ kfree(desc);
+
+ return ret;
+}
+
+/*
+ * By default, the TRNG runs for 200 clocks per sample;
+ * 1600 clocks per sample generates better entropy.
+ */
+static void kick_trng(struct platform_device *pdev)
+{
+ struct device *ctrldev = &pdev->dev;
+ struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctrldev);
+ struct caam_full __iomem *topregs;
+ struct rng4tst __iomem *r4tst;
+ u32 val;
+
+ topregs = (struct caam_full __iomem *)ctrlpriv->ctrl;
+ r4tst = &topregs->ctrl.r4tst[0];
+
+ /* put RNG4 into program mode */
+ setbits32(&r4tst->rtmctl, RTMCTL_PRGM);
+ /* 1600 clocks per sample */
+ val = rd_reg32(&r4tst->rtsdctl);
+ val = (val & ~RTSDCTL_ENT_DLY_MASK) | (1600 << RTSDCTL_ENT_DLY_SHIFT);
+ wr_reg32(&r4tst->rtsdctl, val);
+ /* min. freq. count */
+ wr_reg32(&r4tst->rtfrqmin, 400);
+ /* max. freq. count */
+ wr_reg32(&r4tst->rtfrqmax, 6400);
+ /* put RNG4 into run mode */
+ clrbits32(&r4tst->rtmctl, RTMCTL_PRGM);
+}
+
/* Probe routine for CAAM top (controller) level */
static int caam_probe(struct platform_device *pdev)
{
@@ -58,7 +184,6 @@ static int caam_probe(struct platform_device *pdev)
struct caam_ctrl __iomem *ctrl;
struct caam_full __iomem *topregs;
struct caam_drv_private *ctrlpriv;
- struct caam_deco **deco;
u32 deconum;
#ifdef CONFIG_DEBUG_FS
struct caam_perfmon *perfmon;
@@ -166,9 +291,6 @@ static int caam_probe(struct platform_device *pdev)
ctrlpriv->deco = kmalloc(deconum * sizeof(struct caam_deco *),
GFP_KERNEL);
- deco = (struct caam_deco __force **)&topregs->deco;
- for (d = 0; d < deconum; d++)
- ctrlpriv->deco[d] = deco[d];
/*
* Detect and enable JobRs
* First, find out how many ring spec'ed, allocate references
@@ -238,6 +360,24 @@ static int caam_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ /*
+ * RNG4 based SECs (v5+ | >= i.MX6) need special initialization prior
+ * to executing any descriptors. If there's a problem with init,
+ * remove other subsystems and return; internal padding functions
+ * cannot run without an RNG. This procedure assumes a single RNG4
+ * instance.
+ */
+ if ((rd_reg64(&topregs->ctrl.perfmon.cha_id) & CHA_ID_RNG_MASK)
+ == CHA_ID_RNG_4) {
+ kick_trng(pdev);
+ ret = instantiate_rng(ctrlpriv->jrdev[0]);
+ if (ret) {
+ caam_remove(pdev);
+ return -ENODEV;
+ }
+ ctrlpriv->rng_inst++;
+ }
+
/* NOTE: RTIC detection ought to go here, around Si time */
/* Initialize queue allocator lock */
@@ -337,10 +477,20 @@ static int caam_probe(struct platform_device *pdev)
* start up the API code explicitly, and forego modularization
*/
#ifndef CONFIG_OF
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API
/* FIXME: check status */
caam_algapi_startup(pdev);
#endif
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API
+ caam_algapi_hash_startup(pdev);
+#endif
+
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API
+ if (ctrlpriv->rng_inst)
+ caam_rng_startup(pdev);
+#endif
+#endif /* CONFIG_OF */
return 0;
}
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
index 974a75842da9..adaeb28e8387 100644
--- a/drivers/crypto/caam/desc.h
+++ b/drivers/crypto/caam/desc.h
@@ -2,14 +2,39 @@
* CAAM descriptor composition header
* Definitions to support CAAM descriptor instruction generation
*
- * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
*/
#ifndef DESC_H
#define DESC_H
+/*
+ * 16-byte hardware scatter/gather table
+ * An 8-byte table exists in the hardware spec, but has never been
+ * implemented to date. The 8/16 option is selected at RTL-compile-time.
+ * and this selection is visible in the Compile Time Parameters Register
+ */
+
+#define SEC4_SG_LEN_EXT 0x80000000 /* Entry points to table */
+#define SEC4_SG_LEN_FIN 0x40000000 /* Last ent in table */
+#define SEC4_SG_BPID_MASK 0x000000ff
+#define SEC4_SG_BPID_SHIFT 16
+#define SEC4_SG_LEN_MASK 0x3fffffff /* Excludes EXT and FINAL */
+#define SEC4_SG_OFFS_MASK 0x00001fff
+
+struct sec4_sg_entry {
+#ifdef CONFIG_64BIT
+ u64 ptr;
+#else
+ u32 reserved;
+ u32 ptr;
+#endif
+ u32 len;
+ u32 bpid_offset; /* BPID in high, offset in lowest bits */
+};
+
/* Max size of any CAAM descriptor in 32-bit words, inclusive of header */
-#define MAX_CAAM_DESCSIZE 64
+#define MAX_CAAM_DESCSIZE 64
/* Block size of any entity covered/uncovered with a KEK/TKEK */
#define KEK_BLOCKSIZE 16
@@ -18,38 +43,38 @@
* Supported descriptor command types as they show up
* inside a descriptor command word.
*/
-#define CMD_SHIFT 27
-#define CMD_MASK 0xf8000000
-
-#define CMD_KEY (0x00 << CMD_SHIFT)
-#define CMD_SEQ_KEY (0x01 << CMD_SHIFT)
-#define CMD_LOAD (0x02 << CMD_SHIFT)
-#define CMD_SEQ_LOAD (0x03 << CMD_SHIFT)
-#define CMD_FIFO_LOAD (0x04 << CMD_SHIFT)
-#define CMD_SEQ_FIFO_LOAD (0x05 << CMD_SHIFT)
-#define CMD_STORE (0x0a << CMD_SHIFT)
-#define CMD_SEQ_STORE (0x0b << CMD_SHIFT)
-#define CMD_FIFO_STORE (0x0c << CMD_SHIFT)
-#define CMD_SEQ_FIFO_STORE (0x0d << CMD_SHIFT)
-#define CMD_MOVE_LEN (0x0e << CMD_SHIFT)
-#define CMD_MOVE (0x0f << CMD_SHIFT)
-#define CMD_OPERATION (0x10 << CMD_SHIFT)
-#define CMD_SIGNATURE (0x12 << CMD_SHIFT)
-#define CMD_JUMP (0x14 << CMD_SHIFT)
-#define CMD_MATH (0x15 << CMD_SHIFT)
-#define CMD_DESC_HDR (0x16 << CMD_SHIFT)
-#define CMD_SHARED_DESC_HDR (0x17 << CMD_SHIFT)
-#define CMD_SEQ_IN_PTR (0x1e << CMD_SHIFT)
-#define CMD_SEQ_OUT_PTR (0x1f << CMD_SHIFT)
+#define CMD_SHIFT 27
+#define CMD_MASK 0xf8000000
+
+#define CMD_KEY (0x00 << CMD_SHIFT)
+#define CMD_SEQ_KEY (0x01 << CMD_SHIFT)
+#define CMD_LOAD (0x02 << CMD_SHIFT)
+#define CMD_SEQ_LOAD (0x03 << CMD_SHIFT)
+#define CMD_FIFO_LOAD (0x04 << CMD_SHIFT)
+#define CMD_SEQ_FIFO_LOAD (0x05 << CMD_SHIFT)
+#define CMD_STORE (0x0a << CMD_SHIFT)
+#define CMD_SEQ_STORE (0x0b << CMD_SHIFT)
+#define CMD_FIFO_STORE (0x0c << CMD_SHIFT)
+#define CMD_SEQ_FIFO_STORE (0x0d << CMD_SHIFT)
+#define CMD_MOVE_LEN (0x0e << CMD_SHIFT)
+#define CMD_MOVE (0x0f << CMD_SHIFT)
+#define CMD_OPERATION (0x10 << CMD_SHIFT)
+#define CMD_SIGNATURE (0x12 << CMD_SHIFT)
+#define CMD_JUMP (0x14 << CMD_SHIFT)
+#define CMD_MATH (0x15 << CMD_SHIFT)
+#define CMD_DESC_HDR (0x16 << CMD_SHIFT)
+#define CMD_SHARED_DESC_HDR (0x17 << CMD_SHIFT)
+#define CMD_SEQ_IN_PTR (0x1e << CMD_SHIFT)
+#define CMD_SEQ_OUT_PTR (0x1f << CMD_SHIFT)
/* General-purpose class selector for all commands */
-#define CLASS_SHIFT 25
-#define CLASS_MASK (0x03 << CLASS_SHIFT)
+#define CLASS_SHIFT 25
+#define CLASS_MASK (0x03 << CLASS_SHIFT)
-#define CLASS_NONE (0x00 << CLASS_SHIFT)
-#define CLASS_1 (0x01 << CLASS_SHIFT)
-#define CLASS_2 (0x02 << CLASS_SHIFT)
-#define CLASS_BOTH (0x03 << CLASS_SHIFT)
+#define CLASS_NONE (0x00 << CLASS_SHIFT)
+#define CLASS_1 (0x01 << CLASS_SHIFT)
+#define CLASS_2 (0x02 << CLASS_SHIFT)
+#define CLASS_BOTH (0x03 << CLASS_SHIFT)
/*
* Descriptor header command constructs
@@ -60,82 +85,82 @@
* Do Not Run - marks a descriptor inexecutable if there was
* a preceding error somewhere
*/
-#define HDR_DNR 0x01000000
+#define HDR_DNR 0x01000000
/*
* ONE - should always be set. Combination of ONE (always
* set) and ZRO (always clear) forms an endianness sanity check
*/
-#define HDR_ONE 0x00800000
-#define HDR_ZRO 0x00008000
+#define HDR_ONE 0x00800000
+#define HDR_ZRO 0x00008000
/* Start Index or SharedDesc Length */
-#define HDR_START_IDX_MASK 0x3f
-#define HDR_START_IDX_SHIFT 16
+#define HDR_START_IDX_MASK 0x3f
+#define HDR_START_IDX_SHIFT 16
/* If shared descriptor header, 6-bit length */
-#define HDR_DESCLEN_SHR_MASK 0x3f
+#define HDR_DESCLEN_SHR_MASK 0x3f
/* If non-shared header, 7-bit length */
-#define HDR_DESCLEN_MASK 0x7f
+#define HDR_DESCLEN_MASK 0x7f
/* This is a TrustedDesc (if not SharedDesc) */
-#define HDR_TRUSTED 0x00004000
+#define HDR_TRUSTED 0x00004000
/* Make into TrustedDesc (if not SharedDesc) */
-#define HDR_MAKE_TRUSTED 0x00002000
+#define HDR_MAKE_TRUSTED 0x00002000
/* Save context if self-shared (if SharedDesc) */
-#define HDR_SAVECTX 0x00001000
+#define HDR_SAVECTX 0x00001000
/* Next item points to SharedDesc */
-#define HDR_SHARED 0x00001000
+#define HDR_SHARED 0x00001000
/*
* Reverse Execution Order - execute JobDesc first, then
* execute SharedDesc (normally SharedDesc goes first).
*/
-#define HDR_REVERSE 0x00000800
+#define HDR_REVERSE 0x00000800
/* Propogate DNR property to SharedDesc */
-#define HDR_PROP_DNR 0x00000800
+#define HDR_PROP_DNR 0x00000800
/* JobDesc/SharedDesc share property */
-#define HDR_SD_SHARE_MASK 0x03
-#define HDR_SD_SHARE_SHIFT 8
-#define HDR_JD_SHARE_MASK 0x07
-#define HDR_JD_SHARE_SHIFT 8
+#define HDR_SD_SHARE_MASK 0x03
+#define HDR_SD_SHARE_SHIFT 8
+#define HDR_JD_SHARE_MASK 0x07
+#define HDR_JD_SHARE_SHIFT 8
-#define HDR_SHARE_NEVER (0x00 << HDR_SD_SHARE_SHIFT)
-#define HDR_SHARE_WAIT (0x01 << HDR_SD_SHARE_SHIFT)
-#define HDR_SHARE_SERIAL (0x02 << HDR_SD_SHARE_SHIFT)
-#define HDR_SHARE_ALWAYS (0x03 << HDR_SD_SHARE_SHIFT)
-#define HDR_SHARE_DEFER (0x04 << HDR_SD_SHARE_SHIFT)
+#define HDR_SHARE_NEVER (0x00 << HDR_SD_SHARE_SHIFT)
+#define HDR_SHARE_WAIT (0x01 << HDR_SD_SHARE_SHIFT)
+#define HDR_SHARE_SERIAL (0x02 << HDR_SD_SHARE_SHIFT)
+#define HDR_SHARE_ALWAYS (0x03 << HDR_SD_SHARE_SHIFT)
+#define HDR_SHARE_DEFER (0x04 << HDR_SD_SHARE_SHIFT)
/* JobDesc/SharedDesc descriptor length */
-#define HDR_JD_LENGTH_MASK 0x7f
-#define HDR_SD_LENGTH_MASK 0x3f
+#define HDR_JD_LENGTH_MASK 0x7f
+#define HDR_SD_LENGTH_MASK 0x3f
/*
* KEY/SEQ_KEY Command Constructs
*/
-/* Key Destination Class: 01 = Class 1, 02 - Class 2 */
-#define KEY_DEST_CLASS_SHIFT 25 /* use CLASS_1 or CLASS_2 */
-#define KEY_DEST_CLASS_MASK (0x03 << KEY_DEST_CLASS_SHIFT)
+/* Key Destination Class: 01 = Class 1, 02 - Class 2 */
+#define KEY_DEST_CLASS_SHIFT 25 /* use CLASS_1 or CLASS_2 */
+#define KEY_DEST_CLASS_MASK (0x03 << KEY_DEST_CLASS_SHIFT)
/* Scatter-Gather Table/Variable Length Field */
-#define KEY_SGF 0x01000000
-#define KEY_VLF 0x01000000
+#define KEY_SGF 0x01000000
+#define KEY_VLF 0x01000000
/* Immediate - Key follows command in the descriptor */
-#define KEY_IMM 0x00800000
+#define KEY_IMM 0x00800000
/*
* Encrypted - Key is encrypted either with the KEK, or
* with the TDKEK if TK is set
*/
-#define KEY_ENC 0x00400000
+#define KEY_ENC 0x00400000
/*
* No Write Back - Do not allow key to be FIFO STOREd
@@ -156,16 +181,16 @@
* KDEST - Key Destination: 0 - class key register,
* 1 - PKHA 'e', 2 - AFHA Sbox, 3 - MDHA split-key
*/
-#define KEY_DEST_SHIFT 16
-#define KEY_DEST_MASK (0x03 << KEY_DEST_SHIFT)
+#define KEY_DEST_SHIFT 16
+#define KEY_DEST_MASK (0x03 << KEY_DEST_SHIFT)
-#define KEY_DEST_CLASS_REG (0x00 << KEY_DEST_SHIFT)
-#define KEY_DEST_PKHA_E (0x01 << KEY_DEST_SHIFT)
-#define KEY_DEST_AFHA_SBOX (0x02 << KEY_DEST_SHIFT)
-#define KEY_DEST_MDHA_SPLIT (0x03 << KEY_DEST_SHIFT)
+#define KEY_DEST_CLASS_REG (0x00 << KEY_DEST_SHIFT)
+#define KEY_DEST_PKHA_E (0x01 << KEY_DEST_SHIFT)
+#define KEY_DEST_AFHA_SBOX (0x02 << KEY_DEST_SHIFT)
+#define KEY_DEST_MDHA_SPLIT (0x03 << KEY_DEST_SHIFT)
/* Length in bytes */
-#define KEY_LENGTH_MASK 0x000003ff
+#define KEY_LENGTH_MASK 0x000003ff
/*
* LOAD/SEQ_LOAD/STORE/SEQ_STORE Command Constructs
@@ -175,25 +200,25 @@
* Load/Store Destination: 0 = class independent CCB,
* 1 = class 1 CCB, 2 = class 2 CCB, 3 = DECO
*/
-#define LDST_CLASS_SHIFT 25
-#define LDST_CLASS_MASK (0x03 << LDST_CLASS_SHIFT)
-#define LDST_CLASS_IND_CCB (0x00 << LDST_CLASS_SHIFT)
-#define LDST_CLASS_1_CCB (0x01 << LDST_CLASS_SHIFT)
-#define LDST_CLASS_2_CCB (0x02 << LDST_CLASS_SHIFT)
-#define LDST_CLASS_DECO (0x03 << LDST_CLASS_SHIFT)
+#define LDST_CLASS_SHIFT 25
+#define LDST_CLASS_MASK (0x03 << LDST_CLASS_SHIFT)
+#define LDST_CLASS_IND_CCB (0x00 << LDST_CLASS_SHIFT)
+#define LDST_CLASS_1_CCB (0x01 << LDST_CLASS_SHIFT)
+#define LDST_CLASS_2_CCB (0x02 << LDST_CLASS_SHIFT)
+#define LDST_CLASS_DECO (0x03 << LDST_CLASS_SHIFT)
/* Scatter-Gather Table/Variable Length Field */
-#define LDST_SGF 0x01000000
+#define LDST_SGF 0x01000000
#define LDST_VLF LDST_SGF
-/* Immediate - Key follows this command in descriptor */
-#define LDST_IMM_MASK 1
-#define LDST_IMM_SHIFT 23
-#define LDST_IMM (LDST_IMM_MASK << LDST_IMM_SHIFT)
+/* Immediate - Key follows this command in descriptor */
+#define LDST_IMM_MASK 1
+#define LDST_IMM_SHIFT 23
+#define LDST_IMM (LDST_IMM_MASK << LDST_IMM_SHIFT)
-/* SRC/DST - Destination for LOAD, Source for STORE */
-#define LDST_SRCDST_SHIFT 16
-#define LDST_SRCDST_MASK (0x7f << LDST_SRCDST_SHIFT)
+/* SRC/DST - Destination for LOAD, Source for STORE */
+#define LDST_SRCDST_SHIFT 16
+#define LDST_SRCDST_MASK (0x7f << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_BYTE_CONTEXT (0x20 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_BYTE_KEY (0x40 << LDST_SRCDST_SHIFT)
@@ -205,64 +230,64 @@
#define LDST_SRCDST_WORD_DATASZ_REG (0x02 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_WORD_ICVSZ_REG (0x03 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_WORD_CHACTRL (0x06 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECOCTRL (0x06 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECOCTRL (0x06 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_WORD_IRQCTRL (0x07 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECO_PCLOVRD (0x07 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_PCLOVRD (0x07 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_WORD_CLRW (0x08 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECO_MATH0 (0x08 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_MATH0 (0x08 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_WORD_STAT (0x09 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECO_MATH1 (0x09 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECO_MATH2 (0x0a << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECO_AAD_SZ (0x0b << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECO_MATH3 (0x0b << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_CLASS1_ICV_SZ (0x0c << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_ALTDS_CLASS1 (0x0f << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_PKHA_A_SZ (0x10 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_PKHA_B_SZ (0x11 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_PKHA_N_SZ (0x12 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_PKHA_E_SZ (0x13 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DESCBUF (0x40 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_INFO_FIFO (0x7a << LDST_SRCDST_SHIFT)
-
-/* Offset in source/destination */
-#define LDST_OFFSET_SHIFT 8
-#define LDST_OFFSET_MASK (0xff << LDST_OFFSET_SHIFT)
+#define LDST_SRCDST_WORD_DECO_MATH1 (0x09 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_MATH2 (0x0a << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_AAD_SZ (0x0b << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_MATH3 (0x0b << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_CLASS1_ICV_SZ (0x0c << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_ALTDS_CLASS1 (0x0f << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_PKHA_A_SZ (0x10 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_PKHA_B_SZ (0x11 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_PKHA_N_SZ (0x12 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_PKHA_E_SZ (0x13 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DESCBUF (0x40 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_INFO_FIFO (0x7a << LDST_SRCDST_SHIFT)
+
+/* Offset in source/destination */
+#define LDST_OFFSET_SHIFT 8
+#define LDST_OFFSET_MASK (0xff << LDST_OFFSET_SHIFT)
/* LDOFF definitions used when DST = LDST_SRCDST_WORD_DECOCTRL */
/* These could also be shifted by LDST_OFFSET_SHIFT - this reads better */
-#define LDOFF_CHG_SHARE_SHIFT 0
-#define LDOFF_CHG_SHARE_MASK (0x3 << LDOFF_CHG_SHARE_SHIFT)
-#define LDOFF_CHG_SHARE_NEVER (0x1 << LDOFF_CHG_SHARE_SHIFT)
-#define LDOFF_CHG_SHARE_OK_NO_PROP (0x2 << LDOFF_CHG_SHARE_SHIFT)
-#define LDOFF_CHG_SHARE_OK_PROP (0x3 << LDOFF_CHG_SHARE_SHIFT)
-
-#define LDOFF_ENABLE_AUTO_NFIFO (1 << 2)
-#define LDOFF_DISABLE_AUTO_NFIFO (1 << 3)
-
-#define LDOFF_CHG_NONSEQLIODN_SHIFT 4
-#define LDOFF_CHG_NONSEQLIODN_MASK (0x3 << LDOFF_CHG_NONSEQLIODN_SHIFT)
-#define LDOFF_CHG_NONSEQLIODN_SEQ (0x1 << LDOFF_CHG_NONSEQLIODN_SHIFT)
-#define LDOFF_CHG_NONSEQLIODN_NON_SEQ (0x2 << LDOFF_CHG_NONSEQLIODN_SHIFT)
-#define LDOFF_CHG_NONSEQLIODN_TRUSTED (0x3 << LDOFF_CHG_NONSEQLIODN_SHIFT)
-
-#define LDOFF_CHG_SEQLIODN_SHIFT 6
-#define LDOFF_CHG_SEQLIODN_MASK (0x3 << LDOFF_CHG_SEQLIODN_SHIFT)
-#define LDOFF_CHG_SEQLIODN_SEQ (0x1 << LDOFF_CHG_SEQLIODN_SHIFT)
-#define LDOFF_CHG_SEQLIODN_NON_SEQ (0x2 << LDOFF_CHG_SEQLIODN_SHIFT)
-#define LDOFF_CHG_SEQLIODN_TRUSTED (0x3 << LDOFF_CHG_SEQLIODN_SHIFT)
-
-/* Data length in bytes */
-#define LDST_LEN_SHIFT 0
-#define LDST_LEN_MASK (0xff << LDST_LEN_SHIFT)
+#define LDOFF_CHG_SHARE_SHIFT 0
+#define LDOFF_CHG_SHARE_MASK (0x3 << LDOFF_CHG_SHARE_SHIFT)
+#define LDOFF_CHG_SHARE_NEVER (0x1 << LDOFF_CHG_SHARE_SHIFT)
+#define LDOFF_CHG_SHARE_OK_PROP (0x2 << LDOFF_CHG_SHARE_SHIFT)
+#define LDOFF_CHG_SHARE_OK_NO_PROP (0x3 << LDOFF_CHG_SHARE_SHIFT)
+
+#define LDOFF_ENABLE_AUTO_NFIFO (1 << 2)
+#define LDOFF_DISABLE_AUTO_NFIFO (1 << 3)
+
+#define LDOFF_CHG_NONSEQLIODN_SHIFT 4
+#define LDOFF_CHG_NONSEQLIODN_MASK (0x3 << LDOFF_CHG_NONSEQLIODN_SHIFT)
+#define LDOFF_CHG_NONSEQLIODN_SEQ (0x1 << LDOFF_CHG_NONSEQLIODN_SHIFT)
+#define LDOFF_CHG_NONSEQLIODN_NON_SEQ (0x2 << LDOFF_CHG_NONSEQLIODN_SHIFT)
+#define LDOFF_CHG_NONSEQLIODN_TRUSTED (0x3 << LDOFF_CHG_NONSEQLIODN_SHIFT)
+
+#define LDOFF_CHG_SEQLIODN_SHIFT 6
+#define LDOFF_CHG_SEQLIODN_MASK (0x3 << LDOFF_CHG_SEQLIODN_SHIFT)
+#define LDOFF_CHG_SEQLIODN_SEQ (0x1 << LDOFF_CHG_SEQLIODN_SHIFT)
+#define LDOFF_CHG_SEQLIODN_NON_SEQ (0x2 << LDOFF_CHG_SEQLIODN_SHIFT)
+#define LDOFF_CHG_SEQLIODN_TRUSTED (0x3 << LDOFF_CHG_SEQLIODN_SHIFT)
+
+/* Data length in bytes */
+#define LDST_LEN_SHIFT 0
+#define LDST_LEN_MASK (0xff << LDST_LEN_SHIFT)
/* Special Length definitions when dst=deco-ctrl */
-#define LDLEN_ENABLE_OSL_COUNT (1 << 7)
-#define LDLEN_RST_CHA_OFIFO_PTR (1 << 6)
-#define LDLEN_RST_OFIFO (1 << 5)
-#define LDLEN_SET_OFIFO_OFF_VALID (1 << 4)
-#define LDLEN_SET_OFIFO_OFF_RSVD (1 << 3)
-#define LDLEN_SET_OFIFO_OFFSET_SHIFT 0
-#define LDLEN_SET_OFIFO_OFFSET_MASK (3 << LDLEN_SET_OFIFO_OFFSET_SHIFT)
+#define LDLEN_ENABLE_OSL_COUNT (1 << 7)
+#define LDLEN_RST_CHA_OFIFO_PTR (1 << 6)
+#define LDLEN_RST_OFIFO (1 << 5)
+#define LDLEN_SET_OFIFO_OFF_VALID (1 << 4)
+#define LDLEN_SET_OFIFO_OFF_RSVD (1 << 3)
+#define LDLEN_SET_OFIFO_OFFSET_SHIFT 0
+#define LDLEN_SET_OFIFO_OFFSET_MASK (3 << LDLEN_SET_OFIFO_OFFSET_SHIFT)
/*
* FIFO_LOAD/FIFO_STORE/SEQ_FIFO_LOAD/SEQ_FIFO_STORE
@@ -274,808 +299,808 @@
* 1 = Load for Class1, 2 = Load for Class2, 3 = Load both
* Store Source: 0 = normal, 1 = Class1key, 2 = Class2key
*/
-#define FIFOLD_CLASS_SHIFT 25
-#define FIFOLD_CLASS_MASK (0x03 << FIFOLD_CLASS_SHIFT)
-#define FIFOLD_CLASS_SKIP (0x00 << FIFOLD_CLASS_SHIFT)
-#define FIFOLD_CLASS_CLASS1 (0x01 << FIFOLD_CLASS_SHIFT)
-#define FIFOLD_CLASS_CLASS2 (0x02 << FIFOLD_CLASS_SHIFT)
-#define FIFOLD_CLASS_BOTH (0x03 << FIFOLD_CLASS_SHIFT)
-
-#define FIFOST_CLASS_SHIFT 25
-#define FIFOST_CLASS_MASK (0x03 << FIFOST_CLASS_SHIFT)
-#define FIFOST_CLASS_NORMAL (0x00 << FIFOST_CLASS_SHIFT)
-#define FIFOST_CLASS_CLASS1KEY (0x01 << FIFOST_CLASS_SHIFT)
-#define FIFOST_CLASS_CLASS2KEY (0x02 << FIFOST_CLASS_SHIFT)
+#define FIFOLD_CLASS_SHIFT 25
+#define FIFOLD_CLASS_MASK (0x03 << FIFOLD_CLASS_SHIFT)
+#define FIFOLD_CLASS_SKIP (0x00 << FIFOLD_CLASS_SHIFT)
+#define FIFOLD_CLASS_CLASS1 (0x01 << FIFOLD_CLASS_SHIFT)
+#define FIFOLD_CLASS_CLASS2 (0x02 << FIFOLD_CLASS_SHIFT)
+#define FIFOLD_CLASS_BOTH (0x03 << FIFOLD_CLASS_SHIFT)
+
+#define FIFOST_CLASS_SHIFT 25
+#define FIFOST_CLASS_MASK (0x03 << FIFOST_CLASS_SHIFT)
+#define FIFOST_CLASS_NORMAL (0x00 << FIFOST_CLASS_SHIFT)
+#define FIFOST_CLASS_CLASS1KEY (0x01 << FIFOST_CLASS_SHIFT)
+#define FIFOST_CLASS_CLASS2KEY (0x02 << FIFOST_CLASS_SHIFT)
/*
* Scatter-Gather Table/Variable Length Field
* If set for FIFO_LOAD, refers to a SG table. Within
* SEQ_FIFO_LOAD, is variable input sequence
*/
-#define FIFOLDST_SGF_SHIFT 24
-#define FIFOLDST_SGF_MASK (1 << FIFOLDST_SGF_SHIFT)
-#define FIFOLDST_VLF_MASK (1 << FIFOLDST_SGF_SHIFT)
-#define FIFOLDST_SGF (1 << FIFOLDST_SGF_SHIFT)
-#define FIFOLDST_VLF (1 << FIFOLDST_SGF_SHIFT)
+#define FIFOLDST_SGF_SHIFT 24
+#define FIFOLDST_SGF_MASK (1 << FIFOLDST_SGF_SHIFT)
+#define FIFOLDST_VLF_MASK (1 << FIFOLDST_SGF_SHIFT)
+#define FIFOLDST_SGF (1 << FIFOLDST_SGF_SHIFT)
+#define FIFOLDST_VLF (1 << FIFOLDST_SGF_SHIFT)
/* Immediate - Data follows command in descriptor */
-#define FIFOLD_IMM_SHIFT 23
-#define FIFOLD_IMM_MASK (1 << FIFOLD_IMM_SHIFT)
-#define FIFOLD_IMM (1 << FIFOLD_IMM_SHIFT)
+#define FIFOLD_IMM_SHIFT 23
+#define FIFOLD_IMM_MASK (1 << FIFOLD_IMM_SHIFT)
+#define FIFOLD_IMM (1 << FIFOLD_IMM_SHIFT)
/* Continue - Not the last FIFO store to come */
-#define FIFOST_CONT_SHIFT 23
-#define FIFOST_CONT_MASK (1 << FIFOST_CONT_SHIFT)
-#define FIFOST_CONT_MASK (1 << FIFOST_CONT_SHIFT)
+#define FIFOST_CONT_SHIFT 23
+#define FIFOST_CONT_MASK (1 << FIFOST_CONT_SHIFT)
+#define FIFOST_CONT_MASK (1 << FIFOST_CONT_SHIFT)
/*
* Extended Length - use 32-bit extended length that
* follows the pointer field. Illegal with IMM set
*/
-#define FIFOLDST_EXT_SHIFT 22
-#define FIFOLDST_EXT_MASK (1 << FIFOLDST_EXT_SHIFT)
-#define FIFOLDST_EXT (1 << FIFOLDST_EXT_SHIFT)
+#define FIFOLDST_EXT_SHIFT 22
+#define FIFOLDST_EXT_MASK (1 << FIFOLDST_EXT_SHIFT)
+#define FIFOLDST_EXT (1 << FIFOLDST_EXT_SHIFT)
/* Input data type.*/
-#define FIFOLD_TYPE_SHIFT 16
-#define FIFOLD_CONT_TYPE_SHIFT 19 /* shift past last-flush bits */
-#define FIFOLD_TYPE_MASK (0x3f << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_SHIFT 16
+#define FIFOLD_CONT_TYPE_SHIFT 19 /* shift past last-flush bits */
+#define FIFOLD_TYPE_MASK (0x3f << FIFOLD_TYPE_SHIFT)
/* PK types */
-#define FIFOLD_TYPE_PK (0x00 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_MASK (0x30 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK (0x00 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_MASK (0x30 << FIFOLD_TYPE_SHIFT)
#define FIFOLD_TYPE_PK_TYPEMASK (0x0f << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_A0 (0x00 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_A1 (0x01 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_A2 (0x02 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_A3 (0x03 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_B0 (0x04 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_B1 (0x05 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_B2 (0x06 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_B3 (0x07 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_N (0x08 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_A (0x0c << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_B (0x0d << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A0 (0x00 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A1 (0x01 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A2 (0x02 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A3 (0x03 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B0 (0x04 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B1 (0x05 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B2 (0x06 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B3 (0x07 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_N (0x08 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A (0x0c << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B (0x0d << FIFOLD_TYPE_SHIFT)
/* Other types. Need to OR in last/flush bits as desired */
-#define FIFOLD_TYPE_MSG_MASK (0x38 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_MSG (0x10 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_MSG1OUT2 (0x18 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_IV (0x20 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_BITDATA (0x28 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_AAD (0x30 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_ICV (0x38 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_MSG_MASK (0x38 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_MSG (0x10 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_MSG1OUT2 (0x18 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_IV (0x20 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_BITDATA (0x28 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_AAD (0x30 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_ICV (0x38 << FIFOLD_TYPE_SHIFT)
/* Last/Flush bits for use with "other" types above */
-#define FIFOLD_TYPE_ACT_MASK (0x07 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_NOACTION (0x00 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_FLUSH1 (0x01 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_LAST1 (0x02 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_LAST2FLUSH (0x03 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_LAST2 (0x04 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_ACT_MASK (0x07 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_NOACTION (0x00 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_FLUSH1 (0x01 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LAST1 (0x02 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LAST2FLUSH (0x03 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LAST2 (0x04 << FIFOLD_TYPE_SHIFT)
#define FIFOLD_TYPE_LAST2FLUSH1 (0x05 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_LASTBOTH (0x06 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_LASTBOTHFL (0x07 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LASTBOTH (0x06 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LASTBOTHFL (0x07 << FIFOLD_TYPE_SHIFT)
-#define FIFOLDST_LEN_MASK 0xffff
-#define FIFOLDST_EXT_LEN_MASK 0xffffffff
+#define FIFOLDST_LEN_MASK 0xffff
+#define FIFOLDST_EXT_LEN_MASK 0xffffffff
/* Output data types */
-#define FIFOST_TYPE_SHIFT 16
-#define FIFOST_TYPE_MASK (0x3f << FIFOST_TYPE_SHIFT)
-
-#define FIFOST_TYPE_PKHA_A0 (0x00 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_A1 (0x01 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_A2 (0x02 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_A3 (0x03 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_B0 (0x04 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_B1 (0x05 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_B2 (0x06 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_B3 (0x07 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_N (0x08 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_A (0x0c << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_B (0x0d << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_SHIFT 16
+#define FIFOST_TYPE_MASK (0x3f << FIFOST_TYPE_SHIFT)
+
+#define FIFOST_TYPE_PKHA_A0 (0x00 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_A1 (0x01 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_A2 (0x02 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_A3 (0x03 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B0 (0x04 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B1 (0x05 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B2 (0x06 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B3 (0x07 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_N (0x08 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_A (0x0c << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B (0x0d << FIFOST_TYPE_SHIFT)
#define FIFOST_TYPE_AF_SBOX_JKEK (0x10 << FIFOST_TYPE_SHIFT)
#define FIFOST_TYPE_AF_SBOX_TKEK (0x21 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_E_JKEK (0x22 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_E_TKEK (0x23 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_KEY_KEK (0x24 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_KEY_TKEK (0x25 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_SPLIT_KEK (0x26 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_SPLIT_TKEK (0x27 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_OUTFIFO_KEK (0x28 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_E_JKEK (0x22 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_E_TKEK (0x23 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_KEY_KEK (0x24 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_KEY_TKEK (0x25 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_SPLIT_KEK (0x26 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_SPLIT_TKEK (0x27 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_OUTFIFO_KEK (0x28 << FIFOST_TYPE_SHIFT)
#define FIFOST_TYPE_OUTFIFO_TKEK (0x29 << FIFOST_TYPE_SHIFT)
#define FIFOST_TYPE_MESSAGE_DATA (0x30 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_RNGSTORE (0x34 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_RNGFIFO (0x35 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_SKIP (0x3f << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_RNGSTORE (0x34 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_RNGFIFO (0x35 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_SKIP (0x3f << FIFOST_TYPE_SHIFT)
/*
* OPERATION Command Constructs
*/
/* Operation type selectors - OP TYPE */
-#define OP_TYPE_SHIFT 24
-#define OP_TYPE_MASK (0x07 << OP_TYPE_SHIFT)
+#define OP_TYPE_SHIFT 24
+#define OP_TYPE_MASK (0x07 << OP_TYPE_SHIFT)
-#define OP_TYPE_UNI_PROTOCOL (0x00 << OP_TYPE_SHIFT)
-#define OP_TYPE_PK (0x01 << OP_TYPE_SHIFT)
-#define OP_TYPE_CLASS1_ALG (0x02 << OP_TYPE_SHIFT)
-#define OP_TYPE_CLASS2_ALG (0x04 << OP_TYPE_SHIFT)
-#define OP_TYPE_DECAP_PROTOCOL (0x06 << OP_TYPE_SHIFT)
-#define OP_TYPE_ENCAP_PROTOCOL (0x07 << OP_TYPE_SHIFT)
+#define OP_TYPE_UNI_PROTOCOL (0x00 << OP_TYPE_SHIFT)
+#define OP_TYPE_PK (0x01 << OP_TYPE_SHIFT)
+#define OP_TYPE_CLASS1_ALG (0x02 << OP_TYPE_SHIFT)
+#define OP_TYPE_CLASS2_ALG (0x04 << OP_TYPE_SHIFT)
+#define OP_TYPE_DECAP_PROTOCOL (0x06 << OP_TYPE_SHIFT)
+#define OP_TYPE_ENCAP_PROTOCOL (0x07 << OP_TYPE_SHIFT)
/* ProtocolID selectors - PROTID */
-#define OP_PCLID_SHIFT 16
-#define OP_PCLID_MASK (0xff << 16)
+#define OP_PCLID_SHIFT 16
+#define OP_PCLID_MASK (0xff << 16)
/* Assuming OP_TYPE = OP_TYPE_UNI_PROTOCOL */
-#define OP_PCLID_IKEV1_PRF (0x01 << OP_PCLID_SHIFT)
-#define OP_PCLID_IKEV2_PRF (0x02 << OP_PCLID_SHIFT)
-#define OP_PCLID_SSL30_PRF (0x08 << OP_PCLID_SHIFT)
-#define OP_PCLID_TLS10_PRF (0x09 << OP_PCLID_SHIFT)
-#define OP_PCLID_TLS11_PRF (0x0a << OP_PCLID_SHIFT)
-#define OP_PCLID_DTLS10_PRF (0x0c << OP_PCLID_SHIFT)
-#define OP_PCLID_PRF (0x06 << OP_PCLID_SHIFT)
-#define OP_PCLID_BLOB (0x0d << OP_PCLID_SHIFT)
-#define OP_PCLID_SECRETKEY (0x11 << OP_PCLID_SHIFT)
-#define OP_PCLID_PUBLICKEYPAIR (0x14 << OP_PCLID_SHIFT)
-#define OP_PCLID_DSASIGN (0x15 << OP_PCLID_SHIFT)
-#define OP_PCLID_DSAVERIFY (0x16 << OP_PCLID_SHIFT)
+#define OP_PCLID_IKEV1_PRF (0x01 << OP_PCLID_SHIFT)
+#define OP_PCLID_IKEV2_PRF (0x02 << OP_PCLID_SHIFT)
+#define OP_PCLID_SSL30_PRF (0x08 << OP_PCLID_SHIFT)
+#define OP_PCLID_TLS10_PRF (0x09 << OP_PCLID_SHIFT)
+#define OP_PCLID_TLS11_PRF (0x0a << OP_PCLID_SHIFT)
+#define OP_PCLID_DTLS10_PRF (0x0c << OP_PCLID_SHIFT)
+#define OP_PCLID_PRF (0x06 << OP_PCLID_SHIFT)
+#define OP_PCLID_BLOB (0x0d << OP_PCLID_SHIFT)
+#define OP_PCLID_SECRETKEY (0x11 << OP_PCLID_SHIFT)
+#define OP_PCLID_PUBLICKEYPAIR (0x14 << OP_PCLID_SHIFT)
+#define OP_PCLID_DSASIGN (0x15 << OP_PCLID_SHIFT)
+#define OP_PCLID_DSAVERIFY (0x16 << OP_PCLID_SHIFT)
/* Assuming OP_TYPE = OP_TYPE_DECAP_PROTOCOL/ENCAP_PROTOCOL */
-#define OP_PCLID_IPSEC (0x01 << OP_PCLID_SHIFT)
-#define OP_PCLID_SRTP (0x02 << OP_PCLID_SHIFT)
-#define OP_PCLID_MACSEC (0x03 << OP_PCLID_SHIFT)
-#define OP_PCLID_WIFI (0x04 << OP_PCLID_SHIFT)
-#define OP_PCLID_WIMAX (0x05 << OP_PCLID_SHIFT)
-#define OP_PCLID_SSL30 (0x08 << OP_PCLID_SHIFT)
-#define OP_PCLID_TLS10 (0x09 << OP_PCLID_SHIFT)
-#define OP_PCLID_TLS11 (0x0a << OP_PCLID_SHIFT)
-#define OP_PCLID_TLS12 (0x0b << OP_PCLID_SHIFT)
-#define OP_PCLID_DTLS (0x0c << OP_PCLID_SHIFT)
+#define OP_PCLID_IPSEC (0x01 << OP_PCLID_SHIFT)
+#define OP_PCLID_SRTP (0x02 << OP_PCLID_SHIFT)
+#define OP_PCLID_MACSEC (0x03 << OP_PCLID_SHIFT)
+#define OP_PCLID_WIFI (0x04 << OP_PCLID_SHIFT)
+#define OP_PCLID_WIMAX (0x05 << OP_PCLID_SHIFT)
+#define OP_PCLID_SSL30 (0x08 << OP_PCLID_SHIFT)
+#define OP_PCLID_TLS10 (0x09 << OP_PCLID_SHIFT)
+#define OP_PCLID_TLS11 (0x0a << OP_PCLID_SHIFT)
+#define OP_PCLID_TLS12 (0x0b << OP_PCLID_SHIFT)
+#define OP_PCLID_DTLS (0x0c << OP_PCLID_SHIFT)
/*
* ProtocolInfo selectors
*/
-#define OP_PCLINFO_MASK 0xffff
+#define OP_PCLINFO_MASK 0xffff
/* for OP_PCLID_IPSEC */
-#define OP_PCL_IPSEC_CIPHER_MASK 0xff00
-#define OP_PCL_IPSEC_AUTH_MASK 0x00ff
-
-#define OP_PCL_IPSEC_DES_IV64 0x0100
-#define OP_PCL_IPSEC_DES 0x0200
-#define OP_PCL_IPSEC_3DES 0x0300
-#define OP_PCL_IPSEC_AES_CBC 0x0c00
-#define OP_PCL_IPSEC_AES_CTR 0x0d00
-#define OP_PCL_IPSEC_AES_XTS 0x1600
-#define OP_PCL_IPSEC_AES_CCM8 0x0e00
-#define OP_PCL_IPSEC_AES_CCM12 0x0f00
-#define OP_PCL_IPSEC_AES_CCM16 0x1000
-#define OP_PCL_IPSEC_AES_GCM8 0x1200
-#define OP_PCL_IPSEC_AES_GCM12 0x1300
-#define OP_PCL_IPSEC_AES_GCM16 0x1400
-
-#define OP_PCL_IPSEC_HMAC_NULL 0x0000
-#define OP_PCL_IPSEC_HMAC_MD5_96 0x0001
-#define OP_PCL_IPSEC_HMAC_SHA1_96 0x0002
-#define OP_PCL_IPSEC_AES_XCBC_MAC_96 0x0005
-#define OP_PCL_IPSEC_HMAC_MD5_128 0x0006
-#define OP_PCL_IPSEC_HMAC_SHA1_160 0x0007
-#define OP_PCL_IPSEC_HMAC_SHA2_256_128 0x000c
-#define OP_PCL_IPSEC_HMAC_SHA2_384_192 0x000d
-#define OP_PCL_IPSEC_HMAC_SHA2_512_256 0x000e
+#define OP_PCL_IPSEC_CIPHER_MASK 0xff00
+#define OP_PCL_IPSEC_AUTH_MASK 0x00ff
+
+#define OP_PCL_IPSEC_DES_IV64 0x0100
+#define OP_PCL_IPSEC_DES 0x0200
+#define OP_PCL_IPSEC_3DES 0x0300
+#define OP_PCL_IPSEC_AES_CBC 0x0c00
+#define OP_PCL_IPSEC_AES_CTR 0x0d00
+#define OP_PCL_IPSEC_AES_XTS 0x1600
+#define OP_PCL_IPSEC_AES_CCM8 0x0e00
+#define OP_PCL_IPSEC_AES_CCM12 0x0f00
+#define OP_PCL_IPSEC_AES_CCM16 0x1000
+#define OP_PCL_IPSEC_AES_GCM8 0x1200
+#define OP_PCL_IPSEC_AES_GCM12 0x1300
+#define OP_PCL_IPSEC_AES_GCM16 0x1400
+
+#define OP_PCL_IPSEC_HMAC_NULL 0x0000
+#define OP_PCL_IPSEC_HMAC_MD5_96 0x0001
+#define OP_PCL_IPSEC_HMAC_SHA1_96 0x0002
+#define OP_PCL_IPSEC_AES_XCBC_MAC_96 0x0005
+#define OP_PCL_IPSEC_HMAC_MD5_128 0x0006
+#define OP_PCL_IPSEC_HMAC_SHA1_160 0x0007
+#define OP_PCL_IPSEC_HMAC_SHA2_256_128 0x000c
+#define OP_PCL_IPSEC_HMAC_SHA2_384_192 0x000d
+#define OP_PCL_IPSEC_HMAC_SHA2_512_256 0x000e
/* For SRTP - OP_PCLID_SRTP */
-#define OP_PCL_SRTP_CIPHER_MASK 0xff00
-#define OP_PCL_SRTP_AUTH_MASK 0x00ff
+#define OP_PCL_SRTP_CIPHER_MASK 0xff00
+#define OP_PCL_SRTP_AUTH_MASK 0x00ff
-#define OP_PCL_SRTP_AES_CTR 0x0d00
+#define OP_PCL_SRTP_AES_CTR 0x0d00
-#define OP_PCL_SRTP_HMAC_SHA1_160 0x0007
+#define OP_PCL_SRTP_HMAC_SHA1_160 0x0007
/* For SSL 3.0 - OP_PCLID_SSL30 */
-#define OP_PCL_SSL30_AES_128_CBC_SHA 0x002f
-#define OP_PCL_SSL30_AES_128_CBC_SHA_2 0x0030
-#define OP_PCL_SSL30_AES_128_CBC_SHA_3 0x0031
-#define OP_PCL_SSL30_AES_128_CBC_SHA_4 0x0032
-#define OP_PCL_SSL30_AES_128_CBC_SHA_5 0x0033
-#define OP_PCL_SSL30_AES_128_CBC_SHA_6 0x0034
-#define OP_PCL_SSL30_AES_128_CBC_SHA_7 0x008c
-#define OP_PCL_SSL30_AES_128_CBC_SHA_8 0x0090
-#define OP_PCL_SSL30_AES_128_CBC_SHA_9 0x0094
-#define OP_PCL_SSL30_AES_128_CBC_SHA_10 0xc004
-#define OP_PCL_SSL30_AES_128_CBC_SHA_11 0xc009
-#define OP_PCL_SSL30_AES_128_CBC_SHA_12 0xc00e
-#define OP_PCL_SSL30_AES_128_CBC_SHA_13 0xc013
-#define OP_PCL_SSL30_AES_128_CBC_SHA_14 0xc018
-#define OP_PCL_SSL30_AES_128_CBC_SHA_15 0xc01d
-#define OP_PCL_SSL30_AES_128_CBC_SHA_16 0xc01e
-#define OP_PCL_SSL30_AES_128_CBC_SHA_17 0xc01f
-
-#define OP_PCL_SSL30_AES_256_CBC_SHA 0x0035
-#define OP_PCL_SSL30_AES_256_CBC_SHA_2 0x0036
-#define OP_PCL_SSL30_AES_256_CBC_SHA_3 0x0037
-#define OP_PCL_SSL30_AES_256_CBC_SHA_4 0x0038
-#define OP_PCL_SSL30_AES_256_CBC_SHA_5 0x0039
-#define OP_PCL_SSL30_AES_256_CBC_SHA_6 0x003a
-#define OP_PCL_SSL30_AES_256_CBC_SHA_7 0x008d
-#define OP_PCL_SSL30_AES_256_CBC_SHA_8 0x0091
-#define OP_PCL_SSL30_AES_256_CBC_SHA_9 0x0095
-#define OP_PCL_SSL30_AES_256_CBC_SHA_10 0xc005
-#define OP_PCL_SSL30_AES_256_CBC_SHA_11 0xc00a
-#define OP_PCL_SSL30_AES_256_CBC_SHA_12 0xc00f
-#define OP_PCL_SSL30_AES_256_CBC_SHA_13 0xc014
-#define OP_PCL_SSL30_AES_256_CBC_SHA_14 0xc019
-#define OP_PCL_SSL30_AES_256_CBC_SHA_15 0xc020
-#define OP_PCL_SSL30_AES_256_CBC_SHA_16 0xc021
-#define OP_PCL_SSL30_AES_256_CBC_SHA_17 0xc022
-
-#define OP_PCL_SSL30_3DES_EDE_CBC_MD5 0x0023
-
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA 0x001f
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_2 0x008b
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_3 0x008f
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_4 0x0093
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_5 0x000a
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_6 0x000d
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_7 0x0010
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_8 0x0013
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_9 0x0016
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_10 0x001b
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_11 0xc003
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_12 0xc008
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_13 0xc00d
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_14 0xc012
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_15 0xc017
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_16 0xc01a
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_17 0xc01b
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_18 0xc01c
-
-#define OP_PCL_SSL30_DES40_CBC_MD5 0x0029
-
-#define OP_PCL_SSL30_DES_CBC_MD5 0x0022
-
-#define OP_PCL_SSL30_DES40_CBC_SHA 0x0008
-#define OP_PCL_SSL30_DES40_CBC_SHA_2 0x000b
-#define OP_PCL_SSL30_DES40_CBC_SHA_3 0x000e
-#define OP_PCL_SSL30_DES40_CBC_SHA_4 0x0011
-#define OP_PCL_SSL30_DES40_CBC_SHA_5 0x0014
-#define OP_PCL_SSL30_DES40_CBC_SHA_6 0x0019
-#define OP_PCL_SSL30_DES40_CBC_SHA_7 0x0026
-
-#define OP_PCL_SSL30_DES_CBC_SHA 0x001e
-#define OP_PCL_SSL30_DES_CBC_SHA_2 0x0009
-#define OP_PCL_SSL30_DES_CBC_SHA_3 0x000c
-#define OP_PCL_SSL30_DES_CBC_SHA_4 0x000f
-#define OP_PCL_SSL30_DES_CBC_SHA_5 0x0012
-#define OP_PCL_SSL30_DES_CBC_SHA_6 0x0015
-#define OP_PCL_SSL30_DES_CBC_SHA_7 0x001a
-
-#define OP_PCL_SSL30_RC4_128_MD5 0x0024
-#define OP_PCL_SSL30_RC4_128_MD5_2 0x0004
-#define OP_PCL_SSL30_RC4_128_MD5_3 0x0018
-
-#define OP_PCL_SSL30_RC4_40_MD5 0x002b
-#define OP_PCL_SSL30_RC4_40_MD5_2 0x0003
-#define OP_PCL_SSL30_RC4_40_MD5_3 0x0017
-
-#define OP_PCL_SSL30_RC4_128_SHA 0x0020
-#define OP_PCL_SSL30_RC4_128_SHA_2 0x008a
-#define OP_PCL_SSL30_RC4_128_SHA_3 0x008e
-#define OP_PCL_SSL30_RC4_128_SHA_4 0x0092
-#define OP_PCL_SSL30_RC4_128_SHA_5 0x0005
-#define OP_PCL_SSL30_RC4_128_SHA_6 0xc002
-#define OP_PCL_SSL30_RC4_128_SHA_7 0xc007
-#define OP_PCL_SSL30_RC4_128_SHA_8 0xc00c
-#define OP_PCL_SSL30_RC4_128_SHA_9 0xc011
-#define OP_PCL_SSL30_RC4_128_SHA_10 0xc016
-
-#define OP_PCL_SSL30_RC4_40_SHA 0x0028
+#define OP_PCL_SSL30_AES_128_CBC_SHA 0x002f
+#define OP_PCL_SSL30_AES_128_CBC_SHA_2 0x0030
+#define OP_PCL_SSL30_AES_128_CBC_SHA_3 0x0031
+#define OP_PCL_SSL30_AES_128_CBC_SHA_4 0x0032
+#define OP_PCL_SSL30_AES_128_CBC_SHA_5 0x0033
+#define OP_PCL_SSL30_AES_128_CBC_SHA_6 0x0034
+#define OP_PCL_SSL30_AES_128_CBC_SHA_7 0x008c
+#define OP_PCL_SSL30_AES_128_CBC_SHA_8 0x0090
+#define OP_PCL_SSL30_AES_128_CBC_SHA_9 0x0094
+#define OP_PCL_SSL30_AES_128_CBC_SHA_10 0xc004
+#define OP_PCL_SSL30_AES_128_CBC_SHA_11 0xc009
+#define OP_PCL_SSL30_AES_128_CBC_SHA_12 0xc00e
+#define OP_PCL_SSL30_AES_128_CBC_SHA_13 0xc013
+#define OP_PCL_SSL30_AES_128_CBC_SHA_14 0xc018
+#define OP_PCL_SSL30_AES_128_CBC_SHA_15 0xc01d
+#define OP_PCL_SSL30_AES_128_CBC_SHA_16 0xc01e
+#define OP_PCL_SSL30_AES_128_CBC_SHA_17 0xc01f
+
+#define OP_PCL_SSL30_AES_256_CBC_SHA 0x0035
+#define OP_PCL_SSL30_AES_256_CBC_SHA_2 0x0036
+#define OP_PCL_SSL30_AES_256_CBC_SHA_3 0x0037
+#define OP_PCL_SSL30_AES_256_CBC_SHA_4 0x0038
+#define OP_PCL_SSL30_AES_256_CBC_SHA_5 0x0039
+#define OP_PCL_SSL30_AES_256_CBC_SHA_6 0x003a
+#define OP_PCL_SSL30_AES_256_CBC_SHA_7 0x008d
+#define OP_PCL_SSL30_AES_256_CBC_SHA_8 0x0091
+#define OP_PCL_SSL30_AES_256_CBC_SHA_9 0x0095
+#define OP_PCL_SSL30_AES_256_CBC_SHA_10 0xc005
+#define OP_PCL_SSL30_AES_256_CBC_SHA_11 0xc00a
+#define OP_PCL_SSL30_AES_256_CBC_SHA_12 0xc00f
+#define OP_PCL_SSL30_AES_256_CBC_SHA_13 0xc014
+#define OP_PCL_SSL30_AES_256_CBC_SHA_14 0xc019
+#define OP_PCL_SSL30_AES_256_CBC_SHA_15 0xc020
+#define OP_PCL_SSL30_AES_256_CBC_SHA_16 0xc021
+#define OP_PCL_SSL30_AES_256_CBC_SHA_17 0xc022
+
+#define OP_PCL_SSL30_3DES_EDE_CBC_MD5 0x0023
+
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA 0x001f
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_2 0x008b
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_3 0x008f
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_4 0x0093
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_5 0x000a
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_6 0x000d
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_7 0x0010
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_8 0x0013
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_9 0x0016
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_10 0x001b
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_11 0xc003
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_12 0xc008
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_13 0xc00d
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_14 0xc012
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_15 0xc017
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_16 0xc01a
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_17 0xc01b
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_18 0xc01c
+
+#define OP_PCL_SSL30_DES40_CBC_MD5 0x0029
+
+#define OP_PCL_SSL30_DES_CBC_MD5 0x0022
+
+#define OP_PCL_SSL30_DES40_CBC_SHA 0x0008
+#define OP_PCL_SSL30_DES40_CBC_SHA_2 0x000b
+#define OP_PCL_SSL30_DES40_CBC_SHA_3 0x000e
+#define OP_PCL_SSL30_DES40_CBC_SHA_4 0x0011
+#define OP_PCL_SSL30_DES40_CBC_SHA_5 0x0014
+#define OP_PCL_SSL30_DES40_CBC_SHA_6 0x0019
+#define OP_PCL_SSL30_DES40_CBC_SHA_7 0x0026
+
+#define OP_PCL_SSL30_DES_CBC_SHA 0x001e
+#define OP_PCL_SSL30_DES_CBC_SHA_2 0x0009
+#define OP_PCL_SSL30_DES_CBC_SHA_3 0x000c
+#define OP_PCL_SSL30_DES_CBC_SHA_4 0x000f
+#define OP_PCL_SSL30_DES_CBC_SHA_5 0x0012
+#define OP_PCL_SSL30_DES_CBC_SHA_6 0x0015
+#define OP_PCL_SSL30_DES_CBC_SHA_7 0x001a
+
+#define OP_PCL_SSL30_RC4_128_MD5 0x0024
+#define OP_PCL_SSL30_RC4_128_MD5_2 0x0004
+#define OP_PCL_SSL30_RC4_128_MD5_3 0x0018
+
+#define OP_PCL_SSL30_RC4_40_MD5 0x002b
+#define OP_PCL_SSL30_RC4_40_MD5_2 0x0003
+#define OP_PCL_SSL30_RC4_40_MD5_3 0x0017
+
+#define OP_PCL_SSL30_RC4_128_SHA 0x0020
+#define OP_PCL_SSL30_RC4_128_SHA_2 0x008a
+#define OP_PCL_SSL30_RC4_128_SHA_3 0x008e
+#define OP_PCL_SSL30_RC4_128_SHA_4 0x0092
+#define OP_PCL_SSL30_RC4_128_SHA_5 0x0005
+#define OP_PCL_SSL30_RC4_128_SHA_6 0xc002
+#define OP_PCL_SSL30_RC4_128_SHA_7 0xc007
+#define OP_PCL_SSL30_RC4_128_SHA_8 0xc00c
+#define OP_PCL_SSL30_RC4_128_SHA_9 0xc011
+#define OP_PCL_SSL30_RC4_128_SHA_10 0xc016
+
+#define OP_PCL_SSL30_RC4_40_SHA 0x0028
/* For TLS 1.0 - OP_PCLID_TLS10 */
-#define OP_PCL_TLS10_AES_128_CBC_SHA 0x002f
-#define OP_PCL_TLS10_AES_128_CBC_SHA_2 0x0030
-#define OP_PCL_TLS10_AES_128_CBC_SHA_3 0x0031
-#define OP_PCL_TLS10_AES_128_CBC_SHA_4 0x0032
-#define OP_PCL_TLS10_AES_128_CBC_SHA_5 0x0033
-#define OP_PCL_TLS10_AES_128_CBC_SHA_6 0x0034
-#define OP_PCL_TLS10_AES_128_CBC_SHA_7 0x008c
-#define OP_PCL_TLS10_AES_128_CBC_SHA_8 0x0090
-#define OP_PCL_TLS10_AES_128_CBC_SHA_9 0x0094
-#define OP_PCL_TLS10_AES_128_CBC_SHA_10 0xc004
-#define OP_PCL_TLS10_AES_128_CBC_SHA_11 0xc009
-#define OP_PCL_TLS10_AES_128_CBC_SHA_12 0xc00e
-#define OP_PCL_TLS10_AES_128_CBC_SHA_13 0xc013
-#define OP_PCL_TLS10_AES_128_CBC_SHA_14 0xc018
-#define OP_PCL_TLS10_AES_128_CBC_SHA_15 0xc01d
-#define OP_PCL_TLS10_AES_128_CBC_SHA_16 0xc01e
-#define OP_PCL_TLS10_AES_128_CBC_SHA_17 0xc01f
-
-#define OP_PCL_TLS10_AES_256_CBC_SHA 0x0035
-#define OP_PCL_TLS10_AES_256_CBC_SHA_2 0x0036
-#define OP_PCL_TLS10_AES_256_CBC_SHA_3 0x0037
-#define OP_PCL_TLS10_AES_256_CBC_SHA_4 0x0038
-#define OP_PCL_TLS10_AES_256_CBC_SHA_5 0x0039
-#define OP_PCL_TLS10_AES_256_CBC_SHA_6 0x003a
-#define OP_PCL_TLS10_AES_256_CBC_SHA_7 0x008d
-#define OP_PCL_TLS10_AES_256_CBC_SHA_8 0x0091
-#define OP_PCL_TLS10_AES_256_CBC_SHA_9 0x0095
-#define OP_PCL_TLS10_AES_256_CBC_SHA_10 0xc005
-#define OP_PCL_TLS10_AES_256_CBC_SHA_11 0xc00a
-#define OP_PCL_TLS10_AES_256_CBC_SHA_12 0xc00f
-#define OP_PCL_TLS10_AES_256_CBC_SHA_13 0xc014
-#define OP_PCL_TLS10_AES_256_CBC_SHA_14 0xc019
-#define OP_PCL_TLS10_AES_256_CBC_SHA_15 0xc020
-#define OP_PCL_TLS10_AES_256_CBC_SHA_16 0xc021
-#define OP_PCL_TLS10_AES_256_CBC_SHA_17 0xc022
-
-/* #define OP_PCL_TLS10_3DES_EDE_CBC_MD5 0x0023 */
-
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA 0x001f
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_2 0x008b
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_3 0x008f
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_4 0x0093
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_5 0x000a
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_6 0x000d
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_7 0x0010
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_8 0x0013
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_9 0x0016
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_10 0x001b
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_11 0xc003
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_12 0xc008
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_13 0xc00d
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_14 0xc012
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_15 0xc017
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_16 0xc01a
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_17 0xc01b
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_18 0xc01c
-
-#define OP_PCL_TLS10_DES40_CBC_MD5 0x0029
-
-#define OP_PCL_TLS10_DES_CBC_MD5 0x0022
-
-#define OP_PCL_TLS10_DES40_CBC_SHA 0x0008
-#define OP_PCL_TLS10_DES40_CBC_SHA_2 0x000b
-#define OP_PCL_TLS10_DES40_CBC_SHA_3 0x000e
-#define OP_PCL_TLS10_DES40_CBC_SHA_4 0x0011
-#define OP_PCL_TLS10_DES40_CBC_SHA_5 0x0014
-#define OP_PCL_TLS10_DES40_CBC_SHA_6 0x0019
-#define OP_PCL_TLS10_DES40_CBC_SHA_7 0x0026
-
-
-#define OP_PCL_TLS10_DES_CBC_SHA 0x001e
-#define OP_PCL_TLS10_DES_CBC_SHA_2 0x0009
-#define OP_PCL_TLS10_DES_CBC_SHA_3 0x000c
-#define OP_PCL_TLS10_DES_CBC_SHA_4 0x000f
-#define OP_PCL_TLS10_DES_CBC_SHA_5 0x0012
-#define OP_PCL_TLS10_DES_CBC_SHA_6 0x0015
-#define OP_PCL_TLS10_DES_CBC_SHA_7 0x001a
-
-#define OP_PCL_TLS10_RC4_128_MD5 0x0024
-#define OP_PCL_TLS10_RC4_128_MD5_2 0x0004
-#define OP_PCL_TLS10_RC4_128_MD5_3 0x0018
-
-#define OP_PCL_TLS10_RC4_40_MD5 0x002b
-#define OP_PCL_TLS10_RC4_40_MD5_2 0x0003
-#define OP_PCL_TLS10_RC4_40_MD5_3 0x0017
-
-#define OP_PCL_TLS10_RC4_128_SHA 0x0020
-#define OP_PCL_TLS10_RC4_128_SHA_2 0x008a
-#define OP_PCL_TLS10_RC4_128_SHA_3 0x008e
-#define OP_PCL_TLS10_RC4_128_SHA_4 0x0092
-#define OP_PCL_TLS10_RC4_128_SHA_5 0x0005
-#define OP_PCL_TLS10_RC4_128_SHA_6 0xc002
-#define OP_PCL_TLS10_RC4_128_SHA_7 0xc007
-#define OP_PCL_TLS10_RC4_128_SHA_8 0xc00c
-#define OP_PCL_TLS10_RC4_128_SHA_9 0xc011
-#define OP_PCL_TLS10_RC4_128_SHA_10 0xc016
-
-#define OP_PCL_TLS10_RC4_40_SHA 0x0028
-
-#define OP_PCL_TLS10_3DES_EDE_CBC_MD5 0xff23
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA160 0xff30
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA224 0xff34
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA256 0xff36
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA384 0xff33
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA512 0xff35
-#define OP_PCL_TLS10_AES_128_CBC_SHA160 0xff80
-#define OP_PCL_TLS10_AES_128_CBC_SHA224 0xff84
-#define OP_PCL_TLS10_AES_128_CBC_SHA256 0xff86
-#define OP_PCL_TLS10_AES_128_CBC_SHA384 0xff83
-#define OP_PCL_TLS10_AES_128_CBC_SHA512 0xff85
-#define OP_PCL_TLS10_AES_192_CBC_SHA160 0xff20
-#define OP_PCL_TLS10_AES_192_CBC_SHA224 0xff24
-#define OP_PCL_TLS10_AES_192_CBC_SHA256 0xff26
-#define OP_PCL_TLS10_AES_192_CBC_SHA384 0xff23
-#define OP_PCL_TLS10_AES_192_CBC_SHA512 0xff25
-#define OP_PCL_TLS10_AES_256_CBC_SHA160 0xff60
-#define OP_PCL_TLS10_AES_256_CBC_SHA224 0xff64
-#define OP_PCL_TLS10_AES_256_CBC_SHA256 0xff66
-#define OP_PCL_TLS10_AES_256_CBC_SHA384 0xff63
-#define OP_PCL_TLS10_AES_256_CBC_SHA512 0xff65
+#define OP_PCL_TLS10_AES_128_CBC_SHA 0x002f
+#define OP_PCL_TLS10_AES_128_CBC_SHA_2 0x0030
+#define OP_PCL_TLS10_AES_128_CBC_SHA_3 0x0031
+#define OP_PCL_TLS10_AES_128_CBC_SHA_4 0x0032
+#define OP_PCL_TLS10_AES_128_CBC_SHA_5 0x0033
+#define OP_PCL_TLS10_AES_128_CBC_SHA_6 0x0034
+#define OP_PCL_TLS10_AES_128_CBC_SHA_7 0x008c
+#define OP_PCL_TLS10_AES_128_CBC_SHA_8 0x0090
+#define OP_PCL_TLS10_AES_128_CBC_SHA_9 0x0094
+#define OP_PCL_TLS10_AES_128_CBC_SHA_10 0xc004
+#define OP_PCL_TLS10_AES_128_CBC_SHA_11 0xc009
+#define OP_PCL_TLS10_AES_128_CBC_SHA_12 0xc00e
+#define OP_PCL_TLS10_AES_128_CBC_SHA_13 0xc013
+#define OP_PCL_TLS10_AES_128_CBC_SHA_14 0xc018
+#define OP_PCL_TLS10_AES_128_CBC_SHA_15 0xc01d
+#define OP_PCL_TLS10_AES_128_CBC_SHA_16 0xc01e
+#define OP_PCL_TLS10_AES_128_CBC_SHA_17 0xc01f
+
+#define OP_PCL_TLS10_AES_256_CBC_SHA 0x0035
+#define OP_PCL_TLS10_AES_256_CBC_SHA_2 0x0036
+#define OP_PCL_TLS10_AES_256_CBC_SHA_3 0x0037
+#define OP_PCL_TLS10_AES_256_CBC_SHA_4 0x0038
+#define OP_PCL_TLS10_AES_256_CBC_SHA_5 0x0039
+#define OP_PCL_TLS10_AES_256_CBC_SHA_6 0x003a
+#define OP_PCL_TLS10_AES_256_CBC_SHA_7 0x008d
+#define OP_PCL_TLS10_AES_256_CBC_SHA_8 0x0091
+#define OP_PCL_TLS10_AES_256_CBC_SHA_9 0x0095
+#define OP_PCL_TLS10_AES_256_CBC_SHA_10 0xc005
+#define OP_PCL_TLS10_AES_256_CBC_SHA_11 0xc00a
+#define OP_PCL_TLS10_AES_256_CBC_SHA_12 0xc00f
+#define OP_PCL_TLS10_AES_256_CBC_SHA_13 0xc014
+#define OP_PCL_TLS10_AES_256_CBC_SHA_14 0xc019
+#define OP_PCL_TLS10_AES_256_CBC_SHA_15 0xc020
+#define OP_PCL_TLS10_AES_256_CBC_SHA_16 0xc021
+#define OP_PCL_TLS10_AES_256_CBC_SHA_17 0xc022
+
+/* #define OP_PCL_TLS10_3DES_EDE_CBC_MD5 0x0023 */
+
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA 0x001f
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_2 0x008b
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_3 0x008f
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_4 0x0093
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_5 0x000a
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_6 0x000d
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_7 0x0010
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_8 0x0013
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_9 0x0016
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_10 0x001b
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_11 0xc003
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_12 0xc008
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_13 0xc00d
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_14 0xc012
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_15 0xc017
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_16 0xc01a
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_17 0xc01b
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_18 0xc01c
+
+#define OP_PCL_TLS10_DES40_CBC_MD5 0x0029
+
+#define OP_PCL_TLS10_DES_CBC_MD5 0x0022
+
+#define OP_PCL_TLS10_DES40_CBC_SHA 0x0008
+#define OP_PCL_TLS10_DES40_CBC_SHA_2 0x000b
+#define OP_PCL_TLS10_DES40_CBC_SHA_3 0x000e
+#define OP_PCL_TLS10_DES40_CBC_SHA_4 0x0011
+#define OP_PCL_TLS10_DES40_CBC_SHA_5 0x0014
+#define OP_PCL_TLS10_DES40_CBC_SHA_6 0x0019
+#define OP_PCL_TLS10_DES40_CBC_SHA_7 0x0026
+
+
+#define OP_PCL_TLS10_DES_CBC_SHA 0x001e
+#define OP_PCL_TLS10_DES_CBC_SHA_2 0x0009
+#define OP_PCL_TLS10_DES_CBC_SHA_3 0x000c
+#define OP_PCL_TLS10_DES_CBC_SHA_4 0x000f
+#define OP_PCL_TLS10_DES_CBC_SHA_5 0x0012
+#define OP_PCL_TLS10_DES_CBC_SHA_6 0x0015
+#define OP_PCL_TLS10_DES_CBC_SHA_7 0x001a
+
+#define OP_PCL_TLS10_RC4_128_MD5 0x0024
+#define OP_PCL_TLS10_RC4_128_MD5_2 0x0004
+#define OP_PCL_TLS10_RC4_128_MD5_3 0x0018
+
+#define OP_PCL_TLS10_RC4_40_MD5 0x002b
+#define OP_PCL_TLS10_RC4_40_MD5_2 0x0003
+#define OP_PCL_TLS10_RC4_40_MD5_3 0x0017
+
+#define OP_PCL_TLS10_RC4_128_SHA 0x0020
+#define OP_PCL_TLS10_RC4_128_SHA_2 0x008a
+#define OP_PCL_TLS10_RC4_128_SHA_3 0x008e
+#define OP_PCL_TLS10_RC4_128_SHA_4 0x0092
+#define OP_PCL_TLS10_RC4_128_SHA_5 0x0005
+#define OP_PCL_TLS10_RC4_128_SHA_6 0xc002
+#define OP_PCL_TLS10_RC4_128_SHA_7 0xc007
+#define OP_PCL_TLS10_RC4_128_SHA_8 0xc00c
+#define OP_PCL_TLS10_RC4_128_SHA_9 0xc011
+#define OP_PCL_TLS10_RC4_128_SHA_10 0xc016
+
+#define OP_PCL_TLS10_RC4_40_SHA 0x0028
+
+#define OP_PCL_TLS10_3DES_EDE_CBC_MD5 0xff23
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA160 0xff30
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA224 0xff34
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA256 0xff36
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA384 0xff33
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA512 0xff35
+#define OP_PCL_TLS10_AES_128_CBC_SHA160 0xff80
+#define OP_PCL_TLS10_AES_128_CBC_SHA224 0xff84
+#define OP_PCL_TLS10_AES_128_CBC_SHA256 0xff86
+#define OP_PCL_TLS10_AES_128_CBC_SHA384 0xff83
+#define OP_PCL_TLS10_AES_128_CBC_SHA512 0xff85
+#define OP_PCL_TLS10_AES_192_CBC_SHA160 0xff20
+#define OP_PCL_TLS10_AES_192_CBC_SHA224 0xff24
+#define OP_PCL_TLS10_AES_192_CBC_SHA256 0xff26
+#define OP_PCL_TLS10_AES_192_CBC_SHA384 0xff23
+#define OP_PCL_TLS10_AES_192_CBC_SHA512 0xff25
+#define OP_PCL_TLS10_AES_256_CBC_SHA160 0xff60
+#define OP_PCL_TLS10_AES_256_CBC_SHA224 0xff64
+#define OP_PCL_TLS10_AES_256_CBC_SHA256 0xff66
+#define OP_PCL_TLS10_AES_256_CBC_SHA384 0xff63
+#define OP_PCL_TLS10_AES_256_CBC_SHA512 0xff65
/* For TLS 1.1 - OP_PCLID_TLS11 */
-#define OP_PCL_TLS11_AES_128_CBC_SHA 0x002f
-#define OP_PCL_TLS11_AES_128_CBC_SHA_2 0x0030
-#define OP_PCL_TLS11_AES_128_CBC_SHA_3 0x0031
-#define OP_PCL_TLS11_AES_128_CBC_SHA_4 0x0032
-#define OP_PCL_TLS11_AES_128_CBC_SHA_5 0x0033
-#define OP_PCL_TLS11_AES_128_CBC_SHA_6 0x0034
-#define OP_PCL_TLS11_AES_128_CBC_SHA_7 0x008c
-#define OP_PCL_TLS11_AES_128_CBC_SHA_8 0x0090
-#define OP_PCL_TLS11_AES_128_CBC_SHA_9 0x0094
-#define OP_PCL_TLS11_AES_128_CBC_SHA_10 0xc004
-#define OP_PCL_TLS11_AES_128_CBC_SHA_11 0xc009
-#define OP_PCL_TLS11_AES_128_CBC_SHA_12 0xc00e
-#define OP_PCL_TLS11_AES_128_CBC_SHA_13 0xc013
-#define OP_PCL_TLS11_AES_128_CBC_SHA_14 0xc018
-#define OP_PCL_TLS11_AES_128_CBC_SHA_15 0xc01d
-#define OP_PCL_TLS11_AES_128_CBC_SHA_16 0xc01e
-#define OP_PCL_TLS11_AES_128_CBC_SHA_17 0xc01f
-
-#define OP_PCL_TLS11_AES_256_CBC_SHA 0x0035
-#define OP_PCL_TLS11_AES_256_CBC_SHA_2 0x0036
-#define OP_PCL_TLS11_AES_256_CBC_SHA_3 0x0037
-#define OP_PCL_TLS11_AES_256_CBC_SHA_4 0x0038
-#define OP_PCL_TLS11_AES_256_CBC_SHA_5 0x0039
-#define OP_PCL_TLS11_AES_256_CBC_SHA_6 0x003a
-#define OP_PCL_TLS11_AES_256_CBC_SHA_7 0x008d
-#define OP_PCL_TLS11_AES_256_CBC_SHA_8 0x0091
-#define OP_PCL_TLS11_AES_256_CBC_SHA_9 0x0095
-#define OP_PCL_TLS11_AES_256_CBC_SHA_10 0xc005
-#define OP_PCL_TLS11_AES_256_CBC_SHA_11 0xc00a
-#define OP_PCL_TLS11_AES_256_CBC_SHA_12 0xc00f
-#define OP_PCL_TLS11_AES_256_CBC_SHA_13 0xc014
-#define OP_PCL_TLS11_AES_256_CBC_SHA_14 0xc019
-#define OP_PCL_TLS11_AES_256_CBC_SHA_15 0xc020
-#define OP_PCL_TLS11_AES_256_CBC_SHA_16 0xc021
-#define OP_PCL_TLS11_AES_256_CBC_SHA_17 0xc022
-
-/* #define OP_PCL_TLS11_3DES_EDE_CBC_MD5 0x0023 */
-
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA 0x001f
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_2 0x008b
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_3 0x008f
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_4 0x0093
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_5 0x000a
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_6 0x000d
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_7 0x0010
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_8 0x0013
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_9 0x0016
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_10 0x001b
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_11 0xc003
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_12 0xc008
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_13 0xc00d
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_14 0xc012
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_15 0xc017
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_16 0xc01a
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_17 0xc01b
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_18 0xc01c
-
-#define OP_PCL_TLS11_DES40_CBC_MD5 0x0029
-
-#define OP_PCL_TLS11_DES_CBC_MD5 0x0022
-
-#define OP_PCL_TLS11_DES40_CBC_SHA 0x0008
-#define OP_PCL_TLS11_DES40_CBC_SHA_2 0x000b
-#define OP_PCL_TLS11_DES40_CBC_SHA_3 0x000e
-#define OP_PCL_TLS11_DES40_CBC_SHA_4 0x0011
-#define OP_PCL_TLS11_DES40_CBC_SHA_5 0x0014
-#define OP_PCL_TLS11_DES40_CBC_SHA_6 0x0019
-#define OP_PCL_TLS11_DES40_CBC_SHA_7 0x0026
-
-#define OP_PCL_TLS11_DES_CBC_SHA 0x001e
-#define OP_PCL_TLS11_DES_CBC_SHA_2 0x0009
-#define OP_PCL_TLS11_DES_CBC_SHA_3 0x000c
-#define OP_PCL_TLS11_DES_CBC_SHA_4 0x000f
-#define OP_PCL_TLS11_DES_CBC_SHA_5 0x0012
-#define OP_PCL_TLS11_DES_CBC_SHA_6 0x0015
-#define OP_PCL_TLS11_DES_CBC_SHA_7 0x001a
-
-#define OP_PCL_TLS11_RC4_128_MD5 0x0024
-#define OP_PCL_TLS11_RC4_128_MD5_2 0x0004
-#define OP_PCL_TLS11_RC4_128_MD5_3 0x0018
-
-#define OP_PCL_TLS11_RC4_40_MD5 0x002b
-#define OP_PCL_TLS11_RC4_40_MD5_2 0x0003
-#define OP_PCL_TLS11_RC4_40_MD5_3 0x0017
-
-#define OP_PCL_TLS11_RC4_128_SHA 0x0020
-#define OP_PCL_TLS11_RC4_128_SHA_2 0x008a
-#define OP_PCL_TLS11_RC4_128_SHA_3 0x008e
-#define OP_PCL_TLS11_RC4_128_SHA_4 0x0092
-#define OP_PCL_TLS11_RC4_128_SHA_5 0x0005
-#define OP_PCL_TLS11_RC4_128_SHA_6 0xc002
-#define OP_PCL_TLS11_RC4_128_SHA_7 0xc007
-#define OP_PCL_TLS11_RC4_128_SHA_8 0xc00c
-#define OP_PCL_TLS11_RC4_128_SHA_9 0xc011
-#define OP_PCL_TLS11_RC4_128_SHA_10 0xc016
-
-#define OP_PCL_TLS11_RC4_40_SHA 0x0028
-
-#define OP_PCL_TLS11_3DES_EDE_CBC_MD5 0xff23
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA160 0xff30
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA224 0xff34
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA256 0xff36
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA384 0xff33
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA512 0xff35
-#define OP_PCL_TLS11_AES_128_CBC_SHA160 0xff80
-#define OP_PCL_TLS11_AES_128_CBC_SHA224 0xff84
-#define OP_PCL_TLS11_AES_128_CBC_SHA256 0xff86
-#define OP_PCL_TLS11_AES_128_CBC_SHA384 0xff83
-#define OP_PCL_TLS11_AES_128_CBC_SHA512 0xff85
-#define OP_PCL_TLS11_AES_192_CBC_SHA160 0xff20
-#define OP_PCL_TLS11_AES_192_CBC_SHA224 0xff24
-#define OP_PCL_TLS11_AES_192_CBC_SHA256 0xff26
-#define OP_PCL_TLS11_AES_192_CBC_SHA384 0xff23
-#define OP_PCL_TLS11_AES_192_CBC_SHA512 0xff25
-#define OP_PCL_TLS11_AES_256_CBC_SHA160 0xff60
-#define OP_PCL_TLS11_AES_256_CBC_SHA224 0xff64
-#define OP_PCL_TLS11_AES_256_CBC_SHA256 0xff66
-#define OP_PCL_TLS11_AES_256_CBC_SHA384 0xff63
-#define OP_PCL_TLS11_AES_256_CBC_SHA512 0xff65
+#define OP_PCL_TLS11_AES_128_CBC_SHA 0x002f
+#define OP_PCL_TLS11_AES_128_CBC_SHA_2 0x0030
+#define OP_PCL_TLS11_AES_128_CBC_SHA_3 0x0031
+#define OP_PCL_TLS11_AES_128_CBC_SHA_4 0x0032
+#define OP_PCL_TLS11_AES_128_CBC_SHA_5 0x0033
+#define OP_PCL_TLS11_AES_128_CBC_SHA_6 0x0034
+#define OP_PCL_TLS11_AES_128_CBC_SHA_7 0x008c
+#define OP_PCL_TLS11_AES_128_CBC_SHA_8 0x0090
+#define OP_PCL_TLS11_AES_128_CBC_SHA_9 0x0094
+#define OP_PCL_TLS11_AES_128_CBC_SHA_10 0xc004
+#define OP_PCL_TLS11_AES_128_CBC_SHA_11 0xc009
+#define OP_PCL_TLS11_AES_128_CBC_SHA_12 0xc00e
+#define OP_PCL_TLS11_AES_128_CBC_SHA_13 0xc013
+#define OP_PCL_TLS11_AES_128_CBC_SHA_14 0xc018
+#define OP_PCL_TLS11_AES_128_CBC_SHA_15 0xc01d
+#define OP_PCL_TLS11_AES_128_CBC_SHA_16 0xc01e
+#define OP_PCL_TLS11_AES_128_CBC_SHA_17 0xc01f
+
+#define OP_PCL_TLS11_AES_256_CBC_SHA 0x0035
+#define OP_PCL_TLS11_AES_256_CBC_SHA_2 0x0036
+#define OP_PCL_TLS11_AES_256_CBC_SHA_3 0x0037
+#define OP_PCL_TLS11_AES_256_CBC_SHA_4 0x0038
+#define OP_PCL_TLS11_AES_256_CBC_SHA_5 0x0039
+#define OP_PCL_TLS11_AES_256_CBC_SHA_6 0x003a
+#define OP_PCL_TLS11_AES_256_CBC_SHA_7 0x008d
+#define OP_PCL_TLS11_AES_256_CBC_SHA_8 0x0091
+#define OP_PCL_TLS11_AES_256_CBC_SHA_9 0x0095
+#define OP_PCL_TLS11_AES_256_CBC_SHA_10 0xc005
+#define OP_PCL_TLS11_AES_256_CBC_SHA_11 0xc00a
+#define OP_PCL_TLS11_AES_256_CBC_SHA_12 0xc00f
+#define OP_PCL_TLS11_AES_256_CBC_SHA_13 0xc014
+#define OP_PCL_TLS11_AES_256_CBC_SHA_14 0xc019
+#define OP_PCL_TLS11_AES_256_CBC_SHA_15 0xc020
+#define OP_PCL_TLS11_AES_256_CBC_SHA_16 0xc021
+#define OP_PCL_TLS11_AES_256_CBC_SHA_17 0xc022
+
+/* #define OP_PCL_TLS11_3DES_EDE_CBC_MD5 0x0023 */
+
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA 0x001f
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_2 0x008b
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_3 0x008f
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_4 0x0093
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_5 0x000a
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_6 0x000d
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_7 0x0010
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_8 0x0013
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_9 0x0016
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_10 0x001b
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_11 0xc003
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_12 0xc008
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_13 0xc00d
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_14 0xc012
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_15 0xc017
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_16 0xc01a
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_17 0xc01b
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_18 0xc01c
+
+#define OP_PCL_TLS11_DES40_CBC_MD5 0x0029
+
+#define OP_PCL_TLS11_DES_CBC_MD5 0x0022
+
+#define OP_PCL_TLS11_DES40_CBC_SHA 0x0008
+#define OP_PCL_TLS11_DES40_CBC_SHA_2 0x000b
+#define OP_PCL_TLS11_DES40_CBC_SHA_3 0x000e
+#define OP_PCL_TLS11_DES40_CBC_SHA_4 0x0011
+#define OP_PCL_TLS11_DES40_CBC_SHA_5 0x0014
+#define OP_PCL_TLS11_DES40_CBC_SHA_6 0x0019
+#define OP_PCL_TLS11_DES40_CBC_SHA_7 0x0026
+
+#define OP_PCL_TLS11_DES_CBC_SHA 0x001e
+#define OP_PCL_TLS11_DES_CBC_SHA_2 0x0009
+#define OP_PCL_TLS11_DES_CBC_SHA_3 0x000c
+#define OP_PCL_TLS11_DES_CBC_SHA_4 0x000f
+#define OP_PCL_TLS11_DES_CBC_SHA_5 0x0012
+#define OP_PCL_TLS11_DES_CBC_SHA_6 0x0015
+#define OP_PCL_TLS11_DES_CBC_SHA_7 0x001a
+
+#define OP_PCL_TLS11_RC4_128_MD5 0x0024
+#define OP_PCL_TLS11_RC4_128_MD5_2 0x0004
+#define OP_PCL_TLS11_RC4_128_MD5_3 0x0018
+
+#define OP_PCL_TLS11_RC4_40_MD5 0x002b
+#define OP_PCL_TLS11_RC4_40_MD5_2 0x0003
+#define OP_PCL_TLS11_RC4_40_MD5_3 0x0017
+
+#define OP_PCL_TLS11_RC4_128_SHA 0x0020
+#define OP_PCL_TLS11_RC4_128_SHA_2 0x008a
+#define OP_PCL_TLS11_RC4_128_SHA_3 0x008e
+#define OP_PCL_TLS11_RC4_128_SHA_4 0x0092
+#define OP_PCL_TLS11_RC4_128_SHA_5 0x0005
+#define OP_PCL_TLS11_RC4_128_SHA_6 0xc002
+#define OP_PCL_TLS11_RC4_128_SHA_7 0xc007
+#define OP_PCL_TLS11_RC4_128_SHA_8 0xc00c
+#define OP_PCL_TLS11_RC4_128_SHA_9 0xc011
+#define OP_PCL_TLS11_RC4_128_SHA_10 0xc016
+
+#define OP_PCL_TLS11_RC4_40_SHA 0x0028
+
+#define OP_PCL_TLS11_3DES_EDE_CBC_MD5 0xff23
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA160 0xff30
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA224 0xff34
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA256 0xff36
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA384 0xff33
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA512 0xff35
+#define OP_PCL_TLS11_AES_128_CBC_SHA160 0xff80
+#define OP_PCL_TLS11_AES_128_CBC_SHA224 0xff84
+#define OP_PCL_TLS11_AES_128_CBC_SHA256 0xff86
+#define OP_PCL_TLS11_AES_128_CBC_SHA384 0xff83
+#define OP_PCL_TLS11_AES_128_CBC_SHA512 0xff85
+#define OP_PCL_TLS11_AES_192_CBC_SHA160 0xff20
+#define OP_PCL_TLS11_AES_192_CBC_SHA224 0xff24
+#define OP_PCL_TLS11_AES_192_CBC_SHA256 0xff26
+#define OP_PCL_TLS11_AES_192_CBC_SHA384 0xff23
+#define OP_PCL_TLS11_AES_192_CBC_SHA512 0xff25
+#define OP_PCL_TLS11_AES_256_CBC_SHA160 0xff60
+#define OP_PCL_TLS11_AES_256_CBC_SHA224 0xff64
+#define OP_PCL_TLS11_AES_256_CBC_SHA256 0xff66
+#define OP_PCL_TLS11_AES_256_CBC_SHA384 0xff63
+#define OP_PCL_TLS11_AES_256_CBC_SHA512 0xff65
/* For TLS 1.2 - OP_PCLID_TLS12 */
-#define OP_PCL_TLS12_AES_128_CBC_SHA 0x002f
-#define OP_PCL_TLS12_AES_128_CBC_SHA_2 0x0030
-#define OP_PCL_TLS12_AES_128_CBC_SHA_3 0x0031
-#define OP_PCL_TLS12_AES_128_CBC_SHA_4 0x0032
-#define OP_PCL_TLS12_AES_128_CBC_SHA_5 0x0033
-#define OP_PCL_TLS12_AES_128_CBC_SHA_6 0x0034
-#define OP_PCL_TLS12_AES_128_CBC_SHA_7 0x008c
-#define OP_PCL_TLS12_AES_128_CBC_SHA_8 0x0090
-#define OP_PCL_TLS12_AES_128_CBC_SHA_9 0x0094
-#define OP_PCL_TLS12_AES_128_CBC_SHA_10 0xc004
-#define OP_PCL_TLS12_AES_128_CBC_SHA_11 0xc009
-#define OP_PCL_TLS12_AES_128_CBC_SHA_12 0xc00e
-#define OP_PCL_TLS12_AES_128_CBC_SHA_13 0xc013
-#define OP_PCL_TLS12_AES_128_CBC_SHA_14 0xc018
-#define OP_PCL_TLS12_AES_128_CBC_SHA_15 0xc01d
-#define OP_PCL_TLS12_AES_128_CBC_SHA_16 0xc01e
-#define OP_PCL_TLS12_AES_128_CBC_SHA_17 0xc01f
-
-#define OP_PCL_TLS12_AES_256_CBC_SHA 0x0035
-#define OP_PCL_TLS12_AES_256_CBC_SHA_2 0x0036
-#define OP_PCL_TLS12_AES_256_CBC_SHA_3 0x0037
-#define OP_PCL_TLS12_AES_256_CBC_SHA_4 0x0038
-#define OP_PCL_TLS12_AES_256_CBC_SHA_5 0x0039
-#define OP_PCL_TLS12_AES_256_CBC_SHA_6 0x003a
-#define OP_PCL_TLS12_AES_256_CBC_SHA_7 0x008d
-#define OP_PCL_TLS12_AES_256_CBC_SHA_8 0x0091
-#define OP_PCL_TLS12_AES_256_CBC_SHA_9 0x0095
-#define OP_PCL_TLS12_AES_256_CBC_SHA_10 0xc005
-#define OP_PCL_TLS12_AES_256_CBC_SHA_11 0xc00a
-#define OP_PCL_TLS12_AES_256_CBC_SHA_12 0xc00f
-#define OP_PCL_TLS12_AES_256_CBC_SHA_13 0xc014
-#define OP_PCL_TLS12_AES_256_CBC_SHA_14 0xc019
-#define OP_PCL_TLS12_AES_256_CBC_SHA_15 0xc020
-#define OP_PCL_TLS12_AES_256_CBC_SHA_16 0xc021
-#define OP_PCL_TLS12_AES_256_CBC_SHA_17 0xc022
-
-/* #define OP_PCL_TLS12_3DES_EDE_CBC_MD5 0x0023 */
-
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA 0x001f
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_2 0x008b
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_3 0x008f
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_4 0x0093
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_5 0x000a
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_6 0x000d
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_7 0x0010
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_8 0x0013
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_9 0x0016
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_10 0x001b
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_11 0xc003
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_12 0xc008
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_13 0xc00d
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_14 0xc012
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_15 0xc017
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_16 0xc01a
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_17 0xc01b
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_18 0xc01c
-
-#define OP_PCL_TLS12_DES40_CBC_MD5 0x0029
-
-#define OP_PCL_TLS12_DES_CBC_MD5 0x0022
-
-#define OP_PCL_TLS12_DES40_CBC_SHA 0x0008
-#define OP_PCL_TLS12_DES40_CBC_SHA_2 0x000b
-#define OP_PCL_TLS12_DES40_CBC_SHA_3 0x000e
-#define OP_PCL_TLS12_DES40_CBC_SHA_4 0x0011
-#define OP_PCL_TLS12_DES40_CBC_SHA_5 0x0014
-#define OP_PCL_TLS12_DES40_CBC_SHA_6 0x0019
-#define OP_PCL_TLS12_DES40_CBC_SHA_7 0x0026
-
-#define OP_PCL_TLS12_DES_CBC_SHA 0x001e
-#define OP_PCL_TLS12_DES_CBC_SHA_2 0x0009
-#define OP_PCL_TLS12_DES_CBC_SHA_3 0x000c
-#define OP_PCL_TLS12_DES_CBC_SHA_4 0x000f
-#define OP_PCL_TLS12_DES_CBC_SHA_5 0x0012
-#define OP_PCL_TLS12_DES_CBC_SHA_6 0x0015
-#define OP_PCL_TLS12_DES_CBC_SHA_7 0x001a
-
-#define OP_PCL_TLS12_RC4_128_MD5 0x0024
-#define OP_PCL_TLS12_RC4_128_MD5_2 0x0004
-#define OP_PCL_TLS12_RC4_128_MD5_3 0x0018
-
-#define OP_PCL_TLS12_RC4_40_MD5 0x002b
-#define OP_PCL_TLS12_RC4_40_MD5_2 0x0003
-#define OP_PCL_TLS12_RC4_40_MD5_3 0x0017
-
-#define OP_PCL_TLS12_RC4_128_SHA 0x0020
-#define OP_PCL_TLS12_RC4_128_SHA_2 0x008a
-#define OP_PCL_TLS12_RC4_128_SHA_3 0x008e
-#define OP_PCL_TLS12_RC4_128_SHA_4 0x0092
-#define OP_PCL_TLS12_RC4_128_SHA_5 0x0005
-#define OP_PCL_TLS12_RC4_128_SHA_6 0xc002
-#define OP_PCL_TLS12_RC4_128_SHA_7 0xc007
-#define OP_PCL_TLS12_RC4_128_SHA_8 0xc00c
-#define OP_PCL_TLS12_RC4_128_SHA_9 0xc011
-#define OP_PCL_TLS12_RC4_128_SHA_10 0xc016
-
-#define OP_PCL_TLS12_RC4_40_SHA 0x0028
-
-/* #define OP_PCL_TLS12_AES_128_CBC_SHA256 0x003c */
-#define OP_PCL_TLS12_AES_128_CBC_SHA256_2 0x003e
-#define OP_PCL_TLS12_AES_128_CBC_SHA256_3 0x003f
-#define OP_PCL_TLS12_AES_128_CBC_SHA256_4 0x0040
-#define OP_PCL_TLS12_AES_128_CBC_SHA256_5 0x0067
-#define OP_PCL_TLS12_AES_128_CBC_SHA256_6 0x006c
-
-/* #define OP_PCL_TLS12_AES_256_CBC_SHA256 0x003d */
-#define OP_PCL_TLS12_AES_256_CBC_SHA256_2 0x0068
-#define OP_PCL_TLS12_AES_256_CBC_SHA256_3 0x0069
-#define OP_PCL_TLS12_AES_256_CBC_SHA256_4 0x006a
-#define OP_PCL_TLS12_AES_256_CBC_SHA256_5 0x006b
-#define OP_PCL_TLS12_AES_256_CBC_SHA256_6 0x006d
+#define OP_PCL_TLS12_AES_128_CBC_SHA 0x002f
+#define OP_PCL_TLS12_AES_128_CBC_SHA_2 0x0030
+#define OP_PCL_TLS12_AES_128_CBC_SHA_3 0x0031
+#define OP_PCL_TLS12_AES_128_CBC_SHA_4 0x0032
+#define OP_PCL_TLS12_AES_128_CBC_SHA_5 0x0033
+#define OP_PCL_TLS12_AES_128_CBC_SHA_6 0x0034
+#define OP_PCL_TLS12_AES_128_CBC_SHA_7 0x008c
+#define OP_PCL_TLS12_AES_128_CBC_SHA_8 0x0090
+#define OP_PCL_TLS12_AES_128_CBC_SHA_9 0x0094
+#define OP_PCL_TLS12_AES_128_CBC_SHA_10 0xc004
+#define OP_PCL_TLS12_AES_128_CBC_SHA_11 0xc009
+#define OP_PCL_TLS12_AES_128_CBC_SHA_12 0xc00e
+#define OP_PCL_TLS12_AES_128_CBC_SHA_13 0xc013
+#define OP_PCL_TLS12_AES_128_CBC_SHA_14 0xc018
+#define OP_PCL_TLS12_AES_128_CBC_SHA_15 0xc01d
+#define OP_PCL_TLS12_AES_128_CBC_SHA_16 0xc01e
+#define OP_PCL_TLS12_AES_128_CBC_SHA_17 0xc01f
+
+#define OP_PCL_TLS12_AES_256_CBC_SHA 0x0035
+#define OP_PCL_TLS12_AES_256_CBC_SHA_2 0x0036
+#define OP_PCL_TLS12_AES_256_CBC_SHA_3 0x0037
+#define OP_PCL_TLS12_AES_256_CBC_SHA_4 0x0038
+#define OP_PCL_TLS12_AES_256_CBC_SHA_5 0x0039
+#define OP_PCL_TLS12_AES_256_CBC_SHA_6 0x003a
+#define OP_PCL_TLS12_AES_256_CBC_SHA_7 0x008d
+#define OP_PCL_TLS12_AES_256_CBC_SHA_8 0x0091
+#define OP_PCL_TLS12_AES_256_CBC_SHA_9 0x0095
+#define OP_PCL_TLS12_AES_256_CBC_SHA_10 0xc005
+#define OP_PCL_TLS12_AES_256_CBC_SHA_11 0xc00a
+#define OP_PCL_TLS12_AES_256_CBC_SHA_12 0xc00f
+#define OP_PCL_TLS12_AES_256_CBC_SHA_13 0xc014
+#define OP_PCL_TLS12_AES_256_CBC_SHA_14 0xc019
+#define OP_PCL_TLS12_AES_256_CBC_SHA_15 0xc020
+#define OP_PCL_TLS12_AES_256_CBC_SHA_16 0xc021
+#define OP_PCL_TLS12_AES_256_CBC_SHA_17 0xc022
+
+/* #define OP_PCL_TLS12_3DES_EDE_CBC_MD5 0x0023 */
+
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA 0x001f
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_2 0x008b
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_3 0x008f
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_4 0x0093
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_5 0x000a
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_6 0x000d
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_7 0x0010
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_8 0x0013
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_9 0x0016
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_10 0x001b
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_11 0xc003
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_12 0xc008
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_13 0xc00d
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_14 0xc012
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_15 0xc017
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_16 0xc01a
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_17 0xc01b
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_18 0xc01c
+
+#define OP_PCL_TLS12_DES40_CBC_MD5 0x0029
+
+#define OP_PCL_TLS12_DES_CBC_MD5 0x0022
+
+#define OP_PCL_TLS12_DES40_CBC_SHA 0x0008
+#define OP_PCL_TLS12_DES40_CBC_SHA_2 0x000b
+#define OP_PCL_TLS12_DES40_CBC_SHA_3 0x000e
+#define OP_PCL_TLS12_DES40_CBC_SHA_4 0x0011
+#define OP_PCL_TLS12_DES40_CBC_SHA_5 0x0014
+#define OP_PCL_TLS12_DES40_CBC_SHA_6 0x0019
+#define OP_PCL_TLS12_DES40_CBC_SHA_7 0x0026
+
+#define OP_PCL_TLS12_DES_CBC_SHA 0x001e
+#define OP_PCL_TLS12_DES_CBC_SHA_2 0x0009
+#define OP_PCL_TLS12_DES_CBC_SHA_3 0x000c
+#define OP_PCL_TLS12_DES_CBC_SHA_4 0x000f
+#define OP_PCL_TLS12_DES_CBC_SHA_5 0x0012
+#define OP_PCL_TLS12_DES_CBC_SHA_6 0x0015
+#define OP_PCL_TLS12_DES_CBC_SHA_7 0x001a
+
+#define OP_PCL_TLS12_RC4_128_MD5 0x0024
+#define OP_PCL_TLS12_RC4_128_MD5_2 0x0004
+#define OP_PCL_TLS12_RC4_128_MD5_3 0x0018
+
+#define OP_PCL_TLS12_RC4_40_MD5 0x002b
+#define OP_PCL_TLS12_RC4_40_MD5_2 0x0003
+#define OP_PCL_TLS12_RC4_40_MD5_3 0x0017
+
+#define OP_PCL_TLS12_RC4_128_SHA 0x0020
+#define OP_PCL_TLS12_RC4_128_SHA_2 0x008a
+#define OP_PCL_TLS12_RC4_128_SHA_3 0x008e
+#define OP_PCL_TLS12_RC4_128_SHA_4 0x0092
+#define OP_PCL_TLS12_RC4_128_SHA_5 0x0005
+#define OP_PCL_TLS12_RC4_128_SHA_6 0xc002
+#define OP_PCL_TLS12_RC4_128_SHA_7 0xc007
+#define OP_PCL_TLS12_RC4_128_SHA_8 0xc00c
+#define OP_PCL_TLS12_RC4_128_SHA_9 0xc011
+#define OP_PCL_TLS12_RC4_128_SHA_10 0xc016
+
+#define OP_PCL_TLS12_RC4_40_SHA 0x0028
+
+/* #define OP_PCL_TLS12_AES_128_CBC_SHA256 0x003c */
+#define OP_PCL_TLS12_AES_128_CBC_SHA256_2 0x003e
+#define OP_PCL_TLS12_AES_128_CBC_SHA256_3 0x003f
+#define OP_PCL_TLS12_AES_128_CBC_SHA256_4 0x0040
+#define OP_PCL_TLS12_AES_128_CBC_SHA256_5 0x0067
+#define OP_PCL_TLS12_AES_128_CBC_SHA256_6 0x006c
+
+/* #define OP_PCL_TLS12_AES_256_CBC_SHA256 0x003d */
+#define OP_PCL_TLS12_AES_256_CBC_SHA256_2 0x0068
+#define OP_PCL_TLS12_AES_256_CBC_SHA256_3 0x0069
+#define OP_PCL_TLS12_AES_256_CBC_SHA256_4 0x006a
+#define OP_PCL_TLS12_AES_256_CBC_SHA256_5 0x006b
+#define OP_PCL_TLS12_AES_256_CBC_SHA256_6 0x006d
/* AEAD_AES_xxx_CCM/GCM remain to be defined... */
-#define OP_PCL_TLS12_3DES_EDE_CBC_MD5 0xff23
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA160 0xff30
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA224 0xff34
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA256 0xff36
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA384 0xff33
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA512 0xff35
-#define OP_PCL_TLS12_AES_128_CBC_SHA160 0xff80
-#define OP_PCL_TLS12_AES_128_CBC_SHA224 0xff84
-#define OP_PCL_TLS12_AES_128_CBC_SHA256 0xff86
-#define OP_PCL_TLS12_AES_128_CBC_SHA384 0xff83
-#define OP_PCL_TLS12_AES_128_CBC_SHA512 0xff85
-#define OP_PCL_TLS12_AES_192_CBC_SHA160 0xff20
-#define OP_PCL_TLS12_AES_192_CBC_SHA224 0xff24
-#define OP_PCL_TLS12_AES_192_CBC_SHA256 0xff26
-#define OP_PCL_TLS12_AES_192_CBC_SHA384 0xff23
-#define OP_PCL_TLS12_AES_192_CBC_SHA512 0xff25
-#define OP_PCL_TLS12_AES_256_CBC_SHA160 0xff60
-#define OP_PCL_TLS12_AES_256_CBC_SHA224 0xff64
-#define OP_PCL_TLS12_AES_256_CBC_SHA256 0xff66
-#define OP_PCL_TLS12_AES_256_CBC_SHA384 0xff63
-#define OP_PCL_TLS12_AES_256_CBC_SHA512 0xff65
+#define OP_PCL_TLS12_3DES_EDE_CBC_MD5 0xff23
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA160 0xff30
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA224 0xff34
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA256 0xff36
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA384 0xff33
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA512 0xff35
+#define OP_PCL_TLS12_AES_128_CBC_SHA160 0xff80
+#define OP_PCL_TLS12_AES_128_CBC_SHA224 0xff84
+#define OP_PCL_TLS12_AES_128_CBC_SHA256 0xff86
+#define OP_PCL_TLS12_AES_128_CBC_SHA384 0xff83
+#define OP_PCL_TLS12_AES_128_CBC_SHA512 0xff85
+#define OP_PCL_TLS12_AES_192_CBC_SHA160 0xff20
+#define OP_PCL_TLS12_AES_192_CBC_SHA224 0xff24
+#define OP_PCL_TLS12_AES_192_CBC_SHA256 0xff26
+#define OP_PCL_TLS12_AES_192_CBC_SHA384 0xff23
+#define OP_PCL_TLS12_AES_192_CBC_SHA512 0xff25
+#define OP_PCL_TLS12_AES_256_CBC_SHA160 0xff60
+#define OP_PCL_TLS12_AES_256_CBC_SHA224 0xff64
+#define OP_PCL_TLS12_AES_256_CBC_SHA256 0xff66
+#define OP_PCL_TLS12_AES_256_CBC_SHA384 0xff63
+#define OP_PCL_TLS12_AES_256_CBC_SHA512 0xff65
/* For DTLS - OP_PCLID_DTLS */
-#define OP_PCL_DTLS_AES_128_CBC_SHA 0x002f
-#define OP_PCL_DTLS_AES_128_CBC_SHA_2 0x0030
-#define OP_PCL_DTLS_AES_128_CBC_SHA_3 0x0031
-#define OP_PCL_DTLS_AES_128_CBC_SHA_4 0x0032
-#define OP_PCL_DTLS_AES_128_CBC_SHA_5 0x0033
-#define OP_PCL_DTLS_AES_128_CBC_SHA_6 0x0034
-#define OP_PCL_DTLS_AES_128_CBC_SHA_7 0x008c
-#define OP_PCL_DTLS_AES_128_CBC_SHA_8 0x0090
-#define OP_PCL_DTLS_AES_128_CBC_SHA_9 0x0094
-#define OP_PCL_DTLS_AES_128_CBC_SHA_10 0xc004
-#define OP_PCL_DTLS_AES_128_CBC_SHA_11 0xc009
-#define OP_PCL_DTLS_AES_128_CBC_SHA_12 0xc00e
-#define OP_PCL_DTLS_AES_128_CBC_SHA_13 0xc013
-#define OP_PCL_DTLS_AES_128_CBC_SHA_14 0xc018
-#define OP_PCL_DTLS_AES_128_CBC_SHA_15 0xc01d
-#define OP_PCL_DTLS_AES_128_CBC_SHA_16 0xc01e
-#define OP_PCL_DTLS_AES_128_CBC_SHA_17 0xc01f
-
-#define OP_PCL_DTLS_AES_256_CBC_SHA 0x0035
-#define OP_PCL_DTLS_AES_256_CBC_SHA_2 0x0036
-#define OP_PCL_DTLS_AES_256_CBC_SHA_3 0x0037
-#define OP_PCL_DTLS_AES_256_CBC_SHA_4 0x0038
-#define OP_PCL_DTLS_AES_256_CBC_SHA_5 0x0039
-#define OP_PCL_DTLS_AES_256_CBC_SHA_6 0x003a
-#define OP_PCL_DTLS_AES_256_CBC_SHA_7 0x008d
-#define OP_PCL_DTLS_AES_256_CBC_SHA_8 0x0091
-#define OP_PCL_DTLS_AES_256_CBC_SHA_9 0x0095
-#define OP_PCL_DTLS_AES_256_CBC_SHA_10 0xc005
-#define OP_PCL_DTLS_AES_256_CBC_SHA_11 0xc00a
-#define OP_PCL_DTLS_AES_256_CBC_SHA_12 0xc00f
-#define OP_PCL_DTLS_AES_256_CBC_SHA_13 0xc014
-#define OP_PCL_DTLS_AES_256_CBC_SHA_14 0xc019
-#define OP_PCL_DTLS_AES_256_CBC_SHA_15 0xc020
-#define OP_PCL_DTLS_AES_256_CBC_SHA_16 0xc021
-#define OP_PCL_DTLS_AES_256_CBC_SHA_17 0xc022
-
-/* #define OP_PCL_DTLS_3DES_EDE_CBC_MD5 0x0023 */
-
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA 0x001f
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_2 0x008b
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_3 0x008f
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_4 0x0093
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_5 0x000a
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_6 0x000d
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_7 0x0010
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_8 0x0013
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_9 0x0016
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_10 0x001b
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_11 0xc003
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_12 0xc008
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_13 0xc00d
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_14 0xc012
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_15 0xc017
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_16 0xc01a
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_17 0xc01b
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_18 0xc01c
-
-#define OP_PCL_DTLS_DES40_CBC_MD5 0x0029
-
-#define OP_PCL_DTLS_DES_CBC_MD5 0x0022
-
-#define OP_PCL_DTLS_DES40_CBC_SHA 0x0008
-#define OP_PCL_DTLS_DES40_CBC_SHA_2 0x000b
-#define OP_PCL_DTLS_DES40_CBC_SHA_3 0x000e
-#define OP_PCL_DTLS_DES40_CBC_SHA_4 0x0011
-#define OP_PCL_DTLS_DES40_CBC_SHA_5 0x0014
-#define OP_PCL_DTLS_DES40_CBC_SHA_6 0x0019
-#define OP_PCL_DTLS_DES40_CBC_SHA_7 0x0026
-
-
-#define OP_PCL_DTLS_DES_CBC_SHA 0x001e
-#define OP_PCL_DTLS_DES_CBC_SHA_2 0x0009
-#define OP_PCL_DTLS_DES_CBC_SHA_3 0x000c
-#define OP_PCL_DTLS_DES_CBC_SHA_4 0x000f
-#define OP_PCL_DTLS_DES_CBC_SHA_5 0x0012
-#define OP_PCL_DTLS_DES_CBC_SHA_6 0x0015
-#define OP_PCL_DTLS_DES_CBC_SHA_7 0x001a
-
-
-#define OP_PCL_DTLS_3DES_EDE_CBC_MD5 0xff23
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA160 0xff30
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA224 0xff34
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA256 0xff36
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA384 0xff33
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA512 0xff35
-#define OP_PCL_DTLS_AES_128_CBC_SHA160 0xff80
-#define OP_PCL_DTLS_AES_128_CBC_SHA224 0xff84
-#define OP_PCL_DTLS_AES_128_CBC_SHA256 0xff86
-#define OP_PCL_DTLS_AES_128_CBC_SHA384 0xff83
-#define OP_PCL_DTLS_AES_128_CBC_SHA512 0xff85
-#define OP_PCL_DTLS_AES_192_CBC_SHA160 0xff20
-#define OP_PCL_DTLS_AES_192_CBC_SHA224 0xff24
-#define OP_PCL_DTLS_AES_192_CBC_SHA256 0xff26
-#define OP_PCL_DTLS_AES_192_CBC_SHA384 0xff23
-#define OP_PCL_DTLS_AES_192_CBC_SHA512 0xff25
-#define OP_PCL_DTLS_AES_256_CBC_SHA160 0xff60
-#define OP_PCL_DTLS_AES_256_CBC_SHA224 0xff64
-#define OP_PCL_DTLS_AES_256_CBC_SHA256 0xff66
-#define OP_PCL_DTLS_AES_256_CBC_SHA384 0xff63
-#define OP_PCL_DTLS_AES_256_CBC_SHA512 0xff65
+#define OP_PCL_DTLS_AES_128_CBC_SHA 0x002f
+#define OP_PCL_DTLS_AES_128_CBC_SHA_2 0x0030
+#define OP_PCL_DTLS_AES_128_CBC_SHA_3 0x0031
+#define OP_PCL_DTLS_AES_128_CBC_SHA_4 0x0032
+#define OP_PCL_DTLS_AES_128_CBC_SHA_5 0x0033
+#define OP_PCL_DTLS_AES_128_CBC_SHA_6 0x0034
+#define OP_PCL_DTLS_AES_128_CBC_SHA_7 0x008c
+#define OP_PCL_DTLS_AES_128_CBC_SHA_8 0x0090
+#define OP_PCL_DTLS_AES_128_CBC_SHA_9 0x0094
+#define OP_PCL_DTLS_AES_128_CBC_SHA_10 0xc004
+#define OP_PCL_DTLS_AES_128_CBC_SHA_11 0xc009
+#define OP_PCL_DTLS_AES_128_CBC_SHA_12 0xc00e
+#define OP_PCL_DTLS_AES_128_CBC_SHA_13 0xc013
+#define OP_PCL_DTLS_AES_128_CBC_SHA_14 0xc018
+#define OP_PCL_DTLS_AES_128_CBC_SHA_15 0xc01d
+#define OP_PCL_DTLS_AES_128_CBC_SHA_16 0xc01e
+#define OP_PCL_DTLS_AES_128_CBC_SHA_17 0xc01f
+
+#define OP_PCL_DTLS_AES_256_CBC_SHA 0x0035
+#define OP_PCL_DTLS_AES_256_CBC_SHA_2 0x0036
+#define OP_PCL_DTLS_AES_256_CBC_SHA_3 0x0037
+#define OP_PCL_DTLS_AES_256_CBC_SHA_4 0x0038
+#define OP_PCL_DTLS_AES_256_CBC_SHA_5 0x0039
+#define OP_PCL_DTLS_AES_256_CBC_SHA_6 0x003a
+#define OP_PCL_DTLS_AES_256_CBC_SHA_7 0x008d
+#define OP_PCL_DTLS_AES_256_CBC_SHA_8 0x0091
+#define OP_PCL_DTLS_AES_256_CBC_SHA_9 0x0095
+#define OP_PCL_DTLS_AES_256_CBC_SHA_10 0xc005
+#define OP_PCL_DTLS_AES_256_CBC_SHA_11 0xc00a
+#define OP_PCL_DTLS_AES_256_CBC_SHA_12 0xc00f
+#define OP_PCL_DTLS_AES_256_CBC_SHA_13 0xc014
+#define OP_PCL_DTLS_AES_256_CBC_SHA_14 0xc019
+#define OP_PCL_DTLS_AES_256_CBC_SHA_15 0xc020
+#define OP_PCL_DTLS_AES_256_CBC_SHA_16 0xc021
+#define OP_PCL_DTLS_AES_256_CBC_SHA_17 0xc022
+
+/* #define OP_PCL_DTLS_3DES_EDE_CBC_MD5 0x0023 */
+
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA 0x001f
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_2 0x008b
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_3 0x008f
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_4 0x0093
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_5 0x000a
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_6 0x000d
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_7 0x0010
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_8 0x0013
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_9 0x0016
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_10 0x001b
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_11 0xc003
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_12 0xc008
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_13 0xc00d
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_14 0xc012
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_15 0xc017
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_16 0xc01a
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_17 0xc01b
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_18 0xc01c
+
+#define OP_PCL_DTLS_DES40_CBC_MD5 0x0029
+
+#define OP_PCL_DTLS_DES_CBC_MD5 0x0022
+
+#define OP_PCL_DTLS_DES40_CBC_SHA 0x0008
+#define OP_PCL_DTLS_DES40_CBC_SHA_2 0x000b
+#define OP_PCL_DTLS_DES40_CBC_SHA_3 0x000e
+#define OP_PCL_DTLS_DES40_CBC_SHA_4 0x0011
+#define OP_PCL_DTLS_DES40_CBC_SHA_5 0x0014
+#define OP_PCL_DTLS_DES40_CBC_SHA_6 0x0019
+#define OP_PCL_DTLS_DES40_CBC_SHA_7 0x0026
+
+
+#define OP_PCL_DTLS_DES_CBC_SHA 0x001e
+#define OP_PCL_DTLS_DES_CBC_SHA_2 0x0009
+#define OP_PCL_DTLS_DES_CBC_SHA_3 0x000c
+#define OP_PCL_DTLS_DES_CBC_SHA_4 0x000f
+#define OP_PCL_DTLS_DES_CBC_SHA_5 0x0012
+#define OP_PCL_DTLS_DES_CBC_SHA_6 0x0015
+#define OP_PCL_DTLS_DES_CBC_SHA_7 0x001a
+
+
+#define OP_PCL_DTLS_3DES_EDE_CBC_MD5 0xff23
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA160 0xff30
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA224 0xff34
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA256 0xff36
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA384 0xff33
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA512 0xff35
+#define OP_PCL_DTLS_AES_128_CBC_SHA160 0xff80
+#define OP_PCL_DTLS_AES_128_CBC_SHA224 0xff84
+#define OP_PCL_DTLS_AES_128_CBC_SHA256 0xff86
+#define OP_PCL_DTLS_AES_128_CBC_SHA384 0xff83
+#define OP_PCL_DTLS_AES_128_CBC_SHA512 0xff85
+#define OP_PCL_DTLS_AES_192_CBC_SHA160 0xff20
+#define OP_PCL_DTLS_AES_192_CBC_SHA224 0xff24
+#define OP_PCL_DTLS_AES_192_CBC_SHA256 0xff26
+#define OP_PCL_DTLS_AES_192_CBC_SHA384 0xff23
+#define OP_PCL_DTLS_AES_192_CBC_SHA512 0xff25
+#define OP_PCL_DTLS_AES_256_CBC_SHA160 0xff60
+#define OP_PCL_DTLS_AES_256_CBC_SHA224 0xff64
+#define OP_PCL_DTLS_AES_256_CBC_SHA256 0xff66
+#define OP_PCL_DTLS_AES_256_CBC_SHA384 0xff63
+#define OP_PCL_DTLS_AES_256_CBC_SHA512 0xff65
/* 802.16 WiMAX protinfos */
-#define OP_PCL_WIMAX_OFDM 0x0201
-#define OP_PCL_WIMAX_OFDMA 0x0231
+#define OP_PCL_WIMAX_OFDM 0x0201
+#define OP_PCL_WIMAX_OFDMA 0x0231
/* 802.11 WiFi protinfos */
-#define OP_PCL_WIFI 0xac04
+#define OP_PCL_WIFI 0xac04
/* MacSec protinfos */
-#define OP_PCL_MACSEC 0x0001
+#define OP_PCL_MACSEC 0x0001
/* PKI unidirectional protocol protinfo bits */
-#define OP_PCL_PKPROT_TEST 0x0008
-#define OP_PCL_PKPROT_DECRYPT 0x0004
-#define OP_PCL_PKPROT_ECC 0x0002
-#define OP_PCL_PKPROT_F2M 0x0001
+#define OP_PCL_PKPROT_TEST 0x0008
+#define OP_PCL_PKPROT_DECRYPT 0x0004
+#define OP_PCL_PKPROT_ECC 0x0002
+#define OP_PCL_PKPROT_F2M 0x0001
/* For non-protocol/alg-only op commands */
#define OP_ALG_TYPE_SHIFT 24
@@ -1162,6 +1187,11 @@
#define OP_ALG_AAI_GSM (0x10 << OP_ALG_AAI_SHIFT)
#define OP_ALG_AAI_EDGE (0x20 << OP_ALG_AAI_SHIFT)
+/* RNG4 set */
+#define OP_ALG_RNG4_SHIFT 4
+#define OP_ALG_RNG4_MASK (0x1f3 << OP_ALG_RNG4_SHIFT)
+
+#define OP_ALG_RNG4_SK (0x100 << OP_ALG_RNG4_SHIFT)
#define OP_ALG_AS_SHIFT 2
#define OP_ALG_AS_MASK (0x3 << OP_ALG_AS_SHIFT)
@@ -1181,114 +1211,114 @@
#define OP_ALG_ENCRYPT 1
/* PKHA algorithm type set */
-#define OP_ALG_PK 0x00800000
-#define OP_ALG_PK_FUN_MASK 0x3f /* clrmem, modmath, or cpymem */
+#define OP_ALG_PK 0x00800000
+#define OP_ALG_PK_FUN_MASK 0x3f /* clrmem, modmath, or cpymem */
/* PKHA mode clear memory functions */
-#define OP_ALG_PKMODE_A_RAM 0x80000
-#define OP_ALG_PKMODE_B_RAM 0x40000
-#define OP_ALG_PKMODE_E_RAM 0x20000
-#define OP_ALG_PKMODE_N_RAM 0x10000
-#define OP_ALG_PKMODE_CLEARMEM 0x00001
+#define OP_ALG_PKMODE_A_RAM 0x80000
+#define OP_ALG_PKMODE_B_RAM 0x40000
+#define OP_ALG_PKMODE_E_RAM 0x20000
+#define OP_ALG_PKMODE_N_RAM 0x10000
+#define OP_ALG_PKMODE_CLEARMEM 0x00001
/* PKHA mode modular-arithmetic functions */
-#define OP_ALG_PKMODE_MOD_IN_MONTY 0x80000
-#define OP_ALG_PKMODE_MOD_OUT_MONTY 0x40000
-#define OP_ALG_PKMODE_MOD_F2M 0x20000
-#define OP_ALG_PKMODE_MOD_R2_IN 0x10000
-#define OP_ALG_PKMODE_PRJECTV 0x00800
-#define OP_ALG_PKMODE_TIME_EQ 0x400
-#define OP_ALG_PKMODE_OUT_B 0x000
-#define OP_ALG_PKMODE_OUT_A 0x100
-#define OP_ALG_PKMODE_MOD_ADD 0x002
-#define OP_ALG_PKMODE_MOD_SUB_AB 0x003
-#define OP_ALG_PKMODE_MOD_SUB_BA 0x004
-#define OP_ALG_PKMODE_MOD_MULT 0x005
-#define OP_ALG_PKMODE_MOD_EXPO 0x006
-#define OP_ALG_PKMODE_MOD_REDUCT 0x007
-#define OP_ALG_PKMODE_MOD_INV 0x008
-#define OP_ALG_PKMODE_MOD_ECC_ADD 0x009
-#define OP_ALG_PKMODE_MOD_ECC_DBL 0x00a
-#define OP_ALG_PKMODE_MOD_ECC_MULT 0x00b
-#define OP_ALG_PKMODE_MOD_MONT_CNST 0x00c
-#define OP_ALG_PKMODE_MOD_CRT_CNST 0x00d
-#define OP_ALG_PKMODE_MOD_GCD 0x00e
-#define OP_ALG_PKMODE_MOD_PRIMALITY 0x00f
+#define OP_ALG_PKMODE_MOD_IN_MONTY 0x80000
+#define OP_ALG_PKMODE_MOD_OUT_MONTY 0x40000
+#define OP_ALG_PKMODE_MOD_F2M 0x20000
+#define OP_ALG_PKMODE_MOD_R2_IN 0x10000
+#define OP_ALG_PKMODE_PRJECTV 0x00800
+#define OP_ALG_PKMODE_TIME_EQ 0x400
+#define OP_ALG_PKMODE_OUT_B 0x000
+#define OP_ALG_PKMODE_OUT_A 0x100
+#define OP_ALG_PKMODE_MOD_ADD 0x002
+#define OP_ALG_PKMODE_MOD_SUB_AB 0x003
+#define OP_ALG_PKMODE_MOD_SUB_BA 0x004
+#define OP_ALG_PKMODE_MOD_MULT 0x005
+#define OP_ALG_PKMODE_MOD_EXPO 0x006
+#define OP_ALG_PKMODE_MOD_REDUCT 0x007
+#define OP_ALG_PKMODE_MOD_INV 0x008
+#define OP_ALG_PKMODE_MOD_ECC_ADD 0x009
+#define OP_ALG_PKMODE_MOD_ECC_DBL 0x00a
+#define OP_ALG_PKMODE_MOD_ECC_MULT 0x00b
+#define OP_ALG_PKMODE_MOD_MONT_CNST 0x00c
+#define OP_ALG_PKMODE_MOD_CRT_CNST 0x00d
+#define OP_ALG_PKMODE_MOD_GCD 0x00e
+#define OP_ALG_PKMODE_MOD_PRIMALITY 0x00f
/* PKHA mode copy-memory functions */
-#define OP_ALG_PKMODE_SRC_REG_SHIFT 13
-#define OP_ALG_PKMODE_SRC_REG_MASK (7 << OP_ALG_PKMODE_SRC_REG_SHIFT)
-#define OP_ALG_PKMODE_DST_REG_SHIFT 10
-#define OP_ALG_PKMODE_DST_REG_MASK (7 << OP_ALG_PKMODE_DST_REG_SHIFT)
-#define OP_ALG_PKMODE_SRC_SEG_SHIFT 8
-#define OP_ALG_PKMODE_SRC_SEG_MASK (3 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
-#define OP_ALG_PKMODE_DST_SEG_SHIFT 6
-#define OP_ALG_PKMODE_DST_SEG_MASK (3 << OP_ALG_PKMODE_DST_SEG_SHIFT)
-
-#define OP_ALG_PKMODE_SRC_REG_A (0 << OP_ALG_PKMODE_SRC_REG_SHIFT)
-#define OP_ALG_PKMODE_SRC_REG_B (1 << OP_ALG_PKMODE_SRC_REG_SHIFT)
-#define OP_ALG_PKMODE_SRC_REG_N (3 << OP_ALG_PKMODE_SRC_REG_SHIFT)
-#define OP_ALG_PKMODE_DST_REG_A (0 << OP_ALG_PKMODE_DST_REG_SHIFT)
-#define OP_ALG_PKMODE_DST_REG_B (1 << OP_ALG_PKMODE_DST_REG_SHIFT)
-#define OP_ALG_PKMODE_DST_REG_E (2 << OP_ALG_PKMODE_DST_REG_SHIFT)
-#define OP_ALG_PKMODE_DST_REG_N (3 << OP_ALG_PKMODE_DST_REG_SHIFT)
-#define OP_ALG_PKMODE_SRC_SEG_0 (0 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
-#define OP_ALG_PKMODE_SRC_SEG_1 (1 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
-#define OP_ALG_PKMODE_SRC_SEG_2 (2 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
-#define OP_ALG_PKMODE_SRC_SEG_3 (3 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
-#define OP_ALG_PKMODE_DST_SEG_0 (0 << OP_ALG_PKMODE_DST_SEG_SHIFT)
-#define OP_ALG_PKMODE_DST_SEG_1 (1 << OP_ALG_PKMODE_DST_SEG_SHIFT)
-#define OP_ALG_PKMODE_DST_SEG_2 (2 << OP_ALG_PKMODE_DST_SEG_SHIFT)
-#define OP_ALG_PKMODE_DST_SEG_3 (3 << OP_ALG_PKMODE_DST_SEG_SHIFT)
-#define OP_ALG_PKMODE_CPYMEM_N_SZ 0x80
-#define OP_ALG_PKMODE_CPYMEM_SRC_SZ 0x81
+#define OP_ALG_PKMODE_SRC_REG_SHIFT 13
+#define OP_ALG_PKMODE_SRC_REG_MASK (7 << OP_ALG_PKMODE_SRC_REG_SHIFT)
+#define OP_ALG_PKMODE_DST_REG_SHIFT 10
+#define OP_ALG_PKMODE_DST_REG_MASK (7 << OP_ALG_PKMODE_DST_REG_SHIFT)
+#define OP_ALG_PKMODE_SRC_SEG_SHIFT 8
+#define OP_ALG_PKMODE_SRC_SEG_MASK (3 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
+#define OP_ALG_PKMODE_DST_SEG_SHIFT 6
+#define OP_ALG_PKMODE_DST_SEG_MASK (3 << OP_ALG_PKMODE_DST_SEG_SHIFT)
+
+#define OP_ALG_PKMODE_SRC_REG_A (0 << OP_ALG_PKMODE_SRC_REG_SHIFT)
+#define OP_ALG_PKMODE_SRC_REG_B (1 << OP_ALG_PKMODE_SRC_REG_SHIFT)
+#define OP_ALG_PKMODE_SRC_REG_N (3 << OP_ALG_PKMODE_SRC_REG_SHIFT)
+#define OP_ALG_PKMODE_DST_REG_A (0 << OP_ALG_PKMODE_DST_REG_SHIFT)
+#define OP_ALG_PKMODE_DST_REG_B (1 << OP_ALG_PKMODE_DST_REG_SHIFT)
+#define OP_ALG_PKMODE_DST_REG_E (2 << OP_ALG_PKMODE_DST_REG_SHIFT)
+#define OP_ALG_PKMODE_DST_REG_N (3 << OP_ALG_PKMODE_DST_REG_SHIFT)
+#define OP_ALG_PKMODE_SRC_SEG_0 (0 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
+#define OP_ALG_PKMODE_SRC_SEG_1 (1 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
+#define OP_ALG_PKMODE_SRC_SEG_2 (2 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
+#define OP_ALG_PKMODE_SRC_SEG_3 (3 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
+#define OP_ALG_PKMODE_DST_SEG_0 (0 << OP_ALG_PKMODE_DST_SEG_SHIFT)
+#define OP_ALG_PKMODE_DST_SEG_1 (1 << OP_ALG_PKMODE_DST_SEG_SHIFT)
+#define OP_ALG_PKMODE_DST_SEG_2 (2 << OP_ALG_PKMODE_DST_SEG_SHIFT)
+#define OP_ALG_PKMODE_DST_SEG_3 (3 << OP_ALG_PKMODE_DST_SEG_SHIFT)
+#define OP_ALG_PKMODE_CPYMEM_N_SZ 0x80
+#define OP_ALG_PKMODE_CPYMEM_SRC_SZ 0x81
/*
* SEQ_IN_PTR Command Constructs
*/
/* Release Buffers */
-#define SQIN_RBS 0x04000000
+#define SQIN_RBS 0x04000000
/* Sequence pointer is really a descriptor */
-#define SQIN_INL 0x02000000
+#define SQIN_INL 0x02000000
/* Sequence pointer is a scatter-gather table */
-#define SQIN_SGF 0x01000000
+#define SQIN_SGF 0x01000000
/* Appends to a previous pointer */
-#define SQIN_PRE 0x00800000
+#define SQIN_PRE 0x00800000
/* Use extended length following pointer */
-#define SQIN_EXT 0x00400000
+#define SQIN_EXT 0x00400000
/* Restore sequence with pointer/length */
-#define SQIN_RTO 0x00200000
+#define SQIN_RTO 0x00200000
/* Replace job descriptor */
-#define SQIN_RJD 0x00100000
+#define SQIN_RJD 0x00100000
-#define SQIN_LEN_SHIFT 0
-#define SQIN_LEN_MASK (0xffff << SQIN_LEN_SHIFT)
+#define SQIN_LEN_SHIFT 0
+#define SQIN_LEN_MASK (0xffff << SQIN_LEN_SHIFT)
/*
* SEQ_OUT_PTR Command Constructs
*/
/* Sequence pointer is a scatter-gather table */
-#define SQOUT_SGF 0x01000000
+#define SQOUT_SGF 0x01000000
/* Appends to a previous pointer */
-#define SQOUT_PRE 0x00800000
+#define SQOUT_PRE 0x00800000
/* Restore sequence with pointer/length */
-#define SQOUT_RTO 0x00200000
+#define SQOUT_RTO 0x00200000
/* Use extended length following pointer */
-#define SQOUT_EXT 0x00400000
+#define SQOUT_EXT 0x00400000
-#define SQOUT_LEN_SHIFT 0
-#define SQOUT_LEN_MASK (0xffff << SQOUT_LEN_SHIFT)
+#define SQOUT_LEN_SHIFT 0
+#define SQOUT_LEN_MASK (0xffff << SQOUT_LEN_SHIFT)
/*
@@ -1296,196 +1326,196 @@
*/
/* TYPE field is all that's relevant */
-#define SIGN_TYPE_SHIFT 16
-#define SIGN_TYPE_MASK (0x0f << SIGN_TYPE_SHIFT)
+#define SIGN_TYPE_SHIFT 16
+#define SIGN_TYPE_MASK (0x0f << SIGN_TYPE_SHIFT)
-#define SIGN_TYPE_FINAL (0x00 << SIGN_TYPE_SHIFT)
+#define SIGN_TYPE_FINAL (0x00 << SIGN_TYPE_SHIFT)
#define SIGN_TYPE_FINAL_RESTORE (0x01 << SIGN_TYPE_SHIFT)
#define SIGN_TYPE_FINAL_NONZERO (0x02 << SIGN_TYPE_SHIFT)
-#define SIGN_TYPE_IMM_2 (0x0a << SIGN_TYPE_SHIFT)
-#define SIGN_TYPE_IMM_3 (0x0b << SIGN_TYPE_SHIFT)
-#define SIGN_TYPE_IMM_4 (0x0c << SIGN_TYPE_SHIFT)
+#define SIGN_TYPE_IMM_2 (0x0a << SIGN_TYPE_SHIFT)
+#define SIGN_TYPE_IMM_3 (0x0b << SIGN_TYPE_SHIFT)
+#define SIGN_TYPE_IMM_4 (0x0c << SIGN_TYPE_SHIFT)
/*
* MOVE Command Constructs
*/
-#define MOVE_AUX_SHIFT 25
-#define MOVE_AUX_MASK (3 << MOVE_AUX_SHIFT)
-#define MOVE_AUX_MS (2 << MOVE_AUX_SHIFT)
-#define MOVE_AUX_LS (1 << MOVE_AUX_SHIFT)
-
-#define MOVE_WAITCOMP_SHIFT 24
-#define MOVE_WAITCOMP_MASK (1 << MOVE_WAITCOMP_SHIFT)
-#define MOVE_WAITCOMP (1 << MOVE_WAITCOMP_SHIFT)
-
-#define MOVE_SRC_SHIFT 20
-#define MOVE_SRC_MASK (0x0f << MOVE_SRC_SHIFT)
-#define MOVE_SRC_CLASS1CTX (0x00 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_CLASS2CTX (0x01 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_OUTFIFO (0x02 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_DESCBUF (0x03 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_MATH0 (0x04 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_MATH1 (0x05 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_MATH2 (0x06 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_MATH3 (0x07 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_INFIFO (0x08 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_INFIFO_CL (0x09 << MOVE_SRC_SHIFT)
-
-#define MOVE_DEST_SHIFT 16
-#define MOVE_DEST_MASK (0x0f << MOVE_DEST_SHIFT)
-#define MOVE_DEST_CLASS1CTX (0x00 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_CLASS2CTX (0x01 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_OUTFIFO (0x02 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_DESCBUF (0x03 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_MATH0 (0x04 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_MATH1 (0x05 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_MATH2 (0x06 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_MATH3 (0x07 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_CLASS1INFIFO (0x08 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_CLASS2INFIFO (0x09 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_PK_A (0x0c << MOVE_DEST_SHIFT)
-#define MOVE_DEST_CLASS1KEY (0x0d << MOVE_DEST_SHIFT)
-#define MOVE_DEST_CLASS2KEY (0x0e << MOVE_DEST_SHIFT)
-
-#define MOVE_OFFSET_SHIFT 8
-#define MOVE_OFFSET_MASK (0xff << MOVE_OFFSET_SHIFT)
-
-#define MOVE_LEN_SHIFT 0
-#define MOVE_LEN_MASK (0xff << MOVE_LEN_SHIFT)
-
-#define MOVELEN_MRSEL_SHIFT 0
-#define MOVELEN_MRSEL_MASK (0x3 << MOVE_LEN_SHIFT)
+#define MOVE_AUX_SHIFT 25
+#define MOVE_AUX_MASK (3 << MOVE_AUX_SHIFT)
+#define MOVE_AUX_MS (2 << MOVE_AUX_SHIFT)
+#define MOVE_AUX_LS (1 << MOVE_AUX_SHIFT)
+
+#define MOVE_WAITCOMP_SHIFT 24
+#define MOVE_WAITCOMP_MASK (1 << MOVE_WAITCOMP_SHIFT)
+#define MOVE_WAITCOMP (1 << MOVE_WAITCOMP_SHIFT)
+
+#define MOVE_SRC_SHIFT 20
+#define MOVE_SRC_MASK (0x0f << MOVE_SRC_SHIFT)
+#define MOVE_SRC_CLASS1CTX (0x00 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_CLASS2CTX (0x01 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_OUTFIFO (0x02 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_DESCBUF (0x03 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_MATH0 (0x04 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_MATH1 (0x05 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_MATH2 (0x06 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_MATH3 (0x07 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_INFIFO (0x08 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_INFIFO_CL (0x09 << MOVE_SRC_SHIFT)
+
+#define MOVE_DEST_SHIFT 16
+#define MOVE_DEST_MASK (0x0f << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS1CTX (0x00 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS2CTX (0x01 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_OUTFIFO (0x02 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_DESCBUF (0x03 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_MATH0 (0x04 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_MATH1 (0x05 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_MATH2 (0x06 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_MATH3 (0x07 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS1INFIFO (0x08 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS2INFIFO (0x09 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_PK_A (0x0c << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS1KEY (0x0d << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS2KEY (0x0e << MOVE_DEST_SHIFT)
+
+#define MOVE_OFFSET_SHIFT 8
+#define MOVE_OFFSET_MASK (0xff << MOVE_OFFSET_SHIFT)
+
+#define MOVE_LEN_SHIFT 0
+#define MOVE_LEN_MASK (0xff << MOVE_LEN_SHIFT)
+
+#define MOVELEN_MRSEL_SHIFT 0
+#define MOVELEN_MRSEL_MASK (0x3 << MOVE_LEN_SHIFT)
/*
* MATH Command Constructs
*/
-#define MATH_IFB_SHIFT 26
-#define MATH_IFB_MASK (1 << MATH_IFB_SHIFT)
-#define MATH_IFB (1 << MATH_IFB_SHIFT)
+#define MATH_IFB_SHIFT 26
+#define MATH_IFB_MASK (1 << MATH_IFB_SHIFT)
+#define MATH_IFB (1 << MATH_IFB_SHIFT)
-#define MATH_NFU_SHIFT 25
-#define MATH_NFU_MASK (1 << MATH_NFU_SHIFT)
-#define MATH_NFU (1 << MATH_NFU_SHIFT)
+#define MATH_NFU_SHIFT 25
+#define MATH_NFU_MASK (1 << MATH_NFU_SHIFT)
+#define MATH_NFU (1 << MATH_NFU_SHIFT)
-#define MATH_STL_SHIFT 24
-#define MATH_STL_MASK (1 << MATH_STL_SHIFT)
-#define MATH_STL (1 << MATH_STL_SHIFT)
+#define MATH_STL_SHIFT 24
+#define MATH_STL_MASK (1 << MATH_STL_SHIFT)
+#define MATH_STL (1 << MATH_STL_SHIFT)
/* Function selectors */
-#define MATH_FUN_SHIFT 20
-#define MATH_FUN_MASK (0x0f << MATH_FUN_SHIFT)
-#define MATH_FUN_ADD (0x00 << MATH_FUN_SHIFT)
-#define MATH_FUN_ADDC (0x01 << MATH_FUN_SHIFT)
-#define MATH_FUN_SUB (0x02 << MATH_FUN_SHIFT)
-#define MATH_FUN_SUBB (0x03 << MATH_FUN_SHIFT)
-#define MATH_FUN_OR (0x04 << MATH_FUN_SHIFT)
-#define MATH_FUN_AND (0x05 << MATH_FUN_SHIFT)
-#define MATH_FUN_XOR (0x06 << MATH_FUN_SHIFT)
-#define MATH_FUN_LSHIFT (0x07 << MATH_FUN_SHIFT)
-#define MATH_FUN_RSHIFT (0x08 << MATH_FUN_SHIFT)
-#define MATH_FUN_SHLD (0x09 << MATH_FUN_SHIFT)
-#define MATH_FUN_ZBYT (0x0a << MATH_FUN_SHIFT)
+#define MATH_FUN_SHIFT 20
+#define MATH_FUN_MASK (0x0f << MATH_FUN_SHIFT)
+#define MATH_FUN_ADD (0x00 << MATH_FUN_SHIFT)
+#define MATH_FUN_ADDC (0x01 << MATH_FUN_SHIFT)
+#define MATH_FUN_SUB (0x02 << MATH_FUN_SHIFT)
+#define MATH_FUN_SUBB (0x03 << MATH_FUN_SHIFT)
+#define MATH_FUN_OR (0x04 << MATH_FUN_SHIFT)
+#define MATH_FUN_AND (0x05 << MATH_FUN_SHIFT)
+#define MATH_FUN_XOR (0x06 << MATH_FUN_SHIFT)
+#define MATH_FUN_LSHIFT (0x07 << MATH_FUN_SHIFT)
+#define MATH_FUN_RSHIFT (0x08 << MATH_FUN_SHIFT)
+#define MATH_FUN_SHLD (0x09 << MATH_FUN_SHIFT)
+#define MATH_FUN_ZBYT (0x0a << MATH_FUN_SHIFT)
/* Source 0 selectors */
-#define MATH_SRC0_SHIFT 16
-#define MATH_SRC0_MASK (0x0f << MATH_SRC0_SHIFT)
-#define MATH_SRC0_REG0 (0x00 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_REG1 (0x01 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_REG2 (0x02 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_REG3 (0x03 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_IMM (0x04 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_SEQINLEN (0x08 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_SEQOUTLEN (0x09 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_VARSEQINLEN (0x0a << MATH_SRC0_SHIFT)
-#define MATH_SRC0_VARSEQOUTLEN (0x0b << MATH_SRC0_SHIFT)
-#define MATH_SRC0_ZERO (0x0c << MATH_SRC0_SHIFT)
+#define MATH_SRC0_SHIFT 16
+#define MATH_SRC0_MASK (0x0f << MATH_SRC0_SHIFT)
+#define MATH_SRC0_REG0 (0x00 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_REG1 (0x01 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_REG2 (0x02 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_REG3 (0x03 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_IMM (0x04 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_SEQINLEN (0x08 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_SEQOUTLEN (0x09 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_VARSEQINLEN (0x0a << MATH_SRC0_SHIFT)
+#define MATH_SRC0_VARSEQOUTLEN (0x0b << MATH_SRC0_SHIFT)
+#define MATH_SRC0_ZERO (0x0c << MATH_SRC0_SHIFT)
/* Source 1 selectors */
-#define MATH_SRC1_SHIFT 12
-#define MATH_SRC1_MASK (0x0f << MATH_SRC1_SHIFT)
-#define MATH_SRC1_REG0 (0x00 << MATH_SRC1_SHIFT)
-#define MATH_SRC1_REG1 (0x01 << MATH_SRC1_SHIFT)
-#define MATH_SRC1_REG2 (0x02 << MATH_SRC1_SHIFT)
-#define MATH_SRC1_REG3 (0x03 << MATH_SRC1_SHIFT)
-#define MATH_SRC1_IMM (0x04 << MATH_SRC1_SHIFT)
-#define MATH_SRC1_INFIFO (0x0a << MATH_SRC1_SHIFT)
-#define MATH_SRC1_OUTFIFO (0x0b << MATH_SRC1_SHIFT)
-#define MATH_SRC1_ONE (0x0c << MATH_SRC1_SHIFT)
+#define MATH_SRC1_SHIFT 12
+#define MATH_SRC1_MASK (0x0f << MATH_SRC1_SHIFT)
+#define MATH_SRC1_REG0 (0x00 << MATH_SRC1_SHIFT)
+#define MATH_SRC1_REG1 (0x01 << MATH_SRC1_SHIFT)
+#define MATH_SRC1_REG2 (0x02 << MATH_SRC1_SHIFT)
+#define MATH_SRC1_REG3 (0x03 << MATH_SRC1_SHIFT)
+#define MATH_SRC1_IMM (0x04 << MATH_SRC1_SHIFT)
+#define MATH_SRC1_INFIFO (0x0a << MATH_SRC1_SHIFT)
+#define MATH_SRC1_OUTFIFO (0x0b << MATH_SRC1_SHIFT)
+#define MATH_SRC1_ONE (0x0c << MATH_SRC1_SHIFT)
/* Destination selectors */
-#define MATH_DEST_SHIFT 8
-#define MATH_DEST_MASK (0x0f << MATH_DEST_SHIFT)
-#define MATH_DEST_REG0 (0x00 << MATH_DEST_SHIFT)
-#define MATH_DEST_REG1 (0x01 << MATH_DEST_SHIFT)
-#define MATH_DEST_REG2 (0x02 << MATH_DEST_SHIFT)
-#define MATH_DEST_REG3 (0x03 << MATH_DEST_SHIFT)
-#define MATH_DEST_SEQINLEN (0x08 << MATH_DEST_SHIFT)
-#define MATH_DEST_SEQOUTLEN (0x09 << MATH_DEST_SHIFT)
-#define MATH_DEST_VARSEQINLEN (0x0a << MATH_DEST_SHIFT)
-#define MATH_DEST_VARSEQOUTLEN (0x0b << MATH_DEST_SHIFT)
-#define MATH_DEST_NONE (0x0f << MATH_DEST_SHIFT)
+#define MATH_DEST_SHIFT 8
+#define MATH_DEST_MASK (0x0f << MATH_DEST_SHIFT)
+#define MATH_DEST_REG0 (0x00 << MATH_DEST_SHIFT)
+#define MATH_DEST_REG1 (0x01 << MATH_DEST_SHIFT)
+#define MATH_DEST_REG2 (0x02 << MATH_DEST_SHIFT)
+#define MATH_DEST_REG3 (0x03 << MATH_DEST_SHIFT)
+#define MATH_DEST_SEQINLEN (0x08 << MATH_DEST_SHIFT)
+#define MATH_DEST_SEQOUTLEN (0x09 << MATH_DEST_SHIFT)
+#define MATH_DEST_VARSEQINLEN (0x0a << MATH_DEST_SHIFT)
+#define MATH_DEST_VARSEQOUTLEN (0x0b << MATH_DEST_SHIFT)
+#define MATH_DEST_NONE (0x0f << MATH_DEST_SHIFT)
/* Length selectors */
-#define MATH_LEN_SHIFT 0
-#define MATH_LEN_MASK (0x0f << MATH_LEN_SHIFT)
-#define MATH_LEN_1BYTE 0x01
-#define MATH_LEN_2BYTE 0x02
-#define MATH_LEN_4BYTE 0x04
-#define MATH_LEN_8BYTE 0x08
+#define MATH_LEN_SHIFT 0
+#define MATH_LEN_MASK (0x0f << MATH_LEN_SHIFT)
+#define MATH_LEN_1BYTE 0x01
+#define MATH_LEN_2BYTE 0x02
+#define MATH_LEN_4BYTE 0x04
+#define MATH_LEN_8BYTE 0x08
/*
* JUMP Command Constructs
*/
-#define JUMP_CLASS_SHIFT 25
+#define JUMP_CLASS_SHIFT 25
#define JUMP_CLASS_MASK (3 << JUMP_CLASS_SHIFT)
#define JUMP_CLASS_NONE 0
#define JUMP_CLASS_CLASS1 (1 << JUMP_CLASS_SHIFT)
#define JUMP_CLASS_CLASS2 (2 << JUMP_CLASS_SHIFT)
#define JUMP_CLASS_BOTH (3 << JUMP_CLASS_SHIFT)
-#define JUMP_JSL_SHIFT 24
-#define JUMP_JSL_MASK (1 << JUMP_JSL_SHIFT)
-#define JUMP_JSL (1 << JUMP_JSL_SHIFT)
+#define JUMP_JSL_SHIFT 24
+#define JUMP_JSL_MASK (1 << JUMP_JSL_SHIFT)
+#define JUMP_JSL (1 << JUMP_JSL_SHIFT)
-#define JUMP_TYPE_SHIFT 22
-#define JUMP_TYPE_MASK (0x03 << JUMP_TYPE_SHIFT)
-#define JUMP_TYPE_LOCAL (0x00 << JUMP_TYPE_SHIFT)
-#define JUMP_TYPE_NONLOCAL (0x01 << JUMP_TYPE_SHIFT)
-#define JUMP_TYPE_HALT (0x02 << JUMP_TYPE_SHIFT)
-#define JUMP_TYPE_HALT_USER (0x03 << JUMP_TYPE_SHIFT)
+#define JUMP_TYPE_SHIFT 22
+#define JUMP_TYPE_MASK (0x03 << JUMP_TYPE_SHIFT)
+#define JUMP_TYPE_LOCAL (0x00 << JUMP_TYPE_SHIFT)
+#define JUMP_TYPE_NONLOCAL (0x01 << JUMP_TYPE_SHIFT)
+#define JUMP_TYPE_HALT (0x02 << JUMP_TYPE_SHIFT)
+#define JUMP_TYPE_HALT_USER (0x03 << JUMP_TYPE_SHIFT)
-#define JUMP_TEST_SHIFT 16
-#define JUMP_TEST_MASK (0x03 << JUMP_TEST_SHIFT)
-#define JUMP_TEST_ALL (0x00 << JUMP_TEST_SHIFT)
-#define JUMP_TEST_INVALL (0x01 << JUMP_TEST_SHIFT)
-#define JUMP_TEST_ANY (0x02 << JUMP_TEST_SHIFT)
-#define JUMP_TEST_INVANY (0x03 << JUMP_TEST_SHIFT)
+#define JUMP_TEST_SHIFT 16
+#define JUMP_TEST_MASK (0x03 << JUMP_TEST_SHIFT)
+#define JUMP_TEST_ALL (0x00 << JUMP_TEST_SHIFT)
+#define JUMP_TEST_INVALL (0x01 << JUMP_TEST_SHIFT)
+#define JUMP_TEST_ANY (0x02 << JUMP_TEST_SHIFT)
+#define JUMP_TEST_INVANY (0x03 << JUMP_TEST_SHIFT)
/* Condition codes. JSL bit is factored in */
-#define JUMP_COND_SHIFT 8
-#define JUMP_COND_MASK (0x100ff << JUMP_COND_SHIFT)
-#define JUMP_COND_PK_0 (0x80 << JUMP_COND_SHIFT)
-#define JUMP_COND_PK_GCD_1 (0x40 << JUMP_COND_SHIFT)
-#define JUMP_COND_PK_PRIME (0x20 << JUMP_COND_SHIFT)
-#define JUMP_COND_MATH_N (0x08 << JUMP_COND_SHIFT)
-#define JUMP_COND_MATH_Z (0x04 << JUMP_COND_SHIFT)
-#define JUMP_COND_MATH_C (0x02 << JUMP_COND_SHIFT)
-#define JUMP_COND_MATH_NV (0x01 << JUMP_COND_SHIFT)
-
-#define JUMP_COND_JRP ((0x80 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_SHRD ((0x40 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_SELF ((0x20 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_CALM ((0x10 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_NIP ((0x08 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_NIFP ((0x04 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_NOP ((0x02 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_NCP ((0x01 << JUMP_COND_SHIFT) | JUMP_JSL)
-
-#define JUMP_OFFSET_SHIFT 0
-#define JUMP_OFFSET_MASK (0xff << JUMP_OFFSET_SHIFT)
+#define JUMP_COND_SHIFT 8
+#define JUMP_COND_MASK (0x100ff << JUMP_COND_SHIFT)
+#define JUMP_COND_PK_0 (0x80 << JUMP_COND_SHIFT)
+#define JUMP_COND_PK_GCD_1 (0x40 << JUMP_COND_SHIFT)
+#define JUMP_COND_PK_PRIME (0x20 << JUMP_COND_SHIFT)
+#define JUMP_COND_MATH_N (0x08 << JUMP_COND_SHIFT)
+#define JUMP_COND_MATH_Z (0x04 << JUMP_COND_SHIFT)
+#define JUMP_COND_MATH_C (0x02 << JUMP_COND_SHIFT)
+#define JUMP_COND_MATH_NV (0x01 << JUMP_COND_SHIFT)
+
+#define JUMP_COND_JRP ((0x80 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_SHRD ((0x40 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_SELF ((0x20 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_CALM ((0x10 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_NIP ((0x08 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_NIFP ((0x04 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_NOP ((0x02 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_NCP ((0x01 << JUMP_COND_SHIFT) | JUMP_JSL)
+
+#define JUMP_OFFSET_SHIFT 0
+#define JUMP_OFFSET_MASK (0xff << JUMP_OFFSET_SHIFT)
/*
* NFIFO ENTRY
@@ -1500,20 +1530,20 @@
#define NFIFOENTRY_DEST_BOTH (3 << NFIFOENTRY_DEST_SHIFT)
#define NFIFOENTRY_LC2_SHIFT 29
-#define NFIFOENTRY_LC2_MASK (1 << NFIFOENTRY_LC2_SHIFT)
-#define NFIFOENTRY_LC2 (1 << NFIFOENTRY_LC2_SHIFT)
+#define NFIFOENTRY_LC2_MASK (1 << NFIFOENTRY_LC2_SHIFT)
+#define NFIFOENTRY_LC2 (1 << NFIFOENTRY_LC2_SHIFT)
#define NFIFOENTRY_LC1_SHIFT 28
-#define NFIFOENTRY_LC1_MASK (1 << NFIFOENTRY_LC1_SHIFT)
-#define NFIFOENTRY_LC1 (1 << NFIFOENTRY_LC1_SHIFT)
+#define NFIFOENTRY_LC1_MASK (1 << NFIFOENTRY_LC1_SHIFT)
+#define NFIFOENTRY_LC1 (1 << NFIFOENTRY_LC1_SHIFT)
#define NFIFOENTRY_FC2_SHIFT 27
-#define NFIFOENTRY_FC2_MASK (1 << NFIFOENTRY_FC2_SHIFT)
-#define NFIFOENTRY_FC2 (1 << NFIFOENTRY_FC2_SHIFT)
+#define NFIFOENTRY_FC2_MASK (1 << NFIFOENTRY_FC2_SHIFT)
+#define NFIFOENTRY_FC2 (1 << NFIFOENTRY_FC2_SHIFT)
#define NFIFOENTRY_FC1_SHIFT 26
-#define NFIFOENTRY_FC1_MASK (1 << NFIFOENTRY_FC1_SHIFT)
-#define NFIFOENTRY_FC1 (1 << NFIFOENTRY_FC1_SHIFT)
+#define NFIFOENTRY_FC1_MASK (1 << NFIFOENTRY_FC1_SHIFT)
+#define NFIFOENTRY_FC1 (1 << NFIFOENTRY_FC1_SHIFT)
#define NFIFOENTRY_STYPE_SHIFT 24
#define NFIFOENTRY_STYPE_MASK (3 << NFIFOENTRY_STYPE_SHIFT)
@@ -1525,60 +1555,59 @@
#define NFIFOENTRY_DTYPE_SHIFT 20
#define NFIFOENTRY_DTYPE_MASK (0xF << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_SBOX (0x0 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_AAD (0x1 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_IV (0x2 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_SAD (0x3 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_ICV (0xA << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_SKIP (0xE << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_MSG (0xF << NFIFOENTRY_DTYPE_SHIFT)
-
-#define NFIFOENTRY_DTYPE_PK_A0 (0x0 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_A1 (0x1 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_A2 (0x2 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_A3 (0x3 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_B0 (0x4 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_B1 (0x5 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_B2 (0x6 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_B3 (0x7 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_N (0x8 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_E (0x9 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_A (0xC << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_B (0xD << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_SBOX (0x0 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_AAD (0x1 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_IV (0x2 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_SAD (0x3 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_ICV (0xA << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_SKIP (0xE << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_MSG (0xF << NFIFOENTRY_DTYPE_SHIFT)
+
+#define NFIFOENTRY_DTYPE_PK_A0 (0x0 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_A1 (0x1 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_A2 (0x2 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_A3 (0x3 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_B0 (0x4 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_B1 (0x5 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_B2 (0x6 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_B3 (0x7 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_N (0x8 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_E (0x9 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_A (0xC << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_B (0xD << NFIFOENTRY_DTYPE_SHIFT)
#define NFIFOENTRY_BND_SHIFT 19
-#define NFIFOENTRY_BND_MASK (1 << NFIFOENTRY_BND_SHIFT)
-#define NFIFOENTRY_BND (1 << NFIFOENTRY_BND_SHIFT)
+#define NFIFOENTRY_BND_MASK (1 << NFIFOENTRY_BND_SHIFT)
+#define NFIFOENTRY_BND (1 << NFIFOENTRY_BND_SHIFT)
#define NFIFOENTRY_PTYPE_SHIFT 16
#define NFIFOENTRY_PTYPE_MASK (0x7 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_ZEROS (0x0 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_RND_NOZEROS (0x1 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_INCREMENT (0x2 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_RND (0x3 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_ZEROS_NZ (0x4 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_RND_NZ_LZ (0x5 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_N (0x6 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_RND_NZ_N (0x7 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_ZEROS (0x0 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_RND_NOZEROS (0x1 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_INCREMENT (0x2 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_RND (0x3 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_ZEROS_NZ (0x4 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_RND_NZ_LZ (0x5 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_N (0x6 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_RND_NZ_N (0x7 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_OC_SHIFT 15
-#define NFIFOENTRY_OC_MASK (1 << NFIFOENTRY_OC_SHIFT)
-#define NFIFOENTRY_OC (1 << NFIFOENTRY_OC_SHIFT)
+#define NFIFOENTRY_OC_SHIFT 15
+#define NFIFOENTRY_OC_MASK (1 << NFIFOENTRY_OC_SHIFT)
+#define NFIFOENTRY_OC (1 << NFIFOENTRY_OC_SHIFT)
#define NFIFOENTRY_AST_SHIFT 14
-#define NFIFOENTRY_AST_MASK (1 << NFIFOENTRY_OC_SHIFT)
-#define NFIFOENTRY_AST (1 << NFIFOENTRY_OC_SHIFT)
+#define NFIFOENTRY_AST_MASK (1 << NFIFOENTRY_OC_SHIFT)
+#define NFIFOENTRY_AST (1 << NFIFOENTRY_OC_SHIFT)
-#define NFIFOENTRY_BM_SHIFT 11
-#define NFIFOENTRY_BM_MASK (1 << NFIFOENTRY_BM_SHIFT)
-#define NFIFOENTRY_BM (1 << NFIFOENTRY_BM_SHIFT)
-
-#define NFIFOENTRY_PS_SHIFT 10
-#define NFIFOENTRY_PS_MASK (1 << NFIFOENTRY_PS_SHIFT)
-#define NFIFOENTRY_PS (1 << NFIFOENTRY_PS_SHIFT)
+#define NFIFOENTRY_BM_SHIFT 11
+#define NFIFOENTRY_BM_MASK (1 << NFIFOENTRY_BM_SHIFT)
+#define NFIFOENTRY_BM (1 << NFIFOENTRY_BM_SHIFT)
+#define NFIFOENTRY_PS_SHIFT 10
+#define NFIFOENTRY_PS_MASK (1 << NFIFOENTRY_PS_SHIFT)
+#define NFIFOENTRY_PS (1 << NFIFOENTRY_PS_SHIFT)
#define NFIFOENTRY_DLEN_SHIFT 0
#define NFIFOENTRY_DLEN_MASK (0xFFF << NFIFOENTRY_DLEN_SHIFT)
@@ -1586,20 +1615,4 @@
#define NFIFOENTRY_PLEN_SHIFT 0
#define NFIFOENTRY_PLEN_MASK (0xFF << NFIFOENTRY_PLEN_SHIFT)
-/*
- * PDB internal definitions
- */
-
-/* IPSec ESP CBC Encap/Decap Options */
-#define PDBOPTS_ESPCBC_ARSNONE 0x00 /* no antireplay window */
-#define PDBOPTS_ESPCBC_ARS32 0x40 /* 32-entry antireplay window */
-#define PDBOPTS_ESPCBC_ARS64 0xc0 /* 64-entry antireplay window */
-#define PDBOPTS_ESPCBC_IVSRC 0x20 /* IV comes from internal random gen */
-#define PDBOPTS_ESPCBC_ESN 0x10 /* extended sequence included */
-#define PDBOPTS_ESPCBC_OUTFMT 0x08 /* output only decapsulation (decap) */
-#define PDBOPTS_ESPCBC_IPHDRSRC 0x08 /* IP header comes from PDB (encap) */
-#define PDBOPTS_ESPCBC_INCIPHDR 0x04 /* Prepend IP header to output frame */
-#define PDBOPTS_ESPCBC_IPVSN 0x02 /* process IPv6 header */
-#define PDBOPTS_ESPCBC_TUNNEL 0x01 /* tunnel mode next-header byte */
-
#endif /* DESC_H */
diff --git a/drivers/crypto/caam/desc_constr.h b/drivers/crypto/caam/desc_constr.h
index 1e5d54c72aa8..c85c1f058401 100644
--- a/drivers/crypto/caam/desc_constr.h
+++ b/drivers/crypto/caam/desc_constr.h
@@ -1,7 +1,7 @@
/*
* caam descriptor construction helper functions
*
- * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
+ * Copyright 2008-2012 Freescale Semiconductor, Inc.
*/
#include "desc.h"
@@ -18,9 +18,10 @@
#define PRINT_POS
#endif
-#define SET_OK_PROP_ERRORS (IMMEDIATE | LDST_CLASS_DECO | \
- LDST_SRCDST_WORD_DECOCTRL | \
- (LDOFF_CHG_SHARE_OK_PROP << LDST_OFFSET_SHIFT))
+#define SET_OK_NO_PROP_ERRORS (IMMEDIATE | LDST_CLASS_DECO | \
+ LDST_SRCDST_WORD_DECOCTRL | \
+ (LDOFF_CHG_SHARE_OK_NO_PROP << \
+ LDST_OFFSET_SHIFT))
#define DISABLE_AUTO_INFO_FIFO (IMMEDIATE | LDST_CLASS_DECO | \
LDST_SRCDST_WORD_DECOCTRL | \
(LDOFF_DISABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT))
@@ -50,7 +51,7 @@ static inline void *sh_desc_pdb(u32 *desc)
static inline void init_desc(u32 *desc, u32 options)
{
- *desc = options | HDR_ONE | 1;
+ *desc = (options | HDR_ONE) + 1;
}
static inline void init_sh_desc(u32 *desc, u32 options)
@@ -61,9 +62,9 @@ static inline void init_sh_desc(u32 *desc, u32 options)
static inline void init_sh_desc_pdb(u32 *desc, u32 options, size_t pdb_bytes)
{
- u32 pdb_len = pdb_bytes / CAAM_CMD_SZ + 1;
+ u32 pdb_len = (pdb_bytes + CAAM_CMD_SZ - 1) / CAAM_CMD_SZ;
- init_sh_desc(desc, ((pdb_len << HDR_START_IDX_SHIFT) + pdb_len) |
+ init_sh_desc(desc, (((pdb_len + 1) << HDR_START_IDX_SHIFT) + pdb_len) |
options);
}
@@ -116,6 +117,15 @@ static inline void append_cmd_ptr(u32 *desc, dma_addr_t ptr, int len,
append_ptr(desc, ptr);
}
+/* Write length after pointer, rather than inside command */
+static inline void append_cmd_ptr_extlen(u32 *desc, dma_addr_t ptr,
+ unsigned int len, u32 command)
+{
+ append_cmd(desc, command);
+ append_ptr(desc, ptr);
+ append_cmd(desc, len);
+}
+
static inline void append_cmd_data(u32 *desc, void *data, int len,
u32 command)
{
@@ -165,13 +175,22 @@ static inline void append_##cmd(u32 *desc, dma_addr_t ptr, unsigned int len, \
append_cmd_ptr(desc, ptr, len, CMD_##op | options); \
}
APPEND_CMD_PTR(key, KEY)
-APPEND_CMD_PTR(seq_in_ptr, SEQ_IN_PTR)
-APPEND_CMD_PTR(seq_out_ptr, SEQ_OUT_PTR)
APPEND_CMD_PTR(load, LOAD)
APPEND_CMD_PTR(store, STORE)
APPEND_CMD_PTR(fifo_load, FIFO_LOAD)
APPEND_CMD_PTR(fifo_store, FIFO_STORE)
+#define APPEND_SEQ_PTR_INTLEN(cmd, op) \
+static inline void append_seq_##cmd##_ptr_intlen(u32 *desc, dma_addr_t ptr, \
+ unsigned int len, \
+ u32 options) \
+{ \
+ PRINT_POS; \
+ append_cmd_ptr(desc, ptr, len, CMD_SEQ_##op##_PTR | options); \
+}
+APPEND_SEQ_PTR_INTLEN(in, IN)
+APPEND_SEQ_PTR_INTLEN(out, OUT)
+
#define APPEND_CMD_PTR_TO_IMM(cmd, op) \
static inline void append_##cmd##_as_imm(u32 *desc, void *data, \
unsigned int len, u32 options) \
@@ -182,6 +201,33 @@ static inline void append_##cmd##_as_imm(u32 *desc, void *data, \
APPEND_CMD_PTR_TO_IMM(load, LOAD);
APPEND_CMD_PTR_TO_IMM(fifo_load, FIFO_LOAD);
+#define APPEND_CMD_PTR_EXTLEN(cmd, op) \
+static inline void append_##cmd##_extlen(u32 *desc, dma_addr_t ptr, \
+ unsigned int len, u32 options) \
+{ \
+ PRINT_POS; \
+ append_cmd_ptr_extlen(desc, ptr, len, CMD_##op | SQIN_EXT | options); \
+}
+APPEND_CMD_PTR_EXTLEN(seq_in_ptr, SEQ_IN_PTR)
+APPEND_CMD_PTR_EXTLEN(seq_out_ptr, SEQ_OUT_PTR)
+
+/*
+ * Determine whether to store length internally or externally depending on
+ * the size of its type
+ */
+#define APPEND_CMD_PTR_LEN(cmd, op, type) \
+static inline void append_##cmd(u32 *desc, dma_addr_t ptr, \
+ type len, u32 options) \
+{ \
+ PRINT_POS; \
+ if (sizeof(type) > sizeof(u16)) \
+ append_##cmd##_extlen(desc, ptr, len, options); \
+ else \
+ append_##cmd##_intlen(desc, ptr, len, options); \
+}
+APPEND_CMD_PTR_LEN(seq_in_ptr, SEQ_IN_PTR, u32)
+APPEND_CMD_PTR_LEN(seq_out_ptr, SEQ_OUT_PTR, u32)
+
/*
* 2nd variant for commands whose specified immediate length differs
* from length of immediate data provided, e.g., split keys
diff --git a/drivers/crypto/caam/error.c b/drivers/crypto/caam/error.c
index 7e2d54bffad6..1c5bd0334578 100644
--- a/drivers/crypto/caam/error.c
+++ b/drivers/crypto/caam/error.c
@@ -1,7 +1,7 @@
/*
* CAAM Error Reporting
*
- * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2009-2012 Freescale Semiconductor, Inc.
*/
#include "compat.h"
@@ -104,7 +104,8 @@ static void report_deco_status(u32 status, char *outstr)
{ 0x00, "None. No error." },
{ 0x01, "SGT Length Error. The descriptor is trying to read "
"more data than is contained in the SGT table." },
- { 0x02, "Reserved." },
+ { 0x02, "SGT Null Entry Error. Extension bit was set, but "
+ "SGT entry was null." },
{ 0x03, "Job Ring Control Error. There is a bad value in the "
"Job Ring Control register." },
{ 0x04, "Invalid Descriptor Command. The Descriptor Command "
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index 19e4f25c25a8..18e7385fb2d8 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -100,6 +100,7 @@ struct caam_drv_private {
u8 total_jobrs; /* Total Job Rings in device */
u8 qi_present; /* Nonzero if QI present in device */
int secvio_irq; /* Security violation interrupt number */
+ int rng_inst; /* Total instantiated RNGs */
/* which jr allocated to scatterlist crypto */
atomic_t tfm_count ____cacheline_aligned;
@@ -107,6 +108,8 @@ struct caam_drv_private {
struct device **algapi_jr;
/* list of registered crypto algorithms (mk generic context handle?) */
struct list_head alg_list;
+ /* list of registered hash algorithms (mk generic context handle?) */
+ struct list_head hash_list;
#ifdef CONFIG_ARM
struct clk *caam_clk;
@@ -129,7 +132,28 @@ struct caam_drv_private {
#endif
};
+/*
+ * These startup/shutdown functions exist to enable API startup/shutdown
+ * outside of the OF device detection framework. It's necessary for ARM
+ * kernels as presently delivered.
+ *
+ * Once ARM kernels are shipping with OF support, these functions can
+ * be re-integrated into the normal probe startup/exit functions,
+ * and these prototypes can then be removed.
+ */
+#ifndef CONFIG_OF
void caam_algapi_shutdown(struct platform_device *pdev);
int caam_algapi_startup(struct platform_device *pdev);
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API
+int caam_algapi_hash_startup(struct platform_device *pdev);
+void caam_algapi_hash_shutdown(struct platform_device *pdev);
+#endif
+
+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API
+int caam_rng_startup(struct platform_device *pdev);
+void caam_rng_shutdown(void);
+#endif
+#endif /* CONFIG_OF */
+
#endif /* INTERN_H */
diff --git a/drivers/crypto/caam/key_gen.c b/drivers/crypto/caam/key_gen.c
new file mode 100644
index 000000000000..8e67628b3c1b
--- /dev/null
+++ b/drivers/crypto/caam/key_gen.c
@@ -0,0 +1,124 @@
+/*
+ * CAAM/SEC 4.x functions for handling key-generation jobs
+ *
+ * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
+ *
+ */
+#include "compat.h"
+#include "jr.h"
+#include "error.h"
+#include "desc_constr.h"
+#include "key_gen.h"
+
+void split_key_done(struct device *dev, u32 *desc, u32 err,
+ void *context)
+{
+ struct split_key_result *res = context;
+
+#ifdef DEBUG
+ dev_err(dev, "%s %d: err 0x%x\n", __func__, __LINE__, err);
+#endif
+
+ if (err) {
+ char tmp[CAAM_ERROR_STR_MAX];
+
+ dev_err(dev, "%08x: %s\n", err, caam_jr_strstatus(tmp, err));
+ }
+
+ res->err = err;
+
+ complete(&res->completion);
+}
+EXPORT_SYMBOL(split_key_done);
+/*
+get a split ipad/opad key
+
+Split key generation-----------------------------------------------
+
+[00] 0xb0810008 jobdesc: stidx=1 share=never len=8
+[01] 0x04000014 key: class2->keyreg len=20
+ @0xffe01000
+[03] 0x84410014 operation: cls2-op sha1 hmac init dec
+[04] 0x24940000 fifold: class2 msgdata-last2 len=0 imm
+[05] 0xa4000001 jump: class2 local all ->1 [06]
+[06] 0x64260028 fifostr: class2 mdsplit-jdk len=40
+ @0xffe04000
+*/
+u32 gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
+ int split_key_pad_len, const u8 *key_in, u32 keylen,
+ u32 alg_op)
+{
+ u32 *desc;
+ struct split_key_result result;
+ dma_addr_t dma_addr_in, dma_addr_out;
+ int ret = 0;
+
+ desc = kmalloc(CAAM_CMD_SZ * 6 + CAAM_PTR_SZ * 2, GFP_KERNEL | GFP_DMA);
+
+ init_job_desc(desc, 0);
+
+ dma_addr_in = dma_map_single(jrdev, (void *)key_in, keylen,
+ DMA_TO_DEVICE);
+ if (dma_mapping_error(jrdev, dma_addr_in)) {
+ dev_err(jrdev, "unable to map key input memory\n");
+ kfree(desc);
+ return -ENOMEM;
+ }
+ dma_sync_single_for_device(jrdev, dma_addr_in, keylen, DMA_TO_DEVICE);
+ append_key(desc, dma_addr_in, keylen, CLASS_2 | KEY_DEST_CLASS_REG);
+
+ /* Sets MDHA up into an HMAC-INIT */
+ append_operation(desc, alg_op | OP_ALG_DECRYPT | OP_ALG_AS_INIT);
+
+ /*
+ * do a FIFO_LOAD of zero, this will trigger the internal key expansion
+ * into both pads inside MDHA
+ */
+ append_fifo_load_as_imm(desc, NULL, 0, LDST_CLASS_2_CCB |
+ FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST2);
+
+ /*
+ * FIFO_STORE with the explicit split-key content store
+ * (0x26 output type)
+ */
+ dma_addr_out = dma_map_single(jrdev, key_out, split_key_pad_len,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(jrdev, dma_addr_out)) {
+ dev_err(jrdev, "unable to map key output memory\n");
+ kfree(desc);
+ return -ENOMEM;
+ }
+ append_fifo_store(desc, dma_addr_out, split_key_len,
+ LDST_CLASS_2_CCB | FIFOST_TYPE_SPLIT_KEK);
+
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ctx.key@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, key_in, keylen, 1);
+ print_hex_dump(KERN_ERR, "jobdesc@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1);
+#endif
+
+ result.err = 0;
+ init_completion(&result.completion);
+
+ ret = caam_jr_enqueue(jrdev, desc, split_key_done, &result);
+ if (!ret) {
+ /* in progress */
+ wait_for_completion_interruptible(&result.completion);
+ ret = result.err;
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "ctx.key@"xstr(__LINE__)": ",
+ DUMP_PREFIX_ADDRESS, 16, 4, key_out,
+ split_key_pad_len, 1);
+#endif
+ }
+ dma_sync_single_for_cpu(jrdev, dma_addr_out, split_key_pad_len,
+ DMA_FROM_DEVICE);
+ dma_unmap_single(jrdev, dma_addr_out, split_key_pad_len,
+ DMA_FROM_DEVICE);
+ dma_unmap_single(jrdev, dma_addr_in, keylen, DMA_TO_DEVICE);
+
+ kfree(desc);
+
+ return ret;
+}
diff --git a/drivers/crypto/caam/key_gen.h b/drivers/crypto/caam/key_gen.h
new file mode 100644
index 000000000000..2306b3260614
--- /dev/null
+++ b/drivers/crypto/caam/key_gen.h
@@ -0,0 +1,17 @@
+/*
+ * CAAM/SEC 4.x definitions for handling key-generation jobs
+ *
+ * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
+ *
+ */
+
+struct split_key_result {
+ struct completion completion;
+ int err;
+};
+
+void split_key_done(struct device *dev, u32 *desc, u32 err, void *context);
+
+u32 gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
+ int split_key_pad_len, const u8 *key_in, u32 keylen,
+ u32 alg_op);
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index 888706d2801c..fd8a2a251b8a 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -113,16 +113,104 @@ struct jr_outentry {
} __packed;
/*
+ * CHA version ID / instantiation bitfields
+ * Defined for use within cha_id in perfmon
+ * Note that the same shift/mask selectors can be used to pull out number
+ * of instantiated blocks within cha_num in perfmon, the locations are
+ * the same.
+ */
+
+/* Job Ring */
+#define CHA_ID_JR_SHIFT 60
+#define CHA_ID_JR_MASK (0xfull << CHA_ID_JR_SHIFT)
+
+/* DEscriptor COntroller */
+#define CHA_ID_DECO_SHIFT 56
+#define CHA_ID_DECO_MASK (0xfull << CHA_ID_DECO_SHIFT)
+#define CHA_NUM_DECONUM_SHIFT 56 /* legacy definition */
+#define CHA_NUM_DECONUM_MASK (0xfull << CHA_NUM_DECONUM_SHIFT)
+
+/* ZUC-Authentication */
+#define CHA_ID_ZA_SHIFT 44
+#define CHA_ID_ZA_MASK (0xfull << CHA_ID_ZA_SHIFT)
+
+/* ZUC-Encryption */
+#define CHA_ID_ZE_SHIFT 40
+#define CHA_ID_ZE_MASK (0xfull << CHA_ID_ZE_SHIFT)
+
+/* SNOW f9 */
+#define CHA_ID_SNW9_SHIFT 36
+#define CHA_ID_SNW9_MASK (0xfull << CHA_ID_SNW9_SHIFT)
+
+/* CRC */
+#define CHA_ID_CRC_SHIFT 32
+#define CHA_ID_CRC_MASK (0xfull << CHA_ID_CRC_SHIFT)
+
+/* Public Key */
+#define CHA_ID_PK_SHIFT 28
+#define CHA_ID_PK_MASK (0xfull << CHA_ID_PK_SHIFT)
+
+/* Kasumi */
+#define CHA_ID_KAS_SHIFT 24
+#define CHA_ID_KAS_MASK (0xfull << CHA_ID_KAS_SHIFT)
+
+/* SNOW f8 */
+#define CHA_ID_SNW8_SHIFT 20
+#define CHA_ID_SNW8_MASK (0xfull << CHA_ID_SNW8_SHIFT)
+
+/*
+ * Random Generator
+ * RNG4 = FIPS-verification-compliant, requires init kickstart for use
+ */
+#define CHA_ID_RNG_SHIFT 16
+#define CHA_ID_RNG_MASK (0xfull << CHA_ID_RNG_SHIFT)
+#define CHA_ID_RNG_A (0x1ull << CHA_ID_RNG_SHIFT)
+#define CHA_ID_RNG_B (0x2ull << CHA_ID_RNG_SHIFT)
+#define CHA_ID_RNG_C (0x3ull << CHA_ID_RNG_SHIFT)
+#define CHA_ID_RNG_4 (0x4ull << CHA_ID_RNG_SHIFT)
+
+/*
+ * Message Digest
+ * LP256 = Low Power (MD5/SHA1/SHA224/SHA256 + HMAC)
+ * LP512 = Low Power (LP256 + SHA384/SHA512)
+ * HP = High Power (LP512 + SMAC)
+ */
+#define CHA_ID_MD_SHIFT 12
+#define CHA_ID_MD_MASK (0xfull << CHA_ID_MD_SHIFT)
+#define CHA_ID_MD_LP256 (0x0ull << CHA_ID_MD_SHIFT)
+#define CHA_ID_MD_LP512 (0x1ull << CHA_ID_MD_SHIFT)
+#define CHA_ID_MD_HP (0x2ull << CHA_ID_MD_SHIFT)
+
+/* ARC4 Streamcipher */
+#define CHA_ID_ARC4_SHIFT 8
+#define CHA_ID_ARC4_MASK (0xfull << CHA_ID_ARC4_SHIFT)
+#define CHA_ID_ARC4_LP (0x0ull << CHA_ID_ARC4_SHIFT)
+#define CHA_ID_ARC4_HP (0x1ull << CHA_ID_ARC4_SHIFT)
+
+/* DES Blockcipher Accelerator */
+#define CHA_ID_DES_SHIFT 4
+#define CHA_ID_DES_MASK (0xfull << CHA_ID_DES_SHIFT)
+
+/*
+ * AES Blockcipher + Combo Mode Accelerator
+ * LP = Low Power (includes ECB/CBC/CFB128/OFB/CTR/CCM/CMAC/XCBC-MAC)
+ * HP = High Power (LP + CBCXCBC/CTRXCBC/XTS/GCM)
+ * DIFFPWR = ORed in if differential-power-analysis resistance implemented
+ */
+#define CHA_ID_AES_SHIFT 0
+#define CHA_ID_AES_MASK (0xfull << CHA_ID_AES_SHIFT)
+#define CHA_ID_AES_LP (0x3ull << CHA_ID_AES_SHIFT)
+#define CHA_ID_AES_HP (0x4ull << CHA_ID_AES_SHIFT)
+#define CHA_ID_AES_DIFFPWR (0x1ull << CHA_ID_AES_SHIFT)
+
+
+/*
* caam_perfmon - Performance Monitor/Secure Memory Status/
* CAAM Global Status/Component Version IDs
*
* Spans f00-fff wherever instantiated
*/
-/* Number of DECOs */
-#define CHA_NUM_DECONUM_SHIFT 56
-#define CHA_NUM_DECONUM_MASK (0xfull << CHA_NUM_DECONUM_SHIFT)
-
struct caam_perfmon {
/* Performance Monitor Registers f00-f9f */
u64 req_dequeued; /* PC_REQ_DEQ - Dequeued Requests */
@@ -173,7 +261,7 @@ struct partid {
u32 pidr; /* partition ID, DECO */
};
-/* RNG test mode (replicated twice in some configurations) */
+/* RNGB test mode (replicated twice in some configurations) */
/* Padded out to 0x100 */
struct rngtst {
u32 mode; /* RTSTMODEx - Test mode */
@@ -206,6 +294,31 @@ struct rngtst {
u32 rsvd14[15];
};
+/* RNG4 TRNG test registers */
+struct rng4tst {
+#define RTMCTL_PRGM 0x00010000 /* 1 -> program mode, 0 -> run mode */
+ u32 rtmctl; /* misc. control register */
+ u32 rtscmisc; /* statistical check misc. register */
+ u32 rtpkrrng; /* poker range register */
+ union {
+ u32 rtpkrmax; /* PRGM=1: poker max. limit register */
+ u32 rtpkrsq; /* PRGM=0: poker square calc. result register */
+ };
+#define RTSDCTL_ENT_DLY_SHIFT 16
+#define RTSDCTL_ENT_DLY_MASK (0xffff << RTSDCTL_ENT_DLY_SHIFT)
+ u32 rtsdctl; /* seed control register */
+ union {
+ u32 rtsblim; /* PRGM=1: sparse bit limit register */
+ u32 rttotsam; /* PRGM=0: total samples register */
+ };
+ u32 rtfrqmin; /* frequency count min. limit register */
+ union {
+ u32 rtfrqmax; /* PRGM=1: freq. count max. limit register */
+ u32 rtfrqcnt; /* PRGM=0: freq. count register */
+ };
+ u32 rsvd1[56];
+};
+
/*
* caam_ctrl - basic core configuration
* starts base + 0x0000 padded out to 0x1000
@@ -255,7 +368,10 @@ struct caam_ctrl {
/* RNG Test/Verification/Debug Access 600-7ff */
/* (Useful in Test/Debug modes only...) */
- struct rngtst rtst[2];
+ union {
+ struct rngtst rtst[2];
+ struct rng4tst r4tst[2];
+ };
u32 rsvd9[448];
@@ -663,7 +779,6 @@ struct caam_full {
u64 rsvd[512];
struct caam_assurance assure;
struct caam_queue_if qi;
- struct caam_deco *deco;
};
#endif /* REGS_H */
diff --git a/drivers/crypto/caam/sg_sw_sec4.h b/drivers/crypto/caam/sg_sw_sec4.h
new file mode 100644
index 000000000000..e05fc58c9637
--- /dev/null
+++ b/drivers/crypto/caam/sg_sw_sec4.h
@@ -0,0 +1,165 @@
+/*
+ * CAAM/SEC 4.x functions for using scatterlists in caam driver
+ *
+ * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
+ *
+ */
+
+struct sec4_sg_entry;
+
+/*
+ * convert single dma address to h/w link table format
+ */
+static inline void dma_to_sec4_sg_one(struct sec4_sg_entry *sec4_sg_ptr,
+ dma_addr_t dma, u32 len, u32 offset)
+{
+#ifndef CONFIG_64BIT
+ sec4_sg_ptr->reserved = 0; /* ensure MSB half is zeroed */
+#endif
+ sec4_sg_ptr->ptr = dma;
+ sec4_sg_ptr->len |= (len & SEC4_SG_LEN_MASK);
+ /* Does not add in buffer pool ID's at this time */
+ sec4_sg_ptr->bpid_offset = (offset & SEC4_SG_OFFS_MASK);
+#ifdef DEBUG
+ print_hex_dump(KERN_ERR, "sec4_sg_ptr@: ",
+ DUMP_PREFIX_ADDRESS, 16, 4, sec4_sg_ptr,
+ sizeof(struct sec4_sg_entry), 1);
+#endif
+}
+
+/*
+ * convert scatterlist to h/w link table format
+ * but does not have final bit; instead, returns last entry
+ */
+static inline struct sec4_sg_entry *
+sg_to_sec4_sg(struct scatterlist *sg, int sg_count,
+ struct sec4_sg_entry *sec4_sg_ptr, u32 offset)
+{
+ while (sg_count) {
+ dma_to_sec4_sg_one(sec4_sg_ptr, sg_dma_address(sg),
+ sg_dma_len(sg), offset);
+ sec4_sg_ptr++;
+ sg = scatterwalk_sg_next(sg);
+ sg_count--;
+ }
+ return sec4_sg_ptr - 1;
+}
+
+/*
+ * convert scatterlist to h/w link table format
+ * scatterlist must have been previously dma mapped
+ */
+static inline void sg_to_sec4_sg_last(struct scatterlist *sg, int sg_count,
+ struct sec4_sg_entry *sec4_sg_ptr,
+ u32 offset)
+{
+ sec4_sg_ptr = sg_to_sec4_sg(sg, sg_count, sec4_sg_ptr, offset);
+ sec4_sg_ptr->len |= SEC4_SG_LEN_FIN;
+}
+
+/* count number of elements in scatterlist */
+static inline int __sg_count(struct scatterlist *sg_list, int nbytes,
+ bool *chained)
+{
+ struct scatterlist *sg = sg_list;
+ int sg_nents = 0;
+
+ while (nbytes > 0) {
+ sg_nents++;
+ nbytes -= sg->length;
+ if (!sg_is_last(sg) && (sg + 1)->length == 0)
+ *chained = true;
+ sg = scatterwalk_sg_next(sg);
+ }
+
+ return sg_nents;
+}
+
+/* derive number of elements in scatterlist, but return 0 for 1 */
+static inline int sg_count(struct scatterlist *sg_list, int nbytes,
+ bool *chained)
+{
+ int sg_nents = __sg_count(sg_list, nbytes, chained);
+
+ if (likely(sg_nents == 1))
+ return 0;
+
+ return sg_nents;
+}
+
+static int dma_map_sg_chained(struct device *dev, struct scatterlist *sg,
+ unsigned int nents, enum dma_data_direction dir,
+ bool chained)
+{
+ if (unlikely(chained)) {
+ int i;
+ for (i = 0; i < nents; i++) {
+ dma_map_sg(dev, sg, 1, dir);
+ sg = scatterwalk_sg_next(sg);
+ }
+ } else {
+ dma_map_sg(dev, sg, nents, dir);
+ }
+
+ if ((dir == DMA_TO_DEVICE) || (dir == DMA_BIDIRECTIONAL))
+ dma_sync_sg_for_device(dev, sg, nents, dir);
+
+ return nents;
+}
+
+static int dma_unmap_sg_chained(struct device *dev, struct scatterlist *sg,
+ unsigned int nents, enum dma_data_direction dir,
+ bool chained)
+{
+ if ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL))
+ dma_sync_sg_for_cpu(dev, sg, nents, dir);
+
+ if (unlikely(chained)) {
+ int i;
+ for (i = 0; i < nents; i++) {
+ dma_unmap_sg(dev, sg, 1, dir);
+ sg = scatterwalk_sg_next(sg);
+ }
+ } else {
+ dma_unmap_sg(dev, sg, nents, dir);
+ }
+ return nents;
+}
+
+/* Copy from len bytes of sg to dest, starting from beginning */
+static inline void sg_copy(u8 *dest, struct scatterlist *sg, unsigned int len)
+{
+ struct scatterlist *current_sg = sg;
+ int cpy_index = 0, next_cpy_index = current_sg->length;
+
+ while (next_cpy_index < len) {
+ memcpy(dest + cpy_index, (u8 *) sg_virt(current_sg),
+ current_sg->length);
+ current_sg = scatterwalk_sg_next(current_sg);
+ cpy_index = next_cpy_index;
+ next_cpy_index += current_sg->length;
+ }
+ if (cpy_index < len)
+ memcpy(dest + cpy_index, (u8 *) sg_virt(current_sg),
+ len - cpy_index);
+}
+
+/* Copy sg data, from to_skip to end, to dest */
+static inline void sg_copy_part(u8 *dest, struct scatterlist *sg,
+ int to_skip, unsigned int end)
+{
+ struct scatterlist *current_sg = sg;
+ int sg_index, cpy_index;
+
+ sg_index = current_sg->length;
+ while (sg_index <= to_skip) {
+ current_sg = scatterwalk_sg_next(current_sg);
+ sg_index += current_sg->length;
+ }
+ cpy_index = sg_index - to_skip;
+ memcpy(dest, (u8 *) sg_virt(current_sg) +
+ current_sg->length - cpy_index, cpy_index);
+ current_sg = scatterwalk_sg_next(current_sg);
+ if (end - sg_index)
+ sg_copy(dest + cpy_index, current_sg, end - sg_index);
+}
diff --git a/drivers/crypto/dcp.c b/drivers/crypto/dcp.c
index 7ab595587970..cfc486d5b28c 100644
--- a/drivers/crypto/dcp.c
+++ b/drivers/crypto/dcp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008-2012 Freescale Semiconductor, Inc.
*/
/*
@@ -1317,7 +1317,7 @@ static irqreturn_t dcp_irq(int irq, void *context)
}
/* DCP bootstream verification interface: uses OTP key for crypto */
-static int dcp_bootstream_ioctl(struct inode *inode, struct file *file,
+static long dcp_bootstream_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
struct dcp *sdcp = global_sdcp;
diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c
index 38a3297ae2be..f53dd83438bc 100644
--- a/drivers/crypto/mv_cesa.c
+++ b/drivers/crypto/mv_cesa.c
@@ -713,6 +713,7 @@ static int mv_hash_final(struct ahash_request *req)
{
struct mv_req_hash_ctx *ctx = ahash_request_ctx(req);
+ ahash_request_set_crypt(req, NULL, req->result, 0);
mv_update_hash_req_ctx(ctx, 1, 0);
return mv_handle_req(&req->base);
}
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index fb0f8083b14d..fda11931eef4 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -215,18 +215,17 @@ config PL330_DMA
platform_data for a dma-pl330 device.
config PCH_DMA
- tristate "Intel EG20T PCH / OKI Semi IOH(ML7213/ML7223) DMA support"
+ tristate "Intel EG20T PCH / OKI Semi IOH(ML7213/ML7223/ML7831) DMA support"
depends on PCI && X86
select DMA_ENGINE
help
Enable support for Intel EG20T PCH DMA engine.
-
This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
- Output Hub), ML7213 and ML7223.
- ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is
- for MP(Media Phone) use.
- ML7213/ML7223 is companion chip for Intel Atom E6xx series.
- ML7213/ML7223 is completely compatible for Intel EG20T PCH.
+ Output Hub), ML7213, ML7223 and ML7831.
+ ML7213 IOH is for IVI(In-Vehicle Infotainment) use, ML7223 IOH is
+ for MP(Media Phone) use and ML7831 IOH is for general purpose use.
+ ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series.
+ ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH.
config IMX_SDMA
tristate "i.MX SDMA support"
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index 600cf4916b52..cdd07e4d9803 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -237,10 +237,6 @@ static void atc_dostart(struct at_dma_chan *atchan, struct at_desc *first)
vdbg_dump_regs(atchan);
- /* clear any pending interrupt */
- while (dma_readl(atdma, EBCISR))
- cpu_relax();
-
channel_writel(atchan, SADDR, 0);
channel_writel(atchan, DADDR, 0);
channel_writel(atchan, CTRLA, 0);
@@ -1279,7 +1275,7 @@ static int __init at_dma_probe(struct platform_device *pdev)
tasklet_init(&atchan->tasklet, atc_tasklet,
(unsigned long)atchan);
- atc_enable_irq(atchan);
+ atc_enable_chan_irq(atdma, i);
}
/* set base routines */
@@ -1348,7 +1344,7 @@ static int __exit at_dma_remove(struct platform_device *pdev)
struct at_dma_chan *atchan = to_at_dma_chan(chan);
/* Disable interrupts */
- atc_disable_irq(atchan);
+ atc_disable_chan_irq(atdma, chan->chan_id);
tasklet_disable(&atchan->tasklet);
tasklet_kill(&atchan->tasklet);
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h
index 087dbf1dd39c..19ed47056da8 100644
--- a/drivers/dma/at_hdmac_regs.h
+++ b/drivers/dma/at_hdmac_regs.h
@@ -319,28 +319,27 @@ static void atc_dump_lli(struct at_dma_chan *atchan, struct at_lli *lli)
}
-static void atc_setup_irq(struct at_dma_chan *atchan, int on)
+static void atc_setup_irq(struct at_dma *atdma, int chan_id, int on)
{
- struct at_dma *atdma = to_at_dma(atchan->chan_common.device);
- u32 ebci;
+ u32 ebci;
/* enable interrupts on buffer transfer completion & error */
- ebci = AT_DMA_BTC(atchan->chan_common.chan_id)
- | AT_DMA_ERR(atchan->chan_common.chan_id);
+ ebci = AT_DMA_BTC(chan_id)
+ | AT_DMA_ERR(chan_id);
if (on)
dma_writel(atdma, EBCIER, ebci);
else
dma_writel(atdma, EBCIDR, ebci);
}
-static inline void atc_enable_irq(struct at_dma_chan *atchan)
+static void atc_enable_chan_irq(struct at_dma *atdma, int chan_id)
{
- atc_setup_irq(atchan, 1);
+ atc_setup_irq(atdma, chan_id, 1);
}
-static inline void atc_disable_irq(struct at_dma_chan *atchan)
+static void atc_disable_chan_irq(struct at_dma *atdma, int chan_id)
{
- atc_setup_irq(atchan, 0);
+ atc_setup_irq(atdma, chan_id, 0);
}
diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c
index 11c3e27473f4..3dd2e6a8a93b 100644
--- a/drivers/dma/pch_dma.c
+++ b/drivers/dma/pch_dma.c
@@ -45,7 +45,8 @@
#define DMA_STATUS_MASK_BITS 0x3
#define DMA_STATUS_SHIFT_BITS 16
#define DMA_STATUS_IRQ(x) (0x1 << (x))
-#define DMA_STATUS_ERR(x) (0x1 << ((x) + 8))
+#define DMA_STATUS0_ERR(x) (0x1 << ((x) + 8))
+#define DMA_STATUS2_ERR(x) (0x1 << (x))
#define DMA_DESC_WIDTH_SHIFT_BITS 12
#define DMA_DESC_WIDTH_1_BYTE (0x3 << DMA_DESC_WIDTH_SHIFT_BITS)
@@ -59,7 +60,10 @@
#define DMA_DESC_FOLLOW_WITHOUT_IRQ 0x2
#define DMA_DESC_FOLLOW_WITH_IRQ 0x3
-#define MAX_CHAN_NR 8
+#define MAX_CHAN_NR 12
+
+#define DMA_MASK_CTL0_MODE 0x33333333
+#define DMA_MASK_CTL2_MODE 0x00003333
static unsigned int init_nr_desc_per_channel = 64;
module_param(init_nr_desc_per_channel, uint, 0644);
@@ -133,6 +137,7 @@ struct pch_dma {
#define PCH_DMA_CTL3 0x0C
#define PCH_DMA_STS0 0x10
#define PCH_DMA_STS1 0x14
+#define PCH_DMA_STS2 0x18
#define dma_readl(pd, name) \
readl((pd)->membase + PCH_DMA_##name)
@@ -183,13 +188,19 @@ static void pdc_enable_irq(struct dma_chan *chan, int enable)
{
struct pch_dma *pd = to_pd(chan->device);
u32 val;
+ int pos;
+
+ if (chan->chan_id < 8)
+ pos = chan->chan_id;
+ else
+ pos = chan->chan_id + 8;
val = dma_readl(pd, CTL2);
if (enable)
- val |= 0x1 << chan->chan_id;
+ val |= 0x1 << pos;
else
- val &= ~(0x1 << chan->chan_id);
+ val &= ~(0x1 << pos);
dma_writel(pd, CTL2, val);
@@ -202,35 +213,42 @@ static void pdc_set_dir(struct dma_chan *chan)
struct pch_dma_chan *pd_chan = to_pd_chan(chan);
struct pch_dma *pd = to_pd(chan->device);
u32 val;
+ u32 mask_mode;
+ u32 mask_ctl;
if (chan->chan_id < 8) {
val = dma_readl(pd, CTL0);
- if (pd_chan->dir == DMA_MEM_TO_DEV)
+ mask_mode = DMA_CTL0_MODE_MASK_BITS <<
+ (DMA_CTL0_BITS_PER_CH * chan->chan_id);
+ mask_ctl = DMA_MASK_CTL0_MODE & ~(DMA_CTL0_MODE_MASK_BITS <<
+ (DMA_CTL0_BITS_PER_CH * chan->chan_id));
+ val &= mask_mode;
+ if (pd_chan->dir == DMA_TO_DEVICE)
val |= 0x1 << (DMA_CTL0_BITS_PER_CH * chan->chan_id +
DMA_CTL0_DIR_SHIFT_BITS);
else
val &= ~(0x1 << (DMA_CTL0_BITS_PER_CH * chan->chan_id +
DMA_CTL0_DIR_SHIFT_BITS));
+ val |= mask_ctl;
dma_writel(pd, CTL0, val);
} else {
int ch = chan->chan_id - 8; /* ch8-->0 ch9-->1 ... ch11->3 */
val = dma_readl(pd, CTL3);
- if (pd_chan->dir == DMA_TO_DEVICE)
mask_mode = DMA_CTL0_MODE_MASK_BITS <<
(DMA_CTL0_BITS_PER_CH * ch);
mask_ctl = DMA_MASK_CTL2_MODE & ~(DMA_CTL0_MODE_MASK_BITS <<
(DMA_CTL0_BITS_PER_CH * ch));
val &= mask_mode;
- if (pd_chan->dir == DMA_MEM_TO_DEV)
+ if (pd_chan->dir == DMA_TO_DEVICE)
val |= 0x1 << (DMA_CTL0_BITS_PER_CH * ch +
DMA_CTL0_DIR_SHIFT_BITS);
else
val &= ~(0x1 << (DMA_CTL0_BITS_PER_CH * ch +
DMA_CTL0_DIR_SHIFT_BITS));
-
+ val |= mask_ctl;
dma_writel(pd, CTL3, val);
}
@@ -242,33 +260,37 @@ static void pdc_set_mode(struct dma_chan *chan, u32 mode)
{
struct pch_dma *pd = to_pd(chan->device);
u32 val;
+ u32 mask_ctl;
+ u32 mask_dir;
if (chan->chan_id < 8) {
+ mask_ctl = DMA_MASK_CTL0_MODE & ~(DMA_CTL0_MODE_MASK_BITS <<
+ (DMA_CTL0_BITS_PER_CH * chan->chan_id));
+ mask_dir = 1 << (DMA_CTL0_BITS_PER_CH * chan->chan_id +\
+ DMA_CTL0_DIR_SHIFT_BITS);
val = dma_readl(pd, CTL0);
-
- val &= ~(DMA_CTL0_MODE_MASK_BITS <<
- (DMA_CTL0_BITS_PER_CH * chan->chan_id));
+ val &= mask_dir;
val |= mode << (DMA_CTL0_BITS_PER_CH * chan->chan_id);
-
+ val |= mask_ctl;
dma_writel(pd, CTL0, val);
} else {
int ch = chan->chan_id - 8; /* ch8-->0 ch9-->1 ... ch11->3 */
-
+ mask_ctl = DMA_MASK_CTL2_MODE & ~(DMA_CTL0_MODE_MASK_BITS <<
+ (DMA_CTL0_BITS_PER_CH * ch));
+ mask_dir = 1 << (DMA_CTL0_BITS_PER_CH * ch +\
+ DMA_CTL0_DIR_SHIFT_BITS);
val = dma_readl(pd, CTL3);
-
- val &= ~(DMA_CTL0_MODE_MASK_BITS <<
- (DMA_CTL0_BITS_PER_CH * ch));
+ val &= mask_dir;
val |= mode << (DMA_CTL0_BITS_PER_CH * ch);
-
+ val |= mask_ctl;
dma_writel(pd, CTL3, val);
-
}
dev_dbg(chan2dev(chan), "pdc_set_mode: chan %d -> %x\n",
chan->chan_id, val);
}
-static u32 pdc_get_status(struct pch_dma_chan *pd_chan)
+static u32 pdc_get_status0(struct pch_dma_chan *pd_chan)
{
struct pch_dma *pd = to_pd(pd_chan->chan.device);
u32 val;
@@ -278,9 +300,27 @@ static u32 pdc_get_status(struct pch_dma_chan *pd_chan)
DMA_STATUS_BITS_PER_CH * pd_chan->chan.chan_id));
}
+static u32 pdc_get_status2(struct pch_dma_chan *pd_chan)
+{
+ struct pch_dma *pd = to_pd(pd_chan->chan.device);
+ u32 val;
+
+ val = dma_readl(pd, STS2);
+ return DMA_STATUS_MASK_BITS & (val >> (DMA_STATUS_SHIFT_BITS +
+ DMA_STATUS_BITS_PER_CH * (pd_chan->chan.chan_id - 8)));
+}
+
static bool pdc_is_idle(struct pch_dma_chan *pd_chan)
{
- if (pdc_get_status(pd_chan) == DMA_STATUS_IDLE)
+ u32 sts;
+
+ if (pd_chan->chan.chan_id < 8)
+ sts = pdc_get_status0(pd_chan);
+ else
+ sts = pdc_get_status2(pd_chan);
+
+
+ if (sts == DMA_STATUS_IDLE)
return true;
else
return false;
@@ -501,11 +541,11 @@ static int pd_alloc_chan_resources(struct dma_chan *chan)
list_add_tail(&desc->desc_node, &tmp_list);
}
- spin_lock_bh(&pd_chan->lock);
+ spin_lock_irq(&pd_chan->lock);
list_splice(&tmp_list, &pd_chan->free_list);
pd_chan->descs_allocated = i;
pd_chan->completed_cookie = chan->cookie = 1;
- spin_unlock_bh(&pd_chan->lock);
+ spin_unlock_irq(&pd_chan->lock);
pdc_enable_irq(chan, 1);
@@ -523,10 +563,10 @@ static void pd_free_chan_resources(struct dma_chan *chan)
BUG_ON(!list_empty(&pd_chan->active_list));
BUG_ON(!list_empty(&pd_chan->queue));
- spin_lock_bh(&pd_chan->lock);
+ spin_lock_irq(&pd_chan->lock);
list_splice_init(&pd_chan->free_list, &tmp_list);
pd_chan->descs_allocated = 0;
- spin_unlock_bh(&pd_chan->lock);
+ spin_unlock_irq(&pd_chan->lock);
list_for_each_entry_safe(desc, _d, &tmp_list, desc_node)
pci_pool_free(pd->pool, desc, desc->txd.phys);
@@ -542,10 +582,10 @@ static enum dma_status pd_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
dma_cookie_t last_completed;
int ret;
- spin_lock_bh(&pd_chan->lock);
+ spin_lock_irq(&pd_chan->lock);
last_completed = pd_chan->completed_cookie;
last_used = chan->cookie;
- spin_unlock_bh(&pd_chan->lock);
+ spin_unlock_irq(&pd_chan->lock);
ret = dma_async_is_complete(cookie, last_completed, last_used);
@@ -660,7 +700,7 @@ static int pd_device_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
if (cmd != DMA_TERMINATE_ALL)
return -ENXIO;
- spin_lock_bh(&pd_chan->lock);
+ spin_lock_irq(&pd_chan->lock);
pdc_set_mode(&pd_chan->chan, DMA_CTL0_DISABLE);
@@ -670,7 +710,7 @@ static int pd_device_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
list_for_each_entry_safe(desc, _d, &list, desc_node)
pdc_chain_complete(pd_chan, desc);
- spin_unlock_bh(&pd_chan->lock);
+ spin_unlock_irq(&pd_chan->lock);
return 0;
}
@@ -699,30 +739,45 @@ static irqreturn_t pd_irq(int irq, void *devid)
struct pch_dma *pd = (struct pch_dma *)devid;
struct pch_dma_chan *pd_chan;
u32 sts0;
+ u32 sts2;
int i;
- int ret = IRQ_NONE;
+ int ret0 = IRQ_NONE;
+ int ret2 = IRQ_NONE;
sts0 = dma_readl(pd, STS0);
+ sts2 = dma_readl(pd, STS2);
dev_dbg(pd->dma.dev, "pd_irq sts0: %x\n", sts0);
for (i = 0; i < pd->dma.chancnt; i++) {
pd_chan = &pd->channels[i];
- if (sts0 & DMA_STATUS_IRQ(i)) {
- if (sts0 & DMA_STATUS_ERR(i))
- set_bit(0, &pd_chan->err_status);
+ if (i < 8) {
+ if (sts0 & DMA_STATUS_IRQ(i)) {
+ if (sts0 & DMA_STATUS0_ERR(i))
+ set_bit(0, &pd_chan->err_status);
- tasklet_schedule(&pd_chan->tasklet);
- ret = IRQ_HANDLED;
- }
+ tasklet_schedule(&pd_chan->tasklet);
+ ret0 = IRQ_HANDLED;
+ }
+ } else {
+ if (sts2 & DMA_STATUS_IRQ(i - 8)) {
+ if (sts2 & DMA_STATUS2_ERR(i))
+ set_bit(0, &pd_chan->err_status);
+ tasklet_schedule(&pd_chan->tasklet);
+ ret2 = IRQ_HANDLED;
+ }
+ }
}
/* clear interrupt bits in status register */
- dma_writel(pd, STS0, sts0);
+ if (ret0)
+ dma_writel(pd, STS0, sts0);
+ if (ret2)
+ dma_writel(pd, STS2, sts2);
- return ret;
+ return ret0 | ret2;
}
#ifdef CONFIG_PM
@@ -966,6 +1021,8 @@ static void __devexit pch_dma_remove(struct pci_dev *pdev)
#define PCI_DEVICE_ID_ML7223_DMA2_4CH 0x800E
#define PCI_DEVICE_ID_ML7223_DMA3_4CH 0x8017
#define PCI_DEVICE_ID_ML7223_DMA4_4CH 0x803B
+#define PCI_DEVICE_ID_ML7831_DMA1_8CH 0x8810
+#define PCI_DEVICE_ID_ML7831_DMA2_4CH 0x8815
DEFINE_PCI_DEVICE_TABLE(pch_dma_id_table) = {
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_EG20T_PCH_DMA_8CH), 8 },
@@ -978,6 +1035,8 @@ DEFINE_PCI_DEVICE_TABLE(pch_dma_id_table) = {
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_DMA2_4CH), 4}, /* Video SPI */
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_DMA3_4CH), 4}, /* Security */
{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_DMA4_4CH), 4}, /* FPGA */
+ { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_DMA1_8CH), 8}, /* UART */
+ { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_DMA2_4CH), 4}, /* SPI */
{ 0, },
};
@@ -1005,7 +1064,7 @@ static void __exit pch_dma_exit(void)
module_init(pch_dma_init);
module_exit(pch_dma_exit);
-MODULE_DESCRIPTION("Intel EG20T PCH / OKI SEMICONDUCTOR ML7213 IOH "
- "DMA controller driver");
+MODULE_DESCRIPTION("Intel EG20T PCH / OKI SEMICON ML7213/ML7223/ML7831 IOH"
+ "DMA controller driver");
MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index e6ad3bb6c1a6..4799393247c8 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -216,15 +216,33 @@ struct inbound_phy_packet_event {
struct fw_cdev_event_phy_packet phy_packet;
};
-static inline void __user *u64_to_uptr(__u64 value)
+#ifdef CONFIG_COMPAT
+static void __user *u64_to_uptr(u64 value)
+{
+ if (is_compat_task())
+ return compat_ptr(value);
+ else
+ return (void __user *)(unsigned long)value;
+}
+
+static u64 uptr_to_u64(void __user *ptr)
+{
+ if (is_compat_task())
+ return ptr_to_compat(ptr);
+ else
+ return (u64)(unsigned long)ptr;
+}
+#else
+static inline void __user *u64_to_uptr(u64 value)
{
return (void __user *)(unsigned long)value;
}
-static inline __u64 uptr_to_u64(void __user *ptr)
+static inline u64 uptr_to_u64(void __user *ptr)
{
- return (__u64)(unsigned long)ptr;
+ return (u64)(unsigned long)ptr;
}
+#endif /* CONFIG_COMPAT */
static int fw_device_op_open(struct inode *inode, struct file *file)
{
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c
index 95a471401892..9f661e069318 100644
--- a/drivers/firewire/core-device.c
+++ b/drivers/firewire/core-device.c
@@ -455,15 +455,20 @@ static struct device_attribute fw_device_attributes[] = {
static int read_rom(struct fw_device *device,
int generation, int index, u32 *data)
{
- int rcode;
+ u64 offset = (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4;
+ int i, rcode;
/* device->node_id, accessed below, must not be older than generation */
smp_rmb();
- rcode = fw_run_transaction(device->card, TCODE_READ_QUADLET_REQUEST,
- device->node_id, generation, device->max_speed,
- (CSR_REGISTER_BASE | CSR_CONFIG_ROM) + index * 4,
- data, 4);
+ for (i = 10; i < 100; i += 10) {
+ rcode = fw_run_transaction(device->card,
+ TCODE_READ_QUADLET_REQUEST, device->node_id,
+ generation, device->max_speed, offset, data, 4);
+ if (rcode != RCODE_BUSY)
+ break;
+ msleep(i);
+ }
be32_to_cpus(data);
return rcode;
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index ee76c8ec72f6..271fc518dec5 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -262,6 +262,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_CREATIVE_SB1394 0x4001
#define PCI_DEVICE_ID_JMICRON_JMB38X_FW 0x2380
#define PCI_DEVICE_ID_TI_TSB12LV22 0x8009
#define PCI_VENDOR_ID_PINNACLE_SYSTEMS 0x11bd
@@ -285,6 +286,9 @@ static const struct {
{PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_AGERE_FW643, 6,
QUIRK_NO_MSI},
+ {PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_SB1394, PCI_ANY_ID,
+ QUIRK_RESET_PACKET},
+
{PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB38X_FW, PCI_ANY_ID,
QUIRK_NO_MSI},
@@ -295,7 +299,7 @@ static const struct {
QUIRK_NO_MSI},
{PCI_VENDOR_ID_RICOH, PCI_ANY_ID, PCI_ANY_ID,
- QUIRK_CYCLE_TIMER},
+ QUIRK_CYCLE_TIMER | QUIRK_NO_MSI},
{PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, PCI_ANY_ID,
QUIRK_CYCLE_TIMER | QUIRK_RESET_PACKET | QUIRK_NO_1394A},
@@ -2554,15 +2558,14 @@ static int handle_ir_buffer_fill(struct context *context,
struct iso_context *ctx =
container_of(context, struct iso_context, context);
- if (!last->transfer_status)
+ if (last->res_count != 0)
/* Descriptor(s) not done yet, stop iteration */
return 0;
if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS)
ctx->base.callback.mc(&ctx->base,
le32_to_cpu(last->data_address) +
- le16_to_cpu(last->req_count) -
- le16_to_cpu(last->res_count),
+ le16_to_cpu(last->req_count),
ctx->base.callback_data);
return 1;
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 5f29aafd4462..e27d56c7cc19 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -141,23 +141,213 @@ efivar_create_sysfs_entry(struct efivars *efivars,
/* Return the number of unicode characters in data */
static unsigned long
-utf8_strlen(efi_char16_t *data, unsigned long maxlength)
+utf16_strnlen(efi_char16_t *s, size_t maxlength)
{
unsigned long length = 0;
- while (*data++ != 0 && length < maxlength)
+ while (*s++ != 0 && length < maxlength)
length++;
return length;
}
+static inline unsigned long
+utf16_strlen(efi_char16_t *s)
+{
+ return utf16_strnlen(s, ~0UL);
+}
+
/*
* Return the number of bytes is the length of this string
* Note: this is NOT the same as the number of unicode characters
*/
static inline unsigned long
-utf8_strsize(efi_char16_t *data, unsigned long maxlength)
+utf16_strsize(efi_char16_t *data, unsigned long maxlength)
+{
+ return utf16_strnlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
+}
+
+static bool
+validate_device_path(struct efi_variable *var, int match, u8 *buffer,
+ unsigned long len)
+{
+ struct efi_generic_dev_path *node;
+ int offset = 0;
+
+ node = (struct efi_generic_dev_path *)buffer;
+
+ if (len < sizeof(*node))
+ return false;
+
+ while (offset <= len - sizeof(*node) &&
+ node->length >= sizeof(*node) &&
+ node->length <= len - offset) {
+ offset += node->length;
+
+ if ((node->type == EFI_DEV_END_PATH ||
+ node->type == EFI_DEV_END_PATH2) &&
+ node->sub_type == EFI_DEV_END_ENTIRE)
+ return true;
+
+ node = (struct efi_generic_dev_path *)(buffer + offset);
+ }
+
+ /*
+ * If we're here then either node->length pointed past the end
+ * of the buffer or we reached the end of the buffer without
+ * finding a device path end node.
+ */
+ return false;
+}
+
+static bool
+validate_boot_order(struct efi_variable *var, int match, u8 *buffer,
+ unsigned long len)
+{
+ /* An array of 16-bit integers */
+ if ((len % 2) != 0)
+ return false;
+
+ return true;
+}
+
+static bool
+validate_load_option(struct efi_variable *var, int match, u8 *buffer,
+ unsigned long len)
+{
+ u16 filepathlength;
+ int i, desclength = 0, namelen;
+
+ namelen = utf16_strnlen(var->VariableName, sizeof(var->VariableName));
+
+ /* Either "Boot" or "Driver" followed by four digits of hex */
+ for (i = match; i < match+4; i++) {
+ if (var->VariableName[i] > 127 ||
+ hex_to_bin(var->VariableName[i] & 0xff) < 0)
+ return true;
+ }
+
+ /* Reject it if there's 4 digits of hex and then further content */
+ if (namelen > match + 4)
+ return false;
+
+ /* A valid entry must be at least 8 bytes */
+ if (len < 8)
+ return false;
+
+ filepathlength = buffer[4] | buffer[5] << 8;
+
+ /*
+ * There's no stored length for the description, so it has to be
+ * found by hand
+ */
+ desclength = utf16_strsize((efi_char16_t *)(buffer + 6), len - 6) + 2;
+
+ /* Each boot entry must have a descriptor */
+ if (!desclength)
+ return false;
+
+ /*
+ * If the sum of the length of the description, the claimed filepath
+ * length and the original header are greater than the length of the
+ * variable, it's malformed
+ */
+ if ((desclength + filepathlength + 6) > len)
+ return false;
+
+ /*
+ * And, finally, check the filepath
+ */
+ return validate_device_path(var, match, buffer + desclength + 6,
+ filepathlength);
+}
+
+static bool
+validate_uint16(struct efi_variable *var, int match, u8 *buffer,
+ unsigned long len)
{
- return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
+ /* A single 16-bit integer */
+ if (len != 2)
+ return false;
+
+ return true;
+}
+
+static bool
+validate_ascii_string(struct efi_variable *var, int match, u8 *buffer,
+ unsigned long len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (buffer[i] > 127)
+ return false;
+
+ if (buffer[i] == 0)
+ return true;
+ }
+
+ return false;
+}
+
+struct variable_validate {
+ char *name;
+ bool (*validate)(struct efi_variable *var, int match, u8 *data,
+ unsigned long len);
+};
+
+static const struct variable_validate variable_validate[] = {
+ { "BootNext", validate_uint16 },
+ { "BootOrder", validate_boot_order },
+ { "DriverOrder", validate_boot_order },
+ { "Boot*", validate_load_option },
+ { "Driver*", validate_load_option },
+ { "ConIn", validate_device_path },
+ { "ConInDev", validate_device_path },
+ { "ConOut", validate_device_path },
+ { "ConOutDev", validate_device_path },
+ { "ErrOut", validate_device_path },
+ { "ErrOutDev", validate_device_path },
+ { "Timeout", validate_uint16 },
+ { "Lang", validate_ascii_string },
+ { "PlatformLang", validate_ascii_string },
+ { "", NULL },
+};
+
+static bool
+validate_var(struct efi_variable *var, u8 *data, unsigned long len)
+{
+ int i;
+ u16 *unicode_name = var->VariableName;
+
+ for (i = 0; variable_validate[i].validate != NULL; i++) {
+ const char *name = variable_validate[i].name;
+ int match;
+
+ for (match = 0; ; match++) {
+ char c = name[match];
+ u16 u = unicode_name[match];
+
+ /* All special variables are plain ascii */
+ if (u > 127)
+ return true;
+
+ /* Wildcard in the matching name means we've matched */
+ if (c == '*')
+ return variable_validate[i].validate(var,
+ match, data, len);
+
+ /* Case sensitive match */
+ if (c != u)
+ break;
+
+ /* Reached the end of the string while matching */
+ if (!c)
+ return variable_validate[i].validate(var,
+ match, data, len);
+ }
+ }
+
+ return true;
}
static efi_status_t
@@ -283,6 +473,12 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
return -EINVAL;
}
+ if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
+ validate_var(new_var, new_var->Data, new_var->DataSize) == false) {
+ printk(KERN_ERR "efivars: Malformed variable content\n");
+ return -EINVAL;
+ }
+
spin_lock(&efivars->lock);
status = efivars->ops->set_variable(new_var->VariableName,
&new_var->VendorGuid,
@@ -408,14 +604,20 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
+ if ((new_var->Attributes & ~EFI_VARIABLE_MASK) != 0 ||
+ validate_var(new_var, new_var->Data, new_var->DataSize) == false) {
+ printk(KERN_ERR "efivars: Malformed variable content\n");
+ return -EINVAL;
+ }
+
spin_lock(&efivars->lock);
/*
* Does this variable already exist?
*/
list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
- strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
- strsize2 = utf8_strsize(new_var->VariableName, 1024);
+ strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024);
+ strsize2 = utf16_strsize(new_var->VariableName, 1024);
if (strsize1 == strsize2 &&
!memcmp(&(search_efivar->var.VariableName),
new_var->VariableName, strsize1) &&
@@ -447,8 +649,8 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
/* Create the entry in sysfs. Locking is not required here */
status = efivar_create_sysfs_entry(efivars,
- utf8_strsize(new_var->VariableName,
- 1024),
+ utf16_strsize(new_var->VariableName,
+ 1024),
new_var->VariableName,
&new_var->VendorGuid);
if (status) {
@@ -477,8 +679,8 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
* Does this variable already exist?
*/
list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
- strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
- strsize2 = utf8_strsize(del_var->VariableName, 1024);
+ strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024);
+ strsize2 = utf16_strsize(del_var->VariableName, 1024);
if (strsize1 == strsize2 &&
!memcmp(&(search_efivar->var.VariableName),
del_var->VariableName, strsize1) &&
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index ab93c7abb25f..8ff575258390 100755
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -350,18 +350,19 @@ config GPIO_LANGWELL
Say Y here to support Intel Langwell/Penwell GPIO.
config GPIO_PCH
- tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GPIO"
+ tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7223/ML7831) GPIO"
depends on PCI && X86
help
This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
which is an IOH(Input/Output Hub) for x86 embedded processor.
This driver can access PCH GPIO device.
- This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
- Output Hub), ML7223.
+ This driver also can be used for LAPIS Semiconductor IOH(Input/
+ Output Hub), ML7223 and ML7831.
ML7223 IOH is for MP(Media Phone) use.
- ML7223 is companion chip for Intel Atom E6xx series.
- ML7223 is completely compatible for Intel EG20T PCH.
+ ML7831 IOH is for general purpose use.
+ ML7223/ML7831 is companion chip for Intel Atom E6xx series.
+ ML7223/ML7831 is completely compatible for Intel EG20T PCH.
config GPIO_ML_IOH
tristate "OKI SEMICONDUCTOR ML7213 IOH GPIO support"
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
index 0451d7ac94ac..532f69006264 100644
--- a/drivers/gpio/pca953x.c
+++ b/drivers/gpio/pca953x.c
@@ -437,7 +437,7 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
do {
level = __ffs(pending);
- generic_handle_irq(level + chip->irq_base);
+ handle_nested_irq(level + chip->irq_base);
pending &= ~(1 << level);
} while (pending);
@@ -481,8 +481,8 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
int irq = lvl + chip->irq_base;
irq_set_chip_data(irq, chip);
- irq_set_chip_and_handler(irq, &pca953x_irq_chip,
- handle_simple_irq);
+ irq_set_chip(irq, &pca953x_irq_chip);
+ irq_set_nested_thread(irq, true);
#ifdef CONFIG_ARM
set_irq_flags(irq, IRQF_VALID);
#else
diff --git a/drivers/gpio/pch_gpio.c b/drivers/gpio/pch_gpio.c
index 36919e77c495..de26978b420b 100644
--- a/drivers/gpio/pch_gpio.c
+++ b/drivers/gpio/pch_gpio.c
@@ -287,6 +287,7 @@ static int pch_gpio_resume(struct pci_dev *pdev)
static DEFINE_PCI_DEVICE_TABLE(pch_gpio_pcidev_id) = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8803) },
{ PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8014) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8803) },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, pch_gpio_pcidev_id);
diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c
index 3f46772f0cb2..ba23790450e9 100644
--- a/drivers/gpu/drm/drm_auth.c
+++ b/drivers/gpu/drm/drm_auth.c
@@ -101,7 +101,7 @@ static int drm_add_magic(struct drm_master *master, struct drm_file *priv,
* Searches and unlinks the entry in drm_device::magiclist with the magic
* number hash key, while holding the drm_device::struct_mutex lock.
*/
-static int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
+int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
{
struct drm_magic_entry *pt;
struct drm_hash_item *hash;
@@ -136,6 +136,8 @@ static int drm_remove_magic(struct drm_master *master, drm_magic_t magic)
* If there is a magic number in drm_file::magic then use it, otherwise
* searches an unique non-zero magic number and add it associating it with \p
* file_priv.
+ * This ioctl needs protection by the drm_global_mutex, which protects
+ * struct drm_file::magic and struct drm_magic_entry::priv.
*/
int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
@@ -173,6 +175,8 @@ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv)
* \return zero if authentication successed, or a negative number otherwise.
*
* Checks if \p file_priv is associated with the magic number passed in \arg.
+ * This ioctl needs protection by the drm_global_mutex, which protects
+ * struct drm_file::magic and struct drm_magic_entry::priv.
*/
int drm_authmagic(struct drm_device *dev, void *data,
struct drm_file *file_priv)
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 802b61ac3139..a9dcdc7d3728 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -610,9 +610,13 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
return -EINVAL;
/* Need to resize the fb object !!! */
- if (var->bits_per_pixel > fb->bits_per_pixel || var->xres > fb->width || var->yres > fb->height) {
+ if (var->bits_per_pixel > fb->bits_per_pixel ||
+ var->xres > fb->width || var->yres > fb->height ||
+ var->xres_virtual > fb->width || var->yres_virtual > fb->height) {
DRM_DEBUG("fb userspace requested width/height/bpp is greater than current fb "
- "object %dx%d-%d > %dx%d-%d\n", var->xres, var->yres, var->bits_per_pixel,
+ "request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n",
+ var->xres, var->yres, var->bits_per_pixel,
+ var->xres_virtual, var->yres_virtual,
fb->width, fb->height, fb->bits_per_pixel);
return -EINVAL;
}
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 2ec7d48fc4a8..c42e12cc2ddb 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -486,6 +486,11 @@ int drm_release(struct inode *inode, struct file *filp)
(long)old_encode_dev(file_priv->minor->device),
dev->open_count);
+ /* Release any auth tokens that might point to this file_priv,
+ (do that under the drm_global_mutex) */
+ if (file_priv->magic)
+ (void) drm_remove_magic(file_priv->master, file_priv->magic);
+
/* if the master has gone away we can't do anything with the lock */
if (file_priv->minor->master)
drm_master_release(dev, filp);
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 7eef6e11d9ac..ef164432ba6d 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1451,6 +1451,14 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
diff1 = now - dev_priv->last_time1;
+ /* Prevent division-by-zero if we are asking too fast.
+ * Also, we don't get interesting results if we are polling
+ * faster than once in 10ms, so just return the saved value
+ * in such cases.
+ */
+ if (diff1 <= 10)
+ return dev_priv->chipset_power;
+
count1 = I915_READ(DMIEC);
count2 = I915_READ(DDREC);
count3 = I915_READ(CSIEC);
@@ -1481,6 +1489,8 @@ unsigned long i915_chipset_val(struct drm_i915_private *dev_priv)
dev_priv->last_count1 = total_count;
dev_priv->last_time1 = now;
+ dev_priv->chipset_power = ret;
+
return ret;
}
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index eb91e2dd7914..111686ada271 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -379,6 +379,10 @@ static int i915_drm_freeze(struct drm_device *dev)
/* Modeset on resume, not lid events */
dev_priv->modeset_on_lid = 0;
+ console_lock();
+ intel_fbdev_set_suspend(dev, 1);
+ console_unlock();
+
return 0;
}
@@ -438,7 +442,9 @@ static int i915_drm_thaw(struct drm_device *dev)
drm_irq_install(dev);
/* Resume the modeset for every activated CRTC */
+ mutex_lock(&dev->mode_config.mutex);
drm_helper_resume_force_mode(dev);
+ mutex_unlock(&dev->mode_config.mutex);
if (IS_IRONLAKE_M(dev))
ironlake_enable_rc6(dev);
@@ -448,6 +454,9 @@ static int i915_drm_thaw(struct drm_device *dev)
dev_priv->modeset_on_lid = 0;
+ console_lock();
+ intel_fbdev_set_suspend(dev, 0);
+ console_unlock();
return error;
}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index e0d0e278f62d..b570415c3fd9 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -325,6 +325,8 @@ typedef struct drm_i915_private {
struct timer_list hangcheck_timer;
int hangcheck_count;
uint32_t last_acthd;
+ uint32_t last_acthd_bsd;
+ uint32_t last_acthd_blt;
uint32_t last_instdone;
uint32_t last_instdone1;
@@ -702,6 +704,7 @@ typedef struct drm_i915_private {
u64 last_count1;
unsigned long last_time1;
+ unsigned long chipset_power;
u64 last_count2;
struct timespec last_time2;
unsigned long gfx_power;
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 4934cf84c320..bc927ae3164f 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1046,6 +1046,11 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
return -EINVAL;
}
+ if (args->num_cliprects > UINT_MAX / sizeof(*cliprects)) {
+ DRM_DEBUG("execbuf with %u cliprects\n",
+ args->num_cliprects);
+ return -EINVAL;
+ }
cliprects = kmalloc(args->num_cliprects * sizeof(*cliprects),
GFP_KERNEL);
if (cliprects == NULL) {
@@ -1296,7 +1301,8 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
struct drm_i915_gem_exec_object2 *exec2_list = NULL;
int ret;
- if (args->buffer_count < 1) {
+ if (args->buffer_count < 1 ||
+ args->buffer_count > UINT_MAX / sizeof(*exec2_list)) {
DRM_ERROR("execbuf2 with %d buffers\n", args->buffer_count);
return -EINVAL;
}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 363564704b1b..d05f03c62847 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -422,14 +422,11 @@ static void gen6_pm_rps_work(struct work_struct *work)
mutex_unlock(&dev_priv->dev->struct_mutex);
}
-static void pch_irq_handler(struct drm_device *dev)
+static void pch_irq_handler(struct drm_device *dev, u32 pch_iir)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- u32 pch_iir;
int pipe;
- pch_iir = I915_READ(SDEIIR);
-
if (pch_iir & SDE_AUDIO_POWER_MASK)
DRM_DEBUG_DRIVER("PCH audio power change on port %d\n",
(pch_iir & SDE_AUDIO_POWER_MASK) >>
@@ -527,7 +524,7 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)
if (de_iir & DE_PCH_EVENT_IVB) {
if (pch_iir & SDE_HOTPLUG_MASK_CPT)
queue_work(dev_priv->wq, &dev_priv->hotplug_work);
- pch_irq_handler(dev);
+ pch_irq_handler(dev, pch_iir);
}
if (pm_iir & GEN6_PM_DEFERRED_EVENTS) {
@@ -626,7 +623,7 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)
if (de_iir & DE_PCH_EVENT) {
if (pch_iir & hotplug_mask)
queue_work(dev_priv->wq, &dev_priv->hotplug_work);
- pch_irq_handler(dev);
+ pch_irq_handler(dev, pch_iir);
}
if (de_iir & DE_PCU_EVENT) {
@@ -1665,7 +1662,7 @@ void i915_hangcheck_elapsed(unsigned long data)
{
struct drm_device *dev = (struct drm_device *)data;
drm_i915_private_t *dev_priv = dev->dev_private;
- uint32_t acthd, instdone, instdone1;
+ uint32_t acthd, instdone, instdone1, acthd_bsd, acthd_blt;
bool err = false;
/* If all work is done then ACTHD clearly hasn't advanced. */
@@ -1679,16 +1676,21 @@ void i915_hangcheck_elapsed(unsigned long data)
}
if (INTEL_INFO(dev)->gen < 4) {
- acthd = I915_READ(ACTHD);
instdone = I915_READ(INSTDONE);
instdone1 = 0;
} else {
- acthd = I915_READ(ACTHD_I965);
instdone = I915_READ(INSTDONE_I965);
instdone1 = I915_READ(INSTDONE1);
}
+ acthd = intel_ring_get_active_head(&dev_priv->ring[RCS]);
+ acthd_bsd = HAS_BSD(dev) ?
+ intel_ring_get_active_head(&dev_priv->ring[VCS]) : 0;
+ acthd_blt = HAS_BLT(dev) ?
+ intel_ring_get_active_head(&dev_priv->ring[BCS]) : 0;
if (dev_priv->last_acthd == acthd &&
+ dev_priv->last_acthd_bsd == acthd_bsd &&
+ dev_priv->last_acthd_blt == acthd_blt &&
dev_priv->last_instdone == instdone &&
dev_priv->last_instdone1 == instdone1) {
if (dev_priv->hangcheck_count++ > 1) {
@@ -1720,6 +1722,8 @@ void i915_hangcheck_elapsed(unsigned long data)
dev_priv->hangcheck_count = 0;
dev_priv->last_acthd = acthd;
+ dev_priv->last_acthd_bsd = acthd_bsd;
+ dev_priv->last_acthd_blt = acthd_blt;
dev_priv->last_instdone = instdone;
dev_priv->last_instdone1 = instdone1;
}
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 673f0d2cd4ec..387b2b34e93f 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -537,6 +537,21 @@
#define GEN6_BSD_RNCID 0x12198
+#define GEN7_FF_THREAD_MODE 0x20a0
+#define GEN7_FF_SCHED_MASK 0x0077070
+#define GEN7_FF_TS_SCHED_HS1 (0x5<<16)
+#define GEN7_FF_TS_SCHED_HS0 (0x3<<16)
+#define GEN7_FF_TS_SCHED_LOAD_BALANCE (0x1<<16)
+#define GEN7_FF_TS_SCHED_HW (0x0<<16) /* Default */
+#define GEN7_FF_VS_SCHED_HS1 (0x5<<12)
+#define GEN7_FF_VS_SCHED_HS0 (0x3<<12)
+#define GEN7_FF_VS_SCHED_LOAD_BALANCE (0x1<<12) /* Default */
+#define GEN7_FF_VS_SCHED_HW (0x0<<12)
+#define GEN7_FF_DS_SCHED_HS1 (0x5<<4)
+#define GEN7_FF_DS_SCHED_HS0 (0x3<<4)
+#define GEN7_FF_DS_SCHED_LOAD_BALANCE (0x1<<4) /* Default */
+#define GEN7_FF_DS_SCHED_HW (0x0<<4)
+
/*
* Framebuffer compression (915+ only)
*/
@@ -2274,6 +2289,7 @@
#define PIPECONF_DISABLE 0
#define PIPECONF_DOUBLE_WIDE (1<<30)
#define I965_PIPECONF_ACTIVE (1<<30)
+#define PIPECONF_FRAME_START_DELAY_MASK (3<<27)
#define PIPECONF_SINGLE_WIDE 0
#define PIPECONF_PIPE_UNLOCKED 0
#define PIPECONF_PIPE_LOCKED (1<<25)
@@ -2847,6 +2863,20 @@
#define DISP_TILE_SURFACE_SWIZZLING (1<<13)
#define DISP_FBC_WM_DIS (1<<15)
+/* GEN7 chicken */
+#define GEN7_COMMON_SLICE_CHICKEN1 0x7010
+# define GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC ((1<<10) | (1<<26))
+
+#define GEN7_L3CNTLREG1 0xB01C
+#define GEN7_WA_FOR_GEN7_L3_CONTROL 0x3C4FFF8C
+
+#define GEN7_L3_CHICKEN_MODE_REGISTER 0xB030
+#define GEN7_WA_L3_CHICKEN_MODE 0x20000000
+
+/* WaCatErrorRejectionIssue */
+#define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG 0x9030
+#define GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB (1<<11)
+
/* PCH */
/* south display engine interrupt */
@@ -3371,6 +3401,7 @@
#define GT_FIFO_FREE_ENTRIES 0x120008
#define GEN6_UCGCTL2 0x9404
+# define GEN6_RCZUNIT_CLOCK_GATE_DISABLE (1 << 13)
# define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE (1 << 12)
# define GEN6_RCCUNIT_CLOCK_GATE_DISABLE (1 << 11)
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c
index cf15533aabf6..bc7dcaa1c689 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -34,6 +34,10 @@ static bool i915_pipe_enabled(struct drm_device *dev, enum pipe pipe)
struct drm_i915_private *dev_priv = dev->dev_private;
u32 dpll_reg;
+ /* On IVB, 3rd pipe shares PLL with another one */
+ if (pipe > 1)
+ return false;
+
if (HAS_PCH_SPLIT(dev))
dpll_reg = (pipe == PIPE_A) ? _PCH_DPLL_A : _PCH_DPLL_B;
else
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 927442a11925..e5fa074b7830 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -24,6 +24,7 @@
* Eric Anholt <eric@anholt.net>
*
*/
+#include <linux/dmi.h>
#include <drm/drm_dp_helper.h>
#include "drmP.h"
#include "drm.h"
@@ -592,6 +593,26 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
dev_priv->edp.bpp = 18;
}
+static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
+{
+ DRM_DEBUG_KMS("Falling back to manually reading VBT from "
+ "VBIOS ROM for %s\n",
+ id->ident);
+ return 1;
+}
+
+static const struct dmi_system_id intel_no_opregion_vbt[] = {
+ {
+ .callback = intel_no_opregion_vbt_callback,
+ .ident = "ThinkCentre A57",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "97027RG"),
+ },
+ },
+ { }
+};
+
/**
* intel_parse_bios - find VBT and initialize settings from the BIOS
* @dev: DRM device
@@ -612,7 +633,7 @@ intel_parse_bios(struct drm_device *dev)
init_vbt_defaults(dev_priv);
/* XXX Should this validation be moved to intel_opregion.c? */
- if (dev_priv->opregion.vbt) {
+ if (!dmi_check_system(intel_no_opregion_vbt) && dev_priv->opregion.vbt) {
struct vbt_header *vbt = dev_priv->opregion.vbt;
if (memcmp(vbt->signature, "$VBT", 4) == 0) {
DRM_DEBUG_DRIVER("Using VBT from OpRegion: %20s\n",
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index fed87d6a5b99..4b8e23555179 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5265,7 +5265,7 @@ void intel_crtc_load_lut(struct drm_crtc *crtc)
int i;
/* The clocks have to be on to load the palette. */
- if (!crtc->enabled)
+ if (!crtc->enabled || !intel_crtc->active)
return;
/* use legacy palette for Ironlake */
@@ -6579,6 +6579,13 @@ static void intel_sanitize_modesetting(struct drm_device *dev,
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg, val;
+ int i;
+
+ /* Clear any frame start delays used for debugging left by the BIOS */
+ for_each_pipe(i) {
+ reg = PIPECONF(i);
+ I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
+ }
if (HAS_PCH_SPLIT(dev))
return;
@@ -7445,6 +7452,18 @@ static void gen6_init_clock_gating(struct drm_device *dev)
DISPPLANE_TRICKLE_FEED_DISABLE);
}
+static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv)
+{
+ uint32_t reg = I915_READ(GEN7_FF_THREAD_MODE);
+
+ reg &= ~GEN7_FF_SCHED_MASK;
+ reg |= GEN7_FF_TS_SCHED_HW;
+ reg |= GEN7_FF_VS_SCHED_HW;
+ reg |= GEN7_FF_DS_SCHED_HW;
+
+ I915_WRITE(GEN7_FF_THREAD_MODE, reg);
+}
+
static void ivybridge_init_clock_gating(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -7457,8 +7476,28 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)
I915_WRITE(WM2_LP_ILK, 0);
I915_WRITE(WM1_LP_ILK, 0);
+ /* According to the spec, bit 13 (RCZUNIT) must be set on IVB.
+ * This implements the WaDisableRCZUnitClockGating workaround.
+ */
+ I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE);
+
I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE);
+ /* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */
+ I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1,
+ GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC);
+
+ /* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */
+ I915_WRITE(GEN7_L3CNTLREG1,
+ GEN7_WA_FOR_GEN7_L3_CONTROL);
+ I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER,
+ GEN7_WA_L3_CHICKEN_MODE);
+
+ /* This is required by WaCatErrorRejectionIssue */
+ I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
+ I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
+ GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
+
for_each_pipe(pipe)
I915_WRITE(DSPCNTR(pipe),
I915_READ(DSPCNTR(pipe)) |
@@ -7571,6 +7610,8 @@ static void ironlake_teardown_rc6(struct drm_device *dev)
drm_gem_object_unreference(&dev_priv->pwrctx->base);
dev_priv->pwrctx = NULL;
}
+
+ gen7_setup_fixed_func_scheduler(dev_priv);
}
static void ironlake_disable_rc6(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 14264a8c03eb..bf9fea941617 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1554,6 +1554,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)
intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe);
}
+ DP &= ~DP_AUDIO_OUTPUT_ENABLE;
I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
POSTING_READ(intel_dp->output_reg);
}
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 9ffa61eb4d7e..47bf5e15f03e 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -330,7 +330,7 @@ extern int intel_framebuffer_init(struct drm_device *dev,
struct drm_i915_gem_object *obj);
extern int intel_fbdev_init(struct drm_device *dev);
extern void intel_fbdev_fini(struct drm_device *dev);
-
+extern void intel_fbdev_set_suspend(struct drm_device *dev, int state);
extern void intel_prepare_page_flip(struct drm_device *dev, int plane);
extern void intel_finish_page_flip(struct drm_device *dev, int pipe);
extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index ec49bae73382..d0ce34b78cc7 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -257,6 +257,16 @@ void intel_fbdev_fini(struct drm_device *dev)
kfree(dev_priv->fbdev);
dev_priv->fbdev = NULL;
}
+
+void intel_fbdev_set_suspend(struct drm_device *dev, int state)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ if (!dev_priv->fbdev)
+ return;
+
+ fb_set_suspend(dev_priv->fbdev->helper.fbdev, state);
+}
+
MODULE_LICENSE("GPL and additional rights");
void intel_fb_output_poll_changed(struct drm_device *dev)
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index aa0a8e83142e..236bbe09abd5 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -158,6 +158,10 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
u32 temp;
+ u32 enable_bits = SDVO_ENABLE;
+
+ if (intel_hdmi->has_audio)
+ enable_bits |= SDVO_AUDIO_ENABLE;
temp = I915_READ(intel_hdmi->sdvox_reg);
@@ -170,9 +174,9 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
}
if (mode != DRM_MODE_DPMS_ON) {
- temp &= ~SDVO_ENABLE;
+ temp &= ~enable_bits;
} else {
- temp |= SDVO_ENABLE;
+ temp |= enable_bits;
}
I915_WRITE(intel_hdmi->sdvox_reg, temp);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index b28f7bd9f88a..ff85a91eb014 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -714,6 +714,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
},
{
.callback = intel_no_lvds_dmi_callback,
+ .ident = "AOpen i45GMx-I",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
+ DMI_MATCH(DMI_BOARD_NAME, "i45GMx-I"),
+ },
+ },
+ {
+ .callback = intel_no_lvds_dmi_callback,
.ident = "Aopen i945GTt-VFA",
.matches = {
DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"),
@@ -735,6 +743,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"),
},
},
+ {
+ .callback = intel_no_lvds_dmi_callback,
+ .ident = "MSI Wind Box DC500",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
+ DMI_MATCH(DMI_BOARD_NAME, "MS-7469"),
+ },
+ },
{ } /* terminating entry */
};
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 1f61fc7b754c..2d6039b4571f 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -863,7 +863,7 @@ int intel_init_ring_buffer(struct drm_device *dev,
* of the buffer.
*/
ring->effective_size = ring->size;
- if (IS_I830(ring->dev))
+ if (IS_I830(ring->dev) || IS_845G(ring->dev))
ring->effective_size -= 128;
return 0;
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 30fe554d8936..c90106074743 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -724,6 +724,7 @@ static void intel_sdvo_get_dtd_from_mode(struct intel_sdvo_dtd *dtd,
uint16_t width, height;
uint16_t h_blank_len, h_sync_len, v_blank_len, v_sync_len;
uint16_t h_sync_offset, v_sync_offset;
+ int mode_clock;
width = mode->crtc_hdisplay;
height = mode->crtc_vdisplay;
@@ -738,7 +739,11 @@ static void intel_sdvo_get_dtd_from_mode(struct intel_sdvo_dtd *dtd,
h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start;
v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start;
- dtd->part1.clock = mode->clock / 10;
+ mode_clock = mode->clock;
+ mode_clock /= intel_mode_get_pixel_multiplier(mode) ?: 1;
+ mode_clock /= 10;
+ dtd->part1.clock = mode_clock;
+
dtd->part1.h_active = width & 0xff;
dtd->part1.h_blank = h_blank_len & 0xff;
dtd->part1.h_high = (((width >> 8) & 0xf) << 4) |
@@ -757,10 +762,12 @@ static void intel_sdvo_get_dtd_from_mode(struct intel_sdvo_dtd *dtd,
((v_sync_len & 0x30) >> 4);
dtd->part2.dtd_flags = 0x18;
+ if (mode->flags & DRM_MODE_FLAG_INTERLACE)
+ dtd->part2.dtd_flags |= DTD_FLAG_INTERLACE;
if (mode->flags & DRM_MODE_FLAG_PHSYNC)
- dtd->part2.dtd_flags |= 0x2;
+ dtd->part2.dtd_flags |= DTD_FLAG_HSYNC_POSITIVE;
if (mode->flags & DRM_MODE_FLAG_PVSYNC)
- dtd->part2.dtd_flags |= 0x4;
+ dtd->part2.dtd_flags |= DTD_FLAG_VSYNC_POSITIVE;
dtd->part2.sdvo_flags = 0;
dtd->part2.v_sync_off_high = v_sync_offset & 0xc0;
@@ -794,9 +801,11 @@ static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode,
mode->clock = dtd->part1.clock * 10;
mode->flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
- if (dtd->part2.dtd_flags & 0x2)
+ if (dtd->part2.dtd_flags & DTD_FLAG_INTERLACE)
+ mode->flags |= DRM_MODE_FLAG_INTERLACE;
+ if (dtd->part2.dtd_flags & DTD_FLAG_HSYNC_POSITIVE)
mode->flags |= DRM_MODE_FLAG_PHSYNC;
- if (dtd->part2.dtd_flags & 0x4)
+ if (dtd->part2.dtd_flags & DTD_FLAG_VSYNC_POSITIVE)
mode->flags |= DRM_MODE_FLAG_PVSYNC;
}
@@ -990,7 +999,7 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
struct intel_sdvo *intel_sdvo = to_intel_sdvo(encoder);
u32 sdvox;
struct intel_sdvo_in_out_map in_out;
- struct intel_sdvo_dtd input_dtd;
+ struct intel_sdvo_dtd input_dtd, output_dtd;
int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode);
int rate;
@@ -1015,20 +1024,13 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
intel_sdvo->attached_output))
return;
- /* We have tried to get input timing in mode_fixup, and filled into
- * adjusted_mode.
- */
- if (intel_sdvo->is_tv || intel_sdvo->is_lvds) {
- input_dtd = intel_sdvo->input_dtd;
- } else {
- /* Set the output timing to the screen */
- if (!intel_sdvo_set_target_output(intel_sdvo,
- intel_sdvo->attached_output))
- return;
-
- intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
- (void) intel_sdvo_set_output_timing(intel_sdvo, &input_dtd);
- }
+ /* lvds has a special fixed output timing. */
+ if (intel_sdvo->is_lvds)
+ intel_sdvo_get_dtd_from_mode(&output_dtd,
+ intel_sdvo->sdvo_lvds_fixed_mode);
+ else
+ intel_sdvo_get_dtd_from_mode(&output_dtd, mode);
+ (void) intel_sdvo_set_output_timing(intel_sdvo, &output_dtd);
/* Set the input timing to the screen. Assume always input 0. */
if (!intel_sdvo_set_target_input(intel_sdvo))
@@ -1046,6 +1048,10 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
!intel_sdvo_set_tv_format(intel_sdvo))
return;
+ /* We have tried to get input timing in mode_fixup, and filled into
+ * adjusted_mode.
+ */
+ intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
(void) intel_sdvo_set_input_timing(intel_sdvo, &input_dtd);
switch (pixel_multiplier) {
@@ -1059,15 +1065,13 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
/* Set the SDVO control regs. */
if (INTEL_INFO(dev)->gen >= 4) {
- sdvox = 0;
+ /* The real mode polarity is set by the SDVO commands, using
+ * struct intel_sdvo_dtd. */
+ sdvox = SDVO_VSYNC_ACTIVE_HIGH | SDVO_HSYNC_ACTIVE_HIGH;
if (intel_sdvo->is_hdmi)
sdvox |= intel_sdvo->color_range;
if (INTEL_INFO(dev)->gen < 5)
sdvox |= SDVO_BORDER_ENABLE;
- if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
- sdvox |= SDVO_VSYNC_ACTIVE_HIGH;
- if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
- sdvox |= SDVO_HSYNC_ACTIVE_HIGH;
} else {
sdvox = I915_READ(intel_sdvo->sdvo_reg);
switch (intel_sdvo->sdvo_reg) {
diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h
index 4f4e23bc2d16..c5c8ddf2c1ad 100644
--- a/drivers/gpu/drm/i915/intel_sdvo_regs.h
+++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h
@@ -61,6 +61,11 @@ struct intel_sdvo_caps {
u16 output_flags;
} __attribute__((packed));
+/* Note: SDVO detailed timing flags match EDID misc flags. */
+#define DTD_FLAG_HSYNC_POSITIVE (1 << 1)
+#define DTD_FLAG_VSYNC_POSITIVE (1 << 2)
+#define DTD_FLAG_INTERLACE (1 << 7)
+
/** This matches the EDID DTD structure, more or less */
struct intel_sdvo_dtd {
struct {
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 113e4e7264cd..2136e6bc8937 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -417,7 +417,7 @@ static const struct tv_mode tv_modes[] = {
{
.name = "NTSC-M",
.clock = 108000,
- .refresh = 29970,
+ .refresh = 59940,
.oversample = TV_OVERSAMPLE_8X,
.component_only = 0,
/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 3.580MHz */
@@ -460,7 +460,7 @@ static const struct tv_mode tv_modes[] = {
{
.name = "NTSC-443",
.clock = 108000,
- .refresh = 29970,
+ .refresh = 59940,
.oversample = TV_OVERSAMPLE_8X,
.component_only = 0,
/* 525 Lines, 60 Fields, 15.734KHz line, Sub-Carrier 4.43MHz */
@@ -502,7 +502,7 @@ static const struct tv_mode tv_modes[] = {
{
.name = "NTSC-J",
.clock = 108000,
- .refresh = 29970,
+ .refresh = 59940,
.oversample = TV_OVERSAMPLE_8X,
.component_only = 0,
@@ -545,7 +545,7 @@ static const struct tv_mode tv_modes[] = {
{
.name = "PAL-M",
.clock = 108000,
- .refresh = 29970,
+ .refresh = 59940,
.oversample = TV_OVERSAMPLE_8X,
.component_only = 0,
@@ -589,7 +589,7 @@ static const struct tv_mode tv_modes[] = {
/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
.name = "PAL-N",
.clock = 108000,
- .refresh = 25000,
+ .refresh = 50000,
.oversample = TV_OVERSAMPLE_8X,
.component_only = 0,
@@ -634,7 +634,7 @@ static const struct tv_mode tv_modes[] = {
/* 625 Lines, 50 Fields, 15.625KHz line, Sub-Carrier 4.434MHz */
.name = "PAL",
.clock = 108000,
- .refresh = 25000,
+ .refresh = 50000,
.oversample = TV_OVERSAMPLE_8X,
.component_only = 0,
@@ -821,7 +821,7 @@ static const struct tv_mode tv_modes[] = {
{
.name = "1080i@50Hz",
.clock = 148800,
- .refresh = 25000,
+ .refresh = 50000,
.oversample = TV_OVERSAMPLE_2X,
.component_only = 1,
@@ -847,7 +847,7 @@ static const struct tv_mode tv_modes[] = {
{
.name = "1080i@60Hz",
.clock = 148800,
- .refresh = 30000,
+ .refresh = 60000,
.oversample = TV_OVERSAMPLE_2X,
.component_only = 1,
@@ -1301,6 +1301,11 @@ intel_tv_detect_type (struct intel_tv *intel_tv,
I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN);
I915_WRITE(TV_CTL, save_tv_ctl);
+ POSTING_READ(TV_CTL);
+
+ /* For unknown reasons the hw barfs if we don't do this vblank wait. */
+ intel_wait_for_vblank(intel_tv->base.base.dev,
+ to_intel_crtc(intel_tv->base.base.crtc)->pipe);
/* Restore interrupt config */
if (connector->polled & DRM_CONNECTOR_POLL_HPD) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 2ad49cbf7c8b..5fb98de0c57d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -1075,7 +1075,7 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
nvbo->placement.fpfn = 0;
nvbo->placement.lpfn = dev_priv->fb_mappable_pages;
- nouveau_bo_placement_set(nvbo, TTM_PL_VRAM, 0);
+ nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_VRAM, 0);
return nouveau_bo_validate(nvbo, false, true, false);
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index b52e46018245..cee78b26f60f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -315,6 +315,25 @@ retry:
}
static int
+validate_sync(struct nouveau_channel *chan, struct nouveau_bo *nvbo)
+{
+ struct nouveau_fence *fence = NULL;
+ int ret = 0;
+
+ spin_lock(&nvbo->bo.bdev->fence_lock);
+ if (nvbo->bo.sync_obj)
+ fence = nouveau_fence_ref(nvbo->bo.sync_obj);
+ spin_unlock(&nvbo->bo.bdev->fence_lock);
+
+ if (fence) {
+ ret = nouveau_fence_sync(fence, chan);
+ nouveau_fence_unref(&fence);
+ }
+
+ return ret;
+}
+
+static int
validate_list(struct nouveau_channel *chan, struct list_head *list,
struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr)
{
@@ -327,7 +346,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
list_for_each_entry(nvbo, list, entry) {
struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index];
- ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan);
+ ret = validate_sync(chan, nvbo);
if (unlikely(ret)) {
NV_ERROR(dev, "fail pre-validate sync\n");
return ret;
@@ -350,7 +369,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
return ret;
}
- ret = nouveau_fence_sync(nvbo->bo.sync_obj, chan);
+ ret = validate_sync(chan, nvbo);
if (unlikely(ret)) {
NV_ERROR(dev, "fail post-validate sync\n");
return ret;
diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c
index 9a0aee2f0650..88661eaa2c74 100644
--- a/drivers/gpu/drm/radeon/atom.c
+++ b/drivers/gpu/drm/radeon/atom.c
@@ -1301,8 +1301,11 @@ struct atom_context *atom_parse(struct card_info *card, void *bios)
int atom_asic_init(struct atom_context *ctx)
{
+ struct radeon_device *rdev = ctx->card->dev->dev_private;
int hwi = CU16(ctx->data_table + ATOM_DATA_FWI_PTR);
uint32_t ps[16];
+ int ret;
+
memset(ps, 0, 64);
ps[0] = cpu_to_le32(CU32(hwi + ATOM_FWI_DEFSCLK_PTR));
@@ -1312,7 +1315,17 @@ int atom_asic_init(struct atom_context *ctx)
if (!CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_INIT))
return 1;
- return atom_execute_table(ctx, ATOM_CMD_INIT, ps);
+ ret = atom_execute_table(ctx, ATOM_CMD_INIT, ps);
+ if (ret)
+ return ret;
+
+ memset(ps, 0, 64);
+
+ if (rdev->family < CHIP_R600) {
+ if (CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_SPDFANCNTL))
+ atom_execute_table(ctx, ATOM_CMD_SPDFANCNTL, ps);
+ }
+ return ret;
}
void atom_destroy(struct atom_context *ctx)
diff --git a/drivers/gpu/drm/radeon/atom.h b/drivers/gpu/drm/radeon/atom.h
index 93cfe2086ba0..25fea631dad2 100644
--- a/drivers/gpu/drm/radeon/atom.h
+++ b/drivers/gpu/drm/radeon/atom.h
@@ -44,6 +44,7 @@
#define ATOM_CMD_SETSCLK 0x0A
#define ATOM_CMD_SETMCLK 0x0B
#define ATOM_CMD_SETPCLK 0x0C
+#define ATOM_CMD_SPDFANCNTL 0x39
#define ATOM_DATA_FWI_PTR 0xC
#define ATOM_DATA_IIO_PTR 0x32
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
index 9541995e4b21..071ded119eb9 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -1173,7 +1173,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
WREG32(EVERGREEN_GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
WREG32(EVERGREEN_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
- crtc->mode.vdisplay);
+ target_fb->height);
x &= ~3;
y &= ~1;
WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset,
@@ -1342,7 +1342,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
- crtc->mode.vdisplay);
+ target_fb->height);
x &= ~3;
y &= ~1;
WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset,
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 21c5aa070b95..8846bad45e66 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -926,6 +926,11 @@ int evergreen_pcie_gart_enable(struct radeon_device *rdev)
WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
+ if ((rdev->family == CHIP_JUNIPER) ||
+ (rdev->family == CHIP_CYPRESS) ||
+ (rdev->family == CHIP_HEMLOCK) ||
+ (rdev->family == CHIP_BARTS))
+ WREG32(MC_VM_MD_L1_TLB3_CNTL, tmp);
}
WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
@@ -2064,9 +2069,9 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
WREG32(CC_SYS_RB_BACKEND_DISABLE, rb);
WREG32(GC_USER_RB_BACKEND_DISABLE, rb);
WREG32(CC_GC_SHADER_PIPE_CONFIG, sp);
- }
+ }
- grbm_gfx_index |= SE_BROADCAST_WRITES;
+ grbm_gfx_index = INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES;
WREG32(GRBM_GFX_INDEX, grbm_gfx_index);
WREG32(RLC_GFX_INDEX, grbm_gfx_index);
@@ -3257,6 +3262,18 @@ int evergreen_init(struct radeon_device *rdev)
rdev->accel_working = false;
}
}
+
+ /* Don't start up if the MC ucode is missing on BTC parts.
+ * The default clocks and voltages before the MC ucode
+ * is loaded are not suffient for advanced operations.
+ */
+ if (ASIC_IS_DCE5(rdev)) {
+ if (!rdev->mc_fw && !(rdev->flags & RADEON_IS_IGP)) {
+ DRM_ERROR("radeon: MC ucode required for NI+.\n");
+ return -EINVAL;
+ }
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
index b7b2714f0b32..6078ae4cc16e 100644
--- a/drivers/gpu/drm/radeon/evergreend.h
+++ b/drivers/gpu/drm/radeon/evergreend.h
@@ -230,6 +230,7 @@
#define MC_VM_MD_L1_TLB0_CNTL 0x2654
#define MC_VM_MD_L1_TLB1_CNTL 0x2658
#define MC_VM_MD_L1_TLB2_CNTL 0x265C
+#define MC_VM_MD_L1_TLB3_CNTL 0x2698
#define FUS_MC_VM_MD_L1_TLB0_CNTL 0x265C
#define FUS_MC_VM_MD_L1_TLB1_CNTL 0x2660
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index b94d871487e0..d94f440f1379 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -681,9 +681,7 @@ int r100_irq_process(struct radeon_device *rdev)
WREG32(RADEON_AIC_CNTL, msi_rearm | RS400_MSI_REARM);
break;
default:
- msi_rearm = RREG32(RADEON_MSI_REARM_EN) & ~RV370_MSI_REARM_EN;
- WREG32(RADEON_MSI_REARM_EN, msi_rearm);
- WREG32(RADEON_MSI_REARM_EN, msi_rearm | RV370_MSI_REARM_EN);
+ WREG32(RADEON_MSI_REARM_EN, RV370_MSI_REARM_EN);
break;
}
}
@@ -2069,6 +2067,7 @@ bool r100_gpu_is_lockup(struct radeon_device *rdev)
void r100_bm_disable(struct radeon_device *rdev)
{
u32 tmp;
+ u16 tmp16;
/* disable bus mastering */
tmp = RREG32(R_000030_BUS_CNTL);
@@ -2079,8 +2078,8 @@ void r100_bm_disable(struct radeon_device *rdev)
WREG32(R_000030_BUS_CNTL, (tmp & 0xFFFFFFFF) | 0x00000040);
tmp = RREG32(RADEON_BUS_CNTL);
mdelay(1);
- pci_read_config_word(rdev->pdev, 0x4, (u16*)&tmp);
- pci_write_config_word(rdev->pdev, 0x4, tmp & 0xFFFB);
+ pci_read_config_word(rdev->pdev, 0x4, &tmp16);
+ pci_write_config_word(rdev->pdev, 0x4, tmp16 & 0xFFFB);
mdelay(1);
}
diff --git a/drivers/gpu/drm/radeon/r600_blit_shaders.c b/drivers/gpu/drm/radeon/r600_blit_shaders.c
index 2d1f6c5ee2a7..73e2c7c6edbc 100644
--- a/drivers/gpu/drm/radeon/r600_blit_shaders.c
+++ b/drivers/gpu/drm/radeon/r600_blit_shaders.c
@@ -314,6 +314,10 @@ const u32 r6xx_default_state[] =
0x00000000, /* VGT_VTX_CNT_EN */
0xc0016900,
+ 0x000000d4,
+ 0x00000000, /* SX_MISC */
+
+ 0xc0016900,
0x000002c8,
0x00000000, /* VGT_STRMOUT_BUFFER_EN */
@@ -626,6 +630,10 @@ const u32 r7xx_default_state[] =
0x00000000, /* VGT_VTX_CNT_EN */
0xc0016900,
+ 0x000000d4,
+ 0x00000000, /* SX_MISC */
+
+ 0xc0016900,
0x000002c8,
0x00000000, /* VGT_STRMOUT_BUFFER_EN */
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
index f5ac7e788d81..c45d92191fd8 100644
--- a/drivers/gpu/drm/radeon/r600_hdmi.c
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -196,6 +196,13 @@ static void r600_hdmi_videoinfoframe(
frame[0xD] = (right_bar >> 8);
r600_hdmi_infoframe_checksum(0x82, 0x02, 0x0D, frame);
+ /* Our header values (type, version, length) should be alright, Intel
+ * is using the same. Checksum function also seems to be OK, it works
+ * fine for audio infoframe. However calculated value is always lower
+ * by 2 in comparison to fglrx. It breaks displaying anything in case
+ * of TVs that strictly check the checksum. Hack it manually here to
+ * workaround this issue. */
+ frame[0x0] += 2;
WREG32(offset+R600_HDMI_VIDEOINFOFRAME_0,
frame[0x0] | (frame[0x1] << 8) | (frame[0x2] << 16) | (frame[0x3] << 24));
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 285acc4f1e1d..ef6b426b1ee7 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -480,10 +480,26 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
*/
if ((dev->pdev->device == 0x9498) &&
(dev->pdev->subsystem_vendor == 0x1682) &&
- (dev->pdev->subsystem_device == 0x2452)) {
+ (dev->pdev->subsystem_device == 0x2452) &&
+ (i2c_bus->valid == false) &&
+ !(supported_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))) {
struct radeon_device *rdev = dev->dev_private;
*i2c_bus = radeon_lookup_i2c_gpio(rdev, 0x93);
}
+
+ /* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */
+ if ((dev->pdev->device == 0x9802) &&
+ (dev->pdev->subsystem_vendor == 0x1734) &&
+ (dev->pdev->subsystem_device == 0x11bd)) {
+ if (*connector_type == DRM_MODE_CONNECTOR_VGA) {
+ *connector_type = DRM_MODE_CONNECTOR_DVII;
+ *line_mux = 0x3103;
+ } else if (*connector_type == DRM_MODE_CONNECTOR_DVID) {
+ *connector_type = DRM_MODE_CONNECTOR_DVII;
+ }
+ }
+
+
return true;
}
@@ -2568,7 +2584,11 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
rdev->pm.current_clock_mode_index = 0;
- rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+ if (rdev->pm.default_power_state_index >= 0)
+ rdev->pm.current_vddc =
+ rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+ else
+ rdev->pm.current_vddc = 0;
}
void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable)
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 2109c17a9820..1f6a0f55ad19 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -990,6 +990,10 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
encoder = obj_to_encoder(obj);
+ if (encoder->encoder_type != DRM_MODE_ENCODER_DAC &&
+ encoder->encoder_type != DRM_MODE_ENCODER_TVDAC)
+ continue;
+
encoder_funcs = encoder->helper_private;
if (encoder_funcs->detect) {
if (ret != connector_status_connected) {
@@ -1016,6 +1020,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
* cases the DVI port is actually a virtual KVM port connected to the service
* processor.
*/
+out:
if ((!rdev->is_atom_bios) &&
(ret == connector_status_disconnected) &&
rdev->mode_info.bios_hardcoded_edid_size) {
@@ -1023,7 +1028,6 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
ret = connector_status_connected;
}
-out:
/* updated in get modes as well since we need to know if it's analog or digital */
radeon_connector_update_scratch_regs(connector, ret);
return ret;
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c
index f59a6823301f..3fb222615c6f 100644
--- a/drivers/gpu/drm/radeon/radeon_cursor.c
+++ b/drivers/gpu/drm/radeon/radeon_cursor.c
@@ -151,7 +151,9 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc,
uint32_t height)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
+ struct radeon_device *rdev = crtc->dev->dev_private;
struct drm_gem_object *obj;
+ struct radeon_bo *robj;
uint64_t gpu_addr;
int ret;
@@ -173,7 +175,15 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc,
return -ENOENT;
}
- ret = radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
+ robj = gem_to_radeon_bo(obj);
+ ret = radeon_bo_reserve(robj, false);
+ if (unlikely(ret != 0))
+ goto fail;
+ /* Only 27 bit offset for legacy cursor */
+ ret = radeon_bo_pin_restricted(robj, RADEON_GEM_DOMAIN_VRAM,
+ ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27,
+ &gpu_addr);
+ radeon_bo_unreserve(robj);
if (ret)
goto fail;
@@ -181,7 +191,6 @@ int radeon_crtc_cursor_set(struct drm_crtc *crtc,
radeon_crtc->cursor_height = height;
radeon_lock_cursor(crtc, true);
- /* XXX only 27 bit offset for legacy cursor */
radeon_set_cursor(crtc, obj, gpu_addr);
radeon_show_cursor(crtc);
radeon_lock_cursor(crtc, false);
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 440e6ecccc40..e87893c2c88a 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -223,8 +223,11 @@ int radeon_wb_init(struct radeon_device *rdev)
if (radeon_no_wb == 1)
rdev->wb.enabled = false;
else {
- /* often unreliable on AGP */
if (rdev->flags & RADEON_IS_AGP) {
+ /* often unreliable on AGP */
+ rdev->wb.enabled = false;
+ } else if (rdev->family < CHIP_R300) {
+ /* often unreliable on pre-r300 */
rdev->wb.enabled = false;
} else {
rdev->wb.enabled = true;
@@ -854,6 +857,8 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
return 0;
+ drm_kms_helper_poll_disable(dev);
+
/* turn off display hw */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
@@ -940,6 +945,8 @@ int radeon_resume_kms(struct drm_device *dev)
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
}
+
+ drm_kms_helper_poll_enable(dev);
return 0;
}
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c
index 6c111c1fa3f9..c90425c439d8 100644
--- a/drivers/gpu/drm/radeon/radeon_i2c.c
+++ b/drivers/gpu/drm/radeon/radeon_i2c.c
@@ -898,6 +898,10 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
struct radeon_i2c_chan *i2c;
int ret;
+ /* don't add the mm_i2c bus unless hw_i2c is enabled */
+ if (rec->mm_i2c && (radeon_hw_i2c == 0))
+ return NULL;
+
i2c = kzalloc(sizeof(struct radeon_i2c_chan), GFP_KERNEL);
if (i2c == NULL)
return NULL;
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index fecc1aae3828..eb6fe79c691f 100644
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -134,9 +134,21 @@ static bool radeon_msi_ok(struct radeon_device *rdev)
/* Dell RS690 only seems to work with MSIs. */
if ((rdev->pdev->device == 0x791f) &&
(rdev->pdev->subsystem_vendor == 0x1028) &&
+ (rdev->pdev->subsystem_device == 0x01fc))
+ return true;
+
+ /* Dell RS690 only seems to work with MSIs. */
+ if ((rdev->pdev->device == 0x791f) &&
+ (rdev->pdev->subsystem_vendor == 0x1028) &&
(rdev->pdev->subsystem_device == 0x01fd))
return true;
+ /* RV515 seems to have MSI issues where it loses
+ * MSI rearms occasionally. This leads to lockups and freezes.
+ * disable it by default.
+ */
+ if (rdev->family == CHIP_RV515)
+ return false;
if (rdev->flags & RADEON_IS_IGP) {
/* APUs work fine with MSIs */
if (rdev->family >= CHIP_PALM)
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 976c3b1b1b6e..35da1b474197 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -204,7 +204,8 @@ void radeon_bo_unref(struct radeon_bo **bo)
*bo = NULL;
}
-int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
+int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain, u64 max_offset,
+ u64 *gpu_addr)
{
int r, i;
@@ -212,6 +213,7 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
bo->pin_count++;
if (gpu_addr)
*gpu_addr = radeon_bo_gpu_offset(bo);
+ WARN_ON_ONCE(max_offset != 0);
return 0;
}
radeon_ttm_placement_from_domain(bo, domain);
@@ -219,6 +221,15 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
/* force to pin into visible video ram */
bo->placement.lpfn = bo->rdev->mc.visible_vram_size >> PAGE_SHIFT;
}
+ if (max_offset) {
+ u64 lpfn = max_offset >> PAGE_SHIFT;
+
+ if (!bo->placement.lpfn)
+ bo->placement.lpfn = bo->rdev->mc.gtt_size >> PAGE_SHIFT;
+
+ if (lpfn < bo->placement.lpfn)
+ bo->placement.lpfn = lpfn;
+ }
for (i = 0; i < bo->placement.num_placement; i++)
bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false, false);
@@ -232,6 +243,11 @@ int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
return r;
}
+int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
+{
+ return radeon_bo_pin_restricted(bo, domain, 0, gpu_addr);
+}
+
int radeon_bo_unpin(struct radeon_bo *bo)
{
int r, i;
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h
index ede6c13628f2..7199c6ab027e 100644
--- a/drivers/gpu/drm/radeon/radeon_object.h
+++ b/drivers/gpu/drm/radeon/radeon_object.h
@@ -144,6 +144,8 @@ 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);
extern int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr);
+extern int radeon_bo_pin_restricted(struct radeon_bo *bo, u32 domain,
+ u64 max_offset, u64 *gpu_addr);
extern int radeon_bo_unpin(struct radeon_bo *bo);
extern int radeon_bo_evict_vram(struct radeon_device *rdev);
extern void radeon_bo_force_delete(struct radeon_device *rdev);
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c
index a37a1efdd22a..2026c2d52c57 100644
--- a/drivers/gpu/drm/radeon/rs600.c
+++ b/drivers/gpu/drm/radeon/rs600.c
@@ -324,10 +324,10 @@ void rs600_hpd_fini(struct radeon_device *rdev)
void rs600_bm_disable(struct radeon_device *rdev)
{
- u32 tmp;
+ u16 tmp;
/* disable bus mastering */
- pci_read_config_word(rdev->pdev, 0x4, (u16*)&tmp);
+ pci_read_config_word(rdev->pdev, 0x4, &tmp);
pci_write_config_word(rdev->pdev, 0x4, tmp & 0xFFFB);
mdelay(1);
}
@@ -698,9 +698,7 @@ int rs600_irq_process(struct radeon_device *rdev)
WREG32(RADEON_BUS_CNTL, msi_rearm | RS600_MSI_REARM);
break;
default:
- msi_rearm = RREG32(RADEON_MSI_REARM_EN) & ~RV370_MSI_REARM_EN;
- WREG32(RADEON_MSI_REARM_EN, msi_rearm);
- WREG32(RADEON_MSI_REARM_EN, msi_rearm | RV370_MSI_REARM_EN);
+ WREG32(RADEON_MSI_REARM_EN, RV370_MSI_REARM_EN);
break;
}
}
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
index 84cf82fcac8b..51d20aa63d03 100644
--- a/drivers/gpu/drm/radeon/rv770.c
+++ b/drivers/gpu/drm/radeon/rv770.c
@@ -151,6 +151,8 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev)
WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
+ if (rdev->family == CHIP_RV740)
+ WREG32(MC_VM_MD_L1_TLB3_CNTL, tmp);
WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h
index 79fa588e9ed5..75380927e9c6 100644
--- a/drivers/gpu/drm/radeon/rv770d.h
+++ b/drivers/gpu/drm/radeon/rv770d.h
@@ -174,6 +174,7 @@
#define MC_VM_MD_L1_TLB0_CNTL 0x2654
#define MC_VM_MD_L1_TLB1_CNTL 0x2658
#define MC_VM_MD_L1_TLB2_CNTL 0x265C
+#define MC_VM_MD_L1_TLB3_CNTL 0x2698
#define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203C
#define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038
#define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 81b68508dc13..7632edb2f46e 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -1809,6 +1809,7 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink)
spin_unlock(&glob->lru_lock);
(void) ttm_bo_cleanup_refs(bo, false, false, false);
kref_put(&bo->list_kref, ttm_bo_release_list);
+ spin_lock(&glob->lru_lock);
continue;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index dfe32e62bd90..8a38c91f4c9c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -313,7 +313,7 @@ int vmw_framebuffer_create_handle(struct drm_framebuffer *fb,
unsigned int *handle)
{
if (handle)
- handle = 0;
+ *handle = 0;
return 0;
}
diff --git a/drivers/hid/hid-chicony.c b/drivers/hid/hid-chicony.c
index 8965ad93d510..b99af346fdff 100644
--- a/drivers/hid/hid-chicony.c
+++ b/drivers/hid/hid-chicony.c
@@ -45,6 +45,12 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
case 0xff09: ch_map_key_clear(BTN_9); break;
case 0xff0a: ch_map_key_clear(BTN_A); break;
case 0xff0b: ch_map_key_clear(BTN_B); break;
+ case 0x00f1: ch_map_key_clear(KEY_WLAN); break;
+ case 0x00f2: ch_map_key_clear(KEY_BRIGHTNESSDOWN); break;
+ case 0x00f3: ch_map_key_clear(KEY_BRIGHTNESSUP); break;
+ case 0x00f4: ch_map_key_clear(KEY_DISPLAY_OFF); break;
+ case 0x00f7: ch_map_key_clear(KEY_CAMERA); break;
+ case 0x00f8: ch_map_key_clear(KEY_PROG1); break;
default:
return 0;
}
@@ -53,6 +59,7 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
static const struct hid_device_id ch_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
{ }
};
MODULE_DEVICE_TABLE(hid, ch_devices);
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 763797da2d8a..53576e7c8bcf 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -361,7 +361,7 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item)
case HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
parser->global.report_size = item_udata(item);
- if (parser->global.report_size > 32) {
+ if (parser->global.report_size > 96) {
dbg_hid("invalid report_size %d\n",
parser->global.report_size);
return -1;
@@ -1372,6 +1372,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) },
@@ -1382,11 +1383,13 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
- { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
{ HID_USB_DEVICE(USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2515) },
{ HID_USB_DEVICE(USB_VENDOR_ID_EMS, USB_DEVICE_ID_EMS_TRIO_LINKER_PLUS_II) },
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 206f75021d5d..08cc68ba9ebe 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -21,6 +21,7 @@
#define USB_VENDOR_ID_3M 0x0596
#define USB_DEVICE_ID_3M1968 0x0500
#define USB_DEVICE_ID_3M2256 0x0502
+#define USB_DEVICE_ID_3M3266 0x0506
#define USB_VENDOR_ID_A4TECH 0x09da
#define USB_DEVICE_ID_A4TECH_WCP32PU 0x0006
@@ -58,6 +59,9 @@
#define USB_VENDOR_ID_AIRCABLE 0x16CA
#define USB_DEVICE_ID_AIRCABLE1 0x1502
+#define USB_VENDOR_ID_AIREN 0x1a2c
+#define USB_DEVICE_ID_AIREN_SLIMPLUS 0x0002
+
#define USB_VENDOR_ID_ALCOR 0x058f
#define USB_DEVICE_ID_ALCOR_USBRS232 0x9720
@@ -185,6 +189,7 @@
#define USB_DEVICE_ID_CHICONY_TACTICAL_PAD 0x0418
#define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d
#define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618
+#define USB_DEVICE_ID_CHICONY_WIRELESS2 0x1123
#define USB_VENDOR_ID_CHUNGHWAT 0x2247
#define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001
@@ -230,11 +235,14 @@
#define USB_VENDOR_ID_DWAV 0x0eef
#define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001
-#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH 0x480d
-#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1 0x720c
-#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2 0x72a1
-#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3 0x480e
-#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4 0x726b
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D 0x480d
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E 0x480e
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C 0x720c
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B 0x726b
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1 0x72a1
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA 0x72fa
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302 0x7302
+#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001
#define USB_VENDOR_ID_ELECOM 0x056e
#define USB_DEVICE_ID_ELECOM_BM084 0x0061
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 2074cb3d58ce..91319f90a168 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -603,6 +603,9 @@ static const struct hid_device_id mt_devices[] = {
{ .driver_data = MT_CLS_3M,
HID_USB_DEVICE(USB_VENDOR_ID_3M,
USB_DEVICE_ID_3M2256) },
+ { .driver_data = MT_CLS_3M,
+ HID_USB_DEVICE(USB_VENDOR_ID_3M,
+ USB_DEVICE_ID_3M3266) },
/* ActionStar panels */
{ .driver_data = MT_CLS_DEFAULT,
@@ -639,23 +642,32 @@ static const struct hid_device_id mt_devices[] = {
USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
/* eGalax devices (resistive) */
- { .driver_data = MT_CLS_EGALAX,
+ { .driver_data = MT_CLS_EGALAX,
HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
- USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
- { .driver_data = MT_CLS_EGALAX,
+ USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480D) },
+ { .driver_data = MT_CLS_EGALAX,
HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
- USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
+ USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_480E) },
/* eGalax devices (capacitive) */
- { .driver_data = MT_CLS_EGALAX,
+ { .driver_data = MT_CLS_EGALAX,
+ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+ USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_720C) },
+ { .driver_data = MT_CLS_EGALAX,
+ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+ USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_726B) },
+ { .driver_data = MT_CLS_EGALAX,
+ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+ USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72A1) },
+ { .driver_data = MT_CLS_EGALAX,
HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
- USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
- { .driver_data = MT_CLS_EGALAX,
+ USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_72FA) },
+ { .driver_data = MT_CLS_EGALAX,
HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
- USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
- { .driver_data = MT_CLS_EGALAX,
+ USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7302) },
+ { .driver_data = MT_CLS_EGALAX,
HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
- USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
+ USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
/* Elo TouchSystems IntelliTouch Plus panel */
{ .driver_data = MT_CLS_DUAL_NSMU_CONTACTID,
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 3146fdcda272..85c845f7f61e 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -52,6 +52,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT },
{ USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS, HID_QUIRK_MULTI_INPUT },
+ { USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 2e7757394acc..b42baef3dcd0 100755
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -481,8 +481,9 @@ config SENSORS_JC42
If you say yes here, you get support for JEDEC JC42.4 compliant
temperature sensors, which are used on many DDR3 memory modules for
mobile devices and servers. Support will include, but not be limited
- to, ADT7408, CAT34TS02, CAT6095, MAX6604, MCP9805, MCP98242, MCP98243,
- MCP9843, SE97, SE98, STTS424(E), TSE2002B3, and TS3000B3.
+ to, ADT7408, AT30TS00, CAT34TS02, CAT6095, MAX6604, MCP9804, MCP9805,
+ MCP98242, MCP98243, MCP9843, SE97, SE98, STTS424(E), STTS2002,
+ STTS3000, TSE2002B3, TSE2002GB2, TS3000B3, and TS3000GB2.
This driver can also be built as a module. If so, the module
will be called jc42.
diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c
index e9beeda4cbe5..9a5af38bffd3 100644
--- a/drivers/hwmon/ads1015.c
+++ b/drivers/hwmon/ads1015.c
@@ -284,7 +284,7 @@ static int ads1015_probe(struct i2c_client *client,
continue;
err = device_create_file(&client->dev, &ads1015_in[k].dev_attr);
if (err)
- goto exit_free;
+ goto exit_remove;
}
data->hwmon_dev = hwmon_device_register(&client->dev);
@@ -298,7 +298,6 @@ static int ads1015_probe(struct i2c_client *client,
exit_remove:
for (k = 0; k < ADS1015_CHANNELS; ++k)
device_remove_file(&client->dev, &ads1015_in[k].dev_attr);
-exit_free:
kfree(data);
exit:
return err;
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 6163cfa95c3e..3cf235385f89 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -42,7 +42,7 @@
#define DRVNAME "coretemp"
#define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */
-#define NUM_REAL_CORES 16 /* Number of Real cores per cpu */
+#define NUM_REAL_CORES 32 /* Number of Real cores per cpu */
#define CORETEMP_NAME_LENGTH 17 /* String Length of attrs */
#define MAX_ATTRS 5 /* Maximum no of per-core attrs */
#define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO)
@@ -752,6 +752,10 @@ static void __cpuinit put_core_offline(unsigned int cpu)
indx = TO_ATTR_NO(cpu);
+ /* The core id is too big, just return */
+ if (indx > MAX_CORE_DATA - 1)
+ return;
+
if (pdata->core_data[indx] && pdata->core_data[indx]->cpu == cpu)
coretemp_remove_core(pdata, &pdev->dev, indx);
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
index 92f949767ece..6dbfd3e516e4 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -283,11 +283,11 @@ static inline long temp_from_reg(u8 reg)
static inline u8 temp_to_reg(long val)
{
- if (val < 0)
- val = 0;
- else if (val > 1000 * 0xff)
- val = 0xff;
- return ((val + 500) / 1000);
+ if (val <= 0)
+ return 0;
+ if (val >= 1000 * 0xff)
+ return 0xff;
+ return (val + 500) / 1000;
}
/*
diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c
index 95cbfb3a7077..040a820acd15 100644
--- a/drivers/hwmon/f75375s.c
+++ b/drivers/hwmon/f75375s.c
@@ -159,7 +159,7 @@ static inline void f75375_write8(struct i2c_client *client, u8 reg,
static inline void f75375_write16(struct i2c_client *client, u8 reg,
u16 value)
{
- int err = i2c_smbus_write_byte_data(client, reg, (value << 8));
+ int err = i2c_smbus_write_byte_data(client, reg, (value >> 8));
if (err)
return;
i2c_smbus_write_byte_data(client, reg + 1, (value & 0xFF));
@@ -304,20 +304,21 @@ static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val)
case 0: /* Full speed */
fanmode |= (3 << FAN_CTRL_MODE(nr));
data->pwm[nr] = 255;
- f75375_write8(client, F75375_REG_FAN_PWM_DUTY(nr),
- data->pwm[nr]);
break;
case 1: /* PWM */
fanmode |= (3 << FAN_CTRL_MODE(nr));
break;
case 2: /* AUTOMATIC*/
- fanmode |= (2 << FAN_CTRL_MODE(nr));
+ fanmode |= (1 << FAN_CTRL_MODE(nr));
break;
case 3: /* fan speed */
break;
}
f75375_write8(client, F75375_REG_FAN_TIMER, fanmode);
data->pwm_enable[nr] = val;
+ if (val == 0)
+ f75375_write8(client, F75375_REG_FAN_PWM_DUTY(nr),
+ data->pwm[nr]);
return 0;
}
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
index 523f8fb9e7d9..e8e18cab1fb8 100644
--- a/drivers/hwmon/fam15h_power.c
+++ b/drivers/hwmon/fam15h_power.c
@@ -60,15 +60,15 @@ static ssize_t show_power(struct device *dev,
pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5),
REG_TDP_RUNNING_AVERAGE, &val);
running_avg_capture = (val >> 4) & 0x3fffff;
- running_avg_capture = sign_extend32(running_avg_capture, 22);
- running_avg_range = val & 0xf;
+ running_avg_capture = sign_extend32(running_avg_capture, 21);
+ running_avg_range = (val & 0xf) + 1;
pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5),
REG_TDP_LIMIT3, &val);
tdp_limit = val >> 16;
- curr_pwr_watts = tdp_limit + data->base_tdp -
- (s32)(running_avg_capture >> (running_avg_range + 1));
+ curr_pwr_watts = (tdp_limit + data->base_tdp) << running_avg_range;
+ curr_pwr_watts -= running_avg_capture;
curr_pwr_watts *= data->tdp_to_watts;
/*
@@ -78,7 +78,7 @@ static ssize_t show_power(struct device *dev,
* scaling factor 1/(2^16). For conversion we use
* (10^6)/(2^16) = 15625/(2^10)
*/
- curr_pwr_watts = (curr_pwr_watts * 15625) >> 10;
+ curr_pwr_watts = (curr_pwr_watts * 15625) >> (10 + running_avg_range);
return sprintf(buf, "%u\n", (unsigned int) curr_pwr_watts);
}
static DEVICE_ATTR(power1_input, S_IRUGO, show_power, NULL);
@@ -122,6 +122,41 @@ static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4)
return true;
}
+/*
+ * Newer BKDG versions have an updated recommendation on how to properly
+ * initialize the running average range (was: 0xE, now: 0x9). This avoids
+ * counter saturations resulting in bogus power readings.
+ * We correct this value ourselves to cope with older BIOSes.
+ */
+static DEFINE_PCI_DEVICE_TABLE(affected_device) = {
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
+ { 0 }
+};
+
+static void __devinit tweak_runavg_range(struct pci_dev *pdev)
+{
+ u32 val;
+
+ /*
+ * let this quirk apply only to the current version of the
+ * northbridge, since future versions may change the behavior
+ */
+ if (!pci_match_id(affected_device, pdev))
+ return;
+
+ pci_bus_read_config_dword(pdev->bus,
+ PCI_DEVFN(PCI_SLOT(pdev->devfn), 5),
+ REG_TDP_RUNNING_AVERAGE, &val);
+ if ((val & 0xf) != 0xe)
+ return;
+
+ val &= ~0xf;
+ val |= 0x9;
+ pci_bus_write_config_dword(pdev->bus,
+ PCI_DEVFN(PCI_SLOT(pdev->devfn), 5),
+ REG_TDP_RUNNING_AVERAGE, val);
+}
+
static void __devinit fam15h_power_init_data(struct pci_dev *f4,
struct fam15h_power_data *data)
{
@@ -155,6 +190,13 @@ static int __devinit fam15h_power_probe(struct pci_dev *pdev,
struct device *dev;
int err;
+ /*
+ * though we ignore every other northbridge, we still have to
+ * do the tweaking on _each_ node in MCM processors as the counters
+ * are working hand-in-hand
+ */
+ tweak_runavg_range(pdev);
+
if (!fam15h_power_is_internal_node0(pdev)) {
err = -ENODEV;
goto exit;
diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c
index 02cebb74e206..ed4392406e93 100644
--- a/drivers/hwmon/jc42.c
+++ b/drivers/hwmon/jc42.c
@@ -64,6 +64,7 @@ static const unsigned short normal_i2c[] = {
/* Manufacturer IDs */
#define ADT_MANID 0x11d4 /* Analog Devices */
+#define ATMEL_MANID 0x001f /* Atmel */
#define MAX_MANID 0x004d /* Maxim */
#define IDT_MANID 0x00b3 /* IDT */
#define MCP_MANID 0x0054 /* Microchip */
@@ -77,15 +78,25 @@ static const unsigned short normal_i2c[] = {
#define ADT7408_DEVID 0x0801
#define ADT7408_DEVID_MASK 0xffff
+/* Atmel */
+#define AT30TS00_DEVID 0x8201
+#define AT30TS00_DEVID_MASK 0xffff
+
/* IDT */
#define TS3000B3_DEVID 0x2903 /* Also matches TSE2002B3 */
#define TS3000B3_DEVID_MASK 0xffff
+#define TS3000GB2_DEVID 0x2912 /* Also matches TSE2002GB2 */
+#define TS3000GB2_DEVID_MASK 0xffff
+
/* Maxim */
#define MAX6604_DEVID 0x3e00
#define MAX6604_DEVID_MASK 0xffff
/* Microchip */
+#define MCP9804_DEVID 0x0200
+#define MCP9804_DEVID_MASK 0xfffc
+
#define MCP98242_DEVID 0x2000
#define MCP98242_DEVID_MASK 0xfffc
@@ -113,6 +124,12 @@ static const unsigned short normal_i2c[] = {
#define STTS424E_DEVID 0x0000
#define STTS424E_DEVID_MASK 0xfffe
+#define STTS2002_DEVID 0x0300
+#define STTS2002_DEVID_MASK 0xffff
+
+#define STTS3000_DEVID 0x0200
+#define STTS3000_DEVID_MASK 0xffff
+
static u16 jc42_hysteresis[] = { 0, 1500, 3000, 6000 };
struct jc42_chips {
@@ -123,8 +140,11 @@ struct jc42_chips {
static struct jc42_chips jc42_chips[] = {
{ ADT_MANID, ADT7408_DEVID, ADT7408_DEVID_MASK },
+ { ATMEL_MANID, AT30TS00_DEVID, AT30TS00_DEVID_MASK },
{ IDT_MANID, TS3000B3_DEVID, TS3000B3_DEVID_MASK },
+ { IDT_MANID, TS3000GB2_DEVID, TS3000GB2_DEVID_MASK },
{ MAX_MANID, MAX6604_DEVID, MAX6604_DEVID_MASK },
+ { MCP_MANID, MCP9804_DEVID, MCP9804_DEVID_MASK },
{ MCP_MANID, MCP98242_DEVID, MCP98242_DEVID_MASK },
{ MCP_MANID, MCP98243_DEVID, MCP98243_DEVID_MASK },
{ MCP_MANID, MCP9843_DEVID, MCP9843_DEVID_MASK },
@@ -133,6 +153,8 @@ static struct jc42_chips jc42_chips[] = {
{ NXP_MANID, SE98_DEVID, SE98_DEVID_MASK },
{ STM_MANID, STTS424_DEVID, STTS424_DEVID_MASK },
{ STM_MANID, STTS424E_DEVID, STTS424E_DEVID_MASK },
+ { STM_MANID, STTS2002_DEVID, STTS2002_DEVID_MASK },
+ { STM_MANID, STTS3000_DEVID, STTS3000_DEVID_MASK },
};
/* Each client has this additional data */
@@ -161,10 +183,12 @@ static struct jc42_data *jc42_update_device(struct device *dev);
static const struct i2c_device_id jc42_id[] = {
{ "adt7408", 0 },
+ { "at30ts00", 0 },
{ "cat94ts02", 0 },
{ "cat6095", 0 },
{ "jc42", 0 },
{ "max6604", 0 },
+ { "mcp9804", 0 },
{ "mcp9805", 0 },
{ "mcp98242", 0 },
{ "mcp98243", 0 },
@@ -173,8 +197,10 @@ static const struct i2c_device_id jc42_id[] = {
{ "se97b", 0 },
{ "se98", 0 },
{ "stts424", 0 },
- { "tse2002b3", 0 },
- { "ts3000b3", 0 },
+ { "stts2002", 0 },
+ { "stts3000", 0 },
+ { "tse2002", 0 },
+ { "ts3000", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, jc42_id);
diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c
index f20d9978ee78..8c3df047e568 100644
--- a/drivers/hwmon/max6639.c
+++ b/drivers/hwmon/max6639.c
@@ -72,8 +72,8 @@ static unsigned short normal_i2c[] = { 0x2c, 0x2e, 0x2f, I2C_CLIENT_END };
static const int rpm_ranges[] = { 2000, 4000, 8000, 16000 };
-#define FAN_FROM_REG(val, div, rpm_range) ((val) == 0 ? -1 : \
- (val) == 255 ? 0 : (rpm_ranges[rpm_range] * 30) / ((div + 1) * (val)))
+#define FAN_FROM_REG(val, rpm_range) ((val) == 0 || (val) == 255 ? \
+ 0 : (rpm_ranges[rpm_range] * 30) / (val))
#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT((val) / 1000, 0, 255)
/*
@@ -333,7 +333,7 @@ static ssize_t show_fan_input(struct device *dev,
return PTR_ERR(data);
return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index],
- data->ppr, data->rpm_range));
+ data->rpm_range));
}
static ssize_t show_alarm(struct device *dev,
@@ -429,9 +429,9 @@ static int max6639_init_client(struct i2c_client *client)
struct max6639_data *data = i2c_get_clientdata(client);
struct max6639_platform_data *max6639_info =
client->dev.platform_data;
- int i = 0;
+ int i;
int rpm_range = 1; /* default: 4000 RPM */
- int err = 0;
+ int err;
/* Reset chip to default values, see below for GCONFIG setup */
err = i2c_smbus_write_byte_data(client, MAX6639_REG_GCONFIG,
@@ -446,11 +446,6 @@ static int max6639_init_client(struct i2c_client *client)
else
data->ppr = 2;
data->ppr -= 1;
- err = i2c_smbus_write_byte_data(client,
- MAX6639_REG_FAN_PPR(i),
- data->ppr << 5);
- if (err)
- goto exit;
if (max6639_info)
rpm_range = rpm_range_to_reg(max6639_info->rpm_range);
@@ -458,6 +453,13 @@ static int max6639_init_client(struct i2c_client *client)
for (i = 0; i < 2; i++) {
+ /* Set Fan pulse per revolution */
+ err = i2c_smbus_write_byte_data(client,
+ MAX6639_REG_FAN_PPR(i),
+ data->ppr << 6);
+ if (err)
+ goto exit;
+
/* Fans config PWM, RPM */
err = i2c_smbus_write_byte_data(client,
MAX6639_REG_FAN_CONFIG1(i),
diff --git a/drivers/hwmon/pmbus_core.c b/drivers/hwmon/pmbus_core.c
index 8e31a8e2c746..ffa54dd7dbda 100644
--- a/drivers/hwmon/pmbus_core.c
+++ b/drivers/hwmon/pmbus_core.c
@@ -50,7 +50,8 @@
lcrit_alarm, crit_alarm */
#define PMBUS_IOUT_BOOLEANS_PER_PAGE 3 /* alarm, lcrit_alarm,
crit_alarm */
-#define PMBUS_POUT_BOOLEANS_PER_PAGE 2 /* alarm, crit_alarm */
+#define PMBUS_POUT_BOOLEANS_PER_PAGE 3 /* cap_alarm, alarm, crit_alarm
+ */
#define PMBUS_MAX_BOOLEANS_PER_FAN 2 /* alarm, fault */
#define PMBUS_MAX_BOOLEANS_PER_TEMP 4 /* min_alarm, max_alarm,
lcrit_alarm, crit_alarm */
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c
index cf4330b352ef..9594cdb1cd0f 100644
--- a/drivers/hwmon/sht15.c
+++ b/drivers/hwmon/sht15.c
@@ -883,7 +883,7 @@ static int sht15_invalidate_voltage(struct notifier_block *nb,
static int __devinit sht15_probe(struct platform_device *pdev)
{
- int ret = 0;
+ int ret;
struct sht15_data *data = kzalloc(sizeof(*data), GFP_KERNEL);
u8 status = 0;
@@ -901,6 +901,7 @@ static int __devinit sht15_probe(struct platform_device *pdev)
init_waitqueue_head(&data->wait_queue);
if (pdev->dev.platform_data == NULL) {
+ ret = -EINVAL;
dev_err(&pdev->dev, "no platform data supplied\n");
goto err_free_data;
}
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 4b2fc50c84fe..e51b582bbc58 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -1295,6 +1295,7 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr,
{
struct w83627ehf_data *data = dev_get_drvdata(dev);
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ struct w83627ehf_sio_data *sio_data = dev->platform_data;
int nr = sensor_attr->index;
unsigned long val;
int err;
@@ -1306,6 +1307,11 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr,
if (val > 1)
return -EINVAL;
+
+ /* On NCT67766F, DC mode is only supported for pwm1 */
+ if (sio_data->kind == nct6776 && nr && val != 1)
+ return -EINVAL;
+
mutex_lock(&data->update_lock);
reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]);
data->pwm_mode[nr] = val;
@@ -1577,7 +1583,7 @@ store_##reg(struct device *dev, struct device_attribute *attr, \
val = step_time_to_reg(val, data->pwm_mode[nr]); \
mutex_lock(&data->update_lock); \
data->reg[nr] = val; \
- w83627ehf_write_value(data, W83627EHF_REG_##REG[nr], val); \
+ w83627ehf_write_value(data, data->REG_##REG[nr], val); \
mutex_unlock(&data->update_lock); \
return count; \
} \
@@ -1817,7 +1823,8 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
goto exit;
}
- data = kzalloc(sizeof(struct w83627ehf_data), GFP_KERNEL);
+ data = devm_kzalloc(&pdev->dev, sizeof(struct w83627ehf_data),
+ GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit_release;
@@ -2098,9 +2105,29 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
fan4min = 0;
fan5pin = 0;
} else if (sio_data->kind == nct6776) {
- fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
- fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01);
- fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02);
+ bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80;
+ u8 regval;
+
+ superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
+ regval = superio_inb(sio_data->sioreg, SIO_REG_ENABLE);
+
+ if (regval & 0x80)
+ fan3pin = gpok;
+ else
+ fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
+
+ if (regval & 0x40)
+ fan4pin = gpok;
+ else
+ fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C)
+ & 0x01);
+
+ if (regval & 0x20)
+ fan5pin = gpok;
+ else
+ fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C)
+ & 0x02);
+
fan4min = fan4pin;
} else if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
fan3pin = 1;
@@ -2293,9 +2320,8 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
exit_remove:
w83627ehf_device_remove_files(dev);
- kfree(data);
- platform_set_drvdata(pdev, NULL);
exit_release:
+ platform_set_drvdata(pdev, NULL);
release_region(res->start, IOREGION_LENGTH);
exit:
return err;
@@ -2309,7 +2335,6 @@ static int __devexit w83627ehf_remove(struct platform_device *pdev)
w83627ehf_device_remove_files(&pdev->dev);
release_region(data->addr, IOREGION_LENGTH);
platform_set_drvdata(pdev, NULL);
- kfree(data);
return 0;
}
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index eca3bcc4599d..f2ce8c36816f 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -103,8 +103,14 @@ static int sclhi(struct i2c_algo_bit_data *adap)
* chips may hold it low ("clock stretching") while they
* are processing data internally.
*/
- if (time_after(jiffies, start + adap->timeout))
+ if (time_after(jiffies, start + adap->timeout)) {
+ /* Test one last time, as we may have been preempted
+ * between last check and timeout test.
+ */
+ if (getscl(adap))
+ break;
return -ETIMEDOUT;
+ }
cond_resched();
}
#ifdef DEBUG
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index dd364171f9c5..cd7ac5c6783e 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -140,7 +140,7 @@ static unsigned short ali1535_smba;
defined to make the transition easier. */
static int __devinit ali1535_setup(struct pci_dev *dev)
{
- int retval = -ENODEV;
+ int retval;
unsigned char temp;
/* Check the following things:
@@ -155,6 +155,7 @@ static int __devinit ali1535_setup(struct pci_dev *dev)
if (ali1535_smba == 0) {
dev_warn(&dev->dev,
"ALI1535_smb region uninitialized - upgrade BIOS?\n");
+ retval = -ENODEV;
goto exit;
}
@@ -167,6 +168,7 @@ static int __devinit ali1535_setup(struct pci_dev *dev)
ali1535_driver.name)) {
dev_err(&dev->dev, "ALI1535_smb region 0x%x already in use!\n",
ali1535_smba);
+ retval = -EBUSY;
goto exit;
}
@@ -174,6 +176,7 @@ static int __devinit ali1535_setup(struct pci_dev *dev)
pci_read_config_byte(dev, SMBCFG, &temp);
if ((temp & ALI1535_SMBIO_EN) == 0) {
dev_err(&dev->dev, "SMB device not enabled - upgrade BIOS?\n");
+ retval = -ENODEV;
goto exit_free;
}
@@ -181,6 +184,7 @@ static int __devinit ali1535_setup(struct pci_dev *dev)
pci_read_config_byte(dev, SMBHSTCFG, &temp);
if ((temp & 1) == 0) {
dev_err(&dev->dev, "SMBus controller not enabled - upgrade BIOS?\n");
+ retval = -ENODEV;
goto exit_free;
}
@@ -198,12 +202,11 @@ static int __devinit ali1535_setup(struct pci_dev *dev)
dev_dbg(&dev->dev, "SMBREV = 0x%X\n", temp);
dev_dbg(&dev->dev, "ALI1535_smba = 0x%X\n", ali1535_smba);
- retval = 0;
-exit:
- return retval;
+ return 0;
exit_free:
release_region(ali1535_smba, ALI1535_SMB_IOSIZE);
+exit:
return retval;
}
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
index a76d85fa3ad7..79b4bcb3b85c 100644
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -755,7 +755,7 @@ static int davinci_i2c_remove(struct platform_device *pdev)
dev->clk = NULL;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0);
- free_irq(IRQ_I2C, dev);
+ free_irq(dev->irq, dev);
iounmap(dev->base);
kfree(dev);
diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c
index 8abfa4a03ce1..656b028d9816 100644
--- a/drivers/i2c/busses/i2c-eg20t.c
+++ b/drivers/i2c/busses/i2c-eg20t.c
@@ -242,7 +242,7 @@ static void pch_i2c_init(struct i2c_algo_pch_data *adap)
if (pch_clk > PCH_MAX_CLK)
pch_clk = 62500;
- pch_i2cbc = (pch_clk + (pch_i2c_speed * 4)) / pch_i2c_speed * 8;
+ pch_i2cbc = (pch_clk + (pch_i2c_speed * 4)) / (pch_i2c_speed * 8);
/* Set transfer speed in I2CBC */
iowrite32(pch_i2cbc, p + PCH_I2CBC);
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 7e78f7c87857..3d471d56bf15 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -72,6 +72,7 @@
#define MXS_I2C_QUEUESTAT (0x70)
#define MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY 0x00002000
+#define MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK 0x0000001F
#define MXS_I2C_QUEUECMD (0x80)
@@ -219,14 +220,14 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
int ret;
int flags;
- init_completion(&i2c->cmd_complete);
-
dev_dbg(i2c->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
msg->addr, msg->len, msg->flags, stop);
if (msg->len == 0)
return -EINVAL;
+ init_completion(&i2c->cmd_complete);
+
flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0;
if (msg->flags & I2C_M_RD)
@@ -286,6 +287,7 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
{
struct mxs_i2c_dev *i2c = dev_id;
u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK;
+ bool is_last_cmd;
if (!stat)
return IRQ_NONE;
@@ -300,9 +302,14 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
else
i2c->cmd_err = 0;
- complete(&i2c->cmd_complete);
+ is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) &
+ MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0;
+
+ if (is_last_cmd || i2c->cmd_err)
+ complete(&i2c->cmd_complete);
writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR);
+
return IRQ_HANDLED;
}
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index ff1e127dfea8..4853b52a40a8 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -356,7 +356,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
error = acpi_check_region(smbus->base, smbus->size,
nforce2_driver.name);
if (error)
- return -1;
+ return error;
if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) {
dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n",
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 58a58c7eaa17..137e1a3bfad1 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -235,7 +235,7 @@ const static u8 omap4_reg_map[] = {
[OMAP_I2C_BUF_REG] = 0x94,
[OMAP_I2C_CNT_REG] = 0x98,
[OMAP_I2C_DATA_REG] = 0x9c,
- [OMAP_I2C_SYSC_REG] = 0x20,
+ [OMAP_I2C_SYSC_REG] = 0x10,
[OMAP_I2C_CON_REG] = 0xa4,
[OMAP_I2C_OA_REG] = 0xa8,
[OMAP_I2C_SA_REG] = 0xac,
diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
index 04be9f82e14b..eb8ad538c79f 100644
--- a/drivers/i2c/busses/i2c-pnx.c
+++ b/drivers/i2c/busses/i2c-pnx.c
@@ -546,8 +546,7 @@ static int i2c_pnx_controller_suspend(struct platform_device *pdev,
{
struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
- /* FIXME: shouldn't this be clk_disable? */
- clk_enable(alg_data->clk);
+ clk_disable(alg_data->clk);
return 0;
}
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index 437586611d4a..6d60284cc04b 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -147,7 +147,7 @@ static int __devinit sis5595_setup(struct pci_dev *SIS5595_dev)
u16 a;
u8 val;
int *i;
- int retval = -ENODEV;
+ int retval;
/* Look for imposters */
for (i = blacklist; *i != 0; i++) {
@@ -223,7 +223,7 @@ static int __devinit sis5595_setup(struct pci_dev *SIS5595_dev)
error:
release_region(sis5595_base + SMB_INDEX, 2);
- return retval;
+ return -ENODEV;
}
static int sis5595_transaction(struct i2c_adapter *adap)
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
index e6f539e26f65..b617fd068ac7 100644
--- a/drivers/i2c/busses/i2c-sis630.c
+++ b/drivers/i2c/busses/i2c-sis630.c
@@ -393,7 +393,7 @@ static int __devinit sis630_setup(struct pci_dev *sis630_dev)
{
unsigned char b;
struct pci_dev *dummy = NULL;
- int retval = -ENODEV, i;
+ int retval, i;
/* check for supported SiS devices */
for (i=0; supported[i] > 0 ; i++) {
@@ -418,18 +418,21 @@ static int __devinit sis630_setup(struct pci_dev *sis630_dev)
*/
if (pci_read_config_byte(sis630_dev, SIS630_BIOS_CTL_REG,&b)) {
dev_err(&sis630_dev->dev, "Error: Can't read bios ctl reg\n");
+ retval = -ENODEV;
goto exit;
}
/* if ACPI already enabled , do nothing */
if (!(b & 0x80) &&
pci_write_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, b | 0x80)) {
dev_err(&sis630_dev->dev, "Error: Can't enable ACPI\n");
+ retval = -ENODEV;
goto exit;
}
/* Determine the ACPI base address */
if (pci_read_config_word(sis630_dev,SIS630_ACPI_BASE_REG,&acpi_base)) {
dev_err(&sis630_dev->dev, "Error: Can't determine ACPI base address\n");
+ retval = -ENODEV;
goto exit;
}
@@ -445,6 +448,7 @@ static int __devinit sis630_setup(struct pci_dev *sis630_dev)
sis630_driver.name)) {
dev_err(&sis630_dev->dev, "SMBus registers 0x%04x-0x%04x already "
"in use!\n", acpi_base + SMB_STS, acpi_base + SMB_SAA);
+ retval = -EBUSY;
goto exit;
}
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 0b012f1f8ac5..58261d4725b6 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -324,7 +324,7 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
unsigned char temp;
- int error = -ENODEV;
+ int error;
/* Determine the address of the SMBus areas */
if (force_addr) {
@@ -390,6 +390,7 @@ found:
dev_err(&pdev->dev, "SMBUS: Error: Host SMBus "
"controller not enabled! - upgrade BIOS or "
"use force=1\n");
+ error = -ENODEV;
goto release_region;
}
}
@@ -422,9 +423,11 @@ found:
"SMBus Via Pro adapter at %04x", vt596_smba);
vt596_pdev = pci_dev_get(pdev);
- if (i2c_add_adapter(&vt596_adapter)) {
+ error = i2c_add_adapter(&vt596_adapter);
+ if (error) {
pci_dev_put(vt596_pdev);
vt596_pdev = NULL;
+ goto release_region;
}
/* Always return failure here. This is to allow other drivers to bind
diff --git a/drivers/ide/ide-floppy_ioctl.c b/drivers/ide/ide-floppy_ioctl.c
index d267b7affad6..a22ca8467010 100644
--- a/drivers/ide/ide-floppy_ioctl.c
+++ b/drivers/ide/ide-floppy_ioctl.c
@@ -292,8 +292,7 @@ int ide_floppy_ioctl(ide_drive_t *drive, struct block_device *bdev,
* and CDROM_SEND_PACKET (legacy) ioctls
*/
if (cmd != CDROM_SEND_PACKET && cmd != SCSI_IOCTL_SEND_COMMAND)
- err = scsi_cmd_ioctl(bdev->bd_disk->queue, bdev->bd_disk,
- mode, cmd, argp);
+ err = scsi_cmd_blk_ioctl(bdev, mode, cmd, argp);
if (err == -ENOTTY)
err = generic_ide_ioctl(drive, bdev, cmd, arg);
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index a46dddf61078..026f9aa789e3 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -321,7 +321,8 @@ static int intel_idle_probe(void)
cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &mwait_substates);
if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) ||
- !(ecx & CPUID5_ECX_INTERRUPT_BREAK))
+ !(ecx & CPUID5_ECX_INTERRUPT_BREAK) ||
+ !mwait_substates)
return -ENODEV;
pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates);
@@ -367,7 +368,7 @@ static int intel_idle_probe(void)
if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */
lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
else {
- smp_call_function(__setup_broadcast_timer, (void *)true, 1);
+ on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
register_cpu_notifier(&setup_broadcast_notifier);
}
@@ -459,7 +460,7 @@ static int intel_idle_cpuidle_devices_init(void)
}
}
if (auto_demotion_disable_flags)
- smp_call_function(auto_demotion_disable, NULL, 1);
+ on_each_cpu(auto_demotion_disable, NULL, 1);
return 0;
}
@@ -499,7 +500,7 @@ static void __exit intel_idle_exit(void)
cpuidle_unregister_driver(&intel_idle_driver);
if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE) {
- smp_call_function(__setup_broadcast_timer, (void *)false, 1);
+ on_each_cpu(__setup_broadcast_timer, (void *)false, 1);
unregister_cpu_notifier(&setup_broadcast_notifier);
}
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 8e21d457b899..f2a84c6f8543 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -215,7 +215,9 @@ static int addr4_resolve(struct sockaddr_in *src_in,
neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev);
if (!neigh || !(neigh->nud_state & NUD_VALID)) {
- neigh_event_send(rt->dst.neighbour, NULL);
+ rcu_read_lock();
+ neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
+ rcu_read_unlock();
ret = -ENODATA;
if (neigh)
goto release;
@@ -273,14 +275,16 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
goto put;
}
- neigh = dst->neighbour;
+ rcu_read_lock();
+ neigh = dst_get_neighbour(dst);
if (!neigh || !(neigh->nud_state & NUD_VALID)) {
- neigh_event_send(dst->neighbour, NULL);
+ if (neigh)
+ neigh_event_send(neigh, NULL);
ret = -ENODATA;
- goto put;
+ } else {
+ ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
}
-
- ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
+ rcu_read_unlock();
put:
dst_release(dst);
return ret;
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index 2332dc22aa04..e55ce7a428be 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -1328,6 +1328,7 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
struct iwch_ep *child_ep, *parent_ep = ctx;
struct cpl_pass_accept_req *req = cplhdr(skb);
unsigned int hwtid = GET_TID(req);
+ struct neighbour *neigh;
struct dst_entry *dst;
struct l2t_entry *l2t;
struct rtable *rt;
@@ -1364,7 +1365,10 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
goto reject;
}
dst = &rt->dst;
- l2t = t3_l2t_get(tdev, dst->neighbour, dst->neighbour->dev);
+ rcu_read_lock();
+ neigh = dst_get_neighbour(dst);
+ l2t = t3_l2t_get(tdev, neigh, neigh->dev);
+ rcu_read_unlock();
if (!l2t) {
printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
__func__);
@@ -1874,10 +1878,11 @@ static int is_loopback_dst(struct iw_cm_id *cm_id)
int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
{
- int err = 0;
struct iwch_dev *h = to_iwch_dev(cm_id->device);
+ struct neighbour *neigh;
struct iwch_ep *ep;
struct rtable *rt;
+ int err = 0;
if (is_loopback_dst(cm_id)) {
err = -ENOSYS;
@@ -1933,9 +1938,12 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
}
ep->dst = &rt->dst;
+ rcu_read_lock();
+ neigh = dst_get_neighbour(ep->dst);
+
/* get a l2t entry */
- ep->l2t = t3_l2t_get(ep->com.tdev, ep->dst->neighbour,
- ep->dst->neighbour->dev);
+ ep->l2t = t3_l2t_get(ep->com.tdev, neigh, neigh->dev);
+ rcu_read_unlock();
if (!ep->l2t) {
printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
err = -ENOMEM;
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index 31fb44085c9b..267005d0e66f 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -1325,6 +1325,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
unsigned int stid = GET_POPEN_TID(ntohl(req->tos_stid));
struct tid_info *t = dev->rdev.lldi.tids;
unsigned int hwtid = GET_TID(req);
+ struct neighbour *neigh;
struct dst_entry *dst;
struct l2t_entry *l2t;
struct rtable *rt;
@@ -1357,11 +1358,12 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
goto reject;
}
dst = &rt->dst;
- if (dst->neighbour->dev->flags & IFF_LOOPBACK) {
+ rcu_read_lock();
+ neigh = dst_get_neighbour(dst);
+ if (neigh->dev->flags & IFF_LOOPBACK) {
pdev = ip_dev_find(&init_net, peer_ip);
BUG_ON(!pdev);
- l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, dst->neighbour,
- pdev, 0);
+ l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, pdev, 0);
mtu = pdev->mtu;
tx_chan = cxgb4_port_chan(pdev);
smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
@@ -1372,18 +1374,18 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
rss_qid = dev->rdev.lldi.rxq_ids[cxgb4_port_idx(pdev) * step];
dev_put(pdev);
} else {
- l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, dst->neighbour,
- dst->neighbour->dev, 0);
+ l2t = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, neigh->dev, 0);
mtu = dst_mtu(dst);
- tx_chan = cxgb4_port_chan(dst->neighbour->dev);
- smac_idx = (cxgb4_port_viid(dst->neighbour->dev) & 0x7F) << 1;
+ tx_chan = cxgb4_port_chan(neigh->dev);
+ smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1;
step = dev->rdev.lldi.ntxq / dev->rdev.lldi.nchan;
- txq_idx = cxgb4_port_idx(dst->neighbour->dev) * step;
- ctrlq_idx = cxgb4_port_idx(dst->neighbour->dev);
+ txq_idx = cxgb4_port_idx(neigh->dev) * step;
+ ctrlq_idx = cxgb4_port_idx(neigh->dev);
step = dev->rdev.lldi.nrxq / dev->rdev.lldi.nchan;
rss_qid = dev->rdev.lldi.rxq_ids[
- cxgb4_port_idx(dst->neighbour->dev) * step];
+ cxgb4_port_idx(neigh->dev) * step];
}
+ rcu_read_unlock();
if (!l2t) {
printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
__func__);
@@ -1847,6 +1849,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
struct c4iw_ep *ep;
struct rtable *rt;
struct net_device *pdev;
+ struct neighbour *neigh;
int step;
if ((conn_param->ord > c4iw_max_read_depth) ||
@@ -1908,14 +1911,16 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
}
ep->dst = &rt->dst;
+ rcu_read_lock();
+ neigh = dst_get_neighbour(ep->dst);
+
/* get a l2t entry */
- if (ep->dst->neighbour->dev->flags & IFF_LOOPBACK) {
+ if (neigh->dev->flags & IFF_LOOPBACK) {
PDBG("%s LOOPBACK\n", __func__);
pdev = ip_dev_find(&init_net,
cm_id->remote_addr.sin_addr.s_addr);
ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
- ep->dst->neighbour,
- pdev, 0);
+ neigh, pdev, 0);
ep->mtu = pdev->mtu;
ep->tx_chan = cxgb4_port_chan(pdev);
ep->smac_idx = (cxgb4_port_viid(pdev) & 0x7F) << 1;
@@ -1930,21 +1935,20 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
dev_put(pdev);
} else {
ep->l2t = cxgb4_l2t_get(ep->com.dev->rdev.lldi.l2t,
- ep->dst->neighbour,
- ep->dst->neighbour->dev, 0);
+ neigh, neigh->dev, 0);
ep->mtu = dst_mtu(ep->dst);
- ep->tx_chan = cxgb4_port_chan(ep->dst->neighbour->dev);
- ep->smac_idx = (cxgb4_port_viid(ep->dst->neighbour->dev) &
- 0x7F) << 1;
+ ep->tx_chan = cxgb4_port_chan(neigh->dev);
+ ep->smac_idx = (cxgb4_port_viid(neigh->dev) & 0x7F) << 1;
step = ep->com.dev->rdev.lldi.ntxq /
ep->com.dev->rdev.lldi.nchan;
- ep->txq_idx = cxgb4_port_idx(ep->dst->neighbour->dev) * step;
- ep->ctrlq_idx = cxgb4_port_idx(ep->dst->neighbour->dev);
+ ep->txq_idx = cxgb4_port_idx(neigh->dev) * step;
+ ep->ctrlq_idx = cxgb4_port_idx(neigh->dev);
step = ep->com.dev->rdev.lldi.nrxq /
ep->com.dev->rdev.lldi.nchan;
ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
- cxgb4_port_idx(ep->dst->neighbour->dev) * step];
+ cxgb4_port_idx(neigh->dev) * step];
}
+ rcu_read_unlock();
if (!ep->l2t) {
printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
err = -ENOMEM;
@@ -2312,6 +2316,12 @@ static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb)
unsigned int tid = GET_TID(req);
ep = lookup_tid(t, tid);
+ if (!ep) {
+ printk(KERN_WARNING MOD
+ "Abort on non-existent endpoint, tid %d\n", tid);
+ kfree_skb(skb);
+ return 0;
+ }
if (is_neg_adv_abort(req->status)) {
PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep,
ep->hwtid);
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index 57ffa50f509e..44fc3104e918 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -255,12 +255,9 @@ int mlx4_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
return IB_MAD_RESULT_SUCCESS;
/*
- * Don't process SMInfo queries or vendor-specific
- * MADs -- the SMA can't handle them.
+ * Don't process SMInfo queries -- the SMA can't handle them.
*/
- if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO ||
- ((in_mad->mad_hdr.attr_id & IB_SMP_ATTR_VENDOR_MASK) ==
- IB_SMP_ATTR_VENDOR_MASK))
+ if (in_mad->mad_hdr.attr_id == IB_SMP_ATTR_SM_INFO)
return IB_MAD_RESULT_SUCCESS;
} else if (in_mad->mad_hdr.mgmt_class == IB_MGMT_CLASS_PERF_MGMT ||
in_mad->mad_hdr.mgmt_class == MLX4_IB_VENDOR_CLASS1 ||
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index 2001f20a4361..23c04ff6519b 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -1301,7 +1301,7 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
int is_eth;
int is_vlan = 0;
int is_grh;
- u16 vlan;
+ u16 vlan = 0;
send_size = 0;
for (i = 0; i < wr->num_sge; ++i)
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index e74cdf9ef471..a1f74f6381ba 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -1150,9 +1150,11 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
neigh_release(neigh);
}
- if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID)))
- neigh_event_send(rt->dst.neighbour, NULL);
-
+ if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID))) {
+ rcu_read_lock();
+ neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
+ rcu_read_unlock();
+ }
ip_rt_put(rt);
return rc;
}
diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c
index d8ca0a0b970d..65df26ce538a 100644
--- a/drivers/infiniband/hw/qib/qib_iba6120.c
+++ b/drivers/infiniband/hw/qib/qib_iba6120.c
@@ -2076,9 +2076,11 @@ static void qib_6120_config_ctxts(struct qib_devdata *dd)
static void qib_update_6120_usrhead(struct qib_ctxtdata *rcd, u64 hd,
u32 updegr, u32 egrhd, u32 npkts)
{
- qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
if (updegr)
qib_write_ureg(rcd->dd, ur_rcvegrindexhead, egrhd, rcd->ctxt);
+ mmiowb();
+ qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
+ mmiowb();
}
static u32 qib_6120_hdrqempty(struct qib_ctxtdata *rcd)
diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c
index c765a2eb04cf..759bb63bb3b8 100644
--- a/drivers/infiniband/hw/qib/qib_iba7220.c
+++ b/drivers/infiniband/hw/qib/qib_iba7220.c
@@ -2704,9 +2704,11 @@ static int qib_7220_set_loopback(struct qib_pportdata *ppd, const char *what)
static void qib_update_7220_usrhead(struct qib_ctxtdata *rcd, u64 hd,
u32 updegr, u32 egrhd, u32 npkts)
{
- qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
if (updegr)
qib_write_ureg(rcd->dd, ur_rcvegrindexhead, egrhd, rcd->ctxt);
+ mmiowb();
+ qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
+ mmiowb();
}
static u32 qib_7220_hdrqempty(struct qib_ctxtdata *rcd)
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c
index 8ec5237031a0..49e4a589479d 100644
--- a/drivers/infiniband/hw/qib/qib_iba7322.c
+++ b/drivers/infiniband/hw/qib/qib_iba7322.c
@@ -4060,10 +4060,12 @@ static void qib_update_7322_usrhead(struct qib_ctxtdata *rcd, u64 hd,
*/
if (hd >> IBA7322_HDRHEAD_PKTINT_SHIFT)
adjust_rcv_timeout(rcd, npkts);
- qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
- qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
if (updegr)
qib_write_ureg(rcd->dd, ur_rcvegrindexhead, egrhd, rcd->ctxt);
+ mmiowb();
+ qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
+ qib_write_ureg(rcd->dd, ur_rcvhdrhead, hd, rcd->ctxt);
+ mmiowb();
}
static u32 qib_7322_hdrqempty(struct qib_ctxtdata *rcd)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 7b6985a2e652..936804efb776 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -44,6 +44,7 @@
#include <linux/mutex.h>
#include <net/neighbour.h>
+#include <net/sch_generic.h>
#include <asm/atomic.h>
@@ -117,8 +118,9 @@ struct ipoib_header {
u16 reserved;
};
-struct ipoib_pseudoheader {
- u8 hwaddr[INFINIBAND_ALEN];
+struct ipoib_cb {
+ struct qdisc_skb_cb qdisc_cb;
+ u8 hwaddr[INFINIBAND_ALEN];
};
/* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 86addca9ddf6..b811444dcdd4 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -555,14 +555,17 @@ static int path_rec_start(struct net_device *dev,
return 0;
}
+/* called with rcu_read_lock */
static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_path *path;
struct ipoib_neigh *neigh;
+ struct neighbour *n;
unsigned long flags;
- neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour, skb->dev);
+ n = dst_get_neighbour(skb_dst(skb));
+ neigh = ipoib_neigh_alloc(n, skb->dev);
if (!neigh) {
++dev->stats.tx_dropped;
dev_kfree_skb_any(skb);
@@ -571,9 +574,9 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
spin_lock_irqsave(&priv->lock, flags);
- path = __path_find(dev, skb_dst(skb)->neighbour->ha + 4);
+ path = __path_find(dev, n->ha + 4);
if (!path) {
- path = path_rec_create(dev, skb_dst(skb)->neighbour->ha + 4);
+ path = path_rec_create(dev, n->ha + 4);
if (!path)
goto err_path;
@@ -607,7 +610,7 @@ static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
}
} else {
spin_unlock_irqrestore(&priv->lock, flags);
- ipoib_send(dev, skb, path->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha));
+ ipoib_send(dev, skb, path->ah, IPOIB_QPN(n->ha));
return;
}
} else {
@@ -634,24 +637,28 @@ err_drop:
spin_unlock_irqrestore(&priv->lock, flags);
}
+/* called with rcu_read_lock */
static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(skb->dev);
+ struct dst_entry *dst = skb_dst(skb);
+ struct neighbour *n;
/* Look up path record for unicasts */
- if (skb_dst(skb)->neighbour->ha[4] != 0xff) {
+ n = dst_get_neighbour(dst);
+ if (n->ha[4] != 0xff) {
neigh_add_path(skb, dev);
return;
}
/* Add in the P_Key for multicasts */
- skb_dst(skb)->neighbour->ha[8] = (priv->pkey >> 8) & 0xff;
- skb_dst(skb)->neighbour->ha[9] = priv->pkey & 0xff;
- ipoib_mcast_send(dev, skb_dst(skb)->neighbour->ha + 4, skb);
+ n->ha[8] = (priv->pkey >> 8) & 0xff;
+ n->ha[9] = priv->pkey & 0xff;
+ ipoib_mcast_send(dev, n->ha + 4, skb);
}
static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
- struct ipoib_pseudoheader *phdr)
+ struct ipoib_cb *cb)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_path *path;
@@ -659,17 +666,15 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
spin_lock_irqsave(&priv->lock, flags);
- path = __path_find(dev, phdr->hwaddr + 4);
+ path = __path_find(dev, cb->hwaddr + 4);
if (!path || !path->valid) {
int new_path = 0;
if (!path) {
- path = path_rec_create(dev, phdr->hwaddr + 4);
+ path = path_rec_create(dev, cb->hwaddr + 4);
new_path = 1;
}
if (path) {
- /* put pseudoheader back on for next time */
- skb_push(skb, sizeof *phdr);
__skb_queue_tail(&path->queue, skb);
if (!path->query && path_rec_start(dev, path)) {
@@ -693,12 +698,10 @@ static void unicast_arp_send(struct sk_buff *skb, struct net_device *dev,
be16_to_cpu(path->pathrec.dlid));
spin_unlock_irqrestore(&priv->lock, flags);
- ipoib_send(dev, skb, path->ah, IPOIB_QPN(phdr->hwaddr));
+ ipoib_send(dev, skb, path->ah, IPOIB_QPN(cb->hwaddr));
return;
} else if ((path->query || !path_rec_start(dev, path)) &&
skb_queue_len(&path->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
- /* put pseudoheader back on for next time */
- skb_push(skb, sizeof *phdr);
__skb_queue_tail(&path->queue, skb);
} else {
++dev->stats.tx_dropped;
@@ -712,18 +715,23 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
struct ipoib_neigh *neigh;
+ struct neighbour *n = NULL;
unsigned long flags;
- if (likely(skb_dst(skb) && skb_dst(skb)->neighbour)) {
- if (unlikely(!*to_ipoib_neigh(skb_dst(skb)->neighbour))) {
+ rcu_read_lock();
+ if (likely(skb_dst(skb)))
+ n = dst_get_neighbour(skb_dst(skb));
+
+ if (likely(n)) {
+ if (unlikely(!*to_ipoib_neigh(n))) {
ipoib_path_lookup(skb, dev);
- return NETDEV_TX_OK;
+ goto unlock;
}
- neigh = *to_ipoib_neigh(skb_dst(skb)->neighbour);
+ neigh = *to_ipoib_neigh(n);
if (unlikely((memcmp(&neigh->dgid.raw,
- skb_dst(skb)->neighbour->ha + 4,
+ n->ha + 4,
sizeof(union ib_gid))) ||
(neigh->dev != dev))) {
spin_lock_irqsave(&priv->lock, flags);
@@ -740,17 +748,17 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
ipoib_neigh_free(dev, neigh);
spin_unlock_irqrestore(&priv->lock, flags);
ipoib_path_lookup(skb, dev);
- return NETDEV_TX_OK;
+ goto unlock;
}
if (ipoib_cm_get(neigh)) {
if (ipoib_cm_up(neigh)) {
ipoib_cm_send(dev, skb, ipoib_cm_get(neigh));
- return NETDEV_TX_OK;
+ goto unlock;
}
} else if (neigh->ah) {
- ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(skb_dst(skb)->neighbour->ha));
- return NETDEV_TX_OK;
+ ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha));
+ goto unlock;
}
if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
@@ -762,16 +770,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb_any(skb);
}
} else {
- struct ipoib_pseudoheader *phdr =
- (struct ipoib_pseudoheader *) skb->data;
- skb_pull(skb, sizeof *phdr);
+ struct ipoib_cb *cb = (struct ipoib_cb *) skb->cb;
- if (phdr->hwaddr[4] == 0xff) {
+ if (cb->hwaddr[4] == 0xff) {
/* Add in the P_Key for multicast*/
- phdr->hwaddr[8] = (priv->pkey >> 8) & 0xff;
- phdr->hwaddr[9] = priv->pkey & 0xff;
+ cb->hwaddr[8] = (priv->pkey >> 8) & 0xff;
+ cb->hwaddr[9] = priv->pkey & 0xff;
- ipoib_mcast_send(dev, phdr->hwaddr + 4, skb);
+ ipoib_mcast_send(dev, cb->hwaddr + 4, skb);
} else {
/* unicast GID -- should be ARP or RARP reply */
@@ -780,17 +786,18 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
ipoib_warn(priv, "Unicast, no %s: type %04x, QPN %06x %pI6\n",
skb_dst(skb) ? "neigh" : "dst",
be16_to_cpup((__be16 *) skb->data),
- IPOIB_QPN(phdr->hwaddr),
- phdr->hwaddr + 4);
+ IPOIB_QPN(cb->hwaddr),
+ cb->hwaddr + 4);
dev_kfree_skb_any(skb);
++dev->stats.tx_dropped;
- return NETDEV_TX_OK;
+ goto unlock;
}
- unicast_arp_send(skb, dev, phdr);
+ unicast_arp_send(skb, dev, cb);
}
}
-
+unlock:
+ rcu_read_unlock();
return NETDEV_TX_OK;
}
@@ -819,14 +826,13 @@ static int ipoib_hard_header(struct sk_buff *skb,
header->reserved = 0;
/*
- * If we don't have a neighbour structure, stuff the
- * destination address onto the front of the skb so we can
- * figure out where to send the packet later.
+ * If we don't have a dst_entry structure, stuff the
+ * destination address into skb->cb so we can figure out where
+ * to send the packet later.
*/
- if ((!skb_dst(skb) || !skb_dst(skb)->neighbour) && daddr) {
- struct ipoib_pseudoheader *phdr =
- (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
- memcpy(phdr->hwaddr, daddr, INFINIBAND_ALEN);
+ if (!skb_dst(skb)) {
+ struct ipoib_cb *cb = (struct ipoib_cb *) skb->cb;
+ memcpy(cb->hwaddr, daddr, INFINIBAND_ALEN);
}
return 0;
@@ -1002,11 +1008,7 @@ static void ipoib_setup(struct net_device *dev)
dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
- /*
- * We add in INFINIBAND_ALEN to allow for the destination
- * address "pseudoheader" for skbs without neighbour struct.
- */
- dev->hard_header_len = IPOIB_ENCAP_LEN + INFINIBAND_ALEN;
+ dev->hard_header_len = IPOIB_ENCAP_LEN;
dev->addr_len = INFINIBAND_ALEN;
dev->type = ARPHRD_INFINIBAND;
dev->tx_queue_len = ipoib_sendq_size * 2;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 3871ac663554..8b6350606d57 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -258,17 +258,14 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
netif_tx_lock_bh(dev);
while (!skb_queue_empty(&mcast->pkt_queue)) {
struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue);
+
netif_tx_unlock_bh(dev);
skb->dev = dev;
- if (!skb_dst(skb) || !skb_dst(skb)->neighbour) {
- /* put pseudoheader back on for next time */
- skb_push(skb, sizeof (struct ipoib_pseudoheader));
- }
-
if (dev_queue_xmit(skb))
ipoib_warn(priv, "dev_queue_xmit failed to requeue packet\n");
+
netif_tx_lock_bh(dev);
}
netif_tx_unlock_bh(dev);
@@ -715,11 +712,15 @@ void ipoib_mcast_send(struct net_device *dev, void *mgid, struct sk_buff *skb)
out:
if (mcast && mcast->ah) {
- if (skb_dst(skb) &&
- skb_dst(skb)->neighbour &&
- !*to_ipoib_neigh(skb_dst(skb)->neighbour)) {
- struct ipoib_neigh *neigh = ipoib_neigh_alloc(skb_dst(skb)->neighbour,
- skb->dev);
+ struct dst_entry *dst = skb_dst(skb);
+ struct neighbour *n = NULL;
+
+ rcu_read_lock();
+ if (dst)
+ n = dst_get_neighbour(dst);
+ if (n && !*to_ipoib_neigh(n)) {
+ struct ipoib_neigh *neigh = ipoib_neigh_alloc(n,
+ skb->dev);
if (neigh) {
kref_get(&mcast->ah->ref);
@@ -727,7 +728,7 @@ out:
list_add_tail(&neigh->list, &mcast->neigh_list);
}
}
-
+ rcu_read_unlock();
spin_unlock_irqrestore(&priv->lock, flags);
ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN);
return;
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c
index 8db008de5392..f8f57583f5d0 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.c
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.c
@@ -354,6 +354,9 @@ iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session,
}
ib_conn = ep->dd_data;
+ if (iser_alloc_rx_descriptors(ib_conn))
+ return -ENOMEM;
+
/* binds the iSER connection retrieved from the previously
* connected ep_handle to the iSCSI layer connection. exchanges
* connection pointers */
@@ -388,19 +391,6 @@ iscsi_iser_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
iser_conn->ib_conn = NULL;
}
-static int
-iscsi_iser_conn_start(struct iscsi_cls_conn *cls_conn)
-{
- struct iscsi_conn *conn = cls_conn->dd_data;
- int err;
-
- err = iser_conn_set_full_featured_mode(conn);
- if (err)
- return err;
-
- return iscsi_conn_start(cls_conn);
-}
-
static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session)
{
struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
@@ -686,7 +676,7 @@ static struct iscsi_transport iscsi_iser_transport = {
.get_conn_param = iscsi_conn_get_param,
.get_ep_param = iscsi_iser_get_ep_param,
.get_session_param = iscsi_session_get_param,
- .start_conn = iscsi_iser_conn_start,
+ .start_conn = iscsi_conn_start,
.stop_conn = iscsi_iser_conn_stop,
/* iscsi host params */
.get_host_param = iscsi_host_get_param,
diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h
index 2f02ab0ccc1e..634aef039fe2 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -365,4 +365,5 @@ int iser_dma_map_task_data(struct iscsi_iser_task *iser_task,
void iser_dma_unmap_task_data(struct iscsi_iser_task *iser_task);
int iser_initialize_task_headers(struct iscsi_task *task,
struct iser_tx_desc *tx_desc);
+int iser_alloc_rx_descriptors(struct iser_conn *ib_conn);
#endif
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
index 95a08a8ca8aa..eb1ee6f8d894 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -170,7 +170,7 @@ static void iser_create_send_desc(struct iser_conn *ib_conn,
}
-static int iser_alloc_rx_descriptors(struct iser_conn *ib_conn)
+int iser_alloc_rx_descriptors(struct iser_conn *ib_conn)
{
int i, j;
u64 dma_addr;
@@ -236,23 +236,24 @@ void iser_free_rx_descriptors(struct iser_conn *ib_conn)
kfree(ib_conn->rx_descs);
}
-/**
- * iser_conn_set_full_featured_mode - (iSER API)
- */
-int iser_conn_set_full_featured_mode(struct iscsi_conn *conn)
+static int iser_post_rx_bufs(struct iscsi_conn *conn, struct iscsi_hdr *req)
{
struct iscsi_iser_conn *iser_conn = conn->dd_data;
- iser_dbg("Initially post: %d\n", ISER_MIN_POSTED_RX);
-
- /* Check that there is no posted recv or send buffers left - */
- /* they must be consumed during the login phase */
- BUG_ON(iser_conn->ib_conn->post_recv_buf_count != 0);
- BUG_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0);
+ iser_dbg("req op %x flags %x\n", req->opcode, req->flags);
+ /* check if this is the last login - going to full feature phase */
+ if ((req->flags & ISCSI_FULL_FEATURE_PHASE) != ISCSI_FULL_FEATURE_PHASE)
+ return 0;
- if (iser_alloc_rx_descriptors(iser_conn->ib_conn))
- return -ENOMEM;
+ /*
+ * Check that there is one posted recv buffer (for the last login
+ * response) and no posted send buffers left - they must have been
+ * consumed during previous login phases.
+ */
+ WARN_ON(iser_conn->ib_conn->post_recv_buf_count != 1);
+ WARN_ON(atomic_read(&iser_conn->ib_conn->post_send_buf_count) != 0);
+ iser_dbg("Initially post: %d\n", ISER_MIN_POSTED_RX);
/* Initial post receive buffers */
if (iser_post_recvm(iser_conn->ib_conn, ISER_MIN_POSTED_RX))
return -ENOMEM;
@@ -421,6 +422,9 @@ int iser_send_control(struct iscsi_conn *conn,
err = iser_post_recvl(iser_conn->ib_conn);
if (err)
goto send_control_error;
+ err = iser_post_rx_bufs(conn, task->hdr);
+ if (err)
+ goto send_control_error;
}
err = iser_post_send(iser_conn->ib_conn, mdesc);
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 99d58764ef03..0b9944346ec3 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -426,7 +426,9 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int
/*
* First try "E6 report".
- * ALPS should return 0,0,10 or 0,0,100
+ * ALPS should return 0,0,10 or 0,0,100 if no buttons are pressed.
+ * The bits 0-2 of the first byte will be 1s if some buttons are
+ * pressed.
*/
param[0] = 0;
if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) ||
@@ -441,7 +443,8 @@ static const struct alps_model_info *alps_get_model(struct psmouse *psmouse, int
dbg("E6 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
- if (param[0] != 0 || param[1] != 0 || (param[2] != 10 && param[2] != 100))
+ if ((param[0] & 0xf8) != 0 || param[1] != 0 ||
+ (param[2] != 10 && param[2] != 100))
return NULL;
/*
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index e06e045bf907..6ad728f0e287 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -24,6 +24,7 @@
*/
#include <linux/module.h>
+#include <linux/delay.h>
#include <linux/dmi.h>
#include <linux/input/mt.h>
#include <linux/serio.h>
@@ -760,6 +761,16 @@ static int synaptics_reconnect(struct psmouse *psmouse)
do {
psmouse_reset(psmouse);
+ if (retry) {
+ /*
+ * On some boxes, right after resuming, the touchpad
+ * needs some time to finish initializing (I assume
+ * it needs time to calibrate) and start responding
+ * to Synaptics-specific queries, so let's wait a
+ * bit.
+ */
+ ssleep(1);
+ }
error = synaptics_detect(psmouse, 0);
} while (error && ++retry < 3);
diff --git a/drivers/input/touchscreen/max11801_ts.c b/drivers/input/touchscreen/max11801_ts.c
index 48ee3600a03b..a1ac2d204295 100755
--- a/drivers/input/touchscreen/max11801_ts.c
+++ b/drivers/input/touchscreen/max11801_ts.c
@@ -106,6 +106,7 @@ struct max11801_data {
};
struct i2c_client *max11801_client;
unsigned int max11801_workmode;
+u8 aux_buf[AUX_BUFSIZE];
static int max11801_dcm_write_command(struct i2c_client *client, int command)
{
@@ -115,7 +116,6 @@ static int max11801_dcm_write_command(struct i2c_client *client, int command)
static u32 max11801_dcm_sample_aux(struct i2c_client *client)
{
u8 temp_buf;
- u8 aux_buf[AUX_BUFSIZE];
int ret;
int aux = 0;
u32 sample_data = 0;
@@ -124,15 +124,17 @@ static u32 max11801_dcm_sample_aux(struct i2c_client *client)
mdelay(5);
ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_AUX_MSB,
1, &temp_buf);
- aux_buf[0] = temp_buf;
if (ret < 1)
printk(KERN_DEBUG "FIFO_RD_AUX_MSB read fails\n");
+ else
+ aux_buf[0] = temp_buf;
mdelay(5);
ret = i2c_smbus_read_i2c_block_data(client, FIFO_RD_AUX_LSB,
1, &temp_buf);
- aux_buf[1] = temp_buf;
if (ret < 1)
printk(KERN_DEBUG "FIFO_RD_AUX_LSB read fails\n");
+ else
+ aux_buf[1] = temp_buf;
aux = (aux_buf[0] << 4) +
(aux_buf[1] >> 4);
/*
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index 658e75f18d05..d1dde6577fa9 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -14,6 +14,7 @@
#include "gigaset.h"
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/ratelimit.h>
#include <linux/isdn/capilli.h>
#include <linux/isdn/capicmd.h>
#include <linux/isdn/capiutil.h>
@@ -222,10 +223,14 @@ get_appl(struct gigaset_capi_ctr *iif, u16 appl)
static inline void dump_cmsg(enum debuglevel level, const char *tag, _cmsg *p)
{
#ifdef CONFIG_GIGASET_DEBUG
+ /* dump at most 20 messages in 20 secs */
+ static DEFINE_RATELIMIT_STATE(msg_dump_ratelimit, 20 * HZ, 20);
_cdebbuf *cdb;
if (!(gigaset_debuglevel & level))
return;
+ if (!___ratelimit(&msg_dump_ratelimit, tag))
+ return;
cdb = capi_cmsg2str(p);
if (cdb) {
@@ -2058,12 +2063,6 @@ static void do_reset_b3_req(struct gigaset_capi_ctr *iif,
}
/*
- * dump unsupported/ignored messages at most twice per minute,
- * some apps send those very frequently
- */
-static unsigned long ignored_msg_dump_time;
-
-/*
* unsupported CAPI message handler
*/
static void do_unsupported(struct gigaset_capi_ctr *iif,
@@ -2072,8 +2071,7 @@ static void do_unsupported(struct gigaset_capi_ctr *iif,
{
/* decode message */
capi_message2cmsg(&iif->acmsg, skb->data);
- if (printk_timed_ratelimit(&ignored_msg_dump_time, 30 * 1000))
- dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
+ dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState);
}
@@ -2084,11 +2082,9 @@ static void do_nothing(struct gigaset_capi_ctr *iif,
struct gigaset_capi_appl *ap,
struct sk_buff *skb)
{
- if (printk_timed_ratelimit(&ignored_msg_dump_time, 30 * 1000)) {
- /* decode message */
- capi_message2cmsg(&iif->acmsg, skb->data);
- dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
- }
+ /* decode message */
+ capi_message2cmsg(&iif->acmsg, skb->data);
+ dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg);
dev_kfree_skb_any(skb);
}
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 574b09afedd3..2eba9a12a6ab 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -1897,7 +1897,9 @@ int bitmap_load(mddev_t *mddev)
* re-add of a missing device */
start = mddev->recovery_cp;
+ mutex_lock(&mddev->bitmap_info.mutex);
err = bitmap_init_from_disk(bitmap, start);
+ mutex_unlock(&mddev->bitmap_info.mutex);
}
if (err)
goto out;
@@ -1982,6 +1984,8 @@ location_store(mddev_t *mddev, const char *buf, size_t len)
if (mddev->pers) {
mddev->pers->quiesce(mddev, 1);
rv = bitmap_create(mddev);
+ if (!rv)
+ rv = bitmap_load(mddev);
if (rv) {
bitmap_destroy(mddev);
mddev->bitmap_info.offset = 0;
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index c8827ffd85bb..6f906bc9328b 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -177,7 +177,6 @@ struct crypt_config {
#define MIN_IOS 16
#define MIN_POOL_PAGES 32
-#define MIN_BIO_PAGES 8
static struct kmem_cache *_crypt_io_pool;
@@ -849,12 +848,11 @@ static struct bio *crypt_alloc_buffer(struct dm_crypt_io *io, unsigned size,
}
/*
- * if additional pages cannot be allocated without waiting,
- * return a partially allocated bio, the caller will then try
- * to allocate additional bios while submitting this partial bio
+ * If additional pages cannot be allocated without waiting,
+ * return a partially-allocated bio. The caller will then try
+ * to allocate more bios while submitting this partial bio.
*/
- if (i == (MIN_BIO_PAGES - 1))
- gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT;
+ gfp_mask = (gfp_mask | __GFP_NOWARN) & ~__GFP_WAIT;
len = (size > PAGE_SIZE) ? PAGE_SIZE : size;
@@ -1047,16 +1045,14 @@ static void kcryptd_queue_io(struct dm_crypt_io *io)
queue_work(cc->io_queue, &io->work);
}
-static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io,
- int error, int async)
+static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async)
{
struct bio *clone = io->ctx.bio_out;
struct crypt_config *cc = io->target->private;
- if (unlikely(error < 0)) {
+ if (unlikely(io->error < 0)) {
crypt_free_buffer_pages(cc, clone);
bio_put(clone);
- io->error = -EIO;
crypt_dec_pending(io);
return;
}
@@ -1107,12 +1103,16 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
sector += bio_sectors(clone);
crypt_inc_pending(io);
+
r = crypt_convert(cc, &io->ctx);
+ if (r < 0)
+ io->error = -EIO;
+
crypt_finished = atomic_dec_and_test(&io->ctx.pending);
/* Encryption was already finished, submit io now */
if (crypt_finished) {
- kcryptd_crypt_write_io_submit(io, r, 0);
+ kcryptd_crypt_write_io_submit(io, 0);
/*
* If there was an error, do not try next fragments.
@@ -1163,11 +1163,8 @@ static void kcryptd_crypt_write_convert(struct dm_crypt_io *io)
crypt_dec_pending(io);
}
-static void kcryptd_crypt_read_done(struct dm_crypt_io *io, int error)
+static void kcryptd_crypt_read_done(struct dm_crypt_io *io)
{
- if (unlikely(error < 0))
- io->error = -EIO;
-
crypt_dec_pending(io);
}
@@ -1182,9 +1179,11 @@ static void kcryptd_crypt_read_convert(struct dm_crypt_io *io)
io->sector);
r = crypt_convert(cc, &io->ctx);
+ if (r < 0)
+ io->error = -EIO;
if (atomic_dec_and_test(&io->ctx.pending))
- kcryptd_crypt_read_done(io, r);
+ kcryptd_crypt_read_done(io);
crypt_dec_pending(io);
}
@@ -1205,15 +1204,18 @@ static void kcryptd_async_done(struct crypto_async_request *async_req,
if (!error && cc->iv_gen_ops && cc->iv_gen_ops->post)
error = cc->iv_gen_ops->post(cc, iv_of_dmreq(cc, dmreq), dmreq);
+ if (error < 0)
+ io->error = -EIO;
+
mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool);
if (!atomic_dec_and_test(&ctx->pending))
return;
if (bio_data_dir(io->base_bio) == READ)
- kcryptd_crypt_read_done(io, error);
+ kcryptd_crypt_read_done(io);
else
- kcryptd_crypt_write_io_submit(io, error, 1);
+ kcryptd_crypt_write_io_submit(io, 1);
}
static void kcryptd_crypt(struct work_struct *work)
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index 0bdb201c2c2a..7344534294aa 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -282,7 +282,7 @@ int dm_exception_store_init(void)
return 0;
persistent_fail:
- dm_persistent_snapshot_exit();
+ dm_transient_snapshot_exit();
transient_fail:
return r;
}
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
index ea790623c30b..3e90b8014f98 100644
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -149,8 +149,17 @@ static int flakey_status(struct dm_target *ti, status_type_t type,
static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg)
{
struct flakey_c *fc = ti->private;
+ struct dm_dev *dev = fc->dev;
+ int r = 0;
- return __blkdev_driver_ioctl(fc->dev->bdev, fc->dev->mode, cmd, arg);
+ /*
+ * Only pass ioctls through if the device sizes match exactly.
+ */
+ if (fc->start ||
+ ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
+ r = scsi_verify_blk_ioctl(NULL, cmd);
+
+ return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
}
static int flakey_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index ad2eba40e319..ea5dd289fe2a 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -296,6 +296,8 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
unsigned offset;
unsigned num_bvecs;
sector_t remaining = where->count;
+ struct request_queue *q = bdev_get_queue(where->bdev);
+ sector_t discard_sectors;
/*
* where->count may be zero if rw holds a flush and we need to
@@ -305,9 +307,12 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
/*
* Allocate a suitably sized-bio.
*/
- num_bvecs = dm_sector_div_up(remaining,
- (PAGE_SIZE >> SECTOR_SHIFT));
- num_bvecs = min_t(int, bio_get_nr_vecs(where->bdev), num_bvecs);
+ if (rw & REQ_DISCARD)
+ num_bvecs = 1;
+ else
+ num_bvecs = min_t(int, bio_get_nr_vecs(where->bdev),
+ dm_sector_div_up(remaining, (PAGE_SIZE >> SECTOR_SHIFT)));
+
bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios);
bio->bi_sector = where->sector + (where->count - remaining);
bio->bi_bdev = where->bdev;
@@ -315,10 +320,14 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where,
bio->bi_destructor = dm_bio_destructor;
store_io_and_region_in_bio(bio, io, region);
- /*
- * Try and add as many pages as possible.
- */
- while (remaining) {
+ if (rw & REQ_DISCARD) {
+ discard_sectors = min_t(sector_t, q->limits.max_discard_sectors, remaining);
+ bio->bi_size = discard_sectors << SECTOR_SHIFT;
+ remaining -= discard_sectors;
+ } else while (remaining) {
+ /*
+ * Try and add as many pages as possible.
+ */
dp->get_page(dp, &page, &len, &offset);
len = min(len, to_bytes(remaining));
if (!bio_add_page(bio, page, len, offset))
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 3921e3bb43c1..9728839f844a 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -116,7 +116,17 @@ static int linear_ioctl(struct dm_target *ti, unsigned int cmd,
unsigned long arg)
{
struct linear_c *lc = (struct linear_c *) ti->private;
- return __blkdev_driver_ioctl(lc->dev->bdev, lc->dev->mode, cmd, arg);
+ struct dm_dev *dev = lc->dev;
+ int r = 0;
+
+ /*
+ * Only pass ioctls through if the device sizes match exactly.
+ */
+ if (lc->start ||
+ ti->len != i_size_read(dev->bdev->bd_inode) >> SECTOR_SHIFT)
+ r = scsi_verify_blk_ioctl(NULL, cmd);
+
+ return r ? : __blkdev_driver_ioctl(dev->bdev, dev->mode, cmd, arg);
}
static int linear_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 209991bebd30..70373bfa20bc 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -1584,6 +1584,12 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
spin_unlock_irqrestore(&m->lock, flags);
+ /*
+ * Only pass ioctls through if the device sizes match exactly.
+ */
+ if (!r && ti->len != i_size_read(bdev->bd_inode) >> SECTOR_SHIFT)
+ r = scsi_verify_blk_ioctl(NULL, cmd);
+
return r ? : __blkdev_driver_ioctl(bdev, mode, cmd, arg);
}
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index e5d8904fc8f6..437ae1825f13 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -468,6 +468,7 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv)
INIT_WORK(&rs->md.event_work, do_table_event);
ti->split_io = rs->md.chunk_sectors;
ti->private = rs;
+ ti->num_flush_requests = 1;
mutex_lock(&rs->md.reconfig_mutex);
ret = md_run(&rs->md);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index bc8342812d06..8b04a02672b4 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -348,6 +348,8 @@ void mddev_suspend(mddev_t *mddev)
synchronize_rcu();
wait_event(mddev->sb_wait, atomic_read(&mddev->active_io) == 0);
mddev->pers->quiesce(mddev, 1);
+
+ del_timer_sync(&mddev->safemode_timer);
}
EXPORT_SYMBOL_GPL(mddev_suspend);
@@ -407,7 +409,7 @@ static void submit_flushes(struct work_struct *ws)
atomic_inc(&rdev->nr_pending);
atomic_inc(&rdev->nr_pending);
rcu_read_unlock();
- bi = bio_alloc_mddev(GFP_KERNEL, 0, mddev);
+ bi = bio_alloc_mddev(GFP_NOIO, 0, mddev);
bi->bi_end_io = md_end_flush;
bi->bi_private = rdev;
bi->bi_bdev = rdev->bdev;
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 3a9e59fe7ad3..36f1ed313ae3 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -614,9 +614,22 @@ static void wait_barrier(conf_t *conf)
spin_lock_irq(&conf->resync_lock);
if (conf->barrier) {
conf->nr_waiting++;
- wait_event_lock_irq(conf->wait_barrier, !conf->barrier,
+ /* Wait for the barrier to drop.
+ * However if there are already pending
+ * requests (preventing the barrier from
+ * rising completely), and the
+ * pre-process bio queue isn't empty,
+ * then don't wait, as we need to empty
+ * that queue to get the nr_pending
+ * count down.
+ */
+ wait_event_lock_irq(conf->wait_barrier,
+ !conf->barrier ||
+ (conf->nr_pending &&
+ current->bio_list &&
+ !bio_list_empty(current->bio_list)),
conf->resync_lock,
- );
+ );
conf->nr_waiting--;
}
conf->nr_pending++;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 17cb6ab62308..0d6c42f70a35 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -667,9 +667,22 @@ static void wait_barrier(conf_t *conf)
spin_lock_irq(&conf->resync_lock);
if (conf->barrier) {
conf->nr_waiting++;
- wait_event_lock_irq(conf->wait_barrier, !conf->barrier,
+ /* Wait for the barrier to drop.
+ * However if there are already pending
+ * requests (preventing the barrier from
+ * rising completely), and the
+ * pre-process bio queue isn't empty,
+ * then don't wait, as we need to empty
+ * that queue to get the nr_pending
+ * count down.
+ */
+ wait_event_lock_irq(conf->wait_barrier,
+ !conf->barrier ||
+ (conf->nr_pending &&
+ current->bio_list &&
+ !bio_list_empty(current->bio_list)),
conf->resync_lock,
- );
+ );
conf->nr_waiting--;
}
conf->nr_pending++;
diff --git a/drivers/media/dvb/frontends/lgdt330x.c b/drivers/media/dvb/frontends/lgdt330x.c
index 43971e63baa7..aa63d687d276 100644
--- a/drivers/media/dvb/frontends/lgdt330x.c
+++ b/drivers/media/dvb/frontends/lgdt330x.c
@@ -104,8 +104,8 @@ static int i2c_write_demod_bytes (struct lgdt330x_state* state,
* then reads the data returned for (len) bytes.
*/
-static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
- enum I2C_REG reg, u8* buf, int len)
+static int i2c_read_demod_bytes(struct lgdt330x_state *state,
+ enum I2C_REG reg, u8 *buf, int len)
{
u8 wr [] = { reg };
struct i2c_msg msg [] = {
@@ -118,6 +118,8 @@ static u8 i2c_read_demod_bytes (struct lgdt330x_state* state,
ret = i2c_transfer(state->i2c, msg, 2);
if (ret != 2) {
printk(KERN_WARNING "lgdt330x: %s: addr 0x%02x select 0x%02x error (ret == %i)\n", __func__, state->config->demod_address, reg, ret);
+ if (ret >= 0)
+ ret = -EIO;
} else {
ret = 0;
}
diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c
index 0c8164a2cc36..d755407fb4f9 100644
--- a/drivers/media/dvb/siano/smsusb.c
+++ b/drivers/media/dvb/siano/smsusb.c
@@ -541,6 +541,8 @@ static const struct usb_device_id smsusb_id_table[] __devinitconst = {
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ USB_DEVICE(0x2040, 0xc090),
.driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
+ { USB_DEVICE(0x2040, 0xc0a0),
+ .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM },
{ } /* Terminating entry */
};
diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c
index a43ed6c41bfc..12b91ae1b208 100644
--- a/drivers/media/rc/ene_ir.c
+++ b/drivers/media/rc/ene_ir.c
@@ -1017,22 +1017,6 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
spin_lock_init(&dev->hw_lock);
- /* claim the resources */
- error = -EBUSY;
- dev->hw_io = pnp_port_start(pnp_dev, 0);
- if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) {
- dev->hw_io = -1;
- dev->irq = -1;
- goto error;
- }
-
- dev->irq = pnp_irq(pnp_dev, 0);
- if (request_irq(dev->irq, ene_isr,
- IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) {
- dev->irq = -1;
- goto error;
- }
-
pnp_set_drvdata(pnp_dev, dev);
dev->pnp_dev = pnp_dev;
@@ -1085,6 +1069,22 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
device_set_wakeup_capable(&pnp_dev->dev, true);
device_set_wakeup_enable(&pnp_dev->dev, true);
+ /* claim the resources */
+ error = -EBUSY;
+ dev->hw_io = pnp_port_start(pnp_dev, 0);
+ if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) {
+ dev->hw_io = -1;
+ dev->irq = -1;
+ goto error;
+ }
+
+ dev->irq = pnp_irq(pnp_dev, 0);
+ if (request_irq(dev->irq, ene_isr,
+ IRQF_SHARED, ENE_DRIVER_NAME, (void *)dev)) {
+ dev->irq = -1;
+ goto error;
+ }
+
error = rc_register_device(rdev);
if (error < 0)
goto error;
diff --git a/drivers/media/rc/fintek-cir.c b/drivers/media/rc/fintek-cir.c
index 7f7079b12f23..4218f7369c52 100644
--- a/drivers/media/rc/fintek-cir.c
+++ b/drivers/media/rc/fintek-cir.c
@@ -504,16 +504,6 @@ static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id
spin_lock_init(&fintek->fintek_lock);
- ret = -EBUSY;
- /* now claim resources */
- if (!request_region(fintek->cir_addr,
- fintek->cir_port_len, FINTEK_DRIVER_NAME))
- goto failure;
-
- if (request_irq(fintek->cir_irq, fintek_cir_isr, IRQF_SHARED,
- FINTEK_DRIVER_NAME, (void *)fintek))
- goto failure;
-
pnp_set_drvdata(pdev, fintek);
fintek->pdev = pdev;
@@ -548,6 +538,16 @@ static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id
/* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */
rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD);
+ ret = -EBUSY;
+ /* now claim resources */
+ if (!request_region(fintek->cir_addr,
+ fintek->cir_port_len, FINTEK_DRIVER_NAME))
+ goto failure;
+
+ if (request_irq(fintek->cir_irq, fintek_cir_isr, IRQF_SHARED,
+ FINTEK_DRIVER_NAME, (void *)fintek))
+ goto failure;
+
ret = rc_register_device(rdev);
if (ret)
goto failure;
diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
index ecd3d0280768..c5ca0914087b 100644
--- a/drivers/media/rc/ite-cir.c
+++ b/drivers/media/rc/ite-cir.c
@@ -1519,16 +1519,6 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
/* initialize raw event */
init_ir_raw_event(&itdev->rawir);
- ret = -EBUSY;
- /* now claim resources */
- if (!request_region(itdev->cir_addr,
- dev_desc->io_region_size, ITE_DRIVER_NAME))
- goto failure;
-
- if (request_irq(itdev->cir_irq, ite_cir_isr, IRQF_SHARED,
- ITE_DRIVER_NAME, (void *)itdev))
- goto failure;
-
/* set driver data into the pnp device */
pnp_set_drvdata(pdev, itdev);
itdev->pdev = pdev;
@@ -1604,6 +1594,16 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
rdev->driver_name = ITE_DRIVER_NAME;
rdev->map_name = RC_MAP_RC6_MCE;
+ ret = -EBUSY;
+ /* now claim resources */
+ if (!request_region(itdev->cir_addr,
+ dev_desc->io_region_size, ITE_DRIVER_NAME))
+ goto failure;
+
+ if (request_irq(itdev->cir_irq, ite_cir_isr, IRQF_SHARED,
+ ITE_DRIVER_NAME, (void *)itdev))
+ goto failure;
+
ret = rc_register_device(rdev);
if (ret)
goto failure;
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 9fd019e6b9b5..c212276202f9 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -1027,24 +1027,6 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
spin_lock_init(&nvt->nvt_lock);
spin_lock_init(&nvt->tx.lock);
- ret = -EBUSY;
- /* now claim resources */
- if (!request_region(nvt->cir_addr,
- CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
- goto failure;
-
- if (request_irq(nvt->cir_irq, nvt_cir_isr, IRQF_SHARED,
- NVT_DRIVER_NAME, (void *)nvt))
- goto failure;
-
- if (!request_region(nvt->cir_wake_addr,
- CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
- goto failure;
-
- if (request_irq(nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED,
- NVT_DRIVER_NAME, (void *)nvt))
- goto failure;
-
pnp_set_drvdata(pdev, nvt);
nvt->pdev = pdev;
@@ -1091,6 +1073,24 @@ static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
rdev->tx_resolution = XYZ;
#endif
+ ret = -EBUSY;
+ /* now claim resources */
+ if (!request_region(nvt->cir_addr,
+ CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
+ goto failure;
+
+ if (request_irq(nvt->cir_irq, nvt_cir_isr, IRQF_SHARED,
+ NVT_DRIVER_NAME, (void *)nvt))
+ goto failure;
+
+ if (!request_region(nvt->cir_wake_addr,
+ CIR_IOREG_LENGTH, NVT_DRIVER_NAME))
+ goto failure;
+
+ if (request_irq(nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED,
+ NVT_DRIVER_NAME, (void *)nvt))
+ goto failure;
+
ret = rc_register_device(rdev);
if (ret)
goto failure;
diff --git a/drivers/media/rc/winbond-cir.c b/drivers/media/rc/winbond-cir.c
index 5d06b899e859..9e55a0c9ac5e 100644
--- a/drivers/media/rc/winbond-cir.c
+++ b/drivers/media/rc/winbond-cir.c
@@ -1003,39 +1003,10 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
"(w: 0x%lX, e: 0x%lX, s: 0x%lX, i: %u)\n",
data->wbase, data->ebase, data->sbase, data->irq);
- if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) {
- dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
- data->wbase, data->wbase + WAKEUP_IOMEM_LEN - 1);
- err = -EBUSY;
- goto exit_free_data;
- }
-
- if (!request_region(data->ebase, EHFUNC_IOMEM_LEN, DRVNAME)) {
- dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
- data->ebase, data->ebase + EHFUNC_IOMEM_LEN - 1);
- err = -EBUSY;
- goto exit_release_wbase;
- }
-
- if (!request_region(data->sbase, SP_IOMEM_LEN, DRVNAME)) {
- dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
- data->sbase, data->sbase + SP_IOMEM_LEN - 1);
- err = -EBUSY;
- goto exit_release_ebase;
- }
-
- err = request_irq(data->irq, wbcir_irq_handler,
- IRQF_DISABLED, DRVNAME, device);
- if (err) {
- dev_err(dev, "Failed to claim IRQ %u\n", data->irq);
- err = -EBUSY;
- goto exit_release_sbase;
- }
-
led_trigger_register_simple("cir-tx", &data->txtrigger);
if (!data->txtrigger) {
err = -ENOMEM;
- goto exit_free_irq;
+ goto exit_free_data;
}
led_trigger_register_simple("cir-rx", &data->rxtrigger);
@@ -1058,6 +1029,7 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
goto exit_unregister_led;
}
+ data->dev->driver_type = RC_DRIVER_IR_RAW;
data->dev->driver_name = WBCIR_NAME;
data->dev->input_name = WBCIR_NAME;
data->dev->input_phys = "wbcir/cir0";
@@ -1073,9 +1045,38 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
data->dev->priv = data;
data->dev->dev.parent = &device->dev;
+ if (!request_region(data->wbase, WAKEUP_IOMEM_LEN, DRVNAME)) {
+ dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
+ data->wbase, data->wbase + WAKEUP_IOMEM_LEN - 1);
+ err = -EBUSY;
+ goto exit_free_rc;
+ }
+
+ if (!request_region(data->ebase, EHFUNC_IOMEM_LEN, DRVNAME)) {
+ dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
+ data->ebase, data->ebase + EHFUNC_IOMEM_LEN - 1);
+ err = -EBUSY;
+ goto exit_release_wbase;
+ }
+
+ if (!request_region(data->sbase, SP_IOMEM_LEN, DRVNAME)) {
+ dev_err(dev, "Region 0x%lx-0x%lx already in use!\n",
+ data->sbase, data->sbase + SP_IOMEM_LEN - 1);
+ err = -EBUSY;
+ goto exit_release_ebase;
+ }
+
+ err = request_irq(data->irq, wbcir_irq_handler,
+ IRQF_DISABLED, DRVNAME, device);
+ if (err) {
+ dev_err(dev, "Failed to claim IRQ %u\n", data->irq);
+ err = -EBUSY;
+ goto exit_release_sbase;
+ }
+
err = rc_register_device(data->dev);
if (err)
- goto exit_free_rc;
+ goto exit_free_irq;
device_init_wakeup(&device->dev, 1);
@@ -1083,14 +1084,6 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
return 0;
-exit_free_rc:
- rc_free_device(data->dev);
-exit_unregister_led:
- led_classdev_unregister(&data->led);
-exit_unregister_rxtrigger:
- led_trigger_unregister_simple(data->rxtrigger);
-exit_unregister_txtrigger:
- led_trigger_unregister_simple(data->txtrigger);
exit_free_irq:
free_irq(data->irq, device);
exit_release_sbase:
@@ -1099,6 +1092,14 @@ exit_release_ebase:
release_region(data->ebase, EHFUNC_IOMEM_LEN);
exit_release_wbase:
release_region(data->wbase, WAKEUP_IOMEM_LEN);
+exit_free_rc:
+ rc_free_device(data->dev);
+exit_unregister_led:
+ led_classdev_unregister(&data->led);
+exit_unregister_rxtrigger:
+ led_trigger_unregister_simple(data->rxtrigger);
+exit_unregister_txtrigger:
+ led_trigger_unregister_simple(data->txtrigger);
exit_free_data:
kfree(data);
pnp_set_drvdata(device, NULL);
diff --git a/drivers/media/video/hdpvr/hdpvr-video.c b/drivers/media/video/hdpvr/hdpvr-video.c
index 514aea76eaa5..4c0394a8afd9 100644
--- a/drivers/media/video/hdpvr/hdpvr-video.c
+++ b/drivers/media/video/hdpvr/hdpvr-video.c
@@ -284,12 +284,13 @@ static int hdpvr_start_streaming(struct hdpvr_device *dev)
hdpvr_config_call(dev, CTRL_START_STREAMING_VALUE, 0x00);
+ dev->status = STATUS_STREAMING;
+
INIT_WORK(&dev->worker, hdpvr_transmit_buffers);
queue_work(dev->workqueue, &dev->worker);
v4l2_dbg(MSG_BUFFER, hdpvr_debug, &dev->v4l2_dev,
"streaming started\n");
- dev->status = STATUS_STREAMING;
return 0;
}
diff --git a/drivers/media/video/mxc/capture/Kconfig b/drivers/media/video/mxc/capture/Kconfig
index ba696aa8b6b2..eaebf2eb2f29 100644
--- a/drivers/media/video/mxc/capture/Kconfig
+++ b/drivers/media/video/mxc/capture/Kconfig
@@ -118,9 +118,10 @@ config MXC_CAMERA_OV5640_MIPI
config MXC_CAMERA_SENSOR_CLK
tristate "camera clock"
- depends on !VIDEO_MXC_EMMA_CAMERA
- ---help---
- If you plan to use the Camera with your MXC system, say Y here.
+ depends on !VIDEO_MXC_EMMA_CAMERA
+ ---help---
+ If you plan to use the Camera with your MXC system, say Y here.
+
config MXC_IPU_PRP_VF_SDC
tristate "Pre-Processor VF SDC library"
diff --git a/drivers/media/video/mxc/capture/adv7180.c b/drivers/media/video/mxc/capture/adv7180.c
index 18c51ba78f1e..2656afbb21e4 100644
--- a/drivers/media/video/mxc/capture/adv7180.c
+++ b/drivers/media/video/mxc/capture/adv7180.c
@@ -70,26 +70,12 @@ static struct i2c_driver adv7180_i2c_driver = {
/*!
* Maintains the information on the current state of the sensor.
*/
-static struct sensor {
- struct v4l2_int_device *v4l2_int_device;
- struct i2c_client *i2c_client;
- struct v4l2_pix_format pix;
- struct v4l2_captureparm streamcap;
- bool on;
-
- /* control settings */
- int brightness;
- int hue;
- int contrast;
- int saturation;
- int red;
- int green;
- int blue;
- int ae_mode;
-
+struct sensor {
+ struct sensor_data sen;
v4l2_std_id std_id;
} adv7180_data;
+
/*! List of input video formats supported. The video formats is corresponding
* with v4l2 id in video_fmt_t
*/
@@ -204,10 +190,10 @@ static struct v4l2_queryctrl adv7180_qctrl[] = {
static inline int adv7180_read(u8 reg)
{
int val;
- val = i2c_smbus_read_byte_data(adv7180_data.i2c_client, reg);
+ val = i2c_smbus_read_byte_data(adv7180_data.sen.i2c_client, reg);
if (val < 0) {
- dev_dbg(&adv7180_data.i2c_client->dev,
- "%s:read reg error: reg=%2x \n", __func__, reg);
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ "%s:read reg error: reg=%2x\n", __func__, reg);
return -1;
}
return val;
@@ -221,8 +207,11 @@ static inline int adv7180_read(u8 reg)
*/
static int adv7180_write_reg(u8 reg, u8 val)
{
- if (i2c_smbus_write_byte_data(adv7180_data.i2c_client, reg, val) < 0) {
- dev_dbg(&adv7180_data.i2c_client->dev,
+ s32 ret;
+
+ ret = i2c_smbus_write_byte_data(adv7180_data.sen.i2c_client, reg, val);
+ if (ret < 0) {
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
"%s:write reg error:reg=%2x,val=%2x\n", __func__,
reg, val);
return -1;
@@ -247,7 +236,7 @@ static void adv7180_get_std(v4l2_std_id *std)
int tmp;
int idx;
- dev_dbg(&adv7180_data.i2c_client->dev, "In adv7180_get_std\n");
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180_get_std\n");
/* Make sure power on */
if (tvin_plat->pwdn)
@@ -268,7 +257,7 @@ static void adv7180_get_std(v4l2_std_id *std)
} else {
*std = V4L2_STD_ALL;
idx = ADV7180_NOT_LOCKED;
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
"Got invalid video standard!\n");
}
mutex_unlock(&mutex);
@@ -277,8 +266,8 @@ static void adv7180_get_std(v4l2_std_id *std)
if (*std != adv7180_data.std_id) {
video_idx = idx;
adv7180_data.std_id = *std;
- adv7180_data.pix.width = video_fmts[video_idx].raw_width;
- adv7180_data.pix.height = video_fmts[video_idx].raw_height;
+ adv7180_data.sen.pix.width = video_fmts[video_idx].raw_width;
+ adv7180_data.sen.pix.height = video_fmts[video_idx].raw_height;
}
}
@@ -303,7 +292,7 @@ static void adv7180_get_std(v4l2_std_id *std)
*/
static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
{
- dev_dbg(&adv7180_data.i2c_client->dev, "In adv7180:ioctl_g_ifparm\n");
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_g_ifparm\n");
if (s == NULL) {
pr_err(" ERROR!! no slave device set!\n");
@@ -339,9 +328,9 @@ static int ioctl_s_power(struct v4l2_int_device *s, int on)
{
struct sensor *sensor = s->priv;
- dev_dbg(&adv7180_data.i2c_client->dev, "In adv7180:ioctl_s_power\n");
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_s_power\n");
- if (on && !sensor->on) {
+ if (on && !sensor->sen.on) {
gpio_sensor_active();
/* Make sure pwoer on */
@@ -350,13 +339,13 @@ static int ioctl_s_power(struct v4l2_int_device *s, int on)
if (adv7180_write_reg(ADV7180_PWR_MNG, 0) != 0)
return -EIO;
- } else if (!on && sensor->on) {
+ } else if (!on && sensor->sen.on) {
if (adv7180_write_reg(ADV7180_PWR_MNG, 0x24) != 0)
return -EIO;
gpio_sensor_inactive();
}
- sensor->on = on;
+ sensor->sen.on = on;
return 0;
}
@@ -373,7 +362,7 @@ static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
struct sensor *sensor = s->priv;
struct v4l2_captureparm *cparm = &a->parm.capture;
- dev_dbg(&adv7180_data.i2c_client->dev, "In adv7180:ioctl_g_parm\n");
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_g_parm\n");
switch (a->type) {
/* These are all the possible cases. */
@@ -381,9 +370,9 @@ static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
pr_debug(" type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
memset(a, 0, sizeof(*a));
a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- cparm->capability = sensor->streamcap.capability;
- cparm->timeperframe = sensor->streamcap.timeperframe;
- cparm->capturemode = sensor->streamcap.capturemode;
+ cparm->capability = sensor->sen.streamcap.capability;
+ cparm->timeperframe = sensor->sen.streamcap.timeperframe;
+ cparm->capturemode = sensor->sen.streamcap.capturemode;
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
@@ -415,7 +404,7 @@ static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
*/
static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
{
- dev_dbg(&adv7180_data.i2c_client->dev, "In adv7180:ioctl_s_parm\n");
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_s_parm\n");
switch (a->type) {
/* These are all the possible cases. */
@@ -448,13 +437,13 @@ static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
{
struct sensor *sensor = s->priv;
- dev_dbg(&adv7180_data.i2c_client->dev, "In adv7180:ioctl_g_fmt_cap\n");
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_g_fmt_cap\n");
switch (f->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
pr_debug(" Returning size of %dx%d\n",
- sensor->pix.width, sensor->pix.height);
- f->fmt.pix = sensor->pix;
+ sensor->sen.pix.width, sensor->sen.pix.height);
+ f->fmt.pix = sensor->sen.pix;
break;
case V4L2_BUF_TYPE_PRIVATE: {
@@ -465,7 +454,7 @@ static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
break;
default:
- f->fmt.pix = sensor->pix;
+ f->fmt.pix = sensor->sen.pix;
break;
}
@@ -486,7 +475,7 @@ static int ioctl_queryctrl(struct v4l2_int_device *s,
{
int i;
- dev_dbg(&adv7180_data.i2c_client->dev, "In adv7180:ioctl_queryctrl\n");
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_queryctrl\n");
for (i = 0; i < ARRAY_SIZE(adv7180_qctrl); i++)
if (qc->id && qc->id == adv7180_qctrl[i].id) {
@@ -510,8 +499,9 @@ static int ioctl_queryctrl(struct v4l2_int_device *s,
static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
{
int ret = 0;
+ int sat = 0;
- dev_dbg(&adv7180_data.i2c_client->dev, "In adv7180:ioctl_g_ctrl\n");
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_g_ctrl\n");
/* Make sure power on */
if (tvin_plat->pwdn)
@@ -519,72 +509,73 @@ static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
switch (vc->id) {
case V4L2_CID_BRIGHTNESS:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_BRIGHTNESS\n");
- adv7180_data.brightness = adv7180_read(ADV7180_BRIGHTNESS);
- vc->value = adv7180_data.brightness;
+ adv7180_data.sen.brightness = adv7180_read(ADV7180_BRIGHTNESS);
+ vc->value = adv7180_data.sen.brightness;
break;
case V4L2_CID_CONTRAST:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_CONTRAST\n");
- vc->value = adv7180_data.contrast;
+ vc->value = adv7180_data.sen.contrast;
break;
case V4L2_CID_SATURATION:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_SATURATION\n");
- adv7180_data.saturation = adv7180_read(ADV7180_SD_SATURATION_CB);
- vc->value = adv7180_data.saturation;
+ sat = adv7180_read(ADV7180_SD_SATURATION_CB);
+ adv7180_data.sen.saturation = sat;
+ vc->value = adv7180_data.sen.saturation;
break;
case V4L2_CID_HUE:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_HUE\n");
- vc->value = adv7180_data.hue;
+ vc->value = adv7180_data.sen.hue;
break;
case V4L2_CID_AUTO_WHITE_BALANCE:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_AUTO_WHITE_BALANCE\n");
break;
case V4L2_CID_DO_WHITE_BALANCE:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_DO_WHITE_BALANCE\n");
break;
case V4L2_CID_RED_BALANCE:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_RED_BALANCE\n");
- vc->value = adv7180_data.red;
+ vc->value = adv7180_data.sen.red;
break;
case V4L2_CID_BLUE_BALANCE:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_BLUE_BALANCE\n");
- vc->value = adv7180_data.blue;
+ vc->value = adv7180_data.sen.blue;
break;
case V4L2_CID_GAMMA:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_GAMMA\n");
break;
case V4L2_CID_EXPOSURE:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_EXPOSURE\n");
- vc->value = adv7180_data.ae_mode;
+ vc->value = adv7180_data.sen.ae_mode;
break;
case V4L2_CID_AUTOGAIN:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_AUTOGAIN\n");
break;
case V4L2_CID_GAIN:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_GAIN\n");
break;
case V4L2_CID_HFLIP:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_HFLIP\n");
break;
case V4L2_CID_VFLIP:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_VFLIP\n");
break;
default:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" Default case\n");
vc->value = 0;
ret = -EPERM;
@@ -608,7 +599,7 @@ static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
int retval = 0;
u8 tmp;
- dev_dbg(&adv7180_data.i2c_client->dev, "In adv7180:ioctl_s_ctrl\n");
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_s_ctrl\n");
/* Make sure power on */
if (tvin_plat->pwdn)
@@ -616,70 +607,70 @@ static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
switch (vc->id) {
case V4L2_CID_BRIGHTNESS:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_BRIGHTNESS\n");
tmp = vc->value;
adv7180_write_reg(ADV7180_BRIGHTNESS, tmp);
- adv7180_data.brightness = vc->value;
+ adv7180_data.sen.brightness = vc->value;
break;
case V4L2_CID_CONTRAST:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_CONTRAST\n");
break;
case V4L2_CID_SATURATION:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_SATURATION\n");
tmp = vc->value;
adv7180_write_reg(ADV7180_SD_SATURATION_CB, tmp);
adv7180_write_reg(ADV7180_SD_SATURATION_CR, tmp);
- adv7180_data.saturation = vc->value;
+ adv7180_data.sen.saturation = vc->value;
break;
case V4L2_CID_HUE:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_HUE\n");
break;
case V4L2_CID_AUTO_WHITE_BALANCE:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_AUTO_WHITE_BALANCE\n");
break;
case V4L2_CID_DO_WHITE_BALANCE:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_DO_WHITE_BALANCE\n");
break;
case V4L2_CID_RED_BALANCE:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_RED_BALANCE\n");
break;
case V4L2_CID_BLUE_BALANCE:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_BLUE_BALANCE\n");
break;
case V4L2_CID_GAMMA:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_GAMMA\n");
break;
case V4L2_CID_EXPOSURE:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_EXPOSURE\n");
break;
case V4L2_CID_AUTOGAIN:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_AUTOGAIN\n");
break;
case V4L2_CID_GAIN:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_GAIN\n");
break;
case V4L2_CID_HFLIP:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_HFLIP\n");
break;
case V4L2_CID_VFLIP:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" V4L2_CID_VFLIP\n");
break;
default:
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
" Default case\n");
retval = -EPERM;
break;
@@ -713,7 +704,7 @@ static int ioctl_g_chip_ident(struct v4l2_int_device *s, int *id)
*/
static int ioctl_init(struct v4l2_int_device *s)
{
- dev_dbg(&adv7180_data.i2c_client->dev, "In adv7180:ioctl_init\n");
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180:ioctl_init\n");
return 0;
}
@@ -725,7 +716,7 @@ static int ioctl_init(struct v4l2_int_device *s)
*/
static int ioctl_dev_init(struct v4l2_int_device *s)
{
- dev_dbg(&adv7180_data.i2c_client->dev, "In adv7180:ioctl_dev_init\n");
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "adv7180:ioctl_dev_init\n");
return 0;
}
@@ -806,7 +797,7 @@ static struct v4l2_int_device adv7180_int_device = {
*/
static void adv7180_hard_reset(bool cvbs)
{
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
"In adv7180:adv7180_hard_reset\n");
if (cvbs) {
@@ -1084,6 +1075,8 @@ static int adv7180_probe(struct i2c_client *client,
int ret = 0;
tvin_plat = client->dev.platform_data;
+ printk(KERN_ERR"DBG sensor data is at %p\n", &adv7180_data);
+
pr_debug("In adv7180_probe\n");
if (tvin_plat->dvddio_reg) {
@@ -1139,27 +1132,27 @@ static int adv7180_probe(struct i2c_client *client,
/* Set initial values for the sensor struct. */
memset(&adv7180_data, 0, sizeof(adv7180_data));
- adv7180_data.i2c_client = client;
- adv7180_data.streamcap.timeperframe.denominator = 30;
- adv7180_data.streamcap.timeperframe.numerator = 1;
+ adv7180_data.sen.i2c_client = client;
+ adv7180_data.sen.streamcap.timeperframe.denominator = 30;
+ adv7180_data.sen.streamcap.timeperframe.numerator = 1;
adv7180_data.std_id = V4L2_STD_ALL;
video_idx = ADV7180_NOT_LOCKED;
- adv7180_data.pix.width = video_fmts[video_idx].raw_width;
- adv7180_data.pix.height = video_fmts[video_idx].raw_height;
- adv7180_data.pix.pixelformat = V4L2_PIX_FMT_UYVY; /* YUV422 */
- adv7180_data.pix.priv = 1; /* 1 is used to indicate TV in */
- adv7180_data.on = true;
+ adv7180_data.sen.pix.width = video_fmts[video_idx].raw_width;
+ adv7180_data.sen.pix.height = video_fmts[video_idx].raw_height;
+ adv7180_data.sen.pix.pixelformat = V4L2_PIX_FMT_UYVY; /* YUV422 */
+ adv7180_data.sen.pix.priv = 1; /* 1 is used to indicate TV in */
+ adv7180_data.sen.on = true;
gpio_sensor_active();
- dev_dbg(&adv7180_data.i2c_client->dev,
- "%s:adv7180 probe i2c address is 0x%02X \n",
- __func__, adv7180_data.i2c_client->addr);
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ "%s:adv7180 probe i2c address is 0x%02X\n",
+ __func__, adv7180_data.sen.i2c_client->addr);
/*! Read the revision ID of the tvin chip */
rev_id = adv7180_read(ADV7180_IDENT);
- dev_dbg(&adv7180_data.i2c_client->dev,
- "%s:Analog Device adv7%2X0 detected! \n", __func__,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
+ "%s:Analog Device adv7%2X0 detected!\n", __func__,
rev_id);
/*! ADV7180 initialization. */
@@ -1190,7 +1183,7 @@ static int adv7180_detach(struct i2c_client *client)
{
struct fsl_mxc_tvin_platform_data *plat_data = client->dev.platform_data;
- dev_dbg(&adv7180_data.i2c_client->dev,
+ dev_dbg(&adv7180_data.sen.i2c_client->dev,
"%s:Removing %s video decoder @ 0x%02X from adapter %s\n",
__func__, IF_NAME, client->addr << 1, client->adapter->name);
@@ -1251,7 +1244,7 @@ static __init int adv7180_init(void)
*/
static void __exit adv7180_clean(void)
{
- dev_dbg(&adv7180_data.i2c_client->dev, "In adv7180_clean\n");
+ dev_dbg(&adv7180_data.sen.i2c_client->dev, "In adv7180_clean\n");
i2c_del_driver(&adv7180_i2c_driver);
gpio_sensor_inactive();
}
diff --git a/drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c b/drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c
index 0e0792b65a01..80129ca5d056 100644
--- a/drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c
+++ b/drivers/media/video/mxc/capture/ipu_prp_vf_sdc.c
@@ -1,9 +1,7 @@
/*
* Copyright 2004-2012 Freescale Semiconductor, Inc. All Rights Reserved.
*/
-
-/*
- * The code contained herein is licensed under the GNU General Public
+/* * The code contained herein is licensed under the GNU General Public
* License. You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations:
*
@@ -30,6 +28,33 @@
#define OVERLAY_FB_SUPPORT_NONSTD (cpu_is_mx5())
+static int buffer_num;
+static struct ipu_soc *disp_ipu;
+
+static void get_disp_ipu(cam_data *cam)
+{
+ if (cam->output > 2)
+ disp_ipu = ipu_get_soc(1); /* using DISP4 */
+ else
+ disp_ipu = ipu_get_soc(0);
+}
+
+static irqreturn_t prpvf_rot_eof_callback(int irq, void *dev_id)
+{
+ cam_data *cam = dev_id;
+ pr_debug("buffer_num %d\n", buffer_num);
+
+ if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) {
+ ipu_select_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER, buffer_num);
+ buffer_num = (buffer_num == 0) ? 1 : 0;
+ ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM, IPU_OUTPUT_BUFFER, buffer_num);
+ } else {
+ ipu_select_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER, buffer_num);
+ buffer_num = (buffer_num == 0) ? 1 : 0;
+ ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, IPU_OUTPUT_BUFFER, buffer_num);
+ }
+ return IRQ_HANDLED;
+}
/*
* Function definitions
*/
@@ -66,16 +91,19 @@ static int prpvf_start(void *private)
return 0;
}
+ get_disp_ipu(cam);
+
for (i = 0; i < num_registered_fb; i++) {
char *idstr = registered_fb[i]->fix.id;
- if (strcmp(idstr, "DISP3 FG") == 0) {
+ if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) ||
+ ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) {
fbi = registered_fb[i];
break;
}
}
if (fbi == NULL) {
- printk(KERN_ERR "DISP3 FG fb not found\n");
+ printk(KERN_ERR "DISP FG fb not found\n");
return -EPERM;
}
@@ -104,7 +132,7 @@ static int prpvf_start(void *private)
fbvar.activate |= FB_ACTIVATE_FORCE;
fb_set_var(fbi, &fbvar);
- ipu_disp_set_window_pos(cam->ipu, MEM_FG_SYNC, cam->win.w.left,
+ ipu_disp_set_window_pos(disp_ipu, MEM_FG_SYNC, cam->win.w.left,
cam->win.w.top);
/* Fill black color for framebuffer */
@@ -118,10 +146,10 @@ static int prpvf_start(void *private)
console_unlock();
/* correct display ch buffer address */
- ipu_update_channel_buffer(cam->ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER,
+ ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER,
0, fbi->fix.smem_start +
(fbi->fix.line_length * fbvar.yres));
- ipu_update_channel_buffer(cam->ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER,
+ ipu_update_channel_buffer(disp_ipu, MEM_FG_SYNC, IPU_INPUT_BUFFER,
1, fbi->fix.smem_start);
memset(&vf, 0, sizeof(ipu_channel_params_t));
@@ -269,17 +297,18 @@ static int prpvf_start(void *private)
goto out_2;
}
- err = ipu_link_channels(cam->ipu, CSI_PRP_VF_MEM, MEM_ROT_VF_MEM);
+ ipu_clear_irq(cam->ipu, IPU_IRQ_PRP_VF_ROT_OUT_EOF);
+ err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_VF_ROT_OUT_EOF, prpvf_rot_eof_callback,
+ 0, "Mxc Camera", cam);
if (err < 0) {
- printk(KERN_ERR
- "Error link CSI_PRP_VF_MEM-MEM_ROT_VF_MEM\n");
+ printk(KERN_ERR "Error request irq:IPU_IRQ_PRP_VF_ROT_OUT_EOF\n");
goto out_2;
}
- err = ipu_link_channels(cam->ipu, MEM_ROT_VF_MEM, MEM_FG_SYNC);
+ err = ipu_link_channels(cam->ipu, CSI_PRP_VF_MEM, MEM_ROT_VF_MEM);
if (err < 0) {
printk(KERN_ERR
- "Error link MEM_ROT_VF_MEM-MEM_FG_SYNC\n");
+ "Error link CSI_PRP_VF_MEM-MEM_ROT_VF_MEM\n");
goto out_1;
}
@@ -289,7 +318,6 @@ static int prpvf_start(void *private)
ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, IPU_OUTPUT_BUFFER, 0);
ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, IPU_OUTPUT_BUFFER, 1);
ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM, IPU_OUTPUT_BUFFER, 0);
- ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM, IPU_OUTPUT_BUFFER, 1);
} else {
err = ipu_init_channel_buffer(cam->ipu, CSI_PRP_VF_MEM, IPU_OUTPUT_BUFFER,
vf_out_format, cam->win.w.width,
@@ -304,24 +332,24 @@ static int prpvf_start(void *private)
printk(KERN_ERR "Error initializing CSI_PRP_VF_MEM\n");
goto out_4;
}
-
- err = ipu_link_channels(cam->ipu, CSI_PRP_VF_MEM, MEM_FG_SYNC);
+ ipu_clear_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF);
+ err = ipu_request_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, prpvf_rot_eof_callback,
+ 0, "Mxc Camera", cam);
if (err < 0) {
- printk(KERN_ERR "Error linking ipu channels\n");
+ printk(KERN_ERR "Error request irq:IPU_IRQ_PRP_VF_OUT_EOF\n");
goto out_4;
}
ipu_enable_channel(cam->ipu, CSI_PRP_VF_MEM);
ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, IPU_OUTPUT_BUFFER, 0);
- ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, IPU_OUTPUT_BUFFER, 1);
}
cam->overlay_active = true;
return err;
out_1:
- ipu_unlink_channels(cam->ipu, CSI_PRP_VF_MEM, MEM_ROT_VF_MEM);
+ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, NULL);
out_2:
if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) {
ipu_uninit_channel(cam->ipu, MEM_ROT_VF_MEM);
@@ -370,23 +398,25 @@ static int prpvf_stop(void *private)
for (i = 0; i < num_registered_fb; i++) {
char *idstr = registered_fb[i]->fix.id;
- if (strcmp(idstr, "DISP3 FG") == 0) {
+ if (((strcmp(idstr, "DISP3 FG") == 0) && (cam->output < 3)) ||
+ ((strcmp(idstr, "DISP4 FG") == 0) && (cam->output >= 3))) {
fbi = registered_fb[i];
break;
}
}
if (fbi == NULL) {
- printk(KERN_ERR "DISP3 FG fb not found\n");
+ printk(KERN_ERR "DISP FG fb not found\n");
return -EPERM;
}
if (cam->vf_rotation >= IPU_ROTATE_VERT_FLIP) {
ipu_unlink_channels(cam->ipu, CSI_PRP_VF_MEM, MEM_ROT_VF_MEM);
- ipu_unlink_channels(cam->ipu, MEM_ROT_VF_MEM, MEM_FG_SYNC);
+ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_ROT_OUT_EOF, cam);
} else {
- ipu_unlink_channels(cam->ipu, CSI_PRP_VF_MEM, MEM_FG_SYNC);
+ ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, cam);
}
+ buffer_num = 0;
ipu_disable_channel(cam->ipu, CSI_PRP_VF_MEM, true);
diff --git a/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c b/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c
index e6bf7910faef..ed99d95f1638 100644
--- a/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c
+++ b/drivers/media/video/mxc/capture/ipu_prp_vf_sdc_bg.c
@@ -27,6 +27,15 @@
static int buffer_num;
static int buffer_ready;
+static struct ipu_soc *disp_ipu;
+
+static void get_disp_ipu(cam_data *cam)
+{
+ if (cam->output > 2)
+ disp_ipu = ipu_get_soc(1); /* using DISP4 */
+ else
+ disp_ipu = ipu_get_soc(0);
+}
/*
* Function definitions
@@ -43,7 +52,6 @@ static int buffer_ready;
static irqreturn_t prpvf_sdc_vsync_callback(int irq, void *dev_id)
{
cam_data *cam = dev_id;
- pr_debug("buffer_ready %d buffer_num %d\n", buffer_ready, buffer_num);
if (buffer_ready > 0) {
ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM, IPU_OUTPUT_BUFFER, 0);
buffer_ready--;
@@ -66,9 +74,7 @@ static irqreturn_t prpvf_vf_eof_callback(int irq, void *dev_id)
pr_debug("buffer_ready %d buffer_num %d\n", buffer_ready, buffer_num);
ipu_select_buffer(cam->ipu, MEM_ROT_VF_MEM, IPU_INPUT_BUFFER, buffer_num);
-
buffer_num = (buffer_num == 0) ? 1 : 0;
-
ipu_select_buffer(cam->ipu, CSI_PRP_VF_MEM, IPU_OUTPUT_BUFFER, buffer_num);
buffer_ready++;
return IRQ_HANDLED;
@@ -104,6 +110,8 @@ static int prpvf_start(void *private)
return 0;
}
+ get_disp_ipu(cam);
+
format = cam->v4l2_fb.fmt.pixelformat;
if (cam->v4l2_fb.fmt.pixelformat == IPU_PIX_FMT_BGR24) {
bpp = 3, size = 3;
@@ -280,8 +288,8 @@ static int prpvf_start(void *private)
goto out_2;
}
- ipu_clear_irq(cam->ipu, IPU_IRQ_BG_SF_END);
- err = ipu_request_irq(cam->ipu, IPU_IRQ_BG_SF_END, prpvf_sdc_vsync_callback,
+ ipu_clear_irq(disp_ipu, IPU_IRQ_BG_SF_END);
+ err = ipu_request_irq(disp_ipu, IPU_IRQ_BG_SF_END, prpvf_sdc_vsync_callback,
0, "Mxc Camera", cam);
if (err != 0) {
printk(KERN_ERR "Error registering IPU_IRQ_BG_SF_END irq.\n");
@@ -352,7 +360,7 @@ static int prpvf_stop(void *private)
if (cam->overlay_active == false)
return 0;
- ipu_free_irq(cam->ipu, IPU_IRQ_BG_SF_END, cam);
+ ipu_free_irq(disp_ipu, IPU_IRQ_BG_SF_END, cam);
ipu_free_irq(cam->ipu, IPU_IRQ_PRP_VF_OUT_EOF, cam);
diff --git a/drivers/media/video/mxc/capture/mxc_v4l2_capture.c b/drivers/media/video/mxc/capture/mxc_v4l2_capture.c
index 32e3f7dfd889..5852a30160b4 100644
--- a/drivers/media/video/mxc/capture/mxc_v4l2_capture.c
+++ b/drivers/media/video/mxc/capture/mxc_v4l2_capture.c
@@ -47,7 +47,7 @@
static int video_nr = -1;
/*! This data is used for the output to the display. */
-#define MXC_V4L2_CAPTURE_NUM_OUTPUTS 3
+#define MXC_V4L2_CAPTURE_NUM_OUTPUTS 6
#define MXC_V4L2_CAPTURE_NUM_INPUTS 2
static struct v4l2_output mxc_capture_outputs[MXC_V4L2_CAPTURE_NUM_OUTPUTS] = {
{
@@ -74,6 +74,30 @@ static struct v4l2_output mxc_capture_outputs[MXC_V4L2_CAPTURE_NUM_OUTPUTS] = {
.modulator = 0,
.std = V4L2_STD_UNKNOWN,
},
+ {
+ .index = 3,
+ .name = "DISP4 BG",
+ .type = V4L2_OUTPUT_TYPE_ANALOG,
+ .audioset = 0,
+ .modulator = 0,
+ .std = V4L2_STD_UNKNOWN,
+ },
+ {
+ .index = 4,
+ .name = "DISP4 BG - DI1",
+ .type = V4L2_OUTPUT_TYPE_ANALOG,
+ .audioset = 0,
+ .modulator = 0,
+ .std = V4L2_STD_UNKNOWN,
+ },
+ {
+ .index = 5,
+ .name = "DISP4 FG",
+ .type = V4L2_OUTPUT_TYPE_ANALOG,
+ .audioset = 0,
+ .modulator = 0,
+ .std = V4L2_STD_UNKNOWN,
+ },
};
static struct v4l2_input mxc_capture_inputs[MXC_V4L2_CAPTURE_NUM_INPUTS] = {
@@ -301,7 +325,7 @@ static int mxc_v4l2_prepare_bufs(cam_data *cam, struct v4l2_buffer *buf)
pr_debug("In MVC:mxc_v4l2_prepare_bufs\n");
if (buf->index < 0 || buf->index >= FRAME_NUM || buf->length <
- cam->v2f.fmt.pix.sizeimage) {
+ PAGE_ALIGN(cam->v2f.fmt.pix.sizeimage)) {
pr_err("ERROR: v4l2 capture: mxc_v4l2_prepare_bufs buffers "
"not allocated,index=%d, length=%d\n", buf->index,
buf->length);
@@ -492,7 +516,7 @@ static int verify_preview(cam_data *cam, struct v4l2_window *win)
int *width, *height;
unsigned int ipu_ch = CHAN_NONE;
struct fb_info *bg_fbi = NULL, *fbi = NULL;
- bool foregound_fb;
+ bool foregound_fb = false;
mm_segment_t old_fs;
pr_debug("In MVC: verify_preview\n");
@@ -505,7 +529,8 @@ static int verify_preview(cam_data *cam, struct v4l2_window *win)
}
/* Which DI supports 2 layers? */
- if (strncmp(fbi->fix.id, "DISP3 BG", 8) == 0) {
+ if (((strncmp(fbi->fix.id, "DISP3 BG", 8) == 0) && (cam->output < 3)) ||
+ ((strncmp(fbi->fix.id, "DISP4 BG", 8) == 0) && (cam->output >= 3))) {
if (fbi->fbops->fb_ioctl) {
old_fs = get_fs();
set_fs(KERNEL_DS);
@@ -522,7 +547,8 @@ static int verify_preview(cam_data *cam, struct v4l2_window *win)
/* Found the frame buffer to preview on. */
if (strcmp(fbi->fix.id,
mxc_capture_outputs[cam->output].name) == 0) {
- if (strcmp(fbi->fix.id, "DISP3 FG") == 0)
+ if (((strcmp(fbi->fix.id, "DISP3 FG") == 0) && (cam->output < 3)) ||
+ ((strcmp(fbi->fix.id, "DISP4 FG") == 0) && (cam->output >= 3)))
foregound_fb = true;
cam->overlay_fb = fbi;
@@ -1713,13 +1739,12 @@ static int mxc_v4l_close(struct file *file)
err = stop_preview(cam);
cam->overlay_on = false;
}
+ if (cam->capture_pid == current->pid) {
+ err |= mxc_streamoff(cam);
+ wake_up_interruptible(&cam->enc_queue);
+ }
if (--cam->open_count == 0) {
- if (cam->capture_pid == current->pid) {
- err |= mxc_streamoff(cam);
- wake_up_interruptible(&cam->enc_queue);
- }
-
vidioc_int_s_power(cam->sensor, 0);
ipu_csi_enable_mclk_if(cam->ipu, CSI_MCLK_I2C, cam->csi,
false, false);
diff --git a/drivers/media/video/mxc/capture/ov5640_mipi.c b/drivers/media/video/mxc/capture/ov5640_mipi.c
index d70c71492a97..cdb58f272908 100644
--- a/drivers/media/video/mxc/capture/ov5640_mipi.c
+++ b/drivers/media/video/mxc/capture/ov5640_mipi.c
@@ -170,7 +170,7 @@ static struct reg_value ov5640_init_setting_30fps_VGA[] = {
{0x583b, 0x28, 0, 0}, {0x583c, 0x42, 0, 0}, {0x583d, 0xce, 0, 0},
{0x5025, 0x00, 0, 0}, {0x3a0f, 0x30, 0, 0}, {0x3a10, 0x28, 0, 0},
{0x3a1b, 0x30, 0, 0}, {0x3a1e, 0x26, 0, 0}, {0x3a11, 0x60, 0, 0},
- {0x3a1f, 0x14, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3c00, 0x04, 0, 0},
+ {0x3a1f, 0x14, 0, 0}, {0x3008, 0x02, 0, 0}, {0x3c00, 0x04, 0, 300},
};
static struct reg_value ov5640_setting_30fps_VGA_640_480[] = {
@@ -213,7 +213,7 @@ static struct reg_value ov5640_setting_15fps_VGA_640_480[] = {
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x4713, 0x03, 0, 0},
{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
- {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x3503, 0x00, 0, 0},
+ {0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
};
static struct reg_value ov5640_setting_30fps_XGA_1024_768[] = {
diff --git a/drivers/media/video/mxc/output/mxc_vout.c b/drivers/media/video/mxc/output/mxc_vout.c
index cdf7eb785a64..f1f376db98ce 100644
--- a/drivers/media/video/mxc/output/mxc_vout.c
+++ b/drivers/media/video/mxc/output/mxc_vout.c
@@ -28,6 +28,11 @@
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
+#define UYVY_BLACK (0x00800080)
+#define RGB_BLACK (0x0)
+#define NV12_UV_BLACK (0x80)
+#define NV12_Y_BLACK (0x0)
+
#define MAX_FB_NUM 6
#define FB_BUFS 3
#define VDOA_FB_BUFS (FB_BUFS - 1)
@@ -1104,6 +1109,13 @@ static int mxc_vout_try_format(struct mxc_vout_output *vout, struct v4l2_format
int ret = 0;
struct v4l2_rect rect;
+ if ((f->fmt.pix.field != V4L2_FIELD_NONE) &&
+ (IPU_PIX_FMT_TILED_NV12 == vout->task.input.format)) {
+ v4l2_err(vout->vfd->v4l2_dev,
+ "progressive tiled fmt should used V4L2_FIELD_NONE!\n");
+ return -EINVAL;
+ }
+
if (f->fmt.pix.priv && copy_from_user(&rect,
(void __user *)f->fmt.pix.priv, sizeof(rect)))
return -EFAULT;
@@ -1583,9 +1595,12 @@ static int config_disp_output(struct mxc_vout_output *vout)
struct dma_mem *buf = NULL;
struct fb_info *fbi = vout->fbi;
struct fb_var_screeninfo var;
- int i, display_buf_size, fb_num, ret;
+ int i, fb_num, ret;
u32 fb_base;
u32 size;
+ u32 display_buf_size;
+ u32 *pixel = NULL;
+ u32 color;
int j;
memcpy(&var, &fbi->var, sizeof(var));
@@ -1668,6 +1683,20 @@ static int config_disp_output(struct mxc_vout_output *vout)
fbi->fix.smem_len, fbi->fix.smem_start, fb_base);
}
+ /* fill black when video config changed */
+ color = colorspaceofpixel(vout->task.output.format) == YUV_CS ?
+ UYVY_BLACK : RGB_BLACK;
+ if (vout->task.output.format == IPU_PIX_FMT_NV12) {
+ size = display_buf_size * 8 /
+ fmt_to_bpp(vout->task.output.format);
+ memset(fbi->screen_base, NV12_Y_BLACK, size);
+ memset(fbi->screen_base + size, NV12_UV_BLACK,
+ display_buf_size - size);
+ } else {
+ pixel = (u32 *)fbi->screen_base;
+ for (i = 0; i < (display_buf_size >> 2); i++)
+ *pixel++ = color;
+ }
console_lock();
fbi->flags |= FBINFO_MISC_USEREVENT;
ret = fb_blank(fbi, FB_BLANK_UNBLANK);
@@ -1689,24 +1718,9 @@ static void release_disp_output(struct mxc_vout_output *vout)
{
struct fb_info *fbi = vout->fbi;
struct mxcfb_pos pos;
- struct ipu_pos ipos;
- int ret;
if (vout->release)
return;
- if (get_ipu_channel(fbi) == MEM_BG_SYNC) {
- if (vout->tiled_bypass_pp) {
- vout->task.output.paddr = vout->disp_bufs[0];
- ipos.x = vout->task.input.crop.pos.x;
- ipos.y = vout->task.input.crop.pos.y;
- ret = show_buf(vout, 0, &ipos);
- if (ret < 0)
- v4l2_err(vout->vfd->v4l2_dev,
- "show_buf ret %d\n", ret);
- }
- goto out;
- }
-
console_lock();
fbi->flags |= FBINFO_MISC_USEREVENT;
fb_blank(fbi, FB_BLANK_POWERDOWN);
@@ -1717,7 +1731,17 @@ static void release_disp_output(struct mxc_vout_output *vout)
pos.x = 0;
pos.y = 0;
set_window_position(vout, &pos);
-out:
+
+ if (get_ipu_channel(fbi) == MEM_BG_SYNC) {
+ console_lock();
+ fbi->fix.smem_start = vout->disp_bufs[0];
+ fbi->flags |= FBINFO_MISC_USEREVENT;
+ fb_blank(fbi, FB_BLANK_UNBLANK);
+ fbi->flags &= ~FBINFO_MISC_USEREVENT;
+ console_unlock();
+
+ }
+
vout->release = true;
}
diff --git a/drivers/media/video/pvrusb2/pvrusb2-devattr.c b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
index e799331389b1..c4eca15baf61 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-devattr.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-devattr.c
@@ -319,7 +319,17 @@ static struct tda829x_config tda829x_no_probe = {
.probe_tuner = TDA829X_DONT_PROBE,
};
+static struct tda18271_std_map hauppauge_tda18271_dvbt_std_map = {
+ .dvbt_6 = { .if_freq = 3300, .agc_mode = 3, .std = 4,
+ .if_lvl = 1, .rfagc_top = 0x37, },
+ .dvbt_7 = { .if_freq = 3800, .agc_mode = 3, .std = 5,
+ .if_lvl = 1, .rfagc_top = 0x37, },
+ .dvbt_8 = { .if_freq = 4300, .agc_mode = 3, .std = 6,
+ .if_lvl = 1, .rfagc_top = 0x37, },
+};
+
static struct tda18271_config hauppauge_tda18271_dvb_config = {
+ .std_map = &hauppauge_tda18271_dvbt_std_map,
.gate = TDA18271_GATE_ANALOG,
.output_opt = TDA18271_OUTPUT_LT_OFF,
};
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index bdf19ada9172..e9babcb0887c 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -36,7 +36,7 @@ static char *fimc_clocks[MAX_FIMC_CLOCKS] = {
static struct fimc_fmt fimc_formats[] = {
{
.name = "RGB565",
- .fourcc = V4L2_PIX_FMT_RGB565X,
+ .fourcc = V4L2_PIX_FMT_RGB565,
.depth = { 16 },
.color = S5P_FIMC_RGB565,
.memplanes = 1,
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index 543a80395b7f..5afdbb7bbea5 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -65,6 +65,15 @@ static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain,
goto done;
}
+ /* Prevent excessive memory consumption, as well as integer
+ * overflows.
+ */
+ if (xmap->menu_count == 0 ||
+ xmap->menu_count > UVC_MAX_CONTROL_MENU_ENTRIES) {
+ ret = -EINVAL;
+ goto done;
+ }
+
size = xmap->menu_count * sizeof(*map->menu_info);
map->menu_info = kmalloc(size, GFP_KERNEL);
if (map->menu_info == NULL) {
@@ -701,7 +710,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
break;
}
pin = iterm->id;
- } else if (pin < selector->bNrInPins) {
+ } else if (index < selector->bNrInPins) {
pin = selector->baSourceID[index];
list_for_each_entry(iterm, &chain->entities, chain) {
if (!UVC_ENTITY_IS_ITERM(iterm))
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index 2a38d5e55358..cf2401a041ae 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -200,6 +200,7 @@ struct uvc_xu_control {
/* Maximum allowed number of control mappings per device */
#define UVC_MAX_CONTROL_MAPPINGS 1024
+#define UVC_MAX_CONTROL_MENU_ENTRIES 32
/* Devices quirks */
#define UVC_QUIRK_STATUS_INTERVAL 0x00000001
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
index 69e8c6ffcc49..bda252f04e8a 100644
--- a/drivers/media/video/v4l2-ioctl.c
+++ b/drivers/media/video/v4l2-ioctl.c
@@ -2289,6 +2289,10 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
struct v4l2_ext_controls *ctrls = parg;
if (ctrls->count != 0) {
+ if (ctrls->count > V4L2_CID_MAX_CTRLS) {
+ ret = -EINVAL;
+ break;
+ }
*user_ptr = (void __user *)ctrls->controls;
*kernel_ptr = (void **)&ctrls->controls;
*array_size = sizeof(struct v4l2_ext_control)
diff --git a/drivers/mfd/cs5535-mfd.c b/drivers/mfd/cs5535-mfd.c
index 155fa0407882..e488a78a2fd6 100644
--- a/drivers/mfd/cs5535-mfd.c
+++ b/drivers/mfd/cs5535-mfd.c
@@ -179,7 +179,7 @@ static struct pci_device_id cs5535_mfd_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, cs5535_mfd_pci_tbl);
-static struct pci_driver cs5535_mfd_drv = {
+static struct pci_driver cs5535_mfd_driver = {
.name = DRV_NAME,
.id_table = cs5535_mfd_pci_tbl,
.probe = cs5535_mfd_probe,
@@ -188,12 +188,12 @@ static struct pci_driver cs5535_mfd_drv = {
static int __init cs5535_mfd_init(void)
{
- return pci_register_driver(&cs5535_mfd_drv);
+ return pci_register_driver(&cs5535_mfd_driver);
}
static void __exit cs5535_mfd_exit(void)
{
- pci_unregister_driver(&cs5535_mfd_drv);
+ pci_unregister_driver(&cs5535_mfd_driver);
}
module_init(cs5535_mfd_init);
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 0902523af62d..acf9dad686a1 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -122,7 +122,7 @@ static int mfd_add_device(struct device *parent, int id,
}
if (!cell->ignore_resource_conflicts) {
- ret = acpi_check_resource_conflict(res);
+ ret = acpi_check_resource_conflict(&res[r]);
if (ret)
goto fail_res;
}
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index b8f2a4e7f6e7..f82413a98895 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -362,13 +362,13 @@ int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
return -EPERM;
}
- sid = twl_map[mod_no].sid;
- twl = &twl_modules[sid];
-
if (unlikely(!inuse)) {
- pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid);
+ pr_err("%s: not initialized\n", DRIVER_NAME);
return -EPERM;
}
+ sid = twl_map[mod_no].sid;
+ twl = &twl_modules[sid];
+
mutex_lock(&twl->xfer_lock);
/*
* [MSG1]: fill the register address data
@@ -419,13 +419,13 @@ int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes)
pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
return -EPERM;
}
- sid = twl_map[mod_no].sid;
- twl = &twl_modules[sid];
-
if (unlikely(!inuse)) {
- pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid);
+ pr_err("%s: not initialized\n", DRIVER_NAME);
return -EPERM;
}
+ sid = twl_map[mod_no].sid;
+ twl = &twl_modules[sid];
+
mutex_lock(&twl->xfer_lock);
/* [MSG1] fill the register address data */
msg = &twl->xfer_msg[0];
diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c
index 3941ddcf15fe..834f824d3c11 100644
--- a/drivers/mfd/twl4030-madc.c
+++ b/drivers/mfd/twl4030-madc.c
@@ -510,8 +510,9 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req)
u8 ch_msb, ch_lsb;
int ret;
- if (!req)
+ if (!req || !twl4030_madc)
return -EINVAL;
+
mutex_lock(&twl4030_madc->lock);
if (req->method < TWL4030_MADC_RT || req->method > TWL4030_MADC_SW2) {
ret = -EINVAL;
@@ -530,13 +531,13 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req)
if (ret) {
dev_err(twl4030_madc->dev,
"unable to write sel register 0x%X\n", method->sel + 1);
- return ret;
+ goto out;
}
ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_lsb, method->sel);
if (ret) {
dev_err(twl4030_madc->dev,
"unable to write sel register 0x%X\n", method->sel + 1);
- return ret;
+ goto out;
}
/* Select averaging for all channels if do_avg is set */
if (req->do_avg) {
@@ -546,7 +547,7 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req)
dev_err(twl4030_madc->dev,
"unable to write avg register 0x%X\n",
method->avg + 1);
- return ret;
+ goto out;
}
ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
ch_lsb, method->avg);
@@ -554,7 +555,7 @@ int twl4030_madc_conversion(struct twl4030_madc_request *req)
dev_err(twl4030_madc->dev,
"unable to write sel reg 0x%X\n",
method->sel + 1);
- return ret;
+ goto out;
}
}
if (req->type == TWL4030_MADC_IRQ_ONESHOT && req->func_cb != NULL) {
@@ -706,6 +707,8 @@ static int __devinit twl4030_madc_probe(struct platform_device *pdev)
if (!madc)
return -ENOMEM;
+ madc->dev = &pdev->dev;
+
/*
* Phoenix provides 2 interrupt lines. The first one is connected to
* the OMAP. The other one can be connected to the other processor such
@@ -737,6 +740,28 @@ static int __devinit twl4030_madc_probe(struct platform_device *pdev)
TWL4030_BCI_BCICTL1);
goto err_i2c;
}
+
+ /* Check that MADC clock is on */
+ ret = twl_i2c_read_u8(TWL4030_MODULE_INTBR, &regval, TWL4030_REG_GPBR1);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to read reg GPBR1 0x%X\n",
+ TWL4030_REG_GPBR1);
+ goto err_i2c;
+ }
+
+ /* If MADC clk is not on, turn it on */
+ if (!(regval & TWL4030_GPBR1_MADC_HFCLK_EN)) {
+ dev_info(&pdev->dev, "clk disabled, enabling\n");
+ regval |= TWL4030_GPBR1_MADC_HFCLK_EN;
+ ret = twl_i2c_write_u8(TWL4030_MODULE_INTBR, regval,
+ TWL4030_REG_GPBR1);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to write reg GPBR1 0x%X\n",
+ TWL4030_REG_GPBR1);
+ goto err_i2c;
+ }
+ }
+
platform_set_drvdata(pdev, madc);
mutex_init(&madc->lock);
ret = request_threaded_irq(platform_get_irq(pdev, 0), NULL,
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
index eb3b5f88e566..b0563b66d10b 100644
--- a/drivers/mfd/twl6030-irq.c
+++ b/drivers/mfd/twl6030-irq.c
@@ -145,8 +145,17 @@ static int twl6030_irq_thread(void *data)
}
local_irq_enable();
}
- ret = twl_i2c_write(TWL_MODULE_PIH, sts.bytes,
- REG_INT_STS_A, 3); /* clear INT_STS_A */
+
+ /*
+ * NOTE:
+ * Simulation confirms that documentation is wrong w.r.t the
+ * interrupt status clear operation. A single *byte* write to
+ * any one of STS_A to STS_C register results in all three
+ * STS registers being reset. Since it does not matter which
+ * value is written, all three registers are cleared on a
+ * single byte write, so we just use 0x0 to clear.
+ */
+ ret = twl_i2c_write_u8(TWL_MODULE_PIH, 0x00, REG_INT_STS_A);
if (ret)
pr_warning("twl6030: I2C error in clearing PIH ISR\n");
diff --git a/drivers/misc/cb710/core.c b/drivers/misc/cb710/core.c
index efec4139c3f6..b1f16d6084ae 100644
--- a/drivers/misc/cb710/core.c
+++ b/drivers/misc/cb710/core.c
@@ -244,6 +244,7 @@ static int __devinit cb710_probe(struct pci_dev *pdev,
if (err)
return err;
+ spin_lock_init(&chip->irq_lock);
chip->pdev = pdev;
chip->iobase = pcim_iomap_table(pdev)[0];
diff --git a/drivers/misc/cs5535-mfgpt.c b/drivers/misc/cs5535-mfgpt.c
index bc685bfc4c33..87a390de054c 100644
--- a/drivers/misc/cs5535-mfgpt.c
+++ b/drivers/misc/cs5535-mfgpt.c
@@ -262,7 +262,7 @@ static void __init reset_all_timers(void)
* In other cases (such as with VSAless OpenFirmware), the system firmware
* leaves timers available for us to use.
*/
-static int __init scan_timers(struct cs5535_mfgpt_chip *mfgpt)
+static int __devinit scan_timers(struct cs5535_mfgpt_chip *mfgpt)
{
struct cs5535_mfgpt_timer timer = { .chip = mfgpt };
unsigned long flags;
diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c
index 8cebec5e85ee..cdefef231fbd 100644
--- a/drivers/misc/kgdbts.c
+++ b/drivers/misc/kgdbts.c
@@ -133,12 +133,17 @@ static int force_hwbrks;
static int hwbreaks_ok;
static int hw_break_val;
static int hw_break_val2;
+static int cont_instead_of_sstep;
+static unsigned long cont_thread_id;
+static unsigned long sstep_thread_id;
#if defined(CONFIG_ARM) || defined(CONFIG_MIPS) || defined(CONFIG_SPARC)
static int arch_needs_sstep_emulation = 1;
#else
static int arch_needs_sstep_emulation;
#endif
+static unsigned long cont_addr;
static unsigned long sstep_addr;
+static int restart_from_top_after_write;
static int sstep_state;
/* Storage for the registers, in GDB format. */
@@ -186,7 +191,8 @@ static int kgdbts_unreg_thread(void *ptr)
*/
while (!final_ack)
msleep_interruptible(1500);
-
+ /* Pause for any other threads to exit after final ack. */
+ msleep_interruptible(1000);
if (configured)
kgdb_unregister_io_module(&kgdbts_io_ops);
configured = 0;
@@ -210,7 +216,7 @@ static unsigned long lookup_addr(char *arg)
if (!strcmp(arg, "kgdbts_break_test"))
addr = (unsigned long)kgdbts_break_test;
else if (!strcmp(arg, "sys_open"))
- addr = (unsigned long)sys_open;
+ addr = (unsigned long)do_sys_open;
else if (!strcmp(arg, "do_fork"))
addr = (unsigned long)do_fork;
else if (!strcmp(arg, "hw_break_val"))
@@ -282,6 +288,16 @@ static void hw_break_val_write(void)
hw_break_val++;
}
+static int get_thread_id_continue(char *put_str, char *arg)
+{
+ char *ptr = &put_str[11];
+
+ if (put_str[1] != 'T' || put_str[2] != '0')
+ return 1;
+ kgdb_hex2long(&ptr, &cont_thread_id);
+ return 0;
+}
+
static int check_and_rewind_pc(char *put_str, char *arg)
{
unsigned long addr = lookup_addr(arg);
@@ -298,13 +314,21 @@ static int check_and_rewind_pc(char *put_str, char *arg)
if (addr + BREAK_INSTR_SIZE == ip)
offset = -BREAK_INSTR_SIZE;
#endif
- if (strcmp(arg, "silent") && ip + offset != addr) {
+
+ if (arch_needs_sstep_emulation && sstep_addr &&
+ ip + offset == sstep_addr &&
+ ((!strcmp(arg, "sys_open") || !strcmp(arg, "do_fork")))) {
+ /* This is special case for emulated single step */
+ v2printk("Emul: rewind hit single step bp\n");
+ restart_from_top_after_write = 1;
+ } else if (strcmp(arg, "silent") && ip + offset != addr) {
eprintk("kgdbts: BP mismatch %lx expected %lx\n",
ip + offset, addr);
return 1;
}
/* Readjust the instruction pointer if needed */
ip += offset;
+ cont_addr = ip;
#ifdef GDB_ADJUSTS_BREAK_OFFSET
instruction_pointer_set(&kgdbts_regs, ip);
#endif
@@ -314,6 +338,8 @@ static int check_and_rewind_pc(char *put_str, char *arg)
static int check_single_step(char *put_str, char *arg)
{
unsigned long addr = lookup_addr(arg);
+ static int matched_id;
+
/*
* From an arch indepent point of view the instruction pointer
* should be on a different instruction
@@ -323,6 +349,29 @@ static int check_single_step(char *put_str, char *arg)
gdb_regs_to_pt_regs(kgdbts_gdb_regs, &kgdbts_regs);
v2printk("Singlestep stopped at IP: %lx\n",
instruction_pointer(&kgdbts_regs));
+
+ if (sstep_thread_id != cont_thread_id) {
+ /*
+ * Ensure we stopped in the same thread id as before, else the
+ * debugger should continue until the original thread that was
+ * single stepped is scheduled again, emulating gdb's behavior.
+ */
+ v2printk("ThrID does not match: %lx\n", cont_thread_id);
+ if (arch_needs_sstep_emulation) {
+ if (matched_id &&
+ instruction_pointer(&kgdbts_regs) != addr)
+ goto continue_test;
+ matched_id++;
+ ts.idx -= 2;
+ sstep_state = 0;
+ return 0;
+ }
+ cont_instead_of_sstep = 1;
+ ts.idx -= 4;
+ return 0;
+ }
+continue_test:
+ matched_id = 0;
if (instruction_pointer(&kgdbts_regs) == addr) {
eprintk("kgdbts: SingleStep failed at %lx\n",
instruction_pointer(&kgdbts_regs));
@@ -364,10 +413,40 @@ static int got_break(char *put_str, char *arg)
return 1;
}
+static void get_cont_catch(char *arg)
+{
+ /* Always send detach because the test is completed at this point */
+ fill_get_buf("D");
+}
+
+static int put_cont_catch(char *put_str, char *arg)
+{
+ /* This is at the end of the test and we catch any and all input */
+ v2printk("kgdbts: cleanup task: %lx\n", sstep_thread_id);
+ ts.idx--;
+ return 0;
+}
+
+static int emul_reset(char *put_str, char *arg)
+{
+ if (strncmp(put_str, "$OK", 3))
+ return 1;
+ if (restart_from_top_after_write) {
+ restart_from_top_after_write = 0;
+ ts.idx = -1;
+ }
+ return 0;
+}
+
static void emul_sstep_get(char *arg)
{
if (!arch_needs_sstep_emulation) {
- fill_get_buf(arg);
+ if (cont_instead_of_sstep) {
+ cont_instead_of_sstep = 0;
+ fill_get_buf("c");
+ } else {
+ fill_get_buf(arg);
+ }
return;
}
switch (sstep_state) {
@@ -397,9 +476,11 @@ static void emul_sstep_get(char *arg)
static int emul_sstep_put(char *put_str, char *arg)
{
if (!arch_needs_sstep_emulation) {
- if (!strncmp(put_str+1, arg, 2))
- return 0;
- return 1;
+ char *ptr = &put_str[11];
+ if (put_str[1] != 'T' || put_str[2] != '0')
+ return 1;
+ kgdb_hex2long(&ptr, &sstep_thread_id);
+ return 0;
}
switch (sstep_state) {
case 1:
@@ -410,8 +491,7 @@ static int emul_sstep_put(char *put_str, char *arg)
v2printk("Stopped at IP: %lx\n",
instruction_pointer(&kgdbts_regs));
/* Want to stop at IP + break instruction size by default */
- sstep_addr = instruction_pointer(&kgdbts_regs) +
- BREAK_INSTR_SIZE;
+ sstep_addr = cont_addr + BREAK_INSTR_SIZE;
break;
case 2:
if (strncmp(put_str, "$OK", 3)) {
@@ -423,6 +503,9 @@ static int emul_sstep_put(char *put_str, char *arg)
if (strncmp(put_str, "$T0", 3)) {
eprintk("kgdbts: failed continue sstep\n");
return 1;
+ } else {
+ char *ptr = &put_str[11];
+ kgdb_hex2long(&ptr, &sstep_thread_id);
}
break;
case 4:
@@ -501,10 +584,10 @@ static struct test_struct bad_read_test[] = {
static struct test_struct singlestep_break_test[] = {
{ "?", "S0*" }, /* Clear break points */
{ "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
- { "c", "T0*", }, /* Continue */
+ { "c", "T0*", NULL, get_thread_id_continue }, /* Continue */
+ { "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */
{ "g", "kgdbts_break_test", NULL, check_and_rewind_pc },
{ "write", "OK", write_regs }, /* Write registers */
- { "kgdbts_break_test", "OK", sw_rem_break }, /*remove breakpoint */
{ "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
{ "g", "kgdbts_break_test", NULL, check_single_step },
{ "kgdbts_break_test", "OK", sw_break, }, /* set sw breakpoint */
@@ -522,16 +605,16 @@ static struct test_struct singlestep_break_test[] = {
static struct test_struct do_fork_test[] = {
{ "?", "S0*" }, /* Clear break points */
{ "do_fork", "OK", sw_break, }, /* set sw breakpoint */
- { "c", "T0*", }, /* Continue */
- { "g", "do_fork", NULL, check_and_rewind_pc }, /* check location */
- { "write", "OK", write_regs }, /* Write registers */
+ { "c", "T0*", NULL, get_thread_id_continue }, /* Continue */
{ "do_fork", "OK", sw_rem_break }, /*remove breakpoint */
+ { "g", "do_fork", NULL, check_and_rewind_pc }, /* check location */
+ { "write", "OK", write_regs, emul_reset }, /* Write registers */
{ "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
{ "g", "do_fork", NULL, check_single_step },
{ "do_fork", "OK", sw_break, }, /* set sw breakpoint */
{ "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */
{ "D", "OK", NULL, final_ack_set }, /* detach and unregister I/O */
- { "", "" },
+ { "", "", get_cont_catch, put_cont_catch },
};
/* Test for hitting a breakpoint at sys_open for what ever the number
@@ -540,16 +623,16 @@ static struct test_struct do_fork_test[] = {
static struct test_struct sys_open_test[] = {
{ "?", "S0*" }, /* Clear break points */
{ "sys_open", "OK", sw_break, }, /* set sw breakpoint */
- { "c", "T0*", }, /* Continue */
- { "g", "sys_open", NULL, check_and_rewind_pc }, /* check location */
- { "write", "OK", write_regs }, /* Write registers */
+ { "c", "T0*", NULL, get_thread_id_continue }, /* Continue */
{ "sys_open", "OK", sw_rem_break }, /*remove breakpoint */
+ { "g", "sys_open", NULL, check_and_rewind_pc }, /* check location */
+ { "write", "OK", write_regs, emul_reset }, /* Write registers */
{ "s", "T0*", emul_sstep_get, emul_sstep_put }, /* Single step */
{ "g", "sys_open", NULL, check_single_step },
{ "sys_open", "OK", sw_break, }, /* set sw breakpoint */
{ "7", "T0*", skip_back_repeat_test }, /* Loop based on repeat_test */
{ "D", "OK", NULL, final_ack_set }, /* detach and unregister I/O */
- { "", "" },
+ { "", "", get_cont_catch, put_cont_catch },
};
/*
@@ -692,8 +775,8 @@ static int run_simple_test(int is_get_char, int chr)
/* This callback is a put char which is when kgdb sends data to
* this I/O module.
*/
- if (ts.tst[ts.idx].get[0] == '\0' &&
- ts.tst[ts.idx].put[0] == '\0') {
+ if (ts.tst[ts.idx].get[0] == '\0' && ts.tst[ts.idx].put[0] == '\0' &&
+ !ts.tst[ts.idx].get_handler) {
eprintk("kgdbts: ERROR: beyond end of test on"
" '%s' line %i\n", ts.name, ts.idx);
return 0;
@@ -906,6 +989,17 @@ static void kgdbts_run_tests(void)
if (ptr)
sstep_test = simple_strtol(ptr+1, NULL, 10);
+ /* All HW break point tests */
+ if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) {
+ hwbreaks_ok = 1;
+ v1printk("kgdbts:RUN hw breakpoint test\n");
+ run_breakpoint_test(1);
+ v1printk("kgdbts:RUN hw write breakpoint test\n");
+ run_hw_break_test(1);
+ v1printk("kgdbts:RUN access write breakpoint test\n");
+ run_hw_break_test(0);
+ }
+
/* required internal KGDB tests */
v1printk("kgdbts:RUN plant and detach test\n");
run_plant_and_detach_test(0);
@@ -923,35 +1017,11 @@ static void kgdbts_run_tests(void)
/* ===Optional tests=== */
- /* All HW break point tests */
- if (arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT) {
- hwbreaks_ok = 1;
- v1printk("kgdbts:RUN hw breakpoint test\n");
- run_breakpoint_test(1);
- v1printk("kgdbts:RUN hw write breakpoint test\n");
- run_hw_break_test(1);
- v1printk("kgdbts:RUN access write breakpoint test\n");
- run_hw_break_test(0);
- }
-
if (nmi_sleep) {
v1printk("kgdbts:RUN NMI sleep %i seconds test\n", nmi_sleep);
run_nmi_sleep_test(nmi_sleep);
}
-#ifdef CONFIG_DEBUG_RODATA
- /* Until there is an api to write to read-only text segments, use
- * HW breakpoints for the remainder of any tests, else print a
- * failure message if hw breakpoints do not work.
- */
- if (!(arch_kgdb_ops.flags & KGDB_HW_BREAKPOINT && hwbreaks_ok)) {
- eprintk("kgdbts: HW breakpoints do not work,"
- "skipping remaining tests\n");
- return;
- }
- force_hwbrks = 1;
-#endif /* CONFIG_DEBUG_RODATA */
-
/* If the do_fork test is run it will be the last test that is
* executed because a kernel thread will be spawned at the very
* end to unregister the debug hooks.
diff --git a/drivers/misc/pch_phub.c b/drivers/misc/pch_phub.c
index 97e1a1f18a95..f51c81e1884a 100644
--- a/drivers/misc/pch_phub.c
+++ b/drivers/misc/pch_phub.c
@@ -93,6 +93,7 @@
#define PCH_PHUB_INTPIN_REG_WPERMIT_REG3 0x002C
#define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE 0x0040
#define CLKCFG_REG_OFFSET 0x500
+#define FUNCSEL_REG_OFFSET 0x508
#define PCH_PHUB_OROM_SIZE 15360
@@ -111,11 +112,13 @@
* @intpin_reg_wpermit_reg3: INTPIN_REG_WPERMIT register 3 val
* @int_reduce_control_reg: INT_REDUCE_CONTROL registers val
* @clkcfg_reg: CLK CFG register val
+ * @funcsel_reg: Function select register value
* @pch_phub_base_address: Register base address
* @pch_phub_extrom_base_address: external rom base address
* @pch_mac_start_address: MAC address area start address
* @pch_opt_rom_start_address: Option ROM start address
* @ioh_type: Save IOH type
+ * @pdev: pointer to pci device struct
*/
struct pch_phub_reg {
u32 phub_id_reg;
@@ -131,11 +134,13 @@ struct pch_phub_reg {
u32 intpin_reg_wpermit_reg3;
u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];
u32 clkcfg_reg;
+ u32 funcsel_reg;
void __iomem *pch_phub_base_address;
void __iomem *pch_phub_extrom_base_address;
u32 pch_mac_start_address;
u32 pch_opt_rom_start_address;
int ioh_type;
+ struct pci_dev *pdev;
};
/* SROM SPEC for MAC address assignment offset */
@@ -214,6 +219,8 @@ static void pch_phub_save_reg_conf(struct pci_dev *pdev)
__func__, i, chip->int_reduce_control_reg[i]);
}
chip->clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET);
+ if ((chip->ioh_type == 2) || (chip->ioh_type == 4))
+ chip->funcsel_reg = ioread32(p + FUNCSEL_REG_OFFSET);
}
/* pch_phub_restore_reg_conf - restore register configuration */
@@ -274,6 +281,8 @@ static void pch_phub_restore_reg_conf(struct pci_dev *pdev)
}
iowrite32(chip->clkcfg_reg, p + CLKCFG_REG_OFFSET);
+ if ((chip->ioh_type == 2) || (chip->ioh_type == 4))
+ iowrite32(chip->funcsel_reg, p + FUNCSEL_REG_OFFSET);
}
/**
@@ -494,6 +503,7 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,
unsigned int orom_size;
int ret;
int err;
+ ssize_t rom_size;
struct pch_phub_reg *chip =
dev_get_drvdata(container_of(kobj, struct device, kobj));
@@ -505,6 +515,10 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,
}
/* Get Rom signature */
+ chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
+ if (!chip->pch_phub_extrom_base_address)
+ goto exrom_map_err;
+
pch_phub_read_serial_rom(chip, chip->pch_opt_rom_start_address,
(unsigned char *)&rom_signature);
rom_signature &= 0xff;
@@ -535,10 +549,13 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,
goto return_err;
}
return_ok:
+ pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
mutex_unlock(&pch_phub_mutex);
return addr_offset;
return_err:
+ pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
+exrom_map_err:
mutex_unlock(&pch_phub_mutex);
return_err_nomutex:
return err;
@@ -551,6 +568,7 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,
int err;
unsigned int addr_offset;
int ret;
+ ssize_t rom_size;
struct pch_phub_reg *chip =
dev_get_drvdata(container_of(kobj, struct device, kobj));
@@ -567,6 +585,12 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,
goto return_ok;
}
+ chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
+ if (!chip->pch_phub_extrom_base_address) {
+ err = -ENOMEM;
+ goto exrom_map_err;
+ }
+
for (addr_offset = 0; addr_offset < count; addr_offset++) {
if (PCH_PHUB_OROM_SIZE < off + addr_offset)
goto return_ok;
@@ -581,10 +605,14 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,
}
return_ok:
+ pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
mutex_unlock(&pch_phub_mutex);
return addr_offset;
return_err:
+ pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
+
+exrom_map_err:
mutex_unlock(&pch_phub_mutex);
return err;
}
@@ -594,8 +622,14 @@ static ssize_t show_pch_mac(struct device *dev, struct device_attribute *attr,
{
u8 mac[8];
struct pch_phub_reg *chip = dev_get_drvdata(dev);
+ ssize_t rom_size;
+
+ chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
+ if (!chip->pch_phub_extrom_base_address)
+ return -ENOMEM;
pch_phub_read_gbe_mac_addr(chip, mac);
+ pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
@@ -605,6 +639,7 @@ static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
u8 mac[6];
+ ssize_t rom_size;
struct pch_phub_reg *chip = dev_get_drvdata(dev);
if (count != 18)
@@ -614,7 +649,12 @@ static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr,
(u32 *)&mac[0], (u32 *)&mac[1], (u32 *)&mac[2], (u32 *)&mac[3],
(u32 *)&mac[4], (u32 *)&mac[5]);
+ chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
+ if (!chip->pch_phub_extrom_base_address)
+ return -ENOMEM;
+
pch_phub_write_gbe_mac_addr(chip, mac);
+ pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
return count;
}
@@ -637,7 +677,6 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
int retval;
int ret;
- ssize_t rom_size;
struct pch_phub_reg *chip;
chip = kzalloc(sizeof(struct pch_phub_reg), GFP_KERNEL);
@@ -674,19 +713,7 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
"in pch_phub_base_address variable is %p\n", __func__,
chip->pch_phub_base_address);
- if (id->driver_data != 3) {
- chip->pch_phub_extrom_base_address =\
- pci_map_rom(pdev, &rom_size);
- if (chip->pch_phub_extrom_base_address == 0) {
- dev_err(&pdev->dev, "%s: pci_map_rom FAILED", __func__);
- ret = -ENOMEM;
- goto err_pci_map;
- }
- dev_dbg(&pdev->dev, "%s : "
- "pci_map_rom SUCCESS and value in "
- "pch_phub_extrom_base_address variable is %p\n",
- __func__, chip->pch_phub_extrom_base_address);
- }
+ chip->pdev = pdev; /* Save pci device struct */
if (id->driver_data == 1) { /* EG20T PCH */
retval = sysfs_create_file(&pdev->dev.kobj,
@@ -735,6 +762,8 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
* Device8(GbE)
*/
iowrite32(0x000a0000, chip->pch_phub_base_address + 0x14);
+ /* set the interrupt delay value */
+ iowrite32(0x25, chip->pch_phub_base_address + 0x140);
chip->pch_opt_rom_start_address =\
PCH_PHUB_ROM_START_ADDR_ML7223;
chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223;
@@ -752,8 +781,6 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
* Device6(SATA 2):f
*/
iowrite32(0x0000ffa0, chip->pch_phub_base_address + 0x14);
- /* set the interrupt delay value */
- iowrite32(0x25, chip->pch_phub_base_address + 0x140);
chip->pch_opt_rom_start_address =\
PCH_PHUB_ROM_START_ADDR_ML7223;
chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223;
@@ -783,8 +810,6 @@ exit_bin_attr:
sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
err_sysfs_create:
- pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
-err_pci_map:
pci_iounmap(pdev, chip->pch_phub_base_address);
err_pci_iomap:
pci_release_regions(pdev);
@@ -802,7 +827,6 @@ static void __devexit pch_phub_remove(struct pci_dev *pdev)
sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
sysfs_remove_bin_file(&pdev->dev.kobj, &pch_bin_attr);
- pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
pci_iounmap(pdev, chip->pch_phub_base_address);
pci_release_regions(pdev);
pci_disable_device(pdev);
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index f2427087bb65..520414299399 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -257,6 +257,9 @@ static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
goto idata_err;
}
+ if (!idata->buf_bytes)
+ return idata;
+
idata->buf = kzalloc(idata->buf_bytes, GFP_KERNEL);
if (!idata->buf) {
err = -ENOMEM;
@@ -303,25 +306,6 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
if (IS_ERR(idata))
return PTR_ERR(idata);
- cmd.opcode = idata->ic.opcode;
- cmd.arg = idata->ic.arg;
- cmd.flags = idata->ic.flags;
-
- data.sg = &sg;
- data.sg_len = 1;
- data.blksz = idata->ic.blksz;
- data.blocks = idata->ic.blocks;
-
- sg_init_one(data.sg, idata->buf, idata->buf_bytes);
-
- if (idata->ic.write_flag)
- data.flags = MMC_DATA_WRITE;
- else
- data.flags = MMC_DATA_READ;
-
- mrq.cmd = &cmd;
- mrq.data = &data;
-
md = mmc_blk_get(bdev->bd_disk);
if (!md) {
err = -EINVAL;
@@ -334,6 +318,48 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
goto cmd_done;
}
+ cmd.opcode = idata->ic.opcode;
+ cmd.arg = idata->ic.arg;
+ cmd.flags = idata->ic.flags;
+
+ if (idata->buf_bytes) {
+ data.sg = &sg;
+ data.sg_len = 1;
+ data.blksz = idata->ic.blksz;
+ data.blocks = idata->ic.blocks;
+
+ sg_init_one(data.sg, idata->buf, idata->buf_bytes);
+
+ if (idata->ic.write_flag)
+ data.flags = MMC_DATA_WRITE;
+ else
+ data.flags = MMC_DATA_READ;
+
+ /* data.flags must already be set before doing this. */
+ mmc_set_data_timeout(&data, card);
+
+ /* Allow overriding the timeout_ns for empirical tuning. */
+ if (idata->ic.data_timeout_ns)
+ data.timeout_ns = idata->ic.data_timeout_ns;
+
+ if ((cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
+ /*
+ * Pretend this is a data transfer and rely on the
+ * host driver to compute timeout. When all host
+ * drivers support cmd.cmd_timeout for R1B, this
+ * can be changed to:
+ *
+ * mrq.data = NULL;
+ * cmd.cmd_timeout = idata->ic.cmd_timeout_ms;
+ */
+ data.timeout_ns = idata->ic.cmd_timeout_ms * 1000000;
+ }
+
+ mrq.data = &data;
+ }
+
+ mrq.cmd = &cmd;
+
mmc_claim_host(card->host);
if (idata->ic.is_acmd) {
@@ -342,24 +368,6 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
goto cmd_rel_host;
}
- /* data.flags must already be set before doing this. */
- mmc_set_data_timeout(&data, card);
- /* Allow overriding the timeout_ns for empirical tuning. */
- if (idata->ic.data_timeout_ns)
- data.timeout_ns = idata->ic.data_timeout_ns;
-
- if ((cmd.flags & MMC_RSP_R1B) == MMC_RSP_R1B) {
- /*
- * Pretend this is a data transfer and rely on the host driver
- * to compute timeout. When all host drivers support
- * cmd.cmd_timeout for R1B, this can be changed to:
- *
- * mrq.data = NULL;
- * cmd.cmd_timeout = idata->ic.cmd_timeout_ms;
- */
- data.timeout_ns = idata->ic.cmd_timeout_ms * 1000000;
- }
-
mmc_wait_for_req(card->host, &mrq);
if (cmd.error) {
@@ -571,22 +579,18 @@ static int mmc_blk_cmd_error(struct request *req, const char *name, int error,
req->rq_disk->disk_name, "timed out", name, status);
/* If the status cmd initially failed, retry the r/w cmd */
- if (!status_valid) {
- pr_err("%s: status not valid, retrying timeout\n", req->rq_disk->disk_name);
+ if (!status_valid)
return ERR_RETRY;
- }
+
/*
* If it was a r/w cmd crc error, or illegal command
* (eg, issued in wrong state) then retry - we should
* have corrected the state problem above.
*/
- if (status & (R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND)) {
- pr_err("%s: command error, retrying timeout\n", req->rq_disk->disk_name);
+ if (status & (R1_COM_CRC_ERROR | R1_ILLEGAL_COMMAND))
return ERR_RETRY;
- }
/* Otherwise abort the command */
- pr_err("%s: not retrying timeout\n", req->rq_disk->disk_name);
return ERR_ABORT;
default:
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index d4a50128fe03..e0fa84b02237 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -126,7 +126,6 @@ static int mmc_bus_suspend(struct device *dev)
struct mmc_driver *drv = to_mmc_driver(dev->driver);
struct mmc_card *card = mmc_dev_to_card(dev);
int ret = 0;
- pm_message_t state = { PM_EVENT_SUSPEND };
if (dev->driver && drv->suspend)
ret = drv->suspend(card);
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index c21bc7199618..116639e30d76 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -756,25 +756,6 @@ void mmc_set_clock(struct mmc_host *host, unsigned int hz)
mmc_host_clk_release(host);
}
-void mmc_finish_tuning(struct mmc_host *host)
-{
- host->ios.finish_tuning_flag = 1;
- mmc_set_ios(host);
- host->ios.finish_tuning_flag = 0;
-}
-
-void mmc_set_tuning(struct mmc_host *host, unsigned int tuning)
-{
- WARN_ON(tuning < host->tuning_min);
- if (tuning > host->tuning_max)
- tuning = host->tuning_max;
-
- host->ios.tuning = tuning;
- host->ios.tuning_flag = 1;
- mmc_set_ios(host);
- host->ios.tuning_flag = 0;
-}
-
#ifdef CONFIG_MMC_CLKGATE
/*
* This gates the clock by setting it to 0 Hz.
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index ee1b0ac2f013..00867d0f1bb5 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1225,7 +1225,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
*
* WARNING: eMMC rules are NOT the same as SD DDR
*/
- if (ddr == EXT_CSD_CARD_TYPE_DDR_1_2V) {
+ if (ddr == MMC_1_2V_DDR_MODE) {
err = mmc_set_signal_voltage(host,
MMC_SIGNAL_VOLTAGE_120, 0);
if (err)
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index a7f83f9a42c9..074ded0f4bae 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -624,38 +624,8 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card)
goto out;
/* SPI mode doesn't define CMD19 */
-#ifdef CONFIG_MMC_SDHCI_ESDHC_IMX
- if (!mmc_host_is_spi(card->host) &&
- (card->sd_bus_speed == UHS_SDR104_BUS_SPEED)) {
- int min, max, avg;
-
- min = card->host->tuning_min;
- while (min < card->host->tuning_max) {
- mmc_set_tuning(card->host, min);
- if (!mmc_send_tuning_cmd(card))
- break;
- min += card->host->tuning_step;
- }
-
- max = min + card->host->tuning_step;
- while (max < card->host->tuning_max) {
- mmc_set_tuning(card->host, max);
- if (mmc_send_tuning_cmd(card)) {
- max -= card->host->tuning_step;
- break;
- }
- max += card->host->tuning_step;
- }
-
- avg = (min + max) / 2;
- mmc_set_tuning(card->host, avg);
- mmc_send_tuning_cmd(card);
- mmc_finish_tuning(card->host);
- }
-#else
if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning)
err = card->host->ops->execute_tuning(card->host);
-#endif
out:
kfree(status);
@@ -1049,7 +1019,7 @@ static void mmc_sd_detect(struct mmc_host *host)
BUG_ON(!host);
BUG_ON(!host->card);
-
+
mmc_claim_host(host);
/*
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
index afafc8c81d01..021fed153804 100644
--- a/drivers/mmc/core/sd_ops.c
+++ b/drivers/mmc/core/sd_ops.c
@@ -345,49 +345,6 @@ int mmc_sd_switch(struct mmc_card *card, int mode, int group,
return 0;
}
-int mmc_send_tuning_cmd(struct mmc_card *card)
-{
- struct mmc_request mrq;
- struct mmc_command cmd;
- struct mmc_data data;
- struct scatterlist sg;
- char scr[64];
-
- BUG_ON(!card);
- BUG_ON(!card->host);
-
- memset(&mrq, 0, sizeof(struct mmc_request));
- memset(&cmd, 0, sizeof(struct mmc_command));
- memset(&data, 0, sizeof(struct mmc_data));
- memset(scr, 0, 64);
-
- mrq.cmd = &cmd;
- mrq.data = &data;
-
- cmd.opcode = MMC_SEND_TUNING_BLOCK;
- cmd.arg = 0;
- cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-
- data.blksz = 64;
- data.blocks = 1;
- data.flags = MMC_DATA_READ;
- data.sg = &sg;
- data.sg_len = 1;
-
- sg_init_one(&sg, scr, 64);
-
- mmc_set_data_timeout(&data, card);
-
- mmc_wait_for_req(card->host, &mrq);
-
- if (cmd.error)
- return cmd.error;
- if (data.error)
- return data.error;
-
- return 0;
-}
-
int mmc_app_sd_status(struct mmc_card *card, void *ssr)
{
int err;
diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h
index 2142da4b611c..ffc2305d905f 100644
--- a/drivers/mmc/core/sd_ops.h
+++ b/drivers/mmc/core/sd_ops.h
@@ -20,7 +20,6 @@ int mmc_app_send_scr(struct mmc_card *card, u32 *scr);
int mmc_sd_switch(struct mmc_card *card, int mode, int group,
u8 value, u8 *resp);
int mmc_app_sd_status(struct mmc_card *card, void *ssr);
-int mmc_send_tuning_cmd(struct mmc_card *card);
#endif
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 7b2ee90b893f..e4cd11b97c24 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -685,7 +685,7 @@ static int mmc_sdio_resume(struct mmc_host *host)
}
if (!err && host->sdio_irqs)
- mmc_signal_sdio_irq(host);
+ wake_up_process(host->sdio_irq_thread);
mmc_release_host(host);
/*
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
index 549a34144646..0f687cdeb064 100755
--- a/drivers/mmc/core/sdio_io.c
+++ b/drivers/mmc/core/sdio_io.c
@@ -383,39 +383,6 @@ u8 sdio_readb(struct sdio_func *func, unsigned int addr, int *err_ret)
EXPORT_SYMBOL_GPL(sdio_readb);
/**
- * sdio_readb_ext - read a single byte from a SDIO function
- * @func: SDIO function to access
- * @addr: address to read
- * @err_ret: optional status value from transfer
- * @in: value to add to argument
- *
- * Reads a single byte from the address space of a given SDIO
- * function. If there is a problem reading the address, 0xff
- * is returned and @err_ret will contain the error code.
- */
-unsigned char sdio_readb_ext(struct sdio_func *func, unsigned int addr,
- int *err_ret, unsigned in)
-{
- int ret;
- unsigned char val;
-
- BUG_ON(!func);
-
- if (err_ret)
- *err_ret = 0;
-
- ret = mmc_io_rw_direct(func->card, 0, func->num, addr, (u8)in, &val);
- if (ret) {
- if (err_ret)
- *err_ret = ret;
- return 0xFF;
- }
-
- return val;
-}
-EXPORT_SYMBOL_GPL(sdio_readb_ext);
-
-/**
* sdio_writeb - write a single byte to a SDIO function
* @func: SDIO function to access
* @b: byte to write
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c
index 03ead028d2ce..d58ae9153379 100644
--- a/drivers/mmc/core/sdio_irq.c
+++ b/drivers/mmc/core/sdio_irq.c
@@ -27,18 +27,20 @@
#include "sdio_ops.h"
-static int process_sdio_pending_irqs(struct mmc_card *card)
+static int process_sdio_pending_irqs(struct mmc_host *host)
{
+ struct mmc_card *card = host->card;
int i, ret, count;
unsigned char pending;
struct sdio_func *func;
/*
* Optimization, if there is only 1 function interrupt registered
- * call irq handler directly
+ * and we know an IRQ was signaled then call irq handler directly.
+ * Otherwise do the full probe.
*/
func = card->sdio_single_irq;
- if (func) {
+ if (func && host->sdio_irq_pending) {
func->irq_handler(func);
return 1;
}
@@ -115,7 +117,8 @@ static int sdio_irq_thread(void *_host)
ret = __mmc_claim_host(host, &host->sdio_irq_thread_abort);
if (ret)
break;
- ret = process_sdio_pending_irqs(host->card);
+ ret = process_sdio_pending_irqs(host);
+ host->sdio_irq_pending = false;
mmc_release_host(host);
/*
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index aa8039f473c4..b6cd3867f723 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -468,7 +468,14 @@ err:
static inline unsigned int ns_to_clocks(struct atmel_mci *host,
unsigned int ns)
{
- return (ns * (host->bus_hz / 1000000) + 999) / 1000;
+ /*
+ * It is easier here to use us instead of ns for the timeout,
+ * it prevents from overflows during calculation.
+ */
+ unsigned int us = DIV_ROUND_UP(ns, 1000);
+
+ /* Maximum clock frequency is host->bus_hz/2 */
+ return us * (DIV_ROUND_UP(host->bus_hz, 2000000));
}
static void atmci_set_timeout(struct atmel_mci *host,
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index fef7140eb1d0..e9dd9d2209fd 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -673,7 +673,8 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
unsigned int status)
{
/* First check for errors */
- if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
+ if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR|
+ MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
u32 remain, success;
/* Terminate the DMA transfer */
@@ -752,8 +753,12 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
}
if (!cmd->data || cmd->error) {
- if (host->data)
+ if (host->data) {
+ /* Terminate the DMA transfer */
+ if (dma_inprogress(host))
+ mmci_dma_data_error(host);
mmci_stop_data(host);
+ }
mmci_request_end(host, cmd->mrq);
} else if (!(cmd->data->flags & MMC_DATA_READ)) {
mmci_start_data(host, cmd->data);
@@ -953,8 +958,9 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status);
data = host->data;
- if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|
- MCI_RXOVERRUN|MCI_DATAEND|MCI_DATABLOCKEND) && data)
+ if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_STARTBITERR|
+ MCI_TXUNDERRUN|MCI_RXOVERRUN|MCI_DATAEND|
+ MCI_DATABLOCKEND) && data)
mmci_data_irq(host, data, status);
cmd = host->cmd;
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 8cbc5335fe6f..5263efcda134 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -20,8 +20,10 @@
#include <linux/mmc/host.h>
#include <linux/mmc/sdhci-pltfm.h>
#include <linux/mmc/mmc.h>
+#include <linux/mmc/card.h>
#include <linux/mmc/sdio.h>
#include <linux/mmc/sd.h>
+#include <linux/scatterlist.h>
#include <mach/hardware.h>
#include <mach/esdhc.h>
#include "sdhci.h"
@@ -68,8 +70,15 @@
#define SDHCI_PROT_CTRL_1BIT (0 << 1)
#define SDHCI_PROT_CTRL_LCTL (1 << 0)
-#define SDHCI_FSL_SVN_300 0x11
+/* SDHCI_FSL_SVN_300 only for mx6q and mx6dl */
+#define SDHCI_FSL_SVN_300 0x3
+#define SDHCI_TUNE_CTRL 0xCC
+#define SDHCI_TUNE_CTRL_STD_TUNING_EN (1 << 24)
+
+#define SDHCI_HOST_CAP_UHS_MODE_MASK 0x7
+
+#define SDHCI_TUNING_BLOCK_PATTERN_LEN 64
/*
* There is an INT DMA ERR mis-match between eSDHC and STD SDHC SPEC:
* Bit25 is used in STD SPEC, and is reserved in fsl eSDHC design,
@@ -91,6 +100,9 @@
*/
#define ESDHC_FLAG_MULTIBLK_NO_INT (1 << 1)
+static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val);
+static void esdhc_post_tuning(struct sdhci_host *host);
+
struct pltfm_imx_data {
int flags;
u32 scratchpad;
@@ -98,6 +110,80 @@ struct pltfm_imx_data {
unsigned char uhs_mode;
};
+static void request_done(struct mmc_request *mrq)
+{
+ complete(&mrq->completion);
+}
+
+static int esdhc_send_tuning_cmd(struct sdhci_host *host)
+{
+ struct mmc_command cmd = {0};
+ struct mmc_request mrq = {0};
+ struct mmc_data data = {0};
+ struct scatterlist sg;
+ char tuning_pattern[SDHCI_TUNING_BLOCK_PATTERN_LEN];
+
+ cmd.opcode = MMC_SEND_TUNING_BLOCK;
+ cmd.arg = 0;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
+
+ data.blksz = SDHCI_TUNING_BLOCK_PATTERN_LEN;
+ data.blocks = 1;
+ data.flags = MMC_DATA_READ;
+ data.sg = &sg;
+ data.sg_len = 1;
+
+ sg_init_one(&sg, tuning_pattern, sizeof(tuning_pattern));
+
+ mrq.cmd = &cmd;
+ mrq.cmd->mrq = &mrq;
+ mrq.data = &data;
+ mrq.data->mrq = &mrq;
+ mrq.cmd->data = mrq.data;
+
+ mrq.done = request_done;
+
+ init_completion(&(mrq.completion));
+ sdhci_request(host->mmc, &mrq);
+ wait_for_completion(&(mrq.completion));
+
+ if (cmd.error)
+ return cmd.error;
+ if (data.error)
+ return data.error;
+
+ return 0;
+}
+
+static int esdhc_execute_tuning(struct sdhci_host *host)
+{
+ int min, max, avg;
+
+ min = host->tuning_min;
+ while (min < host->tuning_max) {
+ esdhc_prepare_tuning(host, min);
+ if (!esdhc_send_tuning_cmd(host))
+ break;
+ min += host->tuning_step;
+ }
+
+ max = min + host->tuning_step;
+ while (max < host->tuning_max) {
+ esdhc_prepare_tuning(host, max);
+ if (esdhc_send_tuning_cmd(host)) {
+ max -= host->tuning_step;
+ break;
+ }
+ max += host->tuning_step;
+ }
+
+ avg = (min + max) / 2;
+ esdhc_prepare_tuning(host, avg);
+ esdhc_send_tuning_cmd(host);
+ esdhc_post_tuning(host);
+ return 0;
+}
+
static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg)
{
void __iomem *base = host->ioaddr + (reg & ~0x3);
@@ -157,12 +243,15 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
if ((val & SDHCI_INT_DATA_END) && \
!(val & SDHCI_INT_DMA_END))
val = readl(host->ioaddr + reg);
- } else if (reg == SDHCI_CAPABILITIES_1 && cpu_is_mx6()) {
+ } else if (reg == SDHCI_CAPABILITIES_1
+ && (cpu_is_mx6q() || cpu_is_mx6dl())) {
/*
* on mx6q, no cap_1 available, fake one.
*/
val = SDHCI_SUPPORT_DDR50 | SDHCI_SUPPORT_SDR104 | \
SDHCI_SUPPORT_SDR50;
+ } else if (reg == SDHCI_CAPABILITIES_1 && cpu_is_mx6sl()) {
+ val = readl(host->ioaddr + SDHCI_CAPABILITIES) & 0xFFFF;
} else if (reg == SDHCI_MAX_CURRENT && cpu_is_mx6()) {
/*
* on mx6q, no max current available, fake one.
@@ -275,8 +364,9 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
case SDHCI_HOST_VERSION:
reg ^= 2;
val = readl(host->ioaddr + reg);
- if (((val & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT)
- == SDHCI_FSL_SVN_300) {
+ if ((cpu_is_mx6q() || cpu_is_mx6dl()) &&
+ ((val & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT)
+ == SDHCI_FSL_SVN_300) {
val &= ~SDHCI_SPEC_VER_MASK;
val |= SDHCI_SPEC_300;
}
@@ -289,11 +379,19 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
ret |= (val & SDHCI_VENDOR_SPEC_VSELECT)
? SDHCI_CTRL_VDD_180 : 0;
- val = readl(host->ioaddr + SDHCI_MIX_CTRL);
- ret |= (val & SDHCI_MIX_CTRL_EXE_TUNE)
- ? SDHCI_CTRL_EXEC_TUNING : 0;
- ret |= (val & SDHCI_MIX_CTRL_SMPCLK_SEL)
- ? 0 : SDHCI_CTRL_TUNED_CLK ;
+ if (cpu_is_mx6sl()) {
+ val = readl(host->ioaddr + SDHCI_ACMD12_ERR);
+ ret |= (val & SDHCI_MIX_CTRL_EXE_TUNE)
+ ? SDHCI_CTRL_EXEC_TUNING : 0;
+ ret |= (val & SDHCI_MIX_CTRL_SMPCLK_SEL)
+ ? SDHCI_CTRL_TUNED_CLK : 0;
+ } else {
+ val = readl(host->ioaddr + SDHCI_MIX_CTRL);
+ ret |= (val & SDHCI_MIX_CTRL_EXE_TUNE)
+ ? SDHCI_CTRL_EXEC_TUNING : 0;
+ ret |= (val & SDHCI_MIX_CTRL_SMPCLK_SEL)
+ ? SDHCI_CTRL_TUNED_CLK : 0;
+ }
ret |= SDHCI_CTRL_UHS_MASK & imx_data->uhs_mode;
/* no preset enable available */
ret &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
@@ -304,7 +402,7 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
return readw(host->ioaddr + reg);
}
-void esdhc_post_tuning(struct sdhci_host *host)
+static void esdhc_post_tuning(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct pltfm_imx_data *imx_data = pltfm_host->priv;
@@ -341,7 +439,7 @@ static void esdhc_reset(struct sdhci_host *host)
}
}
-void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
+static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)
{
u32 reg;
@@ -396,11 +494,25 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
* ignore exec_tuning flag written to SDHCI_HOST_CONTROL2,
* tuning will be handled differently for FSL SDHC ip.
*/
- orig_reg = readl(host->ioaddr + SDHCI_MIX_CTRL);
- orig_reg &= ~SDHCI_MIX_CTRL_SMPCLK_SEL;
-
- orig_reg |= (val & SDHCI_CTRL_TUNED_CLK)
- ? 0 : SDHCI_MIX_CTRL_SMPCLK_SEL;
+ if (cpu_is_mx6sl()) {
+ orig_reg = readl(host->ioaddr + SDHCI_TUNE_CTRL);
+ if (val & SDHCI_CTRL_EXEC_TUNING) {
+ orig_reg |= SDHCI_TUNE_CTRL_STD_TUNING_EN;
+ writel(orig_reg,
+ host->ioaddr + SDHCI_TUNE_CTRL);
+
+ orig_reg =
+ readl(host->ioaddr + SDHCI_ACMD12_ERR);
+ orig_reg |= SDHCI_MIX_CTRL_EXE_TUNE;
+ writel(orig_reg,
+ host->ioaddr + SDHCI_ACMD12_ERR);
+ }
+ } else {
+ orig_reg = readl(host->ioaddr + SDHCI_MIX_CTRL);
+ orig_reg &= ~SDHCI_MIX_CTRL_SMPCLK_SEL;
+ orig_reg |= (val & SDHCI_CTRL_TUNED_CLK)
+ ? SDHCI_MIX_CTRL_SMPCLK_SEL : 0;
+ }
if (val & SDHCI_CTRL_UHS_DDR50) {
orig_reg |= SDHCI_MIX_CTRL_DDREN;
@@ -449,8 +561,9 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
return;
case SDHCI_COMMAND:
- if ((host->cmd->opcode == MMC_STOP_TRANSMISSION)
- && (imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT))
+ if ((host->cmd->opcode == MMC_STOP_TRANSMISSION ||
+ host->cmd->opcode == MMC_SET_BLOCK_COUNT) &&
+ (imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT))
val |= SDHCI_CMD_ABORTCMD;
writel(0x08800880, host->ioaddr + SDHCI_CAPABILITIES_1);
@@ -650,8 +763,6 @@ static struct sdhci_ops sdhci_esdhc_ops = {
.set_clock = esdhc_set_clock,
.get_max_clock = esdhc_pltfm_get_max_clock,
.get_min_clock = esdhc_pltfm_get_min_clock,
- .pre_tuning = esdhc_prepare_tuning,
- .post_tuning = esdhc_post_tuning,
.platform_8bit_width = plt_8bit_width,
.platform_clk_ctrl = plt_clk_ctrl,
};
@@ -703,8 +814,7 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
}
pltfm_host->priv = imx_data;
- if (!cpu_is_mx25())
- host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+ host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
if (cpu_is_mx25() || cpu_is_mx35())
/* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
@@ -725,6 +835,9 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
host->ocr_avail_mmc = MMC_VDD_29_30 | MMC_VDD_30_31 | \
MMC_VDD_32_33 | MMC_VDD_33_34;
+ if (cpu_is_mx6q() || cpu_is_mx6dl())
+ sdhci_esdhc_ops.platform_execute_tuning = esdhc_execute_tuning;
+
if (boarddata->support_18v)
host->ocr_avail_sd |= MMC_VDD_165_195;
if (boarddata->support_8bit)
@@ -802,6 +915,10 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
}
+#ifdef CONFIG_PM_RUNTIME
+ host->mmc->caps |= MMC_CAP_POWER_OFF_CARD;
+#endif
+
if (host->clk_mgr_en)
clk_disable(pltfm_host->clk);
return 0;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 29e9b154a84a..50904b60cc61 100755
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -94,7 +94,7 @@ static void sdhci_enable_clk(struct sdhci_host *host)
static void sdhci_disable_clk(struct sdhci_host *host, int delay)
{
- if (host->clk_mgr_en && sdhci_can_gate_clk(host)) {
+ if (host->clk_mgr_en) {
if (delay == 0 && !in_interrupt()) {
if (host->ops->platform_clk_ctrl && host->clk_status)
host->ops->platform_clk_ctrl(host, false);
@@ -308,7 +308,8 @@ static void sdhci_led_control(struct led_classdev *led,
sdhci_activate_led(host);
spin_unlock_irqrestore(&host->lock, flags);
- sdhci_disable_clk(host, CLK_TIMEOUT);
+ if (!sdhci_is_sdio_attached(host))
+ sdhci_disable_clk(host, CLK_TIMEOUT);
}
#endif
@@ -1255,7 +1256,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
* *
\*****************************************************************************/
-static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
+void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
{
struct sdhci_host *host;
bool present;
@@ -1340,18 +1341,6 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
if (host->flags & SDHCI_DEVICE_DEAD)
goto out;
- if (ios->finish_tuning_flag) {
- if (host->ops->post_tuning)
- host->ops->post_tuning(host);
- goto out;
- }
-
- if (ios->tuning_flag) {
- /* means this request is for tuning only */
- if (host->ops->pre_tuning)
- host->ops->pre_tuning(host, ios->tuning);
- goto out;
- }
/*
* Reset the chip on each power off.
* Should clear out any weird states.
@@ -1412,8 +1401,7 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
if ((ios->timing == MMC_TIMING_UHS_SDR50) ||
(ios->timing == MMC_TIMING_UHS_SDR104) ||
(ios->timing == MMC_TIMING_UHS_DDR50) ||
- (ios->timing == MMC_TIMING_UHS_SDR25) ||
- (ios->timing == MMC_TIMING_UHS_SDR12))
+ (ios->timing == MMC_TIMING_UHS_SDR25))
ctrl |= SDHCI_CTRL_HISPD;
ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
@@ -1488,7 +1476,7 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
* signalling timeout and CRC errors even on CMD0. Resetting
* it on each ios seems to solve the problem.
*/
- if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS)
+ if (host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS)
sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
out:
@@ -1516,7 +1504,8 @@ static int check_ro(struct sdhci_host *host)
& SDHCI_WRITE_PROTECT);
spin_unlock_irqrestore(&host->lock, flags);
- sdhci_disable_clk(host, CLK_TIMEOUT);
+ if (!sdhci_is_sdio_attached(host))
+ sdhci_disable_clk(host, CLK_TIMEOUT);
/* This quirk needs to be replaced by a callback-function later */
return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ?
@@ -1702,6 +1691,14 @@ static int sdhci_execute_tuning(struct mmc_host *mmc)
return 0;
}
+ if (ctrl & SDHCI_CTRL_EXEC_TUNING) {
+ if (host->ops->platform_execute_tuning) {
+ spin_unlock(&host->lock);
+ enable_irq(host->irq);
+ return host->ops->platform_execute_tuning(host);
+ }
+ }
+
sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
/*
@@ -2053,7 +2050,8 @@ static void sdhci_tasklet_finish(unsigned long param)
mmiowb();
spin_unlock_irqrestore(&host->lock, flags);
- sdhci_disable_clk(host, CLK_TIMEOUT);
+ if (!sdhci_is_sdio_attached(host))
+ sdhci_disable_clk(host, CLK_TIMEOUT);
mmc_request_done(host->mmc, mrq);
}
@@ -2381,9 +2379,8 @@ int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state)
/* Disable tuning since we are suspending */
if (host->version >= SDHCI_SPEC_300 && host->tuning_count &&
host->tuning_mode == SDHCI_TUNING_MODE_1) {
+ del_timer_sync(&host->tuning_timer);
host->flags &= ~SDHCI_NEEDS_RETUNING;
- mod_timer(&host->tuning_timer, jiffies +
- host->tuning_count * HZ);
}
ret = mmc_suspend_host(host->mmc);
@@ -2400,7 +2397,8 @@ out:
* mmc_suspend_host may disable the clk
*/
sdhci_enable_clk(host);
- sdhci_disable_clk(host, 0);
+ if (!sdhci_is_sdio_attached(host))
+ sdhci_disable_clk(host, 0);
return ret;
}
@@ -2438,7 +2436,8 @@ int sdhci_resume_host(struct sdhci_host *host)
out:
/* sync worker */
- sdhci_disable_clk(host, 0);
+ if (!sdhci_is_sdio_attached(host))
+ sdhci_disable_clk(host, 0);
/* Set the re-tuning expiration flag */
if ((host->version >= SDHCI_SPEC_300) && host->tuning_count &&
@@ -2458,7 +2457,8 @@ void sdhci_enable_irq_wakeups(struct sdhci_host *host)
val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL);
val |= SDHCI_WAKE_ON_INT;
sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL);
- sdhci_disable_clk(host, CLK_TIMEOUT);
+ if (!sdhci_is_sdio_attached(host))
+ sdhci_disable_clk(host, CLK_TIMEOUT);
}
EXPORT_SYMBOL_GPL(sdhci_enable_irq_wakeups);
@@ -2606,7 +2606,8 @@ int sdhci_add_host(struct sdhci_host *host)
printk(KERN_ERR
"%s: Hardware doesn't specify base clock "
"frequency.\n", mmc_hostname(mmc));
- sdhci_disable_clk(host, 0);
+ if (!sdhci_is_sdio_attached(host))
+ sdhci_disable_clk(host, 0);
return -ENODEV;
}
host->max_clk = host->ops->get_max_clock(host);
@@ -2622,7 +2623,8 @@ int sdhci_add_host(struct sdhci_host *host)
printk(KERN_ERR
"%s: Hardware doesn't specify timeout clock "
"frequency.\n", mmc_hostname(mmc));
- sdhci_disable_clk(host, 0);
+ if (!sdhci_is_sdio_attached(host))
+ sdhci_disable_clk(host, 0);
return -ENODEV;
}
}
@@ -2810,7 +2812,8 @@ int sdhci_add_host(struct sdhci_host *host)
if (mmc->ocr_avail == 0) {
printk(KERN_ERR "%s: Hardware doesn't report any "
"support voltages.\n", mmc_hostname(mmc));
- sdhci_disable_clk(host, 0);
+ if (!sdhci_is_sdio_attached(host))
+ sdhci_disable_clk(host, 0);
return -ENODEV;
}
@@ -2934,7 +2937,8 @@ int sdhci_add_host(struct sdhci_host *host)
(host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO");
sdhci_enable_card_detection(host);
- sdhci_disable_clk(host, CLK_TIMEOUT);
+ if (!sdhci_is_sdio_attached(host))
+ sdhci_disable_clk(host, CLK_TIMEOUT);
return 0;
#ifdef CONFIG_SDHCI_USE_LEDS_CLASS
@@ -2945,7 +2949,8 @@ reset:
untasklet:
tasklet_kill(&host->card_tasklet);
tasklet_kill(&host->finish_tasklet);
- sdhci_disable_clk(host, 0);
+ if (!sdhci_is_sdio_attached(host))
+ sdhci_disable_clk(host, 0);
return ret;
}
@@ -2985,7 +2990,8 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
sdhci_enable_clk(host);
if (!dead)
sdhci_reset(host, SDHCI_RESET_ALL);
- sdhci_disable_clk(host, 0);
+ if (!sdhci_is_sdio_attached(host))
+ sdhci_disable_clk(host, 0);
free_irq(host->irq, host);
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 27b12505c65c..ef45fa98dc90 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -274,9 +274,8 @@ struct sdhci_ops {
void (*platform_reset_exit)(struct sdhci_host *host, u8 mask);
int (*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
- void (*pre_tuning)(struct sdhci_host *host, u32 val);
- void (*post_tuning)(struct sdhci_host *host);
void (*platform_clk_ctrl)(struct sdhci_host *host, bool enable);
+ int (*platform_execute_tuning)(struct sdhci_host *host);
};
#ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
@@ -382,4 +381,6 @@ extern int sdhci_resume_host(struct sdhci_host *host);
extern void sdhci_enable_irq_wakeups(struct sdhci_host *host);
#endif
+void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq);
+
#endif /* __SDHCI_HW_H */
diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c
index d4455ffbefd8..52f4b644766a 100644
--- a/drivers/mmc/host/vub300.c
+++ b/drivers/mmc/host/vub300.c
@@ -259,7 +259,7 @@ static int firmware_rom_wait_states = 0x04;
static int firmware_rom_wait_states = 0x1C;
#endif
-module_param(firmware_rom_wait_states, bool, 0644);
+module_param(firmware_rom_wait_states, int, 0644);
MODULE_PARM_DESC(firmware_rom_wait_states,
"ROM wait states byte=RRRIIEEE (Reserved Internal External)");
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
index b78f23169d4e..8cd983cdc643 100644
--- a/drivers/mtd/devices/block2mtd.c
+++ b/drivers/mtd/devices/block2mtd.c
@@ -284,6 +284,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
dev->mtd.erasesize = erase_size;
dev->mtd.writesize = 1;
+ dev->mtd.writebufsize = PAGE_SIZE;
dev->mtd.type = MTD_RAM;
dev->mtd.flags = MTD_CAP_RAM;
dev->mtd.erase = block2mtd_erase;
diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c
index 772a0ff89e0f..09d5b5aaea57 100644
--- a/drivers/mtd/devices/lart.c
+++ b/drivers/mtd/devices/lart.c
@@ -636,6 +636,7 @@ static int __init lart_flash_init (void)
mtd.name = module_name;
mtd.type = MTD_NORFLASH;
mtd.writesize = 1;
+ mtd.writebufsize = 4;
mtd.flags = MTD_CAP_NORFLASH;
mtd.size = FLASH_BLOCKSIZE_PARAM * FLASH_NUMBLOCKS_16m_PARAM + FLASH_BLOCKSIZE_MAIN * FLASH_NUMBLOCKS_16m_MAIN;
mtd.erasesize = FLASH_BLOCKSIZE_MAIN;
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 35180e475c4c..9fad104d4aab 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -930,6 +930,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
flash->mtd.dev.parent = &spi->dev;
flash->page_size = info->page_size;
+ flash->mtd.writebufsize = flash->page_size;
if (info->addr_width)
flash->addr_width = info->addr_width;
diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
index 1e2c430aaad2..867710a09a48 100644
--- a/drivers/mtd/devices/sst25l.c
+++ b/drivers/mtd/devices/sst25l.c
@@ -406,6 +406,7 @@ static int __devinit sst25l_probe(struct spi_device *spi)
flash->mtd.flags = MTD_CAP_NORFLASH;
flash->mtd.erasesize = flash_info->erase_size;
flash->mtd.writesize = flash_info->page_size;
+ flash->mtd.writebufsize = flash_info->page_size;
flash->mtd.size = flash_info->page_size * flash_info->nr_pages;
flash->mtd.erase = sst25l_erase;
flash->mtd.read = sst25l_read;
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index ca385697446e..bff8d4671ad6 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -215,7 +215,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
mutex_lock(&dev->lock);
- if (dev->open++)
+ if (dev->open)
goto unlock;
kref_get(&dev->ref);
@@ -235,6 +235,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
goto error_release;
unlock:
+ dev->open++;
mutex_unlock(&dev->lock);
blktrans_dev_put(dev);
return ret;
diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c
index e3e40f440323..43130e8aceac 100644
--- a/drivers/mtd/mtdoops.c
+++ b/drivers/mtd/mtdoops.c
@@ -253,6 +253,9 @@ static void find_next_position(struct mtdoops_context *cxt)
size_t retlen;
for (page = 0; page < cxt->oops_pages; page++) {
+ if (mtd->block_isbad &&
+ mtd->block_isbad(mtd, page * record_size))
+ continue;
/* Assume the page is used */
mark_page_used(cxt, page);
ret = mtd->read(mtd, page * record_size, MTDOOPS_HEADER_SIZE,
@@ -369,7 +372,7 @@ static void mtdoops_notify_add(struct mtd_info *mtd)
/* oops_page_used is a bit field */
cxt->oops_page_used = vmalloc(DIV_ROUND_UP(mtdoops_pages,
- BITS_PER_LONG));
+ BITS_PER_LONG) * sizeof(unsigned long));
if (!cxt->oops_page_used) {
printk(KERN_ERR "mtdoops: could not allocate page array\n");
return;
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index ccbeaa1e4a8e..cc81cd67f873 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -360,6 +360,7 @@ static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
buf += mtd->oobsize + mtd->writesize;
len -= mtd->writesize;
+ offs += mtd->writesize;
}
return 0;
}
diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c
index ed3d6cd2c6dc..0e34d564941a 100644
--- a/drivers/mtd/sm_ftl.c
+++ b/drivers/mtd/sm_ftl.c
@@ -1256,7 +1256,7 @@ static void sm_remove_dev(struct mtd_blktrans_dev *dev)
static struct mtd_blktrans_ops sm_ftl_ops = {
.name = "smblk",
- .major = -1,
+ .major = 0,
.part_bits = SM_FTL_PARTN_BITS,
.blksize = SM_SECTOR_SIZE,
.getgeo = sm_getgeo,
diff --git a/drivers/mtd/tests/mtd_stresstest.c b/drivers/mtd/tests/mtd_stresstest.c
index 531625fc9259..129bad2e4080 100644
--- a/drivers/mtd/tests/mtd_stresstest.c
+++ b/drivers/mtd/tests/mtd_stresstest.c
@@ -277,6 +277,12 @@ static int __init mtd_stresstest_init(void)
(unsigned long long)mtd->size, mtd->erasesize,
pgsize, ebcnt, pgcnt, mtd->oobsize);
+ if (ebcnt < 2) {
+ printk(PRINT_PREF "error: need at least 2 eraseblocks\n");
+ err = -ENOSPC;
+ goto out_put_mtd;
+ }
+
/* Read or write up 2 eraseblocks at a time */
bufsize = mtd->erasesize * 2;
@@ -315,6 +321,7 @@ out:
kfree(bbt);
vfree(writebuf);
vfree(readbuf);
+out_put_mtd:
put_mtd_device(mtd);
if (err)
printk(PRINT_PREF "error %d occurred\n", err);
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 191f3bb3c41a..cdea6692dea0 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -628,6 +628,9 @@ static int verify_mkvol_req(const struct ubi_device *ubi,
if (req->alignment != 1 && n)
goto bad;
+ if (!req->name[0] || !req->name_len)
+ goto bad;
+
if (req->name_len > UBI_VOL_NAME_MAX) {
err = -ENAMETOOLONG;
goto bad;
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index 3f1a09c5c438..5f0e4c2d9cd3 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -51,7 +51,10 @@ struct ubi_mkvol_req;
pr_debug("UBI DBG " type ": " fmt "\n", ##__VA_ARGS__)
/* Just a debugging messages not related to any specific UBI subsystem */
-#define dbg_msg(fmt, ...) ubi_dbg_msg("msg", fmt, ##__VA_ARGS__)
+#define dbg_msg(fmt, ...) \
+ printk(KERN_DEBUG "UBI DBG (pid %d): %s: " fmt "\n", \
+ current->pid, __func__, ##__VA_ARGS__)
+
/* General debugging messages */
#define dbg_gen(fmt, ...) ubi_dbg_msg("gen", fmt, ##__VA_ARGS__)
/* Messages from the eraseblock association sub-system */
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 4be671815014..c696c9481c95 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -1028,12 +1028,14 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
* 'ubi_wl_put_peb()' function on the @ubi->move_mutex. In turn, we are
* holding @ubi->move_mutex and go sleep on the LEB lock. So, if the
* LEB is already locked, we just do not move it and return
- * %MOVE_CANCEL_RACE, which means that UBI will re-try, but later.
+ * %MOVE_RETRY. Note, we do not return %MOVE_CANCEL_RACE here because
+ * we do not know the reasons of the contention - it may be just a
+ * normal I/O on this LEB, so we want to re-try.
*/
err = leb_write_trylock(ubi, vol_id, lnum);
if (err) {
dbg_wl("contention on LEB %d:%d, cancel", vol_id, lnum);
- return MOVE_CANCEL_RACE;
+ return MOVE_RETRY;
}
/*
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 2135a53732ff..0b49eadebc36 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -1174,7 +1174,7 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
if (!ech)
- goto out_slab;
+ goto out_si;
vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
if (!vidh)
@@ -1235,8 +1235,6 @@ out_vidh:
ubi_free_vid_hdr(ubi, vidh);
out_ech:
kfree(ech);
-out_slab:
- kmem_cache_destroy(si->scan_leb_slab);
out_si:
ubi_scan_destroy_si(si);
return ERR_PTR(err);
@@ -1325,7 +1323,9 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si)
}
}
- kmem_cache_destroy(si->scan_leb_slab);
+ if (si->scan_leb_slab)
+ kmem_cache_destroy(si->scan_leb_slab);
+
kfree(si);
}
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index c6c22295898e..bbfa88d459e0 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -121,6 +121,7 @@ enum {
* PEB
* MOVE_CANCEL_BITFLIPS: canceled because a bit-flip was detected in the
* target PEB
+ * MOVE_RETRY: retry scrubbing the PEB
*/
enum {
MOVE_CANCEL_RACE = 1,
@@ -128,6 +129,7 @@ enum {
MOVE_TARGET_RD_ERR,
MOVE_TARGET_WR_ERR,
MOVE_CANCEL_BITFLIPS,
+ MOVE_RETRY,
};
/**
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index ff2c4956eeff..25f18e9b6432 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -386,7 +386,7 @@ static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int max)
*/
int ubi_wl_get_peb(struct ubi_device *ubi, int dtype)
{
- int err, medium_ec;
+ int err;
struct ubi_wl_entry *e, *first, *last;
ubi_assert(dtype == UBI_LONGTERM || dtype == UBI_SHORTTERM ||
@@ -424,7 +424,7 @@ retry:
* For unknown data we pick a physical eraseblock with medium
* erase counter. But we by no means can pick a physical
* eraseblock with erase counter greater or equivalent than the
- * lowest erase counter plus %WL_FREE_MAX_DIFF.
+ * lowest erase counter plus %WL_FREE_MAX_DIFF/2.
*/
first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry,
u.rb);
@@ -433,10 +433,8 @@ retry:
if (last->ec - first->ec < WL_FREE_MAX_DIFF)
e = rb_entry(ubi->free.rb_node,
struct ubi_wl_entry, u.rb);
- else {
- medium_ec = (first->ec + WL_FREE_MAX_DIFF)/2;
- e = find_wl_entry(&ubi->free, medium_ec);
- }
+ else
+ e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF/2);
break;
case UBI_SHORTTERM:
/*
@@ -792,7 +790,10 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
protect = 1;
goto out_not_moved;
}
-
+ if (err == MOVE_RETRY) {
+ scrubbing = 1;
+ goto out_not_moved;
+ }
if (err == MOVE_CANCEL_BITFLIPS || err == MOVE_TARGET_WR_ERR ||
err == MOVE_TARGET_RD_ERR) {
/*
@@ -1046,7 +1047,6 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
ubi_err("failed to erase PEB %d, error %d", pnum, err);
kfree(wl_wrk);
- kmem_cache_free(ubi_wl_entry_slab, e);
if (err == -EINTR || err == -ENOMEM || err == -EAGAIN ||
err == -EBUSY) {
@@ -1059,14 +1059,16 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
goto out_ro;
}
return err;
- } else if (err != -EIO) {
+ }
+
+ kmem_cache_free(ubi_wl_entry_slab, e);
+ if (err != -EIO)
/*
* If this is not %-EIO, we have no idea what to do. Scheduling
* this physical eraseblock for erasure again would cause
* errors again and again. Well, lets switch to R/O mode.
*/
goto out_ro;
- }
/* It is %-EIO, the PEB went bad */
diff --git a/drivers/mxc/Kconfig b/drivers/mxc/Kconfig
index 441b655da153..5e2bfc0d1f69 100644
--- a/drivers/mxc/Kconfig
+++ b/drivers/mxc/Kconfig
@@ -38,6 +38,7 @@ source "drivers/mxc/amd-gpu/Kconfig"
source "drivers/mxc/gpu-viv/Kconfig"
source "drivers/mxc/thermal/Kconfig"
source "drivers/mxc/mipi/Kconfig"
+source "drivers/mxc/hdmi-cec/Kconfig"
endmenu
diff --git a/drivers/mxc/Makefile b/drivers/mxc/Makefile
index fbcd0fee1801..5d44c89eea04 100644
--- a/drivers/mxc/Makefile
+++ b/drivers/mxc/Makefile
@@ -19,3 +19,4 @@ obj-$(CONFIG_MXC_AMD_GPU) += amd-gpu/
obj-$(CONFIG_MXC_GPU_VIV) += gpu-viv/
obj-$(CONFIG_ANATOP_THERMAL) += thermal/
obj-$(CONFIG_MXC_MIPI_CSI2) += mipi/
+obj-$(CONFIG_MXC_HDMI_CEC) += hdmi-cec/
diff --git a/drivers/mxc/asrc/mxc_asrc.c b/drivers/mxc/asrc/mxc_asrc.c
index db20cbf2971a..4ef31c8fd6db 100644
--- a/drivers/mxc/asrc/mxc_asrc.c
+++ b/drivers/mxc/asrc/mxc_asrc.c
@@ -583,6 +583,26 @@ int asrc_config_pair(struct asrc_config *config)
}
}
+ if ((config->inclk == INCLK_ASRCK1_CLK) &&
+ (config->outclk == OUTCLK_ESAI_TX)) {
+ reg = __raw_readl(g_asrc->vaddr + ASRC_ASRCTR_REG);
+ reg &= ~(1 << (20 + config->pair));
+ reg |= (0x03 << (13 + (config->pair << 1)));
+ __raw_writel(reg, g_asrc->vaddr + ASRC_ASRCTR_REG);
+ err = asrc_set_clock_ratio(config->pair,
+ config->input_sample_rate,
+ config->output_sample_rate);
+ if (err < 0)
+ return err;
+
+ err = asrc_set_process_configuration(config->pair,
+ config->input_sample_rate,
+ config->
+ output_sample_rate);
+ if (err < 0)
+ return err;
+ }
+
/* Config input and output wordwidth */
reg = __raw_readl(
g_asrc->vaddr + ASRC_ASRMCR1A_REG + (config->pair << 2));
diff --git a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c
index 3d825d641f04..633081b09c07 100755
--- a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c
+++ b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c
@@ -1341,7 +1341,6 @@ gckCONTEXT_Update(
gctUINT32 data;
gctUINT index;
gctUINT i, j;
- gctUINT32 wait = gcdGPU_TIMEOUT ? gcdGPU_TIMEOUT : gcvINFINITE;
#if gcdSECURE_USER
gcskSECURE_CACHE_PTR cache;
@@ -1377,7 +1376,9 @@ gckCONTEXT_Update(
/* Wait until the context buffer becomes available; this will
also reset the signal and mark the buffer as busy. */
- gcmkONERROR(gckOS_WaitSignal(Context->os, buffer->signal, wait));
+ gcmkONERROR(gckOS_WaitSignal(
+ Context->os, buffer->signal, gcvINFINITE
+ ));
#if gcdSECURE_USER
/* Get the cache form the database. */
diff --git a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
index ee007ea89916..df15ef422b04 100755
--- a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
+++ b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
@@ -2210,7 +2210,7 @@ gckHARDWARE_Link(
/* Append LINK(bytes / 8), FetchAddress. */
link = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x08 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
- | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (bytes >> 3) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (bytes >> 3) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
gcmkONERROR(
gckOS_WriteMemory(Hardware->os, logical, link));
@@ -2838,10 +2838,10 @@ gckHARDWARE_FlushMMU(
buffer[1]
= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 0:0) - (0 ? 0:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 0:0) - (0 ? 0:0) + 1))))))) << (0 ? 0:0)))
- | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
- | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)))
- | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
- | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 1:1) - (0 ? 1:1) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 1:1) - (0 ? 1:1) + 1))))))) << (0 ? 1:1)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 2:2) - (0 ? 2:2) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 2:2) - (0 ? 2:2) + 1))))))) << (0 ? 2:2)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 3:3) - (0 ? 3:3) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 3:3) - (0 ? 3:3) + 1))))))) << (0 ? 3:3)))
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4)));
gcmkONERROR(gckCOMMAND_Execute(command, 8));
}
@@ -2849,9 +2849,9 @@ gckHARDWARE_FlushMMU(
{
flushSize = 16 * 4;
- gcmkONERROR(gckCOMMAND_Reserve(
+ gcmkONERROR(gckCOMMAND_Reserve(
command, flushSize, &pointer, &bufferSize
- ));
+ ));
buffer = (gctUINT32_PTR) pointer;
@@ -2860,8 +2860,8 @@ gckHARDWARE_FlushMMU(
gcmkONERROR(gckOS_GetPhysicalAddress(command->os, buffer, &physical));
/* Flush cache. */
- buffer[0]
- = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
+ buffer[0]
+ = ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0E03) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)));
@@ -2903,7 +2903,7 @@ gckHARDWARE_FlushMMU(
buffer[8]
= ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27))) | (((gctUINT32) (0x01 & ((gctUINT32) ((((1 ? 31:27) - (0 ? 31:27) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 31:27) - (0 ? 31:27) + 1))))))) << (0 ? 31:27)))
| ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0))) | (((gctUINT32) ((gctUINT32) (0x0061) & ((gctUINT32) ((((1 ? 15:0) - (0 ? 15:0) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 15:0) - (0 ? 15:0) + 1))))))) << (0 ? 15:0)))
- | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
+ | ((((gctUINT32) (0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 25:16) - (0 ? 25:16) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 25:16) - (0 ? 25:16) + 1))))))) << (0 ? 25:16)));
buffer[9]
= (((((gctUINT32) (~0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) | (((gctUINT32) (0x1 & ((gctUINT32) ((((1 ? 4:4) - (0 ? 4:4) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 4:4) - (0 ? 4:4) + 1))))))) << (0 ? 4:4))) & ((((gctUINT32) (~0)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))) | (((gctUINT32) (0x0 & ((gctUINT32) ((((1 ? 7:7) - (0 ? 7:7) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 7:7) - (0 ? 7:7) + 1))))))) << (0 ? 7:7))) );
@@ -4741,7 +4741,7 @@ _ResetGPU(
{
/* Disable clock gating. */
gcmkONERROR(gckOS_WriteRegisterEx(Os,
- Core,
+ Core,
Hardware->powerBaseAddress +
0x00104,
0x00000000));
@@ -4766,7 +4766,7 @@ _ResetGPU(
gcmkONERROR(gckOS_WriteRegisterEx(Os,
Core,
- 0x00000,
+ 0x00000,
((((gctUINT32) (0x00000900)) & ~(((gctUINT32) (((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9))) | (((gctUINT32) ((gctUINT32) (1) & ((gctUINT32) ((((1 ? 9:9) - (0 ? 9:9) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 9:9) - (0 ? 9:9) + 1))))))) << (0 ? 9:9)))));
gcmkONERROR(gckOS_WriteRegisterEx(Os,
@@ -4853,8 +4853,6 @@ gckHARDWARE_Reset(
gceSTATUS status;
gckCOMMAND command;
gctBOOL acquired = gcvFALSE;
- gctBOOL mutexAcquired = gcvFALSE;
- gctUINT32 process, thread;
gcmkHEADER_ARG("Hardware=0x%x", Hardware);
@@ -4870,25 +4868,6 @@ gckHARDWARE_Reset(
gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
}
- status = gckOS_AcquireMutex(Hardware->os, Hardware->powerMutex, 0);
- if (status == gcvSTATUS_TIMEOUT)
- {
- gcmkONERROR(gckOS_GetProcessID(&process));
- gcmkONERROR(gckOS_GetThreadID(&thread));
-
- if ((Hardware->powerProcess == process)
- && (Hardware->powerThread == thread))
- {
- /* No way to recovery from a error in power management. */
- gcmkFOOTER_NO();
- return gcvSTATUS_OK;
- }
- }
- else
- {
- mutexAcquired = gcvTRUE;
- }
-
if (Hardware->chipPowerState == gcvPOWER_ON)
{
/* Acquire the power management semaphore. */
@@ -4921,9 +4900,7 @@ gckHARDWARE_Reset(
/* Force an OFF to ON power switch. */
Hardware->chipPowerState = gcvPOWER_OFF;
-
- gcmkONERROR(gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex));
- mutexAcquired = gcvFALSE;
+ gcmkONERROR(gckHARDWARE_SetPowerManagementState(Hardware, gcvPOWER_ON));
/* Success. */
gcmkFOOTER_NO();
@@ -4937,11 +4914,6 @@ OnError:
gckOS_ReleaseSemaphore(Hardware->os, command->powerSemaphore));
}
- if (mutexAcquired)
- {
- gckOS_ReleaseMutex(Hardware->os, Hardware->powerMutex);
- }
-
/* Return the error. */
gcmkFOOTER();
return status;
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
index e8cdebb140ae..4d16d182b231 100755
--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
@@ -89,18 +89,6 @@ gctCONST_STRING _DispatchText[] =
};
#endif
-#if gcdENABLE_RECOVERY
-void
-_ResetFinishFunction(
- gctPOINTER Data
- )
-{
- gckKERNEL kernel = (gckKERNEL)Data;
-
- gckOS_AtomSet(kernel->os, kernel->resetAtom, 0);
-}
-#endif
-
/*******************************************************************************
**
** gckKERNEL_Construct
@@ -258,17 +246,6 @@ gckKERNEL_Construct(
/* Construct the gckMMU object. */
gcmkONERROR(
gckMMU_Construct(kernel, gcdMMU_SIZE, &kernel->mmu));
-
-#if gcdENABLE_RECOVERY
- gcmkONERROR(
- gckOS_AtomConstruct(Os, &kernel->resetAtom));
-
- gcmkVERIFY_OK(
- gckOS_CreateTimer(Os,
- (gctPOINTER)_ResetFinishFunction,
- (gctPOINTER)kernel,
- &kernel->resetFlagClearTimer));
-#endif
}
#if VIVANTE_PROFILER
@@ -325,19 +302,6 @@ OnError:
gcmkVERIFY_OK(gckOS_AtomDestroy(Os, kernel->atomClients));
}
-#if gcdENABLE_RECOVERY
- if (kernel->resetAtom != gcvNULL)
- {
- gcmkVERIFY_OK(gckOS_AtomDestroy(Os, kernel->resetAtom));
- }
-
- if (kernel->resetFlagClearTimer)
- {
- gcmkVERIFY_OK(gckOS_StopTimer(Os, kernel->resetFlagClearTimer));
- gcmkVERIFY_OK(gckOS_DestoryTimer(Os, kernel->resetFlagClearTimer));
- }
-#endif
-
if (kernel->dbCreated && kernel->db != gcvNULL)
{
if (kernel->db->dbMutex != gcvNULL)
@@ -445,16 +409,6 @@ gckKERNEL_Destroy(
/* Destroy the gckHARDWARE object. */
gcmkVERIFY_OK(gckHARDWARE_Destroy(Kernel->hardware));
-
-#if gcdENABLE_RECOVERY
- gcmkVERIFY_OK(gckOS_AtomDestroy(Kernel->os, Kernel->resetAtom));
-
- if (Kernel->resetFlagClearTimer)
- {
- gcmkVERIFY_OK(gckOS_StopTimer(Kernel->os, Kernel->resetFlagClearTimer));
- gcmkVERIFY_OK(gckOS_DestoryTimer(Kernel->os, Kernel->resetFlagClearTimer));
- }
-#endif
}
/* Detsroy the client atom. */
@@ -1161,70 +1115,10 @@ gckKERNEL_Dispatch(
break;
case gcvUSER_SIGNAL_WAIT:
-#if gcdGPU_TIMEOUT
- if (Interface->u.UserSignal.wait == gcvINFINITE)
- {
- gckHARDWARE hardware;
- gctUINT32 timer = 0;
-
- for(;;)
- {
- /* Wait on the signal. */
- status = gckOS_WaitUserSignal(Kernel->os,
- Interface->u.UserSignal.id,
- gcdGPU_ADVANCETIMER);
-
- if (status == gcvSTATUS_TIMEOUT)
- {
- gcmkONERROR(
- gckOS_SignalQueryHardware(Kernel->os,
- (gctSIGNAL)Interface->u.UserSignal.id,
- &hardware));
-
- if (hardware)
- {
- /* This signal is bound to a hardware,
- ** so the timeout is limited by gcdGPU_TIMEOUT.
- */
- timer += gcdGPU_ADVANCETIMER;
- }
-
- if (timer >= gcdGPU_TIMEOUT)
- {
- gcmkONERROR(
- gckOS_Broadcast(Kernel->os,
- hardware,
- gcvBROADCAST_GPU_STUCK));
-
- timer = 0;
-
- /* If a few process try to reset GPU, only one
- ** of them can do the real reset, other processes
- ** still need to wait for this signal is triggered,
- ** which menas reset is finished.
- */
- continue;
- }
- }
- else
- {
- /* Bail out on other error. */
- gcmkONERROR(status);
-
- /* Wait for signal successfully. */
- break;
- }
- }
- }
- else
-#endif
- {
/* Wait on the signal. */
status = gckOS_WaitUserSignal(Kernel->os,
Interface->u.UserSignal.id,
Interface->u.UserSignal.wait);
- }
-
break;
case gcvUSER_SIGNAL_MAP:
@@ -2627,7 +2521,7 @@ gckKERNEL_Recovery(
)
{
#if gcdENABLE_RECOVERY
-#define gcdEVENT_MASK 0x3FFFFFFF
+#define gcvEVENT_MASK 0x3FFFFFFF
gceSTATUS status;
gckEVENT eventObj;
gckHARDWARE hardware;
@@ -2635,7 +2529,6 @@ gckKERNEL_Recovery(
gctUINT32 processID;
gcskSECURE_CACHE_PTR cache;
#endif
- gctUINT32 oldValue;
gcmkHEADER_ARG("Kernel=0x%x", Kernel);
@@ -2650,6 +2543,22 @@ gckKERNEL_Recovery(
hardware = Kernel->hardware;
gcmkVERIFY_OBJECT(hardware, gcvOBJ_HARDWARE);
+ /* Handle all outstanding events now. */
+#if gcdSMP
+ gcmkONERROR(gckOS_AtomSet(Kernel->os, eventObj->pending, gcvEVENT_MASK));
+#else
+ eventObj->pending = gcvEVENT_MASK;
+#endif
+ gcmkONERROR(gckEVENT_Notify(eventObj, 1));
+
+ /* Again in case more events got submitted. */
+#if gcdSMP
+ gcmkONERROR(gckOS_AtomSet(Kernel->os, eventObj->pending, gcvEVENT_MASK));
+#else
+ eventObj->pending = gcvEVENT_MASK;
+#endif
+ gcmkONERROR(gckEVENT_Notify(eventObj, 2));
+
#if gcdSECURE_USER
/* Flush the secure mapping cache. */
gcmkONERROR(gckOS_GetProcessID(&processID));
@@ -2657,22 +2566,6 @@ gckKERNEL_Recovery(
gcmkONERROR(gckKERNEL_FlushTranslationCache(Kernel, cache, gcvNULL, 0));
#endif
- gcmkONERROR(
- gckOS_AtomicExchange(Kernel->os, Kernel->resetAtom, 1, &oldValue));
-
- if (oldValue)
- {
- /* Some one else will recovery GPU. */
- return gcvSTATUS_OK;
- }
-
- /* Start a timer to clear reset flag, before timer is expired,
- ** other recovery request is ignored. */
- gcmkVERIFY_OK(
- gckOS_StartTimer(Kernel->os,
- Kernel->resetFlagClearTimer,
- gcdGPU_TIMEOUT - 500));
-
/* Try issuing a soft reset for the GPU. */
status = gckHARDWARE_Reset(hardware);
if (status == gcvSTATUS_NOT_SUPPORTED)
@@ -2689,22 +2582,6 @@ gckKERNEL_Recovery(
gcmkONERROR(status);
}
- /* Handle all outstanding events now. */
-#if gcdSMP
- gcmkONERROR(gckOS_AtomSet(Kernel->os, eventObj->pending, gcdEVENT_MASK));
-#else
- eventObj->pending = gcdEVENT_MASK;
-#endif
- gcmkONERROR(gckEVENT_Notify(eventObj, 1));
-
- /* Again in case more events got submitted. */
-#if gcdSMP
- gcmkONERROR(gckOS_AtomSet(Kernel->os, eventObj->pending, gcdEVENT_MASK));
-#else
- eventObj->pending = gcdEVENT_MASK;
-#endif
- gcmkONERROR(gckEVENT_Notify(eventObj, 2));
-
/* Success. */
gcmkFOOTER_NO();
return gcvSTATUS_OK;
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
index e4322aab2499..b627f3b1d5f9 100755
--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
@@ -338,11 +338,6 @@ struct _gckKERNEL
gckDB db;
gctBOOL dbCreated;
-#if gcdENABLE_RECOVERY
- gctPOINTER resetFlagClearTimer;
- gctPOINTER resetAtom;
-#endif
-
/* Pointer to gckEVENT object. */
gcsTIMER timers[8];
gctUINT32 timeOut;
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
index 2244021a9d28..8cf0509cfd92 100755
--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_command.c
@@ -57,7 +57,6 @@ _NewQueue(
{
gceSTATUS status;
gctINT currentIndex, newIndex;
- gctUINT32 wait = gcdGPU_TIMEOUT ? gcdGPU_TIMEOUT : gcvINFINITE;
gcmkHEADER_ARG("Command=0x%x", Command);
@@ -73,7 +72,7 @@ _NewQueue(
gcmkONERROR(gckOS_WaitSignal(
Command->os,
Command->queues[newIndex].signal,
- wait
+ gcvINFINITE
));
#if gcmIS_DEBUG(gcdDEBUG_TRACE)
@@ -2048,13 +2047,6 @@ OnError:
));
}
- if (status == gcvSTATUS_TIMEOUT)
- {
- status = gckOS_Broadcast(Command->os,
- Command->kernel->hardware,
- gcvBROADCAST_GPU_STUCK);
- }
-
/* Return status. */
gcmkFOOTER();
return status;
diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c
index 6c518488871d..e1b21a0df70b 100755
--- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c
+++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c
@@ -328,12 +328,6 @@ __RemoveRecordFromProcessDB(
Record->info.u.UnmapUserMemory.info));
break;
- case gcvHAL_SIGNAL:
- gcmkVERIFY_OK(gckOS_SignalSetHardware(Event->os,
- Record->info.u.Signal.signal,
- Event->kernel->hardware));
- break;
-
default:
break;
}
@@ -729,6 +723,11 @@ gckEVENT_GetEvent(
__FUNCTION__, __LINE__
);
+ /* Broadcast GPU stuck. */
+ gcmkONERROR(gckOS_Broadcast(Event->os,
+ Event->kernel->hardware,
+ gcvBROADCAST_GPU_STUCK));
+
/* Bail out. */
gcmkONERROR(gcvSTATUS_GPU_NOT_RESPONDING);
}
@@ -1495,14 +1494,6 @@ OnError:
Event->queues[id].head = gcvNULL;
}
- if (status == gcvSTATUS_GPU_NOT_RESPONDING)
- {
- /* Broadcast GPU stuck. */
- status = gckOS_Broadcast(Event->os,
- Event->kernel->hardware,
- gcvBROADCAST_GPU_STUCK);
- }
-
/* Return the status. */
gcmkFOOTER();
return status;
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h
index 4633fa2b621a..25ec3eab95f2 100755
--- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h
@@ -2361,19 +2361,7 @@ gckHARDWARE_QueryProfileRegisters(
);
#endif
-gceSTATUS
-gckOS_SignalQueryHardware(
- IN gckOS Os,
- IN gctSIGNAL Signal,
- OUT gckHARDWARE * Hardware
- );
-gceSTATUS
-gckOS_SignalSetHardware(
- IN gckOS Os,
- IN gctSIGNAL Signal,
- gckHARDWARE Hardware
- );
#ifdef __cplusplus
}
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h
index 94379114c15d..d0298eed15e9 100644
--- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_base.h
@@ -635,10 +635,6 @@ gcoHAL_QueryChipFeature(
#endif
-gceSTATUS
-gcoHAL_WaitSignalFromGPU(
- IN gctSIGNAL Signal
- );
/******************************************************************************\
********************************** gcoOS Object *********************************
diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
index f4d07a2536be..d1ddd004dc3c 100755
--- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
+++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
@@ -380,7 +380,7 @@
# if gcdFPGA_BUILD
# define gcdGPU_TIMEOUT 0
# else
-# define gcdGPU_TIMEOUT 10000
+# define gcdGPU_TIMEOUT (2000 * 5)
# endif
#endif
diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
index da6fcfbe44a0..21e6a22317e5 100755
--- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
+++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
@@ -197,8 +197,6 @@ typedef struct _gcsSIGNAL
/* The owner of the signal. */
gctHANDLE process;
- gckHARDWARE hardware;
-
/* ID. */
gctUINT32 id;
}
@@ -1069,7 +1067,7 @@ _FreeAllNonPagedMemoryCache(
#endif /* gcdUSE_NON_PAGED_MEMORY_CACHE */
- /*******************************************************************************
+/*******************************************************************************
** Integer Id Management.
*/
gceSTATUS
@@ -6519,9 +6517,7 @@ gckOS_Broadcast(
case gcvBROADCAST_GPU_STUCK:
gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_GPU_STUCK\n");
-#if !gcdENABLE_RECOVERY
gcmkONERROR(_DumpGPUState(Os, Hardware->core));
-#endif
gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
break;
@@ -7199,7 +7195,6 @@ gckOS_CreateSignal(
/* Save the process ID. */
signal->process = (gctHANDLE) _GetProcessID();
signal->manualReset = ManualReset;
- signal->hardware = gcvNULL;
init_completion(&signal->obj);
atomic_set(&signal->ref, 1);
@@ -7220,61 +7215,6 @@ OnError:
return status;
}
-gceSTATUS
-gckOS_SignalQueryHardware(
- IN gckOS Os,
- IN gctSIGNAL Signal,
- OUT gckHARDWARE * Hardware
- )
-{
- gceSTATUS status;
- gcsSIGNAL_PTR signal;
-
- gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
-
- /* Verify the arguments. */
- gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
- gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
-
- gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)Signal, (gctPOINTER)&signal));
-
- *Hardware = signal->hardware;
-
- gcmkFOOTER_NO();
- return gcvSTATUS_OK;
-OnError:
- gcmkFOOTER();
- return status;
-}
-
-gceSTATUS
-gckOS_SignalSetHardware(
- IN gckOS Os,
- IN gctSIGNAL Signal,
- IN gckHARDWARE Hardware
- )
-{
- gceSTATUS status;
- gcsSIGNAL_PTR signal;
-
- gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
-
- /* Verify the arguments. */
- gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
- gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
-
- gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)Signal, (gctPOINTER)&signal));
-
- signal->hardware = Hardware;
-
- gcmkFOOTER_NO();
- return gcvSTATUS_OK;
-OnError:
- gcmkFOOTER();
- return status;
-}
-
/*******************************************************************************
**
** gckOS_DestroySignal
@@ -7390,9 +7330,6 @@ gckOS_Signal(
if (State)
{
- /* unbind the signal from hardware. */
- signal->hardware = gcvNULL;
-
/* Set the event to a signaled state. */
complete(&signal->obj);
}
diff --git a/drivers/mxc/hdmi-cec/Kconfig b/drivers/mxc/hdmi-cec/Kconfig
new file mode 100644
index 000000000000..0afc58ada696
--- /dev/null
+++ b/drivers/mxc/hdmi-cec/Kconfig
@@ -0,0 +1,14 @@
+#
+# Codec configuration
+#
+
+menu "MXC HDMI CEC (Consumer Electronics Control) support"
+
+config MXC_HDMI_CEC
+ tristate "Support for MXC HDMI CEC (Consumer Electronics Control)"
+ depends on (ARCH_MX6)
+ select MFD_MXC_HDMI
+ ---help---
+ The HDMI CEC device implement low level protocol on i.MX6x platforms.
+
+endmenu
diff --git a/drivers/mxc/hdmi-cec/Makefile b/drivers/mxc/hdmi-cec/Makefile
new file mode 100644
index 000000000000..86cf269879ab
--- /dev/null
+++ b/drivers/mxc/hdmi-cec/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the HDMI CEC drivers.
+#
+
+obj-$(CONFIG_MXC_HDMI_CEC) += mxc_hdmi-cec.o
+
diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c
new file mode 100644
index 000000000000..011fc33ab17e
--- /dev/null
+++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.c
@@ -0,0 +1,584 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*!
+ * @file mxc_hdmi-cec.c
+ *
+ * @brief HDMI CEC system initialization and file operation implementation
+ *
+ * @ingroup HDMI
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/fs.h> /* for struct file_operations */
+#include <linux/stat.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/fsl_devices.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/workqueue.h>
+#include <asm/sizes.h>
+
+#include <linux/console.h>
+#include <linux/types.h>
+#include <linux/mfd/mxc-hdmi-core.h>
+
+#include <mach/mxc_edid.h>
+#include <mach/mxc_hdmi.h>
+
+#include "mxc_hdmi-cec.h"
+
+
+#define MAX_MESSAGE_LEN 17
+
+#define MESSAGE_TYPE_RECEIVE_SUCCESS 1
+#define MESSAGE_TYPE_NOACK 2
+#define MESSAGE_TYPE_DISCONNECTED 3
+#define MESSAGE_TYPE_CONNECTED 4
+#define MESSAGE_TYPE_SEND_SUCCESS 5
+
+
+struct hdmi_cec_priv {
+ int receive_error;
+ int send_error;
+ u8 Logical_address;
+ bool cec_state;
+ u8 last_msg[MAX_MESSAGE_LEN];
+ u8 msg_len;
+ u8 latest_cec_stat;
+ u32 cec_irq;
+ spinlock_t irq_lock;
+ struct delayed_work hdmi_cec_work;
+ struct mutex lock;
+};
+
+struct hdmi_cec_event {
+ int event_type;
+ int msg_len;
+ u8 msg[MAX_MESSAGE_LEN];
+ struct list_head list;
+};
+
+
+static LIST_HEAD(head);
+
+static int hdmi_cec_major;
+static struct class *hdmi_cec_class;
+static struct hdmi_cec_priv hdmi_cec_data;
+static u8 open_count;
+
+static wait_queue_head_t hdmi_cec_queue;
+static irqreturn_t mxc_hdmi_cec_isr(int irq, void *data)
+{
+ struct hdmi_cec_priv *hdmi_cec = data;
+ u8 cec_stat = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&hdmi_cec->irq_lock, flags);
+
+ hdmi_writeb(0x7f, HDMI_IH_MUTE_CEC_STAT0);
+
+ cec_stat = hdmi_readb(HDMI_IH_CEC_STAT0);
+ hdmi_writeb(cec_stat, HDMI_IH_CEC_STAT0);
+ if ((cec_stat & (HDMI_IH_CEC_STAT0_ERROR_INIT | \
+ HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM | \
+ HDMI_IH_CEC_STAT0_DONE)) == 0) {
+ spin_unlock_irqrestore(&hdmi_cec->irq_lock, flags);
+ return IRQ_HANDLED;
+ }
+ pr_debug("HDMI CEC interrupt received\n");
+ hdmi_cec->latest_cec_stat = cec_stat;
+
+ schedule_delayed_work(&(hdmi_cec->hdmi_cec_work), msecs_to_jiffies(20));
+
+ spin_unlock_irqrestore(&hdmi_cec->irq_lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+void mxc_hdmi_cec_handle(u16 cec_stat)
+{
+ u8 val = 0, i = 0;
+ struct hdmi_cec_event *event = NULL;
+ /*The current transmission is successful (for initiator only).*/
+ if (!open_count)
+ return;
+
+ if (cec_stat & HDMI_IH_CEC_STAT0_DONE) {
+ event = vmalloc(sizeof(struct hdmi_cec_event));
+ if (NULL == event) {
+ pr_err("%s:Don't get memory!\n", __func__);
+ return;
+ }
+ memset(event, 0, sizeof(struct hdmi_cec_event));
+ event->event_type = MESSAGE_TYPE_SEND_SUCCESS;
+ mutex_lock(&hdmi_cec_data.lock);
+ list_add_tail(&event->list, &head);
+ mutex_unlock(&hdmi_cec_data.lock);
+ wake_up(&hdmi_cec_queue);
+ }
+ /*EOM is detected so that the received data is ready in the receiver data buffer*/
+ else if (cec_stat & HDMI_IH_CEC_STAT0_EOM) {
+ hdmi_writeb(0x02, HDMI_IH_CEC_STAT0);
+ event = vmalloc(sizeof(struct hdmi_cec_event));
+ if (NULL == event) {
+ pr_err("%s:Don't get memory!\n", __func__);
+ return;
+ }
+ memset(event, 0, sizeof(struct hdmi_cec_event));
+ event->msg_len = hdmi_readb(HDMI_CEC_RX_CNT);
+ if (!event->msg_len) {
+ pr_err("%s: Invalid CEC message length!\n", __func__);
+ return;
+ }
+ event->event_type = MESSAGE_TYPE_RECEIVE_SUCCESS;
+ for (i = 0; i < event->msg_len; i++)
+ event->msg[i] = hdmi_readb(HDMI_CEC_RX_DATA0+i);
+ hdmi_writeb(0x0, HDMI_CEC_LOCK);
+ mutex_lock(&hdmi_cec_data.lock);
+ list_add_tail(&event->list, &head);
+ mutex_unlock(&hdmi_cec_data.lock);
+ wake_up(&hdmi_cec_queue);
+ }
+ /*An error is detected on cec line (for initiator only). */
+ else if (cec_stat & HDMI_IH_CEC_STAT0_ERROR_INIT) {
+ mutex_lock(&hdmi_cec_data.lock);
+ hdmi_cec_data.send_error++;
+ if (hdmi_cec_data.send_error > 5) {
+ pr_err("%s:Re-transmission is attempted more than 5 times!\n", __func__);
+ hdmi_cec_data.send_error = 0;
+ mutex_unlock(&hdmi_cec_data.lock);
+ return;
+ }
+ for (i = 0; i < hdmi_cec_data.msg_len; i++)
+ hdmi_writeb(hdmi_cec_data.last_msg[i], HDMI_CEC_TX_DATA0+i);
+ hdmi_writeb(hdmi_cec_data.msg_len, HDMI_CEC_TX_CNT);
+ val = hdmi_readb(HDMI_CEC_CTRL);
+ val |= 0x01;
+ hdmi_writeb(val, HDMI_CEC_CTRL);
+ mutex_unlock(&hdmi_cec_data.lock);
+ }
+ /*A frame is not acknowledged in a directly addressed message. Or a frame is negatively acknowledged in
+ a broadcast message (for initiator only).*/
+ else if (cec_stat & HDMI_IH_CEC_STAT0_NACK) {
+ event = vmalloc(sizeof(struct hdmi_cec_event));
+ if (NULL == event) {
+ pr_err("%s:Don't get memory!\n", __func__);
+ return;
+ }
+ memset(event, 0, sizeof(struct hdmi_cec_event));
+ event->event_type = MESSAGE_TYPE_NOACK;
+ mutex_lock(&hdmi_cec_data.lock);
+ list_add_tail(&event->list, &head);
+ mutex_unlock(&hdmi_cec_data.lock);
+ wake_up(&hdmi_cec_queue);
+ }
+ /*An error is notified by a follower. Abnormal logic data bit error (for follower).*/
+ else if (cec_stat & HDMI_IH_CEC_STAT0_ERROR_FOLL)
+ hdmi_cec_data.receive_error++;
+ /*HDMI cable connected*/
+ else if (cec_stat & 0x80) {
+ event = vmalloc(sizeof(struct hdmi_cec_event));
+ if (NULL == event) {
+ pr_err("%s:Don't get memory!\n", __func__);
+ return;
+ }
+ memset(event, 0, sizeof(struct hdmi_cec_event));
+ event->event_type = MESSAGE_TYPE_CONNECTED;
+ mutex_lock(&hdmi_cec_data.lock);
+ list_add_tail(&event->list, &head);
+ mutex_unlock(&hdmi_cec_data.lock);
+ wake_up(&hdmi_cec_queue);
+ }
+ /*HDMI cable disconnected*/
+ else if (cec_stat & 0x100) {
+ event = vmalloc(sizeof(struct hdmi_cec_event));
+ if (NULL == event) {
+ pr_err("%s:Don't get memory!\n", __func__);
+ return;
+ }
+ memset(event, 0, sizeof(struct hdmi_cec_event));
+ event->event_type = MESSAGE_TYPE_DISCONNECTED;
+ mutex_lock(&hdmi_cec_data.lock);
+ list_add_tail(&event->list, &head);
+ mutex_unlock(&hdmi_cec_data.lock);
+ wake_up(&hdmi_cec_queue);
+ }
+ return;
+}
+EXPORT_SYMBOL(mxc_hdmi_cec_handle);
+static void mxc_hdmi_cec_worker(struct work_struct *work)
+{
+ u8 val;
+ mxc_hdmi_cec_handle(hdmi_cec_data.latest_cec_stat);
+ val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL | HDMI_IH_CEC_STAT0_ARB_LOST;
+ hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0);
+}
+
+/*!
+ * @brief open function for vpu file operation
+ *
+ * @return 0 on success or negative error code on error
+ */
+static int hdmi_cec_open(struct inode *inode, struct file *filp)
+{
+ mutex_lock(&hdmi_cec_data.lock);
+ if (open_count) {
+ mutex_unlock(&hdmi_cec_data.lock);
+ return -EBUSY;
+ }
+ open_count = 1;
+ filp->private_data = (void *)(&hdmi_cec_data);
+ hdmi_cec_data.Logical_address = 15;
+ hdmi_cec_data.cec_state = false;
+ mutex_unlock(&hdmi_cec_data.lock);
+ return 0;
+}
+static ssize_t hdmi_cec_read(struct file *file, char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ struct hdmi_cec_event *event = NULL;
+ pr_debug("function : %s\n", __func__);
+ if (!open_count)
+ return -ENODEV;
+ mutex_lock(&hdmi_cec_data.lock);
+ if (false == hdmi_cec_data.cec_state) {
+ mutex_unlock(&hdmi_cec_data.lock);
+ return -EACCES;
+ }
+ mutex_unlock(&hdmi_cec_data.lock);
+ /* delete from list */
+ mutex_lock(&hdmi_cec_data.lock);
+ if (list_empty(&head)) {
+ mutex_unlock(&hdmi_cec_data.lock);
+ return -EACCES;
+ }
+ event = list_first_entry(&head, struct hdmi_cec_event, list);
+ list_del(&event->list);
+ mutex_unlock(&hdmi_cec_data.lock);
+ if (copy_to_user(buf,
+ event,
+ sizeof(struct hdmi_cec_event) - sizeof(struct list_head))) {
+ vfree(event);
+ return -EFAULT;
+ }
+ vfree(event);
+ return sizeof(struct hdmi_cec_event);
+}
+static ssize_t hdmi_cec_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ int ret = 0 , i = 0;
+ u8 msg[MAX_MESSAGE_LEN];
+ u8 msg_len = 0, val = 0;
+ pr_debug("function : %s\n", __func__);
+ if (!open_count)
+ return -ENODEV;
+ mutex_lock(&hdmi_cec_data.lock);
+ if (false == hdmi_cec_data.cec_state) {
+ mutex_unlock(&hdmi_cec_data.lock);
+ return -EACCES;
+ }
+ mutex_unlock(&hdmi_cec_data.lock);
+ if (count > MAX_MESSAGE_LEN)
+ return -EINVAL;
+ mutex_lock(&hdmi_cec_data.lock);
+ hdmi_cec_data.send_error = 0;
+ memset(&msg, 0, MAX_MESSAGE_LEN);
+ ret = copy_from_user(&msg, buf, count);
+ if (ret) {
+ ret = -EACCES;
+ goto end;
+ }
+ msg_len = count;
+ hdmi_writeb(msg_len, HDMI_CEC_TX_CNT);
+ for (i = 0; i < msg_len; i++)
+ hdmi_writeb(msg[i], HDMI_CEC_TX_DATA0+i);
+ val = hdmi_readb(HDMI_CEC_CTRL);
+ val |= 0x01;
+ hdmi_writeb(val, HDMI_CEC_CTRL);
+ memcpy(hdmi_cec_data.last_msg, msg, msg_len);
+ hdmi_cec_data.msg_len = msg_len;
+ i = 0;
+ val = hdmi_readb(HDMI_CEC_CTRL);
+ while ((val & 0x01) == 0x1) {
+ msleep(50);
+ i++;
+ if (i > 3) {
+ ret = -EIO;
+ goto end;
+ }
+ val = hdmi_readb(HDMI_CEC_CTRL);
+ }
+end:
+ mutex_unlock(&hdmi_cec_data.lock);
+ return ret;
+}
+
+
+/*!
+ * @brief IO ctrl function for vpu file operation
+ * @param cmd IO ctrl command
+ * @return 0 on success or negative error code on error
+ */
+static long hdmi_cec_ioctl(struct file *filp, u_int cmd,
+ u_long arg)
+{
+ int ret = 0, status = 0;
+ u8 val = 0, msg = 0;
+ struct mxc_edid_cfg hdmi_edid_cfg;
+ pr_debug("function : %s\n", __func__);
+ if (!open_count)
+ return -ENODEV;
+ switch (cmd) {
+ case HDMICEC_IOC_SETLOGICALADDRESS:
+ mutex_lock(&hdmi_cec_data.lock);
+ if (false == hdmi_cec_data.cec_state) {
+ mutex_unlock(&hdmi_cec_data.lock);
+ return -EACCES;
+ }
+ hdmi_cec_data.Logical_address = (u8)arg;
+ if (hdmi_cec_data.Logical_address <= 7) {
+ val = 1 << hdmi_cec_data.Logical_address;
+ hdmi_writeb(val, HDMI_CEC_ADDR_L);
+ hdmi_writeb(0, HDMI_CEC_ADDR_H);
+ } else if (hdmi_cec_data.Logical_address > 7 && hdmi_cec_data.Logical_address <= 15) {
+ val = 1 << (hdmi_cec_data.Logical_address - 8);
+ hdmi_writeb(val, HDMI_CEC_ADDR_H);
+ hdmi_writeb(0, HDMI_CEC_ADDR_L);
+ } else
+ ret = -EINVAL;
+ /*Send Polling message with same source and destination address*/
+ if (0 == ret && 15 != hdmi_cec_data.Logical_address) {
+ msg = (hdmi_cec_data.Logical_address << 4)|hdmi_cec_data.Logical_address;
+ hdmi_writeb(1, HDMI_CEC_TX_CNT);
+ hdmi_writeb(msg, HDMI_CEC_TX_DATA0);
+ val = hdmi_readb(HDMI_CEC_CTRL);
+ val |= 0x01;
+ hdmi_writeb(val, HDMI_CEC_CTRL);
+ }
+ mutex_unlock(&hdmi_cec_data.lock);
+ break;
+ case HDMICEC_IOC_STARTDEVICE:
+ val = hdmi_readb(HDMI_MC_CLKDIS);
+ val &= ~HDMI_MC_CLKDIS_CECCLK_DISABLE;
+ hdmi_writeb(val, HDMI_MC_CLKDIS);
+ hdmi_writeb(0x02, HDMI_CEC_CTRL);
+ val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL | HDMI_IH_CEC_STAT0_ARB_LOST;
+ hdmi_writeb(val, HDMI_CEC_MASK);
+ hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0);
+ val = HDMI_IH_CEC_STAT0_ERROR_INIT | HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM | HDMI_IH_CEC_STAT0_DONE;
+ hdmi_writeb(val, HDMI_CEC_POLARITY);
+ mutex_lock(&hdmi_cec_data.lock);
+ hdmi_cec_data.cec_state = true;
+ mutex_unlock(&hdmi_cec_data.lock);
+ break;
+ case HDMICEC_IOC_STOPDEVICE:
+ hdmi_writeb(0x10, HDMI_CEC_CTRL);
+ val = HDMI_IH_CEC_STAT0_WAKEUP | HDMI_IH_CEC_STAT0_ERROR_FOLL | HDMI_IH_CEC_STAT0_ERROR_INIT | HDMI_IH_CEC_STAT0_ARB_LOST | \
+ HDMI_IH_CEC_STAT0_NACK | HDMI_IH_CEC_STAT0_EOM | HDMI_IH_CEC_STAT0_DONE;
+ hdmi_writeb(val, HDMI_CEC_MASK);
+ hdmi_writeb(val, HDMI_IH_MUTE_CEC_STAT0);
+ hdmi_writeb(0x0, HDMI_CEC_POLARITY);
+ val = hdmi_readb(HDMI_MC_CLKDIS);
+ val |= HDMI_MC_CLKDIS_CECCLK_DISABLE;
+ hdmi_writeb(val, HDMI_MC_CLKDIS);
+ mutex_lock(&hdmi_cec_data.lock);
+ hdmi_cec_data.cec_state = false;
+ mutex_unlock(&hdmi_cec_data.lock);
+ break;
+ case HDMICEC_IOC_GETPHYADDRESS:
+ hdmi_get_edid_cfg(&hdmi_edid_cfg);
+ status = copy_to_user((void __user *)arg,
+ &hdmi_edid_cfg.physical_address,
+ 4*sizeof(u8));
+ if (status)
+ ret = -EFAULT;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+/*!
+ * @brief Release function for vpu file operation
+ * @return 0 on success or negative error code on error
+ */
+static int hdmi_cec_release(struct inode *inode, struct file *filp)
+{
+ mutex_lock(&hdmi_cec_data.lock);
+ if (open_count) {
+ open_count = 0;
+ hdmi_cec_data.cec_state = false;
+ hdmi_cec_data.Logical_address = 15;
+ }
+ mutex_unlock(&hdmi_cec_data.lock);
+
+ return 0;
+}
+
+static unsigned int hdmi_cec_poll(struct file *file, poll_table *wait)
+{
+ unsigned int mask = 0;
+
+ pr_debug("function : %s\n", __func__);
+
+ if (!open_count)
+ return -ENODEV;
+ if (false == hdmi_cec_data.cec_state)
+ return -EACCES;
+
+ poll_wait(file, &hdmi_cec_queue, wait);
+
+ if (!list_empty(&head))
+ mask |= (POLLIN | POLLRDNORM);
+ return mask;
+}
+
+
+const struct file_operations hdmi_cec_fops = {
+ .owner = THIS_MODULE,
+ .read = hdmi_cec_read,
+ .write = hdmi_cec_write,
+ .open = hdmi_cec_open,
+ .unlocked_ioctl = hdmi_cec_ioctl,
+ .release = hdmi_cec_release,
+ .poll = hdmi_cec_poll,
+};
+
+static int hdmi_cec_dev_probe(struct platform_device *pdev)
+{
+ int err = 0;
+ struct device *temp_class;
+ struct resource *res;
+
+ hdmi_cec_major = register_chrdev(hdmi_cec_major, "mxc_hdmi_cec", &hdmi_cec_fops);
+ if (hdmi_cec_major < 0) {
+ pr_err("hdmi_cec: unable to get a major for HDMI CEC\n");
+ err = -EBUSY;
+ goto out;
+ }
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (unlikely(res == NULL)) {
+ pr_err("hdmi_cec:No HDMI irq line provided\n");
+ goto err_out_chrdev;
+ }
+ spin_lock_init(&hdmi_cec_data.irq_lock);
+ hdmi_cec_data.cec_irq = res->start;
+
+ err = request_irq(hdmi_cec_data.cec_irq, mxc_hdmi_cec_isr, IRQF_SHARED,
+ "mxc_hdmi_cec", &hdmi_cec_data);
+ if (err < 0) {
+ pr_err("hdmi_cec:Unable to request irq: %d\n", err);
+ goto err_out_chrdev;
+ }
+
+ hdmi_cec_class = class_create(THIS_MODULE, "mxc_hdmi_cec");
+ if (IS_ERR(hdmi_cec_class)) {
+ err = PTR_ERR(hdmi_cec_class);
+ goto err_out_chrdev;
+ }
+
+ temp_class = device_create(hdmi_cec_class, NULL, MKDEV(hdmi_cec_major, 0),
+ NULL, "mxc_hdmi_cec");
+ if (IS_ERR(temp_class)) {
+ err = PTR_ERR(temp_class);
+ goto err_out_class;
+ }
+
+ mutex_init(&hdmi_cec_data.lock);
+ hdmi_cec_data.Logical_address = 15;
+ platform_set_drvdata(pdev, &hdmi_cec_data);
+ INIT_DELAYED_WORK(&hdmi_cec_data.hdmi_cec_work, mxc_hdmi_cec_worker);
+ printk(KERN_INFO "HDMI CEC initialized\n");
+ goto out;
+
+err_out_class:
+ device_destroy(hdmi_cec_class, MKDEV(hdmi_cec_major, 0));
+ class_destroy(hdmi_cec_class);
+err_out_chrdev:
+ unregister_chrdev(hdmi_cec_major, "mxc_hdmi_cec");
+out:
+ return err;
+}
+
+static int hdmi_cec_dev_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int hdmi_cec_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ return 0;
+}
+
+static int hdmi_cec_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+#else
+#define hdmi_cec_suspend NULL
+#define hdmi_cec_resume NULL
+#endif /* !CONFIG_PM */
+
+/*! Driver definition
+ *
+ */
+static struct platform_driver mxc_hdmi_cec_driver = {
+ .driver = {
+ .name = "mxc_hdmi_cec",
+ },
+ .probe = hdmi_cec_dev_probe,
+ .remove = hdmi_cec_dev_remove,
+ .suspend = hdmi_cec_suspend,
+ .resume = hdmi_cec_resume,
+};
+
+static int __init hdmi_cec_init(void)
+{
+ int ret = platform_driver_register(&mxc_hdmi_cec_driver);
+
+ init_waitqueue_head(&hdmi_cec_queue);
+ INIT_LIST_HEAD(&head);
+ return ret;
+}
+
+static void __exit hdmi_cec_exit(void)
+{
+ if (hdmi_cec_major > 0) {
+ device_destroy(hdmi_cec_class, MKDEV(hdmi_cec_major, 0));
+ class_destroy(hdmi_cec_class);
+ unregister_chrdev(hdmi_cec_major, "mxc_vpu");
+ hdmi_cec_major = 0;
+ }
+
+ platform_driver_unregister(&mxc_hdmi_cec_driver);
+ return;
+}
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("Linux HDMI CEC driver for Freescale i.MX/MXC");
+MODULE_LICENSE("GPL");
+
+module_init(hdmi_cec_init);
+module_exit(hdmi_cec_exit);
diff --git a/drivers/mxc/hdmi-cec/mxc_hdmi-cec.h b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.h
new file mode 100644
index 000000000000..a95b4cedf0c8
--- /dev/null
+++ b/drivers/mxc/hdmi-cec/mxc_hdmi-cec.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef _HDMICEC_H_
+#define _HDMICEC_H_
+#include <linux/ioctl.h> /* needed for the _IOW etc stuff used later */
+
+
+/*
+ * Ioctl definitions
+ */
+
+/* Use 'k' as magic number */
+#define HDMICEC_IOC_MAGIC 'H'
+/*
+ * S means "Set" through a ptr,
+ * T means "Tell" directly with the argument value
+ * G means "Get": reply by setting through a pointer
+ * Q means "Query": response is on the return value
+ * X means "eXchange": G and S atomically
+ * H means "sHift": T and Q atomically
+ */
+#define HDMICEC_IOC_SETLOGICALADDRESS _IOW(HDMICEC_IOC_MAGIC, 1, unsigned char)
+#define HDMICEC_IOC_STARTDEVICE _IO(HDMICEC_IOC_MAGIC, 2)
+#define HDMICEC_IOC_STOPDEVICE _IO(HDMICEC_IOC_MAGIC, 3)
+#define HDMICEC_IOC_GETPHYADDRESS _IOR(HDMICEC_IOC_MAGIC, 4, unsigned char[4])
+
+#endif /* !_HDMICEC_H_ */
diff --git a/drivers/mxc/ipu3/ipu_device.c b/drivers/mxc/ipu3/ipu_device.c
index 3899b89bef40..8c5aef0a8408 100644
--- a/drivers/mxc/ipu3/ipu_device.c
+++ b/drivers/mxc/ipu3/ipu_device.c
@@ -782,13 +782,14 @@ static void update_offset(unsigned int fmt,
*stride = width * bytes_per_pixel(fmt);
}
-static int update_split_setting(struct ipu_task_entry *t)
+static int update_split_setting(struct ipu_task_entry *t, bool vdi_split)
{
struct stripe_param left_stripe;
struct stripe_param right_stripe;
struct stripe_param up_stripe;
struct stripe_param down_stripe;
u32 iw, ih, ow, oh;
+ u32 max_width;
if (t->output.rotate >= IPU_ROTATE_90_RIGHT)
return IPU_CHECK_ERR_SPLIT_WITH_ROT;
@@ -800,9 +801,13 @@ static int update_split_setting(struct ipu_task_entry *t)
oh = t->output.crop.h;
if (t->set.split_mode & RL_SPLIT) {
+ if (vdi_split)
+ max_width = soc_max_vdi_in_width();
+ else
+ max_width = soc_max_out_width();
ipu_calc_stripes_sizes(iw,
ow,
- soc_max_out_width(),
+ max_width,
(((unsigned long long)1) << 32), /* 32bit for fractional*/
1, /* equal stripes */
t->input.format,
@@ -871,6 +876,7 @@ static int check_task(struct ipu_task_entry *t)
int tmp;
int ret = IPU_CHECK_OK;
int timeout;
+ bool vdi_split = false;
if ((IPU_PIX_FMT_TILED_NV12 == t->overlay.format) ||
(IPU_PIX_FMT_TILED_NV12F == t->overlay.format) ||
@@ -1027,6 +1033,11 @@ static int check_task(struct ipu_task_entry *t)
t->set.split_mode |= RL_SPLIT;
if (t->output.crop.h > soc_max_out_height())
t->set.split_mode |= UD_SPLIT;
+ if (!t->set.split_mode && (t->set.mode & VDI_MODE) &&
+ (t->input.crop.w > soc_max_vdi_in_width())) {
+ t->set.split_mode |= RL_SPLIT;
+ vdi_split = true;
+ }
if (t->set.split_mode) {
if ((t->set.split_mode == RL_SPLIT) ||
(t->set.split_mode == UD_SPLIT))
@@ -1036,7 +1047,7 @@ static int check_task(struct ipu_task_entry *t)
if (t->timeout < timeout)
t->timeout = timeout;
- ret = update_split_setting(t);
+ ret = update_split_setting(t, vdi_split);
if (ret > IPU_CHECK_ERR_MIN)
goto done;
}
diff --git a/drivers/mxc/vpu/mxc_vpu.c b/drivers/mxc/vpu/mxc_vpu.c
index 4574208fefb8..0d36a25d8850 100644
--- a/drivers/mxc/vpu/mxc_vpu.c
+++ b/drivers/mxc/vpu/mxc_vpu.c
@@ -39,6 +39,7 @@
#include <linux/workqueue.h>
#include <linux/sched.h>
#include <linux/vmalloc.h>
+#include <linux/regulator/consumer.h>
#include <linux/page-flags.h>
#include <linux/mm_types.h>
#include <linux/types.h>
@@ -231,11 +232,8 @@ static irqreturn_t vpu_jpu_irq_handler(int irq, void *dev_id)
*
* @return true return is a valid phy memory address, false return not.
*/
-bool vpu_is_valid_phy_memory(u32 vaddr, u32 paddr, u32 size)
+bool vpu_is_valid_phy_memory(u32 paddr)
{
- if (virt_addr_valid((void *)vaddr) && is_vmalloc_addr((void *)vaddr))
- return false;
-
if (paddr > top_address_DRAM)
return false;
@@ -249,8 +247,19 @@ bool vpu_is_valid_phy_memory(u32 vaddr, u32 paddr, u32 size)
*/
static int vpu_open(struct inode *inode, struct file *filp)
{
+ struct regulator *vpu_regulator;
+
mutex_lock(&vpu_data.lock);
- open_count++;
+
+ if (open_count++ == 0) {
+ vpu_regulator = regulator_get(NULL, "cpu_vddvpu");
+ if (IS_ERR(vpu_regulator))
+ printk(KERN_ERR
+ "%s: failed to get vpu regulator\n", __func__);
+ else
+ regulator_enable(vpu_regulator);
+ }
+
filp->private_data = (void *)(&vpu_data);
mutex_unlock(&vpu_data.lock);
return 0;
@@ -502,13 +511,10 @@ static long vpu_ioctl(struct file *filp, u_int cmd,
ret = -EFAULT;
break;
}
- check_memory.virt_uaddr = (u32)__va(check_memory.phy_addr);
- ret = vpu_is_valid_phy_memory((u32)check_memory.virt_uaddr,
- (u32)check_memory.phy_addr,
- check_memory.size);
- pr_debug("vpu: memory phy:0x%x va:0x%x %s phy memory\n",
- check_memory.phy_addr, check_memory.virt_uaddr,
- (ret ? "is" : "isn't"));
+ ret = vpu_is_valid_phy_memory((u32)check_memory.phy_addr);
+
+ pr_debug("vpu: memory phy:0x%x %s phy memory\n",
+ check_memory.phy_addr, (ret ? "is" : "isn't"));
/* borrow .size to pass back the result. */
check_memory.size = ret;
ret = copy_to_user((void __user *)arg, &check_memory,
@@ -522,6 +528,7 @@ static long vpu_ioctl(struct file *filp, u_int cmd,
default:
{
printk(KERN_ERR "No such IOCTL, cmd is %d\n", cmd);
+ ret = -EINVAL;
break;
}
}
@@ -534,8 +541,18 @@ static long vpu_ioctl(struct file *filp, u_int cmd,
*/
static int vpu_release(struct inode *inode, struct file *filp)
{
+ struct regulator *vpu_regulator;
+
mutex_lock(&vpu_data.lock);
if (open_count > 0 && !(--open_count)) {
+
+ vpu_regulator = regulator_get(NULL, "cpu_vddvpu");
+ if (IS_ERR(vpu_regulator))
+ printk(KERN_ERR
+ "%s: failed to get vpu regulator\n", __func__);
+ else
+ regulator_disable(vpu_regulator);
+
vpu_free_buffers();
/* Free shared memory when vpu device is idle */
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 8cc22568ebd3..41afc408077d 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -1842,7 +1842,7 @@ vortex_timer(unsigned long data)
ok = 1;
}
- if (!netif_carrier_ok(dev))
+ if (dev->flags & IFF_SLAVE || !netif_carrier_ok(dev))
next_tick = 5*HZ;
if (vp->medialock)
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 10c45051caea..a8b82da3956e 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -992,6 +992,11 @@ static inline void cp_start_hw (struct cp_private *cp)
cpw8(Cmd, RxOn | TxOn);
}
+static void cp_enable_irq(struct cp_private *cp)
+{
+ cpw16_f(IntrMask, cp_intr_mask);
+}
+
static void cp_init_hw (struct cp_private *cp)
{
struct net_device *dev = cp->dev;
@@ -1031,8 +1036,6 @@ static void cp_init_hw (struct cp_private *cp)
cpw16(MultiIntr, 0);
- cpw16_f(IntrMask, cp_intr_mask);
-
cpw8_f(Cfg9346, Cfg9346_Lock);
}
@@ -1164,6 +1167,8 @@ static int cp_open (struct net_device *dev)
if (rc)
goto err_out_hw;
+ cp_enable_irq(cp);
+
netif_carrier_off(dev);
mii_check_media(&cp->mii_if, netif_msg_link(cp), true);
netif_start_queue(dev);
@@ -2052,6 +2057,7 @@ static int cp_resume (struct pci_dev *pdev)
/* FIXME: sh*t may happen if the Rx ring buffer is depleted */
cp_init_rings_index (cp);
cp_init_hw (cp);
+ cp_enable_irq(cp);
netif_start_queue (dev);
spin_lock_irqsave (&cp->lock, flags);
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 2eb7e3d69eb5..b31778aee935 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2573,7 +2573,7 @@ config S6GMAC
source "drivers/net/stmmac/Kconfig"
config PCH_GBE
- tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GbE"
+ tristate "Intel EG20T PCH/OKI SEMICONDUCTOR IOH(ML7223/ML7831) GbE"
depends on PCI
select MII
---help---
@@ -2586,10 +2586,11 @@ config PCH_GBE
This driver enables Gigabit Ethernet function.
This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
- Output Hub), ML7223.
- ML7223 IOH is for MP(Media Phone) use.
- ML7223 is companion chip for Intel Atom E6xx series.
- ML7223 is completely compatible for Intel EG20T PCH.
+ Output Hub), ML7223/ML7831.
+ ML7223 IOH is for MP(Media Phone) use. ML7831 IOH is for general
+ purpose use.
+ ML7223/ML7831 is companion chip for Intel Atom E6xx series.
+ ML7223/ML7831 is completely compatible for Intel EG20T PCH.
endif # NETDEV_1000
diff --git a/drivers/net/atl1c/atl1c_main.c b/drivers/net/atl1c/atl1c_main.c
index 1269ba5d6e56..5e34e21f8889 100644
--- a/drivers/net/atl1c/atl1c_main.c
+++ b/drivers/net/atl1c/atl1c_main.c
@@ -2223,10 +2223,6 @@ static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb,
dev_info(&adapter->pdev->dev, "tx locked\n");
return NETDEV_TX_LOCKED;
}
- if (skb->mark == 0x01)
- type = atl1c_trans_high;
- else
- type = atl1c_trans_normal;
if (atl1c_tpd_avail(adapter, type) < tpd_req) {
/* no enough descriptor, just stop queue */
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
index cd5789ff3726..48c27d34eacd 100644
--- a/drivers/net/atlx/atl1.c
+++ b/drivers/net/atlx/atl1.c
@@ -2476,7 +2476,7 @@ static irqreturn_t atl1_intr(int irq, void *data)
"pcie phy link down %x\n", status);
if (netif_running(adapter->netdev)) { /* reset MAC */
iowrite32(0, adapter->hw.hw_addr + REG_IMR);
- schedule_work(&adapter->pcie_dma_to_rst_task);
+ schedule_work(&adapter->reset_dev_task);
return IRQ_HANDLED;
}
}
@@ -2488,7 +2488,7 @@ static irqreturn_t atl1_intr(int irq, void *data)
"pcie DMA r/w error (status = 0x%x)\n",
status);
iowrite32(0, adapter->hw.hw_addr + REG_IMR);
- schedule_work(&adapter->pcie_dma_to_rst_task);
+ schedule_work(&adapter->reset_dev_task);
return IRQ_HANDLED;
}
@@ -2633,10 +2633,10 @@ static void atl1_down(struct atl1_adapter *adapter)
atl1_clean_rx_ring(adapter);
}
-static void atl1_tx_timeout_task(struct work_struct *work)
+static void atl1_reset_dev_task(struct work_struct *work)
{
struct atl1_adapter *adapter =
- container_of(work, struct atl1_adapter, tx_timeout_task);
+ container_of(work, struct atl1_adapter, reset_dev_task);
struct net_device *netdev = adapter->netdev;
netif_device_detach(netdev);
@@ -3034,12 +3034,10 @@ static int __devinit atl1_probe(struct pci_dev *pdev,
(unsigned long)adapter);
adapter->phy_timer_pending = false;
- INIT_WORK(&adapter->tx_timeout_task, atl1_tx_timeout_task);
+ INIT_WORK(&adapter->reset_dev_task, atl1_reset_dev_task);
INIT_WORK(&adapter->link_chg_task, atlx_link_chg_task);
- INIT_WORK(&adapter->pcie_dma_to_rst_task, atl1_tx_timeout_task);
-
err = register_netdev(netdev);
if (err)
goto err_common;
diff --git a/drivers/net/atlx/atl1.h b/drivers/net/atlx/atl1.h
index 68de8cbfb3ec..c27b724a834b 100644
--- a/drivers/net/atlx/atl1.h
+++ b/drivers/net/atlx/atl1.h
@@ -759,9 +759,8 @@ struct atl1_adapter {
u16 link_speed;
u16 link_duplex;
spinlock_t lock;
- struct work_struct tx_timeout_task;
+ struct work_struct reset_dev_task;
struct work_struct link_chg_task;
- struct work_struct pcie_dma_to_rst_task;
struct timer_list phy_config_timer;
bool phy_timer_pending;
diff --git a/drivers/net/atlx/atlx.c b/drivers/net/atlx/atlx.c
index afb7f7dd1bb1..2b7af060d49f 100644
--- a/drivers/net/atlx/atlx.c
+++ b/drivers/net/atlx/atlx.c
@@ -193,7 +193,7 @@ static void atlx_tx_timeout(struct net_device *netdev)
{
struct atlx_adapter *adapter = netdev_priv(netdev);
/* Do the reset outside of interrupt context */
- schedule_work(&adapter->tx_timeout_task);
+ schedule_work(&adapter->reset_dev_task);
}
/*
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 2df9276720a0..5e725e07d61b 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -871,16 +871,12 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[])
}
}
-/* hw is a boolean parameter that determines whether we should try and
- * set the hw address of the device as well as the hw address of the
- * net_device
- */
-static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw)
+static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[])
{
struct net_device *dev = slave->dev;
struct sockaddr s_addr;
- if (!hw) {
+ if (slave->bond->params.mode == BOND_MODE_TLB) {
memcpy(dev->dev_addr, addr, dev->addr_len);
return 0;
}
@@ -910,8 +906,8 @@ static void alb_swap_mac_addr(struct bonding *bond, struct slave *slave1, struct
u8 tmp_mac_addr[ETH_ALEN];
memcpy(tmp_mac_addr, slave1->dev->dev_addr, ETH_ALEN);
- alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr, bond->alb_info.rlb_enabled);
- alb_set_slave_mac_addr(slave2, tmp_mac_addr, bond->alb_info.rlb_enabled);
+ alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr);
+ alb_set_slave_mac_addr(slave2, tmp_mac_addr);
}
@@ -1058,8 +1054,7 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
/* Try setting slave mac to bond address and fall-through
to code handling that situation below... */
- alb_set_slave_mac_addr(slave, bond->dev->dev_addr,
- bond->alb_info.rlb_enabled);
+ alb_set_slave_mac_addr(slave, bond->dev->dev_addr);
}
/* The slave's address is equal to the address of the bond.
@@ -1095,8 +1090,7 @@ static int alb_handle_addr_collision_on_attach(struct bonding *bond, struct slav
}
if (free_mac_slave) {
- alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr,
- bond->alb_info.rlb_enabled);
+ alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr);
pr_warning("%s: Warning: the hw address of slave %s is in use by the bond; giving it the hw address of %s\n",
bond->dev->name, slave->dev->name,
@@ -1452,8 +1446,7 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave)
{
int res;
- res = alb_set_slave_mac_addr(slave, slave->perm_hwaddr,
- bond->alb_info.rlb_enabled);
+ res = alb_set_slave_mac_addr(slave, slave->perm_hwaddr);
if (res) {
return res;
}
@@ -1604,8 +1597,7 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
alb_swap_mac_addr(bond, swap_slave, new_slave);
} else {
/* set the new_slave to the bond mac address */
- alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr,
- bond->alb_info.rlb_enabled);
+ alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr);
}
if (swap_slave) {
@@ -1665,8 +1657,7 @@ int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave);
alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave);
} else {
- alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr,
- bond->alb_info.rlb_enabled);
+ alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr);
read_lock(&bond->lock);
alb_send_learning_packets(bond->curr_active_slave, bond_dev->dev_addr);
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 2065cb4002b5..e6da842cb288 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1905,7 +1905,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
"but new slave device does not support netpoll.\n",
bond_dev->name);
res = -EBUSY;
- goto err_close;
+ goto err_detach;
}
}
#endif
@@ -1914,7 +1914,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
res = bond_create_slave_symlinks(bond_dev, slave_dev);
if (res)
- goto err_close;
+ goto err_detach;
res = netdev_rx_handler_register(slave_dev, bond_handle_frame,
new_slave);
@@ -1935,6 +1935,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
err_dest_symlinks:
bond_destroy_slave_symlinks(bond_dev, slave_dev);
+err_detach:
+ write_lock_bh(&bond->lock);
+ bond_detach_slave(bond, new_slave);
+ write_unlock_bh(&bond->lock);
+
err_close:
dev_close(slave_dev);
@@ -3071,7 +3076,11 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks)
trans_start + delta_in_ticks)) ||
bond->curr_active_slave != slave) {
slave->link = BOND_LINK_UP;
- bond->current_arp_slave = NULL;
+ if (bond->current_arp_slave) {
+ bond_set_slave_inactive_flags(
+ bond->current_arp_slave);
+ bond->current_arp_slave = NULL;
+ }
pr_info("%s: link status definitely up for interface %s.\n",
bond->dev->name, slave->dev->name);
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 7e5cc0bd913d..1f8a8244f23e 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -688,7 +688,7 @@ static int c_can_get_berr_counter(const struct net_device *dev,
*
* We iterate from priv->tx_echo to priv->tx_next and check if the
* packet has been transmitted, echo it back to the CAN framework.
- * If we discover a not yet transmitted package, stop looking for more.
+ * If we discover a not yet transmitted packet, stop looking for more.
*/
static void c_can_do_tx(struct net_device *dev)
{
@@ -700,7 +700,7 @@ static void c_can_do_tx(struct net_device *dev)
for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) {
msg_obj_no = get_tx_echo_msg_obj(priv);
val = c_can_read_reg32(priv, &priv->regs->txrqst1);
- if (!(val & (1 << msg_obj_no))) {
+ if (!(val & (1 << (msg_obj_no - 1)))) {
can_get_echo_skb(dev,
msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
stats->tx_bytes += priv->read_reg(priv,
@@ -708,6 +708,8 @@ static void c_can_do_tx(struct net_device *dev)
& IF_MCONT_DLC_MASK;
stats->tx_packets++;
c_can_inval_msg_object(dev, 0, msg_obj_no);
+ } else {
+ break;
}
}
@@ -952,7 +954,7 @@ static int c_can_poll(struct napi_struct *napi, int quota)
struct net_device *dev = napi->dev;
struct c_can_priv *priv = netdev_priv(dev);
- irqstatus = priv->read_reg(priv, &priv->regs->interrupt);
+ irqstatus = priv->irqstatus;
if (!irqstatus)
goto end;
@@ -1030,12 +1032,11 @@ end:
static irqreturn_t c_can_isr(int irq, void *dev_id)
{
- u16 irqstatus;
struct net_device *dev = (struct net_device *)dev_id;
struct c_can_priv *priv = netdev_priv(dev);
- irqstatus = priv->read_reg(priv, &priv->regs->interrupt);
- if (!irqstatus)
+ priv->irqstatus = priv->read_reg(priv, &priv->regs->interrupt);
+ if (!priv->irqstatus)
return IRQ_NONE;
/* disable all interrupts and schedule the NAPI */
@@ -1065,10 +1066,11 @@ static int c_can_open(struct net_device *dev)
goto exit_irq_fail;
}
+ napi_enable(&priv->napi);
+
/* start the c_can controller */
c_can_start(dev);
- napi_enable(&priv->napi);
netif_start_queue(dev);
return 0;
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index 9b7fbef3d09a..5f32d34af507 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -76,6 +76,7 @@ struct c_can_priv {
unsigned int tx_next;
unsigned int tx_echo;
void *priv; /* for board-specific data */
+ u16 irqstatus;
};
struct net_device *alloc_c_can_dev(void);
diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
index 3f2e12c3ac1b..015b5152b0de 100644
--- a/drivers/net/cxgb3/cxgb3_offload.c
+++ b/drivers/net/cxgb3/cxgb3_offload.c
@@ -971,7 +971,7 @@ static int nb_callback(struct notifier_block *self, unsigned long event,
case (NETEVENT_REDIRECT):{
struct netevent_redirect *nr = ctx;
cxgb_redirect(nr->old, nr->new);
- cxgb_neigh_update(nr->new->neighbour);
+ cxgb_neigh_update(dst_get_neighbour(nr->new));
break;
}
default:
@@ -1116,8 +1116,8 @@ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
struct l2t_entry *e;
struct t3c_tid_entry *te;
- olddev = old->neighbour->dev;
- newdev = new->neighbour->dev;
+ olddev = dst_get_neighbour(old)->dev;
+ newdev = dst_get_neighbour(new)->dev;
if (!is_offloading(olddev))
return;
if (!is_offloading(newdev)) {
@@ -1134,7 +1134,7 @@ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
}
/* Add new L2T entry */
- e = t3_l2t_get(tdev, new->neighbour, newdev);
+ e = t3_l2t_get(tdev, dst_get_neighbour(new), newdev);
if (!e) {
printk(KERN_ERR "%s: couldn't allocate new l2t entry!\n",
__func__);
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index dcc4a170b0f3..e5efe3aec0f4 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -1008,7 +1008,7 @@ static void emac_rx_handler(void *token, int len, int status)
int ret;
/* free and bail if we are shutting down */
- if (unlikely(!netif_running(ndev) || !netif_carrier_ok(ndev))) {
+ if (unlikely(!netif_running(ndev))) {
dev_kfree_skb_any(skb);
return;
}
@@ -1037,7 +1037,9 @@ static void emac_rx_handler(void *token, int len, int status)
recycle:
ret = cpdma_chan_submit(priv->rxchan, skb, skb->data,
skb_tailroom(skb), GFP_KERNEL);
- if (WARN_ON(ret < 0))
+
+ WARN_ON(ret == -ENOMEM);
+ if (unlikely(ret < 0))
dev_kfree_skb_any(skb);
}
diff --git a/drivers/net/davinci_mdio.c b/drivers/net/davinci_mdio.c
index 7615040df756..f470ab64b093 100644
--- a/drivers/net/davinci_mdio.c
+++ b/drivers/net/davinci_mdio.c
@@ -181,6 +181,11 @@ static inline int wait_for_user_access(struct davinci_mdio_data *data)
__davinci_mdio_reset(data);
return -EAGAIN;
}
+
+ reg = __raw_readl(&regs->user[0].access);
+ if ((reg & USERACCESS_GO) == 0)
+ return 0;
+
dev_err(data->dev, "timed out waiting for user access\n");
return -ETIMEDOUT;
}
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 39cf9b9bd673..3fa19c162112 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -106,14 +106,14 @@ static int dummy_dev_init(struct net_device *dev)
return 0;
}
-static void dummy_dev_free(struct net_device *dev)
+static void dummy_dev_uninit(struct net_device *dev)
{
free_percpu(dev->dstats);
- free_netdev(dev);
}
static const struct net_device_ops dummy_netdev_ops = {
.ndo_init = dummy_dev_init,
+ .ndo_uninit = dummy_dev_uninit,
.ndo_start_xmit = dummy_xmit,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_multicast_list = set_multicast_list,
@@ -127,7 +127,7 @@ static void dummy_setup(struct net_device *dev)
/* Initialize the device structure. */
dev->netdev_ops = &dummy_netdev_ops;
- dev->destructor = dummy_dev_free;
+ dev->destructor = free_netdev;
/* Fill in device structure with ethernet-generic values. */
dev->tx_queue_len = 0;
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 8676899120c3..2c71884eb46e 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -150,6 +150,8 @@ struct e1000_buffer {
unsigned long time_stamp;
u16 length;
u16 next_to_watch;
+ unsigned int segs;
+ unsigned int bytecount;
u16 mapped_as_page;
};
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 76e8af00d86d..99525f9b41b6 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -2798,7 +2798,7 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
struct e1000_buffer *buffer_info;
unsigned int len = skb_headlen(skb);
unsigned int offset = 0, size, count = 0, i;
- unsigned int f;
+ unsigned int f, bytecount, segs;
i = tx_ring->next_to_use;
@@ -2899,7 +2899,13 @@ static int e1000_tx_map(struct e1000_adapter *adapter,
}
}
+ segs = skb_shinfo(skb)->gso_segs ?: 1;
+ /* multiply data chunks by size of headers */
+ bytecount = ((segs - 1) * skb_headlen(skb)) + skb->len;
+
tx_ring->buffer_info[i].skb = skb;
+ tx_ring->buffer_info[i].segs = segs;
+ tx_ring->buffer_info[i].bytecount = bytecount;
tx_ring->buffer_info[first].next_to_watch = i;
return count;
@@ -3573,14 +3579,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter,
cleaned = (i == eop);
if (cleaned) {
- struct sk_buff *skb = buffer_info->skb;
- unsigned int segs, bytecount;
- segs = skb_shinfo(skb)->gso_segs ?: 1;
- /* multiply data chunks by size of headers */
- bytecount = ((segs - 1) * skb_headlen(skb)) +
- skb->len;
- total_tx_packets += segs;
- total_tx_bytes += bytecount;
+ total_tx_packets += buffer_info->segs;
+ total_tx_bytes += buffer_info->bytecount;
}
e1000_unmap_and_free_tx_resource(adapter, buffer_info);
tx_desc->upper.data = 0;
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index 9549879e66a0..8a265f3528de 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -311,6 +311,7 @@ struct e1000_adapter {
u32 txd_cmd;
bool detect_tx_hung;
+ bool tx_hang_recheck;
u8 tx_timeout_factor;
u32 tx_int_delay;
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 3310c3d477d7..5430a9a4a28c 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -930,6 +930,7 @@ static void e1000_print_hw_hang(struct work_struct *work)
struct e1000_adapter *adapter = container_of(work,
struct e1000_adapter,
print_hang_task);
+ struct net_device *netdev = adapter->netdev;
struct e1000_ring *tx_ring = adapter->tx_ring;
unsigned int i = tx_ring->next_to_clean;
unsigned int eop = tx_ring->buffer_info[i].next_to_watch;
@@ -941,6 +942,21 @@ static void e1000_print_hw_hang(struct work_struct *work)
if (test_bit(__E1000_DOWN, &adapter->state))
return;
+ if (!adapter->tx_hang_recheck &&
+ (adapter->flags2 & FLAG2_DMA_BURST)) {
+ /* May be block on write-back, flush and detect again
+ * flush pending descriptor writebacks to memory
+ */
+ ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
+ /* execute the writes immediately */
+ e1e_flush();
+ adapter->tx_hang_recheck = true;
+ return;
+ }
+ /* Real hang detected */
+ adapter->tx_hang_recheck = false;
+ netif_stop_queue(netdev);
+
e1e_rphy(hw, PHY_STATUS, &phy_status);
e1e_rphy(hw, PHY_1000T_STATUS, &phy_1000t_status);
e1e_rphy(hw, PHY_EXT_STATUS, &phy_ext_status);
@@ -1054,10 +1070,10 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter)
if (tx_ring->buffer_info[i].time_stamp &&
time_after(jiffies, tx_ring->buffer_info[i].time_stamp
+ (adapter->tx_timeout_factor * HZ)) &&
- !(er32(STATUS) & E1000_STATUS_TXOFF)) {
+ !(er32(STATUS) & E1000_STATUS_TXOFF))
schedule_work(&adapter->print_hang_task);
- netif_stop_queue(netdev);
- }
+ else
+ adapter->tx_hang_recheck = false;
}
adapter->total_tx_bytes += total_tx_bytes;
adapter->total_tx_packets += total_tx_packets;
@@ -3678,6 +3694,7 @@ static int e1000_open(struct net_device *netdev)
e1000_irq_enable(adapter);
+ adapter->tx_hang_recheck = false;
netif_start_queue(netdev);
adapter->idle_check = true;
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index acb2965ae77d..1ae6cb0f0210 100755
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -1541,7 +1541,6 @@ fec_restart(struct net_device *dev, int duplex)
writel(1, fep->hwp + FEC_ECNTRL);
udelay(10);
- /*
/* if uboot don't set MAC address, get MAC address
* from command line; if command line don't set MAC
* address, get from OCOTP; otherwise, allocate random
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index 19738143aa91..1d1ccec60728 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -2228,19 +2228,11 @@ jme_change_mtu(struct net_device *netdev, int new_mtu)
((new_mtu) < IPV6_MIN_MTU))
return -EINVAL;
- if (new_mtu > 4000) {
- jme->reg_rxcs &= ~RXCS_FIFOTHNP;
- jme->reg_rxcs |= RXCS_FIFOTHNP_64QW;
- jme_restart_rx_engine(jme);
- } else {
- jme->reg_rxcs &= ~RXCS_FIFOTHNP;
- jme->reg_rxcs |= RXCS_FIFOTHNP_128QW;
- jme_restart_rx_engine(jme);
- }
netdev->mtu = new_mtu;
netdev_update_features(netdev);
+ jme_restart_rx_engine(jme);
jme_reset_link(jme);
return 0;
diff --git a/drivers/net/jme.h b/drivers/net/jme.h
index e9aaeca96abc..fff885e9274e 100644
--- a/drivers/net/jme.h
+++ b/drivers/net/jme.h
@@ -734,7 +734,7 @@ enum jme_rxcs_values {
RXCS_RETRYCNT_60 = 0x00000F00,
RXCS_DEFAULT = RXCS_FIFOTHTP_128T |
- RXCS_FIFOTHNP_128QW |
+ RXCS_FIFOTHNP_16QW |
RXCS_DMAREQSZ_128B |
RXCS_RETRYGAP_256ns |
RXCS_RETRYCNT_32,
diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c
index bb6eb5c52fad..50ec391a639f 100644
--- a/drivers/net/ks8851_mll.c
+++ b/drivers/net/ks8851_mll.c
@@ -39,7 +39,7 @@
#define DRV_NAME "ks8851_mll"
static u8 KS_DEFAULT_MAC_ADDRESS[] = { 0x00, 0x10, 0xA1, 0x86, 0x95, 0x11 };
-#define MAX_RECV_FRAMES 32
+#define MAX_RECV_FRAMES 255
#define MAX_BUF_SIZE 2048
#define TX_BUF_SIZE 2000
#define RX_BUF_SIZE 2000
diff --git a/drivers/net/ksz884x.c b/drivers/net/ksz884x.c
index 41ea5920c158..95b6664e9366 100644
--- a/drivers/net/ksz884x.c
+++ b/drivers/net/ksz884x.c
@@ -5679,7 +5679,7 @@ static int netdev_set_mac_address(struct net_device *dev, void *addr)
memcpy(hw->override_addr, mac->sa_data, MAC_ADDR_LEN);
}
- memcpy(dev->dev_addr, mac->sa_data, MAX_ADDR_LEN);
+ memcpy(dev->dev_addr, mac->sa_data, ETH_ALEN);
interrupt = hw_block_intr(hw);
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index ab4723d92a64..735f726729d9 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -247,7 +247,7 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
xmit_world:
skb->ip_summed = ip_summed;
- skb_set_dev(skb, vlan->lowerdev);
+ skb->dev = vlan->lowerdev;
return dev_queue_xmit(skb);
}
diff --git a/drivers/net/pch_gbe/pch_gbe_main.c b/drivers/net/pch_gbe/pch_gbe_main.c
index eac3c5ca9731..236d00ec64cc 100644
--- a/drivers/net/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/pch_gbe/pch_gbe_main.c
@@ -39,6 +39,9 @@ const char pch_driver_version[] = DRV_VERSION;
#define PCI_VENDOR_ID_ROHM 0x10db
#define PCI_DEVICE_ID_ROHM_ML7223_GBE 0x8013
+/* Macros for ML7831 */
+#define PCI_DEVICE_ID_ROHM_ML7831_GBE 0x8802
+
#define PCH_GBE_TX_WEIGHT 64
#define PCH_GBE_RX_WEIGHT 64
#define PCH_GBE_RX_BUFFER_WRITE 16
@@ -717,13 +720,6 @@ static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter)
iowrite32(rdba, &hw->reg->RX_DSC_BASE);
iowrite32(rdlen, &hw->reg->RX_DSC_SIZE);
iowrite32((rdba + rdlen), &hw->reg->RX_DSC_SW_P);
-
- /* Enables Receive DMA */
- rxdma = ioread32(&hw->reg->DMA_CTRL);
- rxdma |= PCH_GBE_RX_DMA_EN;
- iowrite32(rxdma, &hw->reg->DMA_CTRL);
- /* Enables Receive */
- iowrite32(PCH_GBE_MRE_MAC_RX_EN, &hw->reg->MAC_RX_EN);
}
/**
@@ -1097,6 +1093,19 @@ void pch_gbe_update_stats(struct pch_gbe_adapter *adapter)
spin_unlock_irqrestore(&adapter->stats_lock, flags);
}
+static void pch_gbe_start_receive(struct pch_gbe_hw *hw)
+{
+ u32 rxdma;
+
+ /* Enables Receive DMA */
+ rxdma = ioread32(&hw->reg->DMA_CTRL);
+ rxdma |= PCH_GBE_RX_DMA_EN;
+ iowrite32(rxdma, &hw->reg->DMA_CTRL);
+ /* Enables Receive */
+ iowrite32(PCH_GBE_MRE_MAC_RX_EN, &hw->reg->MAC_RX_EN);
+ return;
+}
+
/**
* pch_gbe_intr - Interrupt Handler
* @irq: Interrupt number
@@ -1701,6 +1710,12 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
int err;
+ /* Ensure we have a valid MAC */
+ if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
+ pr_err("Error: Invalid MAC address\n");
+ return -EINVAL;
+ }
+
/* hardware has been reset, we need to reload some things */
pch_gbe_set_multi(netdev);
@@ -1717,6 +1732,7 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
pch_gbe_alloc_tx_buffers(adapter, tx_ring);
pch_gbe_alloc_rx_buffers(adapter, rx_ring, rx_ring->count);
adapter->tx_queue_len = netdev->tx_queue_len;
+ pch_gbe_start_receive(&adapter->hw);
mod_timer(&adapter->watchdog_timer, jiffies);
@@ -2118,7 +2134,7 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget)
/* If no Tx and not enough Rx work done,
* exit the polling mode
*/
- if ((work_done < budget) || !netif_running(netdev))
+ if (work_done < budget)
poll_end_flag = true;
}
@@ -2392,9 +2408,14 @@ static int pch_gbe_probe(struct pci_dev *pdev,
memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len);
if (!is_valid_ether_addr(netdev->dev_addr)) {
- dev_err(&pdev->dev, "Invalid MAC Address\n");
- ret = -EIO;
- goto err_free_adapter;
+ /*
+ * If the MAC is invalid (or just missing), display a warning
+ * but do not abort setting up the device. pch_gbe_up will
+ * prevent the interface from being brought up until a valid MAC
+ * is set.
+ */
+ dev_err(&pdev->dev, "Invalid MAC address, "
+ "interface disabled.\n");
}
setup_timer(&adapter->watchdog_timer, pch_gbe_watchdog,
(unsigned long)adapter);
@@ -2452,6 +2473,13 @@ static DEFINE_PCI_DEVICE_TABLE(pch_gbe_pcidev_id) = {
.class = (PCI_CLASS_NETWORK_ETHERNET << 8),
.class_mask = (0xFFFF00)
},
+ {.vendor = PCI_VENDOR_ID_ROHM,
+ .device = PCI_DEVICE_ID_ROHM_ML7831_GBE,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .class = (PCI_CLASS_NETWORK_ETHERNET << 8),
+ .class_mask = (0xFFFF00)
+ },
/* required last entry */
{0}
};
diff --git a/drivers/net/pch_gbe/pch_gbe_param.c b/drivers/net/pch_gbe/pch_gbe_param.c
index 5b5d90a47e29..fb74ef9c81a2 100644
--- a/drivers/net/pch_gbe/pch_gbe_param.c
+++ b/drivers/net/pch_gbe/pch_gbe_param.c
@@ -320,10 +320,10 @@ static void pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter)
pr_debug("AutoNeg specified along with Speed or Duplex, AutoNeg parameter ignored\n");
hw->phy.autoneg_advertised = opt.def;
} else {
- hw->phy.autoneg_advertised = AutoNeg;
- pch_gbe_validate_option(
- (int *)(&hw->phy.autoneg_advertised),
- &opt, adapter);
+ int tmp = AutoNeg;
+
+ pch_gbe_validate_option(&tmp, &opt, adapter);
+ hw->phy.autoneg_advertised = tmp;
}
}
@@ -494,9 +494,10 @@ void pch_gbe_check_options(struct pch_gbe_adapter *adapter)
.arg = { .l = { .nr = (int)ARRAY_SIZE(fc_list),
.p = fc_list } }
};
- hw->mac.fc = FlowControl;
- pch_gbe_validate_option((int *)(&hw->mac.fc),
- &opt, adapter);
+ int tmp = FlowControl;
+
+ pch_gbe_validate_option(&tmp, &opt, adapter);
+ hw->mac.fc = tmp;
}
pch_gbe_check_copper_options(adapter);
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index 47c8339a0359..2843c90f712f 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -241,7 +241,7 @@ MODULE_DEVICE_TABLE(of, mdio_ofgpio_match);
static struct platform_driver mdio_ofgpio_driver = {
.driver = {
- .name = "mdio-gpio",
+ .name = "mdio-ofgpio",
.owner = THIS_MODULE,
.of_match_table = mdio_ofgpio_match,
},
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 4609bc0e2f56..b890401cab93 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -968,7 +968,6 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
proto = npindex_to_proto[npi];
put_unaligned_be16(proto, pp);
- netif_stop_queue(dev);
skb_queue_tail(&ppp->file.xq, skb);
ppp_xmit_process(ppp);
return NETDEV_TX_OK;
@@ -1063,6 +1062,8 @@ ppp_xmit_process(struct ppp *ppp)
code that we can accept some more. */
if (!ppp->xmit_pending && !skb_peek(&ppp->file.xq))
netif_wake_queue(ppp->dev);
+ else
+ netif_stop_queue(ppp->dev);
}
ppp_xmit_unlock(ppp);
}
@@ -2019,14 +2020,22 @@ ppp_mp_reconstruct(struct ppp *ppp)
continue;
}
if (PPP_MP_CB(p)->sequence != seq) {
+ u32 oldseq;
/* Fragment `seq' is missing. If it is after
minseq, it might arrive later, so stop here. */
if (seq_after(seq, minseq))
break;
/* Fragment `seq' is lost, keep going. */
lost = 1;
+ oldseq = seq;
seq = seq_before(minseq, PPP_MP_CB(p)->sequence)?
minseq + 1: PPP_MP_CB(p)->sequence;
+
+ if (ppp->debug & 1)
+ netdev_printk(KERN_DEBUG, ppp->dev,
+ "lost frag %u..%u\n",
+ oldseq, seq-1);
+
goto again;
}
@@ -2071,6 +2080,10 @@ ppp_mp_reconstruct(struct ppp *ppp)
struct sk_buff *tmp2;
skb_queue_reverse_walk_from_safe(list, p, tmp2) {
+ if (ppp->debug & 1)
+ netdev_printk(KERN_DEBUG, ppp->dev,
+ "discarding frag %u\n",
+ PPP_MP_CB(p)->sequence);
__skb_unlink(p, list);
kfree_skb(p);
}
@@ -2086,6 +2099,17 @@ ppp_mp_reconstruct(struct ppp *ppp)
/* If we have discarded any fragments,
signal a receive error. */
if (PPP_MP_CB(head)->sequence != ppp->nextseq) {
+ skb_queue_walk_safe(list, p, tmp) {
+ if (p == head)
+ break;
+ if (ppp->debug & 1)
+ netdev_printk(KERN_DEBUG, ppp->dev,
+ "discarding frag %u\n",
+ PPP_MP_CB(p)->sequence);
+ __skb_unlink(p, list);
+ kfree_skb(p);
+ }
+
if (ppp->debug & 1)
netdev_printk(KERN_DEBUG, ppp->dev,
" missed pkts %u..%u\n",
diff --git a/drivers/net/pptp.c b/drivers/net/pptp.c
index 1286fe212dc4..4b3a68b69a67 100644
--- a/drivers/net/pptp.c
+++ b/drivers/net/pptp.c
@@ -418,10 +418,8 @@ static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr,
lock_sock(sk);
opt->src_addr = sp->sa_addr.pptp;
- if (add_chan(po)) {
- release_sock(sk);
+ if (add_chan(po))
error = -EBUSY;
- }
release_sock(sk);
return error;
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c
index 62e43649466e..4004fc2477be 100644
--- a/drivers/net/sfc/rx.c
+++ b/drivers/net/sfc/rx.c
@@ -155,11 +155,10 @@ static int efx_init_rx_buffers_skb(struct efx_rx_queue *rx_queue)
if (unlikely(!skb))
return -ENOMEM;
- /* Adjust the SKB for padding and checksum */
+ /* Adjust the SKB for padding */
skb_reserve(skb, NET_IP_ALIGN);
rx_buf->len = skb_len - NET_IP_ALIGN;
rx_buf->is_page = false;
- skb->ip_summed = CHECKSUM_UNNECESSARY;
rx_buf->dma_addr = pci_map_single(efx->pci_dev,
skb->data, rx_buf->len,
@@ -498,6 +497,7 @@ static void efx_rx_packet_gro(struct efx_channel *channel,
EFX_BUG_ON_PARANOID(!checksummed);
rx_buf->u.skb = NULL;
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
gro_result = napi_gro_receive(napi, skb);
}
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 3ee41da130c2..f2e31c87d9fe 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -94,6 +94,10 @@ static int disable_msi = 0;
module_param(disable_msi, int, 0);
MODULE_PARM_DESC(disable_msi, "Disable Message Signaled Interrupt (MSI)");
+static int legacy_pme = 0;
+module_param(legacy_pme, int, 0);
+MODULE_PARM_DESC(legacy_pme, "Legacy power management");
+
static DEFINE_PCI_DEVICE_TABLE(sky2_id_table) = {
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, /* SK-9Sxx */
{ PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, /* SK-9Exx */
@@ -794,6 +798,13 @@ static void sky2_wol_init(struct sky2_port *sky2)
/* Disable PiG firmware */
sky2_write16(hw, B0_CTST, Y2_HW_WOL_OFF);
+ /* Needed by some broken BIOSes, use PCI rather than PCI-e for WOL */
+ if (legacy_pme) {
+ u32 reg1 = sky2_pci_read32(hw, PCI_DEV_REG1);
+ reg1 |= PCI_Y2_PME_LEGACY;
+ sky2_pci_write32(hw, PCI_DEV_REG1, reg1);
+ }
+
/* block receiver */
sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
}
@@ -2333,8 +2344,13 @@ static struct sk_buff *receive_copy(struct sky2_port *sky2,
skb_copy_from_linear_data(re->skb, skb->data, length);
skb->ip_summed = re->skb->ip_summed;
skb->csum = re->skb->csum;
+ skb->rxhash = re->skb->rxhash;
+ skb->vlan_tci = re->skb->vlan_tci;
+
pci_dma_sync_single_for_device(sky2->hw->pdev, re->data_addr,
length, PCI_DMA_FROMDEVICE);
+ re->skb->vlan_tci = 0;
+ re->skb->rxhash = 0;
re->skb->ip_summed = CHECKSUM_NONE;
skb_put(skb, length);
}
@@ -2419,9 +2435,6 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
struct sk_buff *skb = NULL;
u16 count = (status & GMR_FS_LEN) >> 16;
- if (status & GMR_FS_VLAN)
- count -= VLAN_HLEN; /* Account for vlan tag */
-
netif_printk(sky2, rx_status, KERN_DEBUG, dev,
"rx slot %u status 0x%x len %d\n",
sky2->rx_next, status, length);
@@ -2429,6 +2442,9 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
sky2->rx_next = (sky2->rx_next + 1) % sky2->rx_pending;
prefetch(sky2->rx_ring + sky2->rx_next);
+ if (vlan_tx_tag_present(re->skb))
+ count -= VLAN_HLEN; /* Account for vlan tag */
+
/* This chip has hardware problems that generates bogus status.
* So do only marginal checking and expect higher level protocols
* to handle crap frames.
@@ -2486,11 +2502,8 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
}
static inline void sky2_skb_rx(const struct sky2_port *sky2,
- u32 status, struct sk_buff *skb)
+ struct sk_buff *skb)
{
- if (status & GMR_FS_VLAN)
- __vlan_hwaccel_put_tag(skb, be16_to_cpu(sky2->rx_tag));
-
if (skb->ip_summed == CHECKSUM_NONE)
netif_receive_skb(skb);
else
@@ -2544,6 +2557,14 @@ static void sky2_rx_checksum(struct sky2_port *sky2, u32 status)
}
}
+static void sky2_rx_tag(struct sky2_port *sky2, u16 length)
+{
+ struct sk_buff *skb;
+
+ skb = sky2->rx_ring[sky2->rx_next].skb;
+ __vlan_hwaccel_put_tag(skb, be16_to_cpu(length));
+}
+
static void sky2_rx_hash(struct sky2_port *sky2, u32 status)
{
struct sk_buff *skb;
@@ -2602,8 +2623,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
}
skb->protocol = eth_type_trans(skb, dev);
-
- sky2_skb_rx(sky2, status, skb);
+ sky2_skb_rx(sky2, skb);
/* Stop after net poll weight */
if (++work_done >= to_do)
@@ -2611,11 +2631,11 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
break;
case OP_RXVLAN:
- sky2->rx_tag = length;
+ sky2_rx_tag(sky2, length);
break;
case OP_RXCHKSVLAN:
- sky2->rx_tag = length;
+ sky2_rx_tag(sky2, length);
/* fall through */
case OP_RXCHKS:
if (likely(dev->features & NETIF_F_RXCSUM))
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h
index 318c9ae7bf91..a79a1662ea9e 100644
--- a/drivers/net/sky2.h
+++ b/drivers/net/sky2.h
@@ -2236,7 +2236,6 @@ struct sky2_port {
u16 rx_pending;
u16 rx_data_size;
u16 rx_nfrags;
- u16 rx_tag;
struct {
unsigned long last;
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
index c6d47d10590c..3d12e8ce9393 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/smsc911x.c
@@ -1083,10 +1083,8 @@ smsc911x_rx_counterrors(struct net_device *dev, unsigned int rxstat)
/* Quickly dumps bad packets */
static void
-smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktbytes)
+smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktwords)
{
- unsigned int pktwords = (pktbytes + NET_IP_ALIGN + 3) >> 2;
-
if (likely(pktwords >= 4)) {
unsigned int timeout = 500;
unsigned int val;
@@ -1150,7 +1148,7 @@ static int smsc911x_poll(struct napi_struct *napi, int budget)
continue;
}
- skb = netdev_alloc_skb(dev, pktlength + NET_IP_ALIGN);
+ skb = netdev_alloc_skb(dev, pktwords << 2);
if (unlikely(!skb)) {
SMSC_WARN(pdata, rx_err,
"Unable to allocate skb for rx packet");
@@ -1160,14 +1158,12 @@ static int smsc911x_poll(struct napi_struct *napi, int budget)
break;
}
- skb->data = skb->head;
- skb_reset_tail_pointer(skb);
+ pdata->ops->rx_readfifo(pdata,
+ (unsigned int *)skb->data, pktwords);
/* Align IP on 16B boundary */
skb_reserve(skb, NET_IP_ALIGN);
skb_put(skb, pktlength - 4);
- pdata->ops->rx_readfifo(pdata,
- (unsigned int *)skb->head, pktwords);
skb->protocol = eth_type_trans(skb, dev);
skb_checksum_none_assert(skb);
netif_receive_skb(skb);
@@ -1390,7 +1386,7 @@ static int smsc911x_open(struct net_device *dev)
smsc911x_reg_write(pdata, FIFO_INT, temp);
/* set RX Data offset to 2 bytes for alignment */
- smsc911x_reg_write(pdata, RX_CFG, (2 << 8));
+ smsc911x_reg_write(pdata, RX_CFG, (NET_IP_ALIGN << 8));
/* enable NAPI polling before enabling RX interrupts */
napi_enable(&pdata->napi);
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index ab5930099267..361beb797d1e 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -2363,7 +2363,7 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state)
netif_device_detach(dev);
/* Switch off MAC, remember WOL setting */
- gp->asleep_wol = gp->wake_on_lan;
+ gp->asleep_wol = !!gp->wake_on_lan;
gem_do_stop(dev, gp->asleep_wol);
} else
gp->asleep_wol = 0;
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index bc8c183d622c..c4ab8a721b4a 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -740,8 +740,13 @@ static inline unsigned int tg3_has_work(struct tg3_napi *tnapi)
if (sblk->status & SD_STATUS_LINK_CHG)
work_exists = 1;
}
- /* check for RX/TX work to do */
- if (sblk->idx[0].tx_consumer != tnapi->tx_cons ||
+
+ /* check for TX work to do */
+ if (sblk->idx[0].tx_consumer != tnapi->tx_cons)
+ work_exists = 1;
+
+ /* check for RX work to do */
+ if (tnapi->rx_rcb_prod_idx &&
*(tnapi->rx_rcb_prod_idx) != tnapi->rx_rcb_ptr)
work_exists = 1;
@@ -5216,6 +5221,9 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget)
return work_done;
}
+ if (!tnapi->rx_rcb_prod_idx)
+ return work_done;
+
/* run RX thread, within the bounds set by NAPI.
* All RX "locking" is done by ensuring outside
* code synchronizes with tg3->napi.poll()
@@ -6626,6 +6634,12 @@ static int tg3_alloc_consistent(struct tg3 *tp)
*/
switch (i) {
default:
+ if (tg3_flag(tp, ENABLE_RSS)) {
+ tnapi->rx_rcb_prod_idx = NULL;
+ break;
+ }
+ /* Fall through */
+ case 1:
tnapi->rx_rcb_prod_idx = &sblk->idx[0].rx_producer;
break;
case 2:
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index c5c4b4def7fb..c44e0e489ba9 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -371,7 +371,7 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
skb_pull(skb, (size + 1) & 0xfffe);
- if (skb->len == 0)
+ if (skb->len < sizeof(header))
break;
head = (u8 *) skb->data;
@@ -398,7 +398,7 @@ static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
u32 packet_len;
u32 padbytes = 0xffff0000;
- padlen = ((skb->len + 4) % 512) ? 0 : 4;
+ padlen = ((skb->len + 4) & (dev->maxpacket - 1)) ? 0 : 4;
if ((!skb_cloned(skb)) &&
((headroom + tailroom) >= (4 + padlen))) {
@@ -420,7 +420,7 @@ static struct sk_buff *asix_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
cpu_to_le32s(&packet_len);
skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len));
- if ((skb->len % 512) == 0) {
+ if (padlen) {
cpu_to_le32s(&padbytes);
memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes));
skb_put(skb, sizeof(padbytes));
@@ -1485,6 +1485,10 @@ static const struct usb_device_id products [] = {
USB_DEVICE (0x6189, 0x182d),
.driver_info = (unsigned long) &ax8817x_info,
}, {
+ // Sitecom LN-031 "USB 2.0 10/100/1000 Ethernet adapter"
+ USB_DEVICE (0x0df6, 0x0056),
+ .driver_info = (unsigned long) &ax88178_info,
+}, {
// corega FEther USB2-TX
USB_DEVICE (0x07aa, 0x0017),
.driver_info = (unsigned long) &ax8817x_info,
@@ -1560,6 +1564,10 @@ static const struct usb_device_id products [] = {
// ASIX 88772a
USB_DEVICE(0x0db0, 0xa877),
.driver_info = (unsigned long) &ax88772_info,
+}, {
+ // Asus USB Ethernet Adapter
+ USB_DEVICE (0x0b95, 0x7e2b),
+ .driver_info = (unsigned long) &ax88772_info,
},
{ }, // END
};
diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c
index 882f53f708df..82d43b214f93 100644
--- a/drivers/net/usb/cdc_eem.c
+++ b/drivers/net/usb/cdc_eem.c
@@ -93,6 +93,7 @@ static int eem_bind(struct usbnet *dev, struct usb_interface *intf)
/* no jumbogram (16K) support for now */
dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN;
+ dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
return 0;
}
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index c924ea2bce07..544c309e0d95 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -83,6 +83,7 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
struct cdc_state *info = (void *) &dev->data;
int status;
int rndis;
+ bool android_rndis_quirk = false;
struct usb_driver *driver = driver_of(intf);
struct usb_cdc_mdlm_desc *desc = NULL;
struct usb_cdc_mdlm_detail_desc *detail = NULL;
@@ -195,6 +196,11 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
info->control,
info->u->bSlaveInterface0,
info->data);
+ /* fall back to hard-wiring for RNDIS */
+ if (rndis) {
+ android_rndis_quirk = true;
+ goto next_desc;
+ }
goto bad_desc;
}
if (info->control != intf) {
@@ -271,11 +277,15 @@ next_desc:
/* Microsoft ActiveSync based and some regular RNDIS devices lack the
* CDC descriptors, so we'll hard-wire the interfaces and not check
* for descriptors.
+ *
+ * Some Android RNDIS devices have a CDC Union descriptor pointing
+ * to non-existing interfaces. Ignore that and attempt the same
+ * hard-wired 0 and 1 interfaces.
*/
- if (rndis && !info->u) {
+ if (rndis && (!info->u || android_rndis_quirk)) {
info->control = usb_ifnum_to_if(dev->udev, 0);
info->data = usb_ifnum_to_if(dev->udev, 1);
- if (!info->control || !info->data) {
+ if (!info->control || !info->data || info->control != intf) {
dev_dbg(&intf->dev,
"rndis: master #0/%p slave #1/%p\n",
info->control,
@@ -472,6 +482,7 @@ static const struct driver_info wwan_info = {
/*-------------------------------------------------------------------------*/
#define HUAWEI_VENDOR_ID 0x12D1
+#define NOVATEL_VENDOR_ID 0x1410
static const struct usb_device_id products [] = {
/*
@@ -570,6 +581,13 @@ static const struct usb_device_id products [] = {
.driver_info = (unsigned long)&wwan_info,
},
+/* Logitech Harmony 900 - uses the pseudo-MDLM (BLAN) driver */
+{
+ USB_DEVICE_AND_INTERFACE_INFO(0x046d, 0xc11f, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+ .driver_info = 0,
+},
+
/*
* WHITELIST!!!
*
@@ -582,6 +600,21 @@ static const struct usb_device_id products [] = {
* because of bugs/quirks in a given product (like Zaurus, above).
*/
{
+ /* Novatel USB551L */
+ /* This match must come *before* the generic CDC-ETHER match so that
+ * we get FLAG_WWAN set on the device, since it's descriptors are
+ * generic CDC-ETHER.
+ */
+ .match_flags = USB_DEVICE_ID_MATCH_VENDOR
+ | USB_DEVICE_ID_MATCH_PRODUCT
+ | USB_DEVICE_ID_MATCH_INT_INFO,
+ .idVendor = NOVATEL_VENDOR_ID,
+ .idProduct = 0xB001,
+ .bInterfaceClass = USB_CLASS_COMM,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET,
+ .bInterfaceProtocol = USB_CDC_PROTO_NONE,
+ .driver_info = (unsigned long)&wwan_info,
+}, {
USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
USB_CDC_PROTO_NONE),
.driver_info = (unsigned long) &cdc_info,
diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c
index 8f9b7f760458..9cf4e47e55bf 100644
--- a/drivers/net/usb/ipheth.c
+++ b/drivers/net/usb/ipheth.c
@@ -60,6 +60,7 @@
#define USB_PRODUCT_IPHONE_3GS 0x1294
#define USB_PRODUCT_IPHONE_4 0x1297
#define USB_PRODUCT_IPHONE_4_VZW 0x129c
+#define USB_PRODUCT_IPHONE_4S 0x12a0
#define IPHETH_USBINTF_CLASS 255
#define IPHETH_USBINTF_SUBCLASS 253
@@ -103,6 +104,10 @@ static struct usb_device_id ipheth_table[] = {
USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4_VZW,
IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
IPHETH_USBINTF_PROTO) },
+ { USB_DEVICE_AND_INTERFACE_INFO(
+ USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S,
+ IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
+ IPHETH_USBINTF_PROTO) },
{ }
};
MODULE_DEVICE_TABLE(usb, ipheth_table);
diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c
index ed1b43210584..864448b76120 100644
--- a/drivers/net/usb/sierra_net.c
+++ b/drivers/net/usb/sierra_net.c
@@ -943,7 +943,7 @@ struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
}
static const u8 sierra_net_ifnum_list[] = { 7, 10, 11 };
-static const struct sierra_net_info_data sierra_net_info_data_68A3 = {
+static const struct sierra_net_info_data sierra_net_info_data_direct_ip = {
.rx_urb_size = 8 * 1024,
.whitelist = {
.infolen = ARRAY_SIZE(sierra_net_ifnum_list),
@@ -951,7 +951,7 @@ static const struct sierra_net_info_data sierra_net_info_data_68A3 = {
}
};
-static const struct driver_info sierra_net_info_68A3 = {
+static const struct driver_info sierra_net_info_direct_ip = {
.description = "Sierra Wireless USB-to-WWAN Modem",
.flags = FLAG_WWAN | FLAG_SEND_ZLP,
.bind = sierra_net_bind,
@@ -959,12 +959,18 @@ static const struct driver_info sierra_net_info_68A3 = {
.status = sierra_net_status,
.rx_fixup = sierra_net_rx_fixup,
.tx_fixup = sierra_net_tx_fixup,
- .data = (unsigned long)&sierra_net_info_data_68A3,
+ .data = (unsigned long)&sierra_net_info_data_direct_ip,
};
static const struct usb_device_id products[] = {
{USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */
- .driver_info = (unsigned long) &sierra_net_info_68A3},
+ .driver_info = (unsigned long) &sierra_net_info_direct_ip},
+ {USB_DEVICE(0x0F3D, 0x68A3), /* AT&T Direct IP modem */
+ .driver_info = (unsigned long) &sierra_net_info_direct_ip},
+ {USB_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */
+ .driver_info = (unsigned long) &sierra_net_info_direct_ip},
+ {USB_DEVICE(0x0F3D, 0x68AA), /* AT&T Direct IP LTE modem */
+ .driver_info = (unsigned long) &sierra_net_info_direct_ip},
{}, /* last item */
};
diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c
index 15b3d6888ae9..de0de3ee6392 100644
--- a/drivers/net/usb/smsc75xx.c
+++ b/drivers/net/usb/smsc75xx.c
@@ -1049,6 +1049,7 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
dev->net->ethtool_ops = &smsc75xx_ethtool_ops;
dev->net->flags |= IFF_MULTICAST;
dev->net->hard_header_len += SMSC75XX_TX_OVERHEAD;
+ dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
return 0;
}
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index f74f3ce71526..e5c15bbbe62f 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -1190,7 +1190,7 @@ static const struct driver_info smsc95xx_info = {
.rx_fixup = smsc95xx_rx_fixup,
.tx_fixup = smsc95xx_tx_fixup,
.status = smsc95xx_status,
- .flags = FLAG_ETHER | FLAG_SEND_ZLP,
+ .flags = FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR,
};
static const struct usb_device_id products[] = {
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index ce395fe5de26..dd225fc65a8e 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -277,17 +277,32 @@ int usbnet_change_mtu (struct net_device *net, int new_mtu)
}
EXPORT_SYMBOL_GPL(usbnet_change_mtu);
+/* The caller must hold list->lock */
+static void __usbnet_queue_skb(struct sk_buff_head *list,
+ struct sk_buff *newsk, enum skb_state state)
+{
+ struct skb_data *entry = (struct skb_data *) newsk->cb;
+
+ __skb_queue_tail(list, newsk);
+ entry->state = state;
+}
+
/*-------------------------------------------------------------------------*/
/* some LK 2.4 HCDs oopsed if we freed or resubmitted urbs from
* completion callbacks. 2.5 should have fixed those bugs...
*/
-static void defer_bh(struct usbnet *dev, struct sk_buff *skb, struct sk_buff_head *list)
+static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb,
+ struct sk_buff_head *list, enum skb_state state)
{
unsigned long flags;
+ enum skb_state old_state;
+ struct skb_data *entry = (struct skb_data *) skb->cb;
spin_lock_irqsave(&list->lock, flags);
+ old_state = entry->state;
+ entry->state = state;
__skb_unlink(skb, list);
spin_unlock(&list->lock);
spin_lock(&dev->done.lock);
@@ -295,6 +310,7 @@ static void defer_bh(struct usbnet *dev, struct sk_buff *skb, struct sk_buff_hea
if (dev->done.qlen == 1)
tasklet_schedule(&dev->bh);
spin_unlock_irqrestore(&dev->done.lock, flags);
+ return old_state;
}
/* some work can't be done in tasklets, so we use keventd
@@ -335,7 +351,6 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
entry = (struct skb_data *) skb->cb;
entry->urb = urb;
entry->dev = dev;
- entry->state = rx_start;
entry->length = 0;
usb_fill_bulk_urb (urb, dev->udev, dev->in,
@@ -367,7 +382,7 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags)
tasklet_schedule (&dev->bh);
break;
case 0:
- __skb_queue_tail (&dev->rxq, skb);
+ __usbnet_queue_skb(&dev->rxq, skb, rx_start);
}
} else {
netif_dbg(dev, ifdown, dev->net, "rx: stopped\n");
@@ -418,16 +433,17 @@ static void rx_complete (struct urb *urb)
struct skb_data *entry = (struct skb_data *) skb->cb;
struct usbnet *dev = entry->dev;
int urb_status = urb->status;
+ enum skb_state state;
skb_put (skb, urb->actual_length);
- entry->state = rx_done;
+ state = rx_done;
entry->urb = NULL;
switch (urb_status) {
/* success */
case 0:
if (skb->len < dev->net->hard_header_len) {
- entry->state = rx_cleanup;
+ state = rx_cleanup;
dev->net->stats.rx_errors++;
dev->net->stats.rx_length_errors++;
netif_dbg(dev, rx_err, dev->net,
@@ -466,7 +482,7 @@ static void rx_complete (struct urb *urb)
"rx throttle %d\n", urb_status);
}
block:
- entry->state = rx_cleanup;
+ state = rx_cleanup;
entry->urb = urb;
urb = NULL;
break;
@@ -477,17 +493,18 @@ block:
// FALLTHROUGH
default:
- entry->state = rx_cleanup;
+ state = rx_cleanup;
dev->net->stats.rx_errors++;
netif_dbg(dev, rx_err, dev->net, "rx status %d\n", urb_status);
break;
}
- defer_bh(dev, skb, &dev->rxq);
+ state = defer_bh(dev, skb, &dev->rxq, state);
if (urb) {
if (netif_running (dev->net) &&
- !test_bit (EVENT_RX_HALT, &dev->flags)) {
+ !test_bit (EVENT_RX_HALT, &dev->flags) &&
+ state != unlink_start) {
rx_submit (dev, urb, GFP_ATOMIC);
return;
}
@@ -573,18 +590,34 @@ EXPORT_SYMBOL_GPL(usbnet_purge_paused_rxq);
static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
{
unsigned long flags;
- struct sk_buff *skb, *skbnext;
+ struct sk_buff *skb;
int count = 0;
spin_lock_irqsave (&q->lock, flags);
- skb_queue_walk_safe(q, skb, skbnext) {
+ while (!skb_queue_empty(q)) {
struct skb_data *entry;
struct urb *urb;
int retval;
- entry = (struct skb_data *) skb->cb;
+ skb_queue_walk(q, skb) {
+ entry = (struct skb_data *) skb->cb;
+ if (entry->state != unlink_start)
+ goto found;
+ }
+ break;
+found:
+ entry->state = unlink_start;
urb = entry->urb;
+ /*
+ * Get reference count of the URB to avoid it to be
+ * freed during usb_unlink_urb, which may trigger
+ * use-after-free problem inside usb_unlink_urb since
+ * usb_unlink_urb is always racing with .complete
+ * handler(include defer_bh).
+ */
+ usb_get_urb(urb);
+ spin_unlock_irqrestore(&q->lock, flags);
// during some PM-driven resume scenarios,
// these (async) unlinks complete immediately
retval = usb_unlink_urb (urb);
@@ -592,6 +625,8 @@ static int unlink_urbs (struct usbnet *dev, struct sk_buff_head *q)
netdev_dbg(dev->net, "unlink urb err, %d\n", retval);
else
count++;
+ usb_put_urb(urb);
+ spin_lock_irqsave(&q->lock, flags);
}
spin_unlock_irqrestore (&q->lock, flags);
return count;
@@ -1022,9 +1057,7 @@ static void tx_complete (struct urb *urb)
}
usb_autopm_put_interface_async(dev->intf);
- urb->dev = NULL;
- entry->state = tx_done;
- defer_bh(dev, skb, &dev->txq);
+ (void) defer_bh(dev, skb, &dev->txq, tx_done);
}
/*-------------------------------------------------------------------------*/
@@ -1077,7 +1110,6 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
entry = (struct skb_data *) skb->cb;
entry->urb = urb;
entry->dev = dev;
- entry->state = tx_start;
entry->length = length;
usb_fill_bulk_urb (urb, dev->udev, dev->out,
@@ -1136,7 +1168,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
break;
case 0:
net->trans_start = jiffies;
- __skb_queue_tail (&dev->txq, skb);
+ __usbnet_queue_skb(&dev->txq, skb, tx_start);
if (dev->txq.qlen >= TX_QLEN (dev))
netif_stop_queue (net);
}
diff --git a/drivers/net/usb/zaurus.c b/drivers/net/usb/zaurus.c
index 1a2234c20514..c1e6a446d13c 100644
--- a/drivers/net/usb/zaurus.c
+++ b/drivers/net/usb/zaurus.c
@@ -332,6 +332,11 @@ static const struct usb_device_id products [] = {
.driver_info = ZAURUS_PXA_INFO,
},
{
+ /* Motorola Rokr E6 */
+ USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6027, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long) &bogus_mdlm_info,
+}, {
/* Motorola MOTOMAGX phones */
USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM,
USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
@@ -349,6 +354,13 @@ static const struct usb_device_id products [] = {
ZAURUS_MASTER_INTERFACE,
.driver_info = OLYMPUS_MXL_INFO,
},
+
+/* Logitech Harmony 900 - uses the pseudo-MDLM (BLAN) driver */
+{
+ USB_DEVICE_AND_INTERFACE_INFO(0x046d, 0xc11f, USB_CLASS_COMM,
+ USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
+ .driver_info = (unsigned long) &bogus_mdlm_info,
+},
{ }, // END
};
MODULE_DEVICE_TABLE(usb, products);
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 4bf7c6d4ab90..6c0a3b0f0afd 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -421,7 +421,9 @@ static void veth_dellink(struct net_device *dev, struct list_head *head)
unregister_netdevice_queue(peer, head);
}
-static const struct nla_policy veth_policy[VETH_INFO_MAX + 1];
+static const struct nla_policy veth_policy[VETH_INFO_MAX + 1] = {
+ [VETH_INFO_PEER] = { .len = sizeof(struct ifinfomsg) },
+};
static struct rtnl_link_ops veth_link_ops = {
.kind = DRV_NAME,
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 06daa9d6fee8..c7e493461e0a 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -2513,9 +2513,6 @@ static int velocity_close(struct net_device *dev)
if (dev->irq != 0)
free_irq(dev->irq, dev);
- /* Power down the chip */
- pci_set_power_state(vptr->pdev, PCI_D3hot);
-
velocity_free_rings(vptr);
vptr->flags &= (~VELOCITY_FLAGS_OPENED);
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 67402350d0df..0ef676dcb9c3 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -830,13 +830,8 @@ vmxnet3_parse_and_copy_hdr(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
ctx->l4_hdr_size = ((struct tcphdr *)
skb_transport_header(skb))->doff * 4;
else if (iph->protocol == IPPROTO_UDP)
- /*
- * Use tcp header size so that bytes to
- * be copied are more than required by
- * the device.
- */
ctx->l4_hdr_size =
- sizeof(struct tcphdr);
+ sizeof(struct udphdr);
else
ctx->l4_hdr_size = 0;
} else {
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index e08d75e3f170..862be0500091 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -69,10 +69,10 @@
/*
* Version numbers
*/
-#define VMXNET3_DRIVER_VERSION_STRING "1.1.18.0-k"
+#define VMXNET3_DRIVER_VERSION_STRING "1.1.29.0-k"
/* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */
-#define VMXNET3_DRIVER_VERSION_NUM 0x01011200
+#define VMXNET3_DRIVER_VERSION_NUM 0x01011D00
#if defined(CONFIG_PCI_MSI)
/* RSS only makes sense if MSI-X is supported. */
diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c
index 2edd8fe1c1f3..0a998638e1b5 100644
--- a/drivers/net/wimax/i2400m/netdev.c
+++ b/drivers/net/wimax/i2400m/netdev.c
@@ -606,7 +606,8 @@ static void i2400m_get_drvinfo(struct net_device *net_dev,
struct i2400m *i2400m = net_dev_to_i2400m(net_dev);
strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver) - 1);
- strncpy(info->fw_version, i2400m->fw_name, sizeof(info->fw_version) - 1);
+ strncpy(info->fw_version,
+ i2400m->fw_name ? : "", sizeof(info->fw_version) - 1);
if (net_dev->dev.parent)
strncpy(info->bus_info, dev_name(net_dev->dev.parent),
sizeof(info->bus_info) - 1);
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index 441bb33f17ad..0f23b1a789e3 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -489,8 +489,6 @@ static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah)
ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows);
ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows);
ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows);
- ATH_ALLOC_BANK(ah->addac5416_21,
- ah->iniAddac.ia_rows * ah->iniAddac.ia_columns);
ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows);
return 0;
@@ -519,7 +517,6 @@ static void ar5008_hw_rf_free_ext_banks(struct ath_hw *ah)
ATH_FREE_BANK(ah->analogBank6Data);
ATH_FREE_BANK(ah->analogBank6TPCData);
ATH_FREE_BANK(ah->analogBank7Data);
- ATH_FREE_BANK(ah->addac5416_21);
ATH_FREE_BANK(ah->bank6Temp);
#undef ATH_FREE_BANK
@@ -799,27 +796,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
ah->eep_ops->set_addac(ah, chan);
- if (AR_SREV_5416_22_OR_LATER(ah)) {
- REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
- } else {
- struct ar5416IniArray temp;
- u32 addacSize =
- sizeof(u32) * ah->iniAddac.ia_rows *
- ah->iniAddac.ia_columns;
-
- /* For AR5416 2.0/2.1 */
- memcpy(ah->addac5416_21,
- ah->iniAddac.ia_array, addacSize);
-
- /* override CLKDRV value at [row, column] = [31, 1] */
- (ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0;
-
- temp.ia_array = ah->addac5416_21;
- temp.ia_columns = ah->iniAddac.ia_columns;
- temp.ia_rows = ah->iniAddac.ia_rows;
- REG_WRITE_ARRAY(&temp, 1, regWrites);
- }
-
+ REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
ENABLE_REGWRITE_BUFFER(ah);
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index c32f9d1b2152..30bf703c0448 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -179,6 +179,25 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac,
ARRAY_SIZE(ar5416Addac), 2);
}
+
+ /* iniAddac needs to be modified for these chips */
+ if (AR_SREV_9160(ah) || !AR_SREV_5416_22_OR_LATER(ah)) {
+ struct ar5416IniArray *addac = &ah->iniAddac;
+ u32 size = sizeof(u32) * addac->ia_rows * addac->ia_columns;
+ u32 *data;
+
+ data = kmalloc(size, GFP_KERNEL);
+ if (!data)
+ return;
+
+ memcpy(data, addac->ia_array, size);
+ addac->ia_array = data;
+
+ if (!AR_SREV_5416_22_OR_LATER(ah)) {
+ /* override CLKDRV value */
+ INI_RA(addac, 31,1) = 0;
+ }
+ }
}
/* Support for Japan ch.14 (2484) spread */
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index a1250c586e40..1f2f97f6038f 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -19,7 +19,6 @@
/* Common calibration code */
-#define ATH9K_NF_TOO_HIGH -60
static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
{
@@ -335,10 +334,10 @@ static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf)
"NF calibrated [%s] [chain %d] is %d\n",
(i >= 3 ? "ext" : "ctl"), i % 3, nf[i]);
- if (nf[i] > ATH9K_NF_TOO_HIGH) {
+ if (nf[i] > limit->max) {
ath_dbg(common, ATH_DBG_CALIBRATE,
"NF[%d] (%d) > MAX (%d), correcting to MAX\n",
- i, nf[i], ATH9K_NF_TOO_HIGH);
+ i, nf[i], limit->max);
nf[i] = limit->max;
} else if (nf[i] < limit->min) {
ath_dbg(common, ATH_DBG_CALIBRATE,
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 939cc9d76c2e..9dc2666fd1c9 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -763,7 +763,6 @@ struct ath_hw {
u32 *analogBank6Data;
u32 *analogBank6TPCData;
u32 *analogBank7Data;
- u32 *addac5416_21;
u32 *bank6Temp;
u8 txpower_limit;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 5362306d4034..a126a3e238f6 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1828,6 +1828,9 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,
struct ath_softc *sc = hw->priv;
struct ath_node *an = (struct ath_node *) sta->drv_priv;
+ if (!(sc->sc_flags & SC_OP_TXAGGR))
+ return;
+
switch (cmd) {
case STA_NOTIFY_SLEEP:
an->sleeping = true;
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index ba7f36ab0a74..9d965e37b00a 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -1252,7 +1252,9 @@ static void ath_rc_init(struct ath_softc *sc,
ath_rc_priv->max_valid_rate = k;
ath_rc_sort_validrates(rate_table, ath_rc_priv);
- ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
+ ath_rc_priv->rate_max_phy = (k > 4) ?
+ ath_rc_priv->valid_rate_index[k-4] :
+ ath_rc_priv->valid_rate_index[k-1];
ath_rc_priv->rate_table = rate_table;
ath_dbg(common, ATH_DBG_CONFIG,
@@ -1326,7 +1328,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
fc = hdr->frame_control;
for (i = 0; i < sc->hw->max_rates; i++) {
struct ieee80211_tx_rate *rate = &tx_info->status.rates[i];
- if (!rate->count)
+ if (rate->idx < 0 || !rate->count)
break;
final_ts_idx = i;
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index e94084fcf6f5..f190f3219fc5 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -1245,6 +1245,7 @@ static bool carl9170_tx_ps_drop(struct ar9170 *ar, struct sk_buff *skb)
atomic_dec(&ar->tx_ampdu_upload);
tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+ carl9170_release_dev_space(ar, skb);
carl9170_tx_status(ar, skb, false);
return true;
}
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index 87813c33bdc2..b2707d733e92 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -2182,6 +2182,7 @@ static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
{
int rc = 0;
unsigned long flags;
+ unsigned long now, end;
spin_lock_irqsave(&priv->lock, flags);
if (priv->status & STATUS_HCMD_ACTIVE) {
@@ -2223,10 +2224,20 @@ static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd)
}
spin_unlock_irqrestore(&priv->lock, flags);
+ now = jiffies;
+ end = now + HOST_COMPLETE_TIMEOUT;
+again:
rc = wait_event_interruptible_timeout(priv->wait_command_queue,
!(priv->
status & STATUS_HCMD_ACTIVE),
- HOST_COMPLETE_TIMEOUT);
+ end - now);
+ if (rc < 0) {
+ now = jiffies;
+ if (time_before(now, end))
+ goto again;
+ rc = 0;
+ }
+
if (rc == 0) {
spin_lock_irqsave(&priv->lock, flags);
if (priv->status & STATUS_HCMD_ACTIVE) {
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945.c b/drivers/net/wireless/iwlegacy/iwl-3945.c
index dcc1552c0464..effeabb031b5 100644
--- a/drivers/net/wireless/iwlegacy/iwl-3945.c
+++ b/drivers/net/wireless/iwlegacy/iwl-3945.c
@@ -1872,11 +1872,12 @@ static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
struct iwl_priv *priv = container_of(work, struct iwl_priv,
_3945.thermal_periodic.work);
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
- return;
-
mutex_lock(&priv->mutex);
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status) || priv->txq == NULL)
+ goto out;
+
iwl3945_reg_txpower_periodic(priv);
+out:
mutex_unlock(&priv->mutex);
}
diff --git a/drivers/net/wireless/iwlegacy/iwl3945-base.c b/drivers/net/wireless/iwlegacy/iwl3945-base.c
index 421d5c8b8e3f..101a2c2fe177 100644
--- a/drivers/net/wireless/iwlegacy/iwl3945-base.c
+++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c
@@ -2763,7 +2763,7 @@ static void iwl3945_bg_alive_start(struct work_struct *data)
container_of(data, struct iwl_priv, alive_start.work);
mutex_lock(&priv->mutex);
- if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status) || priv->txq == NULL)
goto out;
iwl3945_alive_start(priv);
@@ -2910,14 +2910,13 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
IWL_WARN(priv, "Invalid scan band\n");
return -EIO;
}
-
/*
- * If active scaning is requested but a certain channel
- * is marked passive, we can do active scanning if we
- * detect transmissions.
+ * If active scaning is requested but a certain channel is marked
+ * passive, we can do active scanning if we detect transmissions. For
+ * passive only scanning disable switching to active on any channel.
*/
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
- IWL_GOOD_CRC_TH_DISABLED;
+ IWL_GOOD_CRC_TH_NEVER;
if (!priv->is_internal_short_scan) {
scan->tx_cmd.len = cpu_to_le16(
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index f803fb62f8bc..857cf613092f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -2023,6 +2023,7 @@ static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
case IEEE80211_SMPS_STATIC:
case IEEE80211_SMPS_DYNAMIC:
return IWL_NUM_IDLE_CHAINS_SINGLE;
+ case IEEE80211_SMPS_AUTOMATIC:
case IEEE80211_SMPS_OFF:
return active_cnt;
default:
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 592b0cfcf717..2aed7a05e2cd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -878,6 +878,7 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
if ((priv->bt_traffic_load != priv->last_bt_traffic_load) ||
(priv->bt_full_concurrent != full_concurrent)) {
priv->bt_full_concurrent = full_concurrent;
+ priv->last_bt_traffic_load = priv->bt_traffic_load;
/* Update uCode's rate table. */
tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index b849ad79e145..272bcdfe53a4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -442,6 +442,9 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
mutex_lock(&priv->mutex);
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ goto out;
+
if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
goto out;
@@ -490,8 +493,8 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
if (ctx->ht.enabled) {
/* if HT40 is used, it should not change
* after associated except channel switch */
- if (iwl_is_associated_ctx(ctx) &&
- !ctx->ht.is_40mhz)
+ if (!ctx->ht.is_40mhz ||
+ !iwl_is_associated_ctx(ctx))
iwlagn_config_ht40(conf, ctx);
} else
ctx->ht.is_40mhz = false;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
index 0bd722cee5ae..5c9999db33ba 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c
@@ -477,7 +477,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
sizeof(struct iwl_keyinfo));
priv->stations[sta_id].sta.key.key_flags =
STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
- priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
+ priv->stations[sta_id].sta.key.key_offset = keyconf->hw_key_idx;
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 4974cd7837cb..67cd2e3b6b6c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -385,7 +385,10 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
tx_cmd->tid_tspec = qc[0] & 0xf;
tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
} else {
- tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+ if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
+ tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+ else
+ tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
}
priv->cfg->ops->utils->tx_cmd_protection(priv, info, fc, &tx_flags);
@@ -775,10 +778,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd));
iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
- /* Set up entry for this TFD in Tx byte-count array */
- if (info->flags & IEEE80211_TX_CTL_AMPDU)
- iwlagn_txq_update_byte_cnt_tbl(priv, txq,
- le16_to_cpu(tx_cmd->len));
+ iwlagn_txq_update_byte_cnt_tbl(priv, txq, le16_to_cpu(tx_cmd->len));
pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys,
firstlen, PCI_DMA_BIDIRECTIONAL);
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
index b33ceb1c066a..d895ff972d66 100644
--- a/drivers/net/wireless/p54/p54spi.c
+++ b/drivers/net/wireless/p54/p54spi.c
@@ -623,19 +623,19 @@ static int __devinit p54spi_probe(struct spi_device *spi)
ret = spi_setup(spi);
if (ret < 0) {
dev_err(&priv->spi->dev, "spi_setup failed");
- goto err_free_common;
+ goto err_free;
}
ret = gpio_request(p54spi_gpio_power, "p54spi power");
if (ret < 0) {
dev_err(&priv->spi->dev, "power GPIO request failed: %d", ret);
- goto err_free_common;
+ goto err_free;
}
ret = gpio_request(p54spi_gpio_irq, "p54spi irq");
if (ret < 0) {
dev_err(&priv->spi->dev, "irq GPIO request failed: %d", ret);
- goto err_free_common;
+ goto err_free_gpio_power;
}
gpio_direction_output(p54spi_gpio_power, 0);
@@ -646,7 +646,7 @@ static int __devinit p54spi_probe(struct spi_device *spi)
priv->spi);
if (ret < 0) {
dev_err(&priv->spi->dev, "request_irq() failed");
- goto err_free_common;
+ goto err_free_gpio_irq;
}
irq_set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING);
@@ -678,6 +678,12 @@ static int __devinit p54spi_probe(struct spi_device *spi)
return 0;
err_free_common:
+ free_irq(gpio_to_irq(p54spi_gpio_irq), spi);
+err_free_gpio_irq:
+ gpio_free(p54spi_gpio_irq);
+err_free_gpio_power:
+ gpio_free(p54spi_gpio_power);
+err_free:
p54_free_common(priv->hw);
return ret;
}
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 55cd3e1f75bc..dab7dc16a6cb 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -426,7 +426,6 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
- int mask = (state == STATE_RADIO_IRQ_ON);
u32 reg;
unsigned long flags;
@@ -448,25 +447,14 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
}
spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
- rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
- rt2x00_set_field32(&reg, INT_MASK_CSR_RXDELAYINT, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_TXDELAYINT, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_AC0_DMA_DONE, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_AC1_DMA_DONE, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_AC2_DMA_DONE, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_AC3_DMA_DONE, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_HCCA_DMA_DONE, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_MGMT_DMA_DONE, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_MCU_COMMAND, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_RXTX_COHERENT, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_TBTT, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_PRE_TBTT, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, mask);
- rt2x00_set_field32(&reg, INT_MASK_CSR_GPTIMER, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_RX_COHERENT, 0);
- rt2x00_set_field32(&reg, INT_MASK_CSR_TX_COHERENT, 0);
+ reg = 0;
+ if (state == STATE_RADIO_IRQ_ON) {
+ rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, 1);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_TBTT, 1);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_PRE_TBTT, 1);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, 1);
+ rt2x00_set_field32(&reg, INT_MASK_CSR_AUTO_WAKEUP, 1);
+ }
rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 6e7fe941b95d..0781fb0e77f1 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -819,11 +819,14 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x050d, 0x8053) },
{ USB_DEVICE(0x050d, 0x805c) },
{ USB_DEVICE(0x050d, 0x815c) },
+ { USB_DEVICE(0x050d, 0x825a) },
{ USB_DEVICE(0x050d, 0x825b) },
{ USB_DEVICE(0x050d, 0x935a) },
{ USB_DEVICE(0x050d, 0x935b) },
/* Buffalo */
{ USB_DEVICE(0x0411, 0x00e8) },
+ { USB_DEVICE(0x0411, 0x0158) },
+ { USB_DEVICE(0x0411, 0x015d) },
{ USB_DEVICE(0x0411, 0x016f) },
{ USB_DEVICE(0x0411, 0x01a2) },
/* Corega */
@@ -838,13 +841,17 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x07d1, 0x3c0e) },
{ USB_DEVICE(0x07d1, 0x3c0f) },
{ USB_DEVICE(0x07d1, 0x3c11) },
+ { USB_DEVICE(0x07d1, 0x3c13) },
+ { USB_DEVICE(0x07d1, 0x3c15) },
{ USB_DEVICE(0x07d1, 0x3c16) },
+ { USB_DEVICE(0x2001, 0x3c1b) },
/* Draytek */
{ USB_DEVICE(0x07fa, 0x7712) },
/* Edimax */
{ USB_DEVICE(0x7392, 0x7711) },
{ USB_DEVICE(0x7392, 0x7717) },
{ USB_DEVICE(0x7392, 0x7718) },
+ { USB_DEVICE(0x7392, 0x7722) },
/* Encore */
{ USB_DEVICE(0x203d, 0x1480) },
{ USB_DEVICE(0x203d, 0x14a9) },
@@ -878,6 +885,8 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x13b1, 0x0031) },
{ USB_DEVICE(0x1737, 0x0070) },
{ USB_DEVICE(0x1737, 0x0071) },
+ { USB_DEVICE(0x1737, 0x0077) },
+ { USB_DEVICE(0x1737, 0x0078) },
/* Logitec */
{ USB_DEVICE(0x0789, 0x0162) },
{ USB_DEVICE(0x0789, 0x0163) },
@@ -901,9 +910,13 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0db0, 0x871b) },
{ USB_DEVICE(0x0db0, 0x871c) },
{ USB_DEVICE(0x0db0, 0x899a) },
+ /* Ovislink */
+ { USB_DEVICE(0x1b75, 0x3071) },
+ { USB_DEVICE(0x1b75, 0x3072) },
/* Para */
{ USB_DEVICE(0x20b8, 0x8888) },
/* Pegatron */
+ { USB_DEVICE(0x1d4d, 0x0002) },
{ USB_DEVICE(0x1d4d, 0x000c) },
{ USB_DEVICE(0x1d4d, 0x000e) },
{ USB_DEVICE(0x1d4d, 0x0011) },
@@ -941,6 +954,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0df6, 0x0048) },
{ USB_DEVICE(0x0df6, 0x0051) },
{ USB_DEVICE(0x0df6, 0x005f) },
+ { USB_DEVICE(0x0df6, 0x0060) },
/* SMC */
{ USB_DEVICE(0x083a, 0x6618) },
{ USB_DEVICE(0x083a, 0x7511) },
@@ -955,7 +969,9 @@ static struct usb_device_id rt2800usb_device_table[] = {
/* Sparklan */
{ USB_DEVICE(0x15a9, 0x0006) },
/* Sweex */
+ { USB_DEVICE(0x177f, 0x0153) },
{ USB_DEVICE(0x177f, 0x0302) },
+ { USB_DEVICE(0x177f, 0x0313) },
/* U-Media */
{ USB_DEVICE(0x157e, 0x300e) },
{ USB_DEVICE(0x157e, 0x3013) },
@@ -973,6 +989,8 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0586, 0x341e) },
{ USB_DEVICE(0x0586, 0x343e) },
#ifdef CONFIG_RT2800USB_RT33XX
+ /* Belkin */
+ { USB_DEVICE(0x050d, 0x945b) },
/* Ralink */
{ USB_DEVICE(0x148f, 0x3370) },
{ USB_DEVICE(0x148f, 0x8070) },
@@ -997,6 +1015,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x148f, 0x3572) },
/* Sitecom */
{ USB_DEVICE(0x0df6, 0x0041) },
+ { USB_DEVICE(0x0df6, 0x0062) },
/* Toshiba */
{ USB_DEVICE(0x0930, 0x0a07) },
/* Zinwell */
@@ -1036,27 +1055,24 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x13d3, 0x3322) },
/* Belkin */
{ USB_DEVICE(0x050d, 0x1003) },
- { USB_DEVICE(0x050d, 0x825a) },
/* Buffalo */
{ USB_DEVICE(0x0411, 0x012e) },
{ USB_DEVICE(0x0411, 0x0148) },
{ USB_DEVICE(0x0411, 0x0150) },
- { USB_DEVICE(0x0411, 0x015d) },
/* Corega */
{ USB_DEVICE(0x07aa, 0x0041) },
{ USB_DEVICE(0x07aa, 0x0042) },
{ USB_DEVICE(0x18c5, 0x0008) },
/* D-Link */
{ USB_DEVICE(0x07d1, 0x3c0b) },
- { USB_DEVICE(0x07d1, 0x3c13) },
- { USB_DEVICE(0x07d1, 0x3c15) },
{ USB_DEVICE(0x07d1, 0x3c17) },
{ USB_DEVICE(0x2001, 0x3c17) },
/* Edimax */
{ USB_DEVICE(0x7392, 0x4085) },
- { USB_DEVICE(0x7392, 0x7722) },
/* Encore */
{ USB_DEVICE(0x203d, 0x14a1) },
+ /* Fujitsu Stylistic 550 */
+ { USB_DEVICE(0x1690, 0x0761) },
/* Gemtek */
{ USB_DEVICE(0x15a9, 0x0010) },
/* Gigabyte */
@@ -1068,20 +1084,13 @@ static struct usb_device_id rt2800usb_device_table[] = {
/* LevelOne */
{ USB_DEVICE(0x1740, 0x0605) },
{ USB_DEVICE(0x1740, 0x0615) },
- /* Linksys */
- { USB_DEVICE(0x1737, 0x0077) },
- { USB_DEVICE(0x1737, 0x0078) },
/* Logitec */
{ USB_DEVICE(0x0789, 0x0168) },
{ USB_DEVICE(0x0789, 0x0169) },
/* Motorola */
{ USB_DEVICE(0x100d, 0x9032) },
- /* Ovislink */
- { USB_DEVICE(0x1b75, 0x3071) },
- { USB_DEVICE(0x1b75, 0x3072) },
/* Pegatron */
{ USB_DEVICE(0x05a6, 0x0101) },
- { USB_DEVICE(0x1d4d, 0x0002) },
{ USB_DEVICE(0x1d4d, 0x0010) },
/* Planex */
{ USB_DEVICE(0x2019, 0x5201) },
@@ -1095,16 +1104,11 @@ static struct usb_device_id rt2800usb_device_table[] = {
{ USB_DEVICE(0x0df6, 0x004a) },
{ USB_DEVICE(0x0df6, 0x004d) },
{ USB_DEVICE(0x0df6, 0x0053) },
- { USB_DEVICE(0x0df6, 0x0060) },
- { USB_DEVICE(0x0df6, 0x0062) },
/* SMC */
{ USB_DEVICE(0x083a, 0xa512) },
{ USB_DEVICE(0x083a, 0xc522) },
{ USB_DEVICE(0x083a, 0xd522) },
{ USB_DEVICE(0x083a, 0xf511) },
- /* Sweex */
- { USB_DEVICE(0x177f, 0x0153) },
- { USB_DEVICE(0x177f, 0x0313) },
/* Zyxel */
{ USB_DEVICE(0x0586, 0x341a) },
#endif
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index dffaa8f45f19..5bd2c55c991f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -410,10 +410,14 @@ void rt2x00lib_txdone(struct queue_entry *entry,
/*
* If the data queue was below the threshold before the txdone
* handler we must make sure the packet queue in the mac80211 stack
- * is reenabled when the txdone handler has finished.
+ * is reenabled when the txdone handler has finished. This has to be
+ * serialized with rt2x00mac_tx(), otherwise we can wake up queue
+ * before it was stopped.
*/
+ spin_lock_bh(&entry->queue->tx_lock);
if (!rt2x00queue_threshold(entry->queue))
rt2x00queue_unpause_queue(entry->queue);
+ spin_unlock_bh(&entry->queue->tx_lock);
}
EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index a76fdbe6d7dc..bc159bed4f6d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -152,13 +152,22 @@ void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
if (unlikely(rt2x00queue_write_tx_frame(queue, skb, false)))
goto exit_fail;
+ /*
+ * Pausing queue has to be serialized with rt2x00lib_txdone(). Note
+ * we should not use spin_lock_bh variant as bottom halve was already
+ * disabled before ieee80211_xmit() call.
+ */
+ spin_lock(&queue->tx_lock);
if (rt2x00queue_threshold(queue))
rt2x00queue_pause_queue(queue);
+ spin_unlock(&queue->tx_lock);
return;
exit_fail:
+ spin_lock(&queue->tx_lock);
rt2x00queue_pause_queue(queue);
+ spin_unlock(&queue->tx_lock);
exit_free_skb:
dev_kfree_skb_any(skb);
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 2886d250de5e..76f26ad044a2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -562,6 +562,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
u8 rate_idx, rate_flags;
int ret = 0;
+ /*
+ * That function must be called with bh disabled.
+ */
spin_lock(&queue->tx_lock);
entry = rt2x00queue_get_entry(queue, Q_INDEX);
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index c872a232427f..c29f3980c1fd 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -954,8 +954,13 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw)
memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));
ring = &rtlpci->tx_ring[BEACON_QUEUE];
pskb = __skb_dequeue(&ring->queue);
- if (pskb)
+ if (pskb) {
+ struct rtl_tx_desc *entry = &ring->desc[ring->idx];
+ pci_unmap_single(rtlpci->pdev, rtlpriv->cfg->ops->get_desc(
+ (u8 *) entry, true, HW_DESC_TXBUFF_ADDR),
+ pskb->len, PCI_DMA_TODEVICE);
kfree_skb(pskb);
+ }
/*NB: the beacon data buffer must be 32-bit aligned. */
pskb = ieee80211_beacon_get(hw, mac->vif);
@@ -1180,10 +1185,12 @@ static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw,
ring->idx = (ring->idx + 1) % ring->entries;
}
- pci_free_consistent(rtlpci->pdev,
- sizeof(*ring->desc) * ring->entries,
- ring->desc, ring->dma);
- ring->desc = NULL;
+ if (ring->desc) {
+ pci_free_consistent(rtlpci->pdev,
+ sizeof(*ring->desc) * ring->entries,
+ ring->desc, ring->dma);
+ ring->desc = NULL;
+ }
}
static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci)
@@ -1207,12 +1214,14 @@ static void _rtl_pci_free_rx_ring(struct rtl_pci *rtlpci)
kfree_skb(skb);
}
- pci_free_consistent(rtlpci->pdev,
+ if (rtlpci->rx_ring[rx_queue_idx].desc) {
+ pci_free_consistent(rtlpci->pdev,
sizeof(*rtlpci->rx_ring[rx_queue_idx].
desc) * rtlpci->rxringcount,
rtlpci->rx_ring[rx_queue_idx].desc,
rtlpci->rx_ring[rx_queue_idx].dma);
- rtlpci->rx_ring[rx_queue_idx].desc = NULL;
+ rtlpci->rx_ring[rx_queue_idx].desc = NULL;
+ }
}
}
@@ -1979,6 +1988,7 @@ void rtl_pci_disconnect(struct pci_dev *pdev)
rtl_deinit_deferred_work(hw);
rtlpriv->intf_ops->adapter_stop(hw);
}
+ rtlpriv->cfg->ops->disable_interrupt(hw);
/*deinit rfkill */
rtl_deinit_rfkill(hw);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
index 97183829b9be..2d33d7d8403f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
@@ -523,6 +523,10 @@ void rtl92c_dm_write_dig(struct ieee80211_hw *hw)
dm_digtable.cur_igvalue, dm_digtable.pre_igvalue,
dm_digtable.backoff_val));
+ dm_digtable.cur_igvalue += 2;
+ if (dm_digtable.cur_igvalue > 0x3f)
+ dm_digtable.cur_igvalue = 0x3f;
+
if (dm_digtable.pre_igvalue != dm_digtable.cur_igvalue) {
rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
dm_digtable.cur_igvalue);
@@ -1218,13 +1222,18 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
("PreState = %d, CurState = %d\n",
p_ra->pre_ratr_state, p_ra->ratr_state));
- rcu_read_lock();
- sta = ieee80211_find_sta(mac->vif, mac->bssid);
+ /* Only the PCI card uses sta in the update rate table
+ * callback routine */
+ if (rtlhal->interface == INTF_PCI) {
+ rcu_read_lock();
+ sta = ieee80211_find_sta(mac->vif, mac->bssid);
+ }
rtlpriv->cfg->ops->update_rate_tbl(hw, sta,
p_ra->ratr_state);
p_ra->pre_ratr_state = p_ra->ratr_state;
- rcu_read_unlock();
+ if (rtlhal->interface == INTF_PCI)
+ rcu_read_unlock();
}
}
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
index 3b5af0113d7f..0c77a14a3821 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c
@@ -196,6 +196,8 @@ static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw,
/* Allocate skb buffer to contain firmware */
/* info and tx descriptor info. */
skb = dev_alloc_skb(frag_length);
+ if (!skb)
+ return false;
skb_reserve(skb, extra_descoffset);
seg_ptr = (u8 *)skb_put(skb, (u32)(frag_length -
extra_descoffset));
@@ -575,6 +577,8 @@ static bool _rtl92s_firmware_set_h2c_cmd(struct ieee80211_hw *hw, u8 h2c_cmd,
len = _rtl92s_get_h2c_cmdlen(MAX_TRANSMIT_BUFFER_SIZE, 1, &cmd_len);
skb = dev_alloc_skb(len);
+ if (!skb)
+ return false;
cb_desc = (struct rtl_tcb_desc *)(skb->cb);
cb_desc->queue_index = TXCMD_QUEUE;
cb_desc->cmd_or_init = DESC_PACKET_TYPE_NORMAL;
diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/wl1251/main.c
index a14a48c99cdc..de9210c102eb 100644
--- a/drivers/net/wireless/wl1251/main.c
+++ b/drivers/net/wireless/wl1251/main.c
@@ -479,6 +479,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
cancel_work_sync(&wl->irq_work);
cancel_work_sync(&wl->tx_work);
cancel_work_sync(&wl->filter_work);
+ cancel_delayed_work_sync(&wl->elp_work);
mutex_lock(&wl->mutex);
diff --git a/drivers/net/wireless/wl1251/sdio.c b/drivers/net/wireless/wl1251/sdio.c
index f51a0241a440..4cf5c2e201d5 100644
--- a/drivers/net/wireless/wl1251/sdio.c
+++ b/drivers/net/wireless/wl1251/sdio.c
@@ -259,6 +259,7 @@ static int wl1251_sdio_probe(struct sdio_func *func,
}
if (wl->irq) {
+ irq_set_status_flags(wl->irq, IRQ_NOAUTOEN);
ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl);
if (ret < 0) {
wl1251_error("request_irq() failed: %d", ret);
@@ -266,7 +267,6 @@ static int wl1251_sdio_probe(struct sdio_func *func,
}
irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
- disable_irq(wl->irq);
wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq;
wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq;
@@ -314,8 +314,8 @@ static void __devexit wl1251_sdio_remove(struct sdio_func *func)
if (wl->irq)
free_irq(wl->irq, wl);
- kfree(wl_sdio);
wl1251_free_hw(wl);
+ kfree(wl_sdio);
sdio_claim_host(func);
sdio_release_irq(func);
diff --git a/drivers/net/wireless/wl1251/spi.c b/drivers/net/wireless/wl1251/spi.c
index af6448c4d3e2..49f3651423de 100644
--- a/drivers/net/wireless/wl1251/spi.c
+++ b/drivers/net/wireless/wl1251/spi.c
@@ -280,6 +280,7 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi)
wl->use_eeprom = pdata->use_eeprom;
+ irq_set_status_flags(wl->irq, IRQ_NOAUTOEN);
ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl);
if (ret < 0) {
wl1251_error("request_irq() failed: %d", ret);
@@ -288,8 +289,6 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi)
irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
- disable_irq(wl->irq);
-
ret = wl1251_init_ieee80211(wl);
if (ret)
goto out_irq;
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index b07f8b7e5f11..e0e16888fe8e 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -328,6 +328,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
nvs_ptr += 3;
for (i = 0; i < burst_len; i++) {
+ if (nvs_ptr + 3 >= (u8 *) wl->nvs + nvs_len)
+ goto out_badnvs;
+
val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
| (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
@@ -339,6 +342,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
nvs_ptr += 4;
dest_addr += 4;
}
+
+ if (nvs_ptr >= (u8 *) wl->nvs + nvs_len)
+ goto out_badnvs;
}
/*
@@ -350,6 +356,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
*/
nvs_ptr = (u8 *)wl->nvs +
ALIGN(nvs_ptr - (u8 *)wl->nvs + 7, 4);
+
+ if (nvs_ptr >= (u8 *) wl->nvs + nvs_len)
+ goto out_badnvs;
+
nvs_len -= nvs_ptr - (u8 *)wl->nvs;
/* Now we must set the partition correctly */
@@ -365,6 +375,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
kfree(nvs_aligned);
return 0;
+
+out_badnvs:
+ wl1271_error("nvs data is malformed");
+ return -EILSEQ;
}
static void wl1271_boot_enable_interrupts(struct wl1271 *wl)
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 42935ac72663..b8ec8cd69b04 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -121,6 +121,11 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
if (!wl->nvs)
return -ENODEV;
+ if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
+ wl1271_warning("FEM index from INI out of bounds");
+ return -EINVAL;
+ }
+
gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
if (!gen_parms)
return -ENOMEM;
@@ -144,6 +149,12 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
gp->tx_bip_fem_manufacturer =
gen_parms->general_params.tx_bip_fem_manufacturer;
+ if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
+ wl1271_warning("FEM index from FW out of bounds");
+ ret = -EINVAL;
+ goto out;
+ }
+
wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n",
answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer);
@@ -163,6 +174,11 @@ int wl128x_cmd_general_parms(struct wl1271 *wl)
if (!wl->nvs)
return -ENODEV;
+ if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
+ wl1271_warning("FEM index from ini out of bounds");
+ return -EINVAL;
+ }
+
gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
if (!gen_parms)
return -ENOMEM;
@@ -187,6 +203,12 @@ int wl128x_cmd_general_parms(struct wl1271 *wl)
gp->tx_bip_fem_manufacturer =
gen_parms->general_params.tx_bip_fem_manufacturer;
+ if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
+ wl1271_warning("FEM index from FW out of bounds");
+ ret = -EINVAL;
+ goto out;
+ }
+
wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n",
answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer);
diff --git a/drivers/oprofile/oprofile_files.c b/drivers/oprofile/oprofile_files.c
index 89f63456646f..84a208dbed93 100644
--- a/drivers/oprofile/oprofile_files.c
+++ b/drivers/oprofile/oprofile_files.c
@@ -45,7 +45,7 @@ static ssize_t timeout_write(struct file *file, char const __user *buf,
return -EINVAL;
retval = oprofilefs_ulong_from_user(&val, buf, count);
- if (retval)
+ if (retval <= 0)
return retval;
retval = oprofile_set_timeout(val);
@@ -84,7 +84,7 @@ static ssize_t depth_write(struct file *file, char const __user *buf, size_t cou
return -EINVAL;
retval = oprofilefs_ulong_from_user(&val, buf, count);
- if (retval)
+ if (retval <= 0)
return retval;
retval = oprofile_set_ulong(&oprofile_backtrace_depth, val);
@@ -141,9 +141,10 @@ static ssize_t enable_write(struct file *file, char const __user *buf, size_t co
return -EINVAL;
retval = oprofilefs_ulong_from_user(&val, buf, count);
- if (retval)
+ if (retval <= 0)
return retval;
+ retval = 0;
if (val)
retval = oprofile_start();
else
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c
index e9ff6f7770be..1c0b799b30bc 100644
--- a/drivers/oprofile/oprofilefs.c
+++ b/drivers/oprofile/oprofilefs.c
@@ -60,6 +60,13 @@ ssize_t oprofilefs_ulong_to_user(unsigned long val, char __user *buf, size_t cou
}
+/*
+ * Note: If oprofilefs_ulong_from_user() returns 0, then *val remains
+ * unchanged and might be uninitialized. This follows write syscall
+ * implementation when count is zero: "If count is zero ... [and if]
+ * no errors are detected, 0 will be returned without causing any
+ * other effect." (man 2 write)
+ */
int oprofilefs_ulong_from_user(unsigned long *val, char const __user *buf, size_t count)
{
char tmpbuf[TMPBUFSIZE];
@@ -79,7 +86,7 @@ int oprofilefs_ulong_from_user(unsigned long *val, char const __user *buf, size_
spin_lock_irqsave(&oprofilefs_lock, flags);
*val = simple_strtoul(tmpbuf, NULL, 0);
spin_unlock_irqrestore(&oprofilefs_lock, flags);
- return 0;
+ return count;
}
@@ -99,7 +106,7 @@ static ssize_t ulong_write_file(struct file *file, char const __user *buf, size_
return -EINVAL;
retval = oprofilefs_ulong_from_user(&value, buf, count);
- if (retval)
+ if (retval <= 0)
return retval;
retval = oprofile_set_ulong(file->private_data, value);
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 2f10328bf661..e1749825008d 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -869,5 +869,15 @@ EXPORT_SYMBOL(pci_msi_enabled);
void pci_msi_init_pci_dev(struct pci_dev *dev)
{
+ int pos;
INIT_LIST_HEAD(&dev->msi_list);
+
+ /* Disable the msi hardware to avoid screaming interrupts
+ * during boot. This is the power on reset default so
+ * usually this should be a noop.
+ */
+ pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
+ if (pos)
+ msi_set_enable(dev, pos, 0);
+ msix_set_enable(dev, 0);
}
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index d36f41ea8cbf..56b04bc80a12 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -393,7 +393,6 @@ static int __init acpi_pci_init(void)
if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n");
- pcie_clear_aspm();
pcie_no_aspm();
}
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 6892601fc76f..0ff0182f176a 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -68,7 +68,7 @@ struct pcie_link_state {
struct aspm_latency acceptable[8];
};
-static int aspm_disabled, aspm_force, aspm_clear_state;
+static int aspm_disabled, aspm_force;
static bool aspm_support_enabled = true;
static DEFINE_MUTEX(aspm_lock);
static LIST_HEAD(link_list);
@@ -500,9 +500,6 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
int pos;
u32 reg32;
- if (aspm_clear_state)
- return -EINVAL;
-
/*
* Some functions in a slot might not all be PCIe functions,
* very strange. Disable ASPM for the whole slot
@@ -511,6 +508,16 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
pos = pci_pcie_cap(child);
if (!pos)
return -EINVAL;
+
+ /*
+ * If ASPM is disabled then we're not going to change
+ * the BIOS state. It's safe to continue even if it's a
+ * pre-1.1 device
+ */
+
+ if (aspm_disabled)
+ continue;
+
/*
* Disable ASPM for pre-1.1 PCIe device, we follow MS to use
* RBER bit to determine if a function is 1.1 version device
@@ -574,9 +581,6 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
return;
- if (aspm_disabled && !aspm_clear_state)
- return;
-
/* VIA has a strange chipset, root port is under a bridge */
if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT &&
pdev->bus->self)
@@ -608,7 +612,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
* the BIOS's expectation, we'll do so once pci_enable_device() is
* called.
*/
- if (aspm_policy != POLICY_POWERSAVE || aspm_clear_state) {
+ if (aspm_policy != POLICY_POWERSAVE) {
pcie_config_aspm_path(link);
pcie_set_clkpm(link, policy_to_clkpm_state(link));
}
@@ -649,8 +653,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
struct pci_dev *parent = pdev->bus->self;
struct pcie_link_state *link, *root, *parent_link;
- if ((aspm_disabled && !aspm_clear_state) || !pci_is_pcie(pdev) ||
- !parent || !parent->link_state)
+ if (!pci_is_pcie(pdev) || !parent || !parent->link_state)
return;
if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
(parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
@@ -734,13 +737,18 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
* pci_disable_link_state - disable pci device's link state, so the link will
* never enter specific states
*/
-static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
+static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem,
+ bool force)
{
struct pci_dev *parent = pdev->bus->self;
struct pcie_link_state *link;
- if (aspm_disabled || !pci_is_pcie(pdev))
+ if (aspm_disabled && !force)
return;
+
+ if (!pci_is_pcie(pdev))
+ return;
+
if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
parent = pdev;
@@ -768,16 +776,31 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
void pci_disable_link_state_locked(struct pci_dev *pdev, int state)
{
- __pci_disable_link_state(pdev, state, false);
+ __pci_disable_link_state(pdev, state, false, false);
}
EXPORT_SYMBOL(pci_disable_link_state_locked);
void pci_disable_link_state(struct pci_dev *pdev, int state)
{
- __pci_disable_link_state(pdev, state, true);
+ __pci_disable_link_state(pdev, state, true, false);
}
EXPORT_SYMBOL(pci_disable_link_state);
+void pcie_clear_aspm(struct pci_bus *bus)
+{
+ struct pci_dev *child;
+
+ /*
+ * Clear any ASPM setup that the firmware has carried out on this bus
+ */
+ list_for_each_entry(child, &bus->devices, bus_list) {
+ __pci_disable_link_state(child, PCIE_LINK_STATE_L0S |
+ PCIE_LINK_STATE_L1 |
+ PCIE_LINK_STATE_CLKPM,
+ false, true);
+ }
+}
+
static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
{
int i;
@@ -935,6 +958,7 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
static int __init pcie_aspm_disable(char *str)
{
if (!strcmp(str, "off")) {
+ aspm_policy = POLICY_DEFAULT;
aspm_disabled = 1;
aspm_support_enabled = false;
printk(KERN_INFO "PCIe ASPM is disabled\n");
@@ -947,16 +971,18 @@ static int __init pcie_aspm_disable(char *str)
__setup("pcie_aspm=", pcie_aspm_disable);
-void pcie_clear_aspm(void)
-{
- if (!aspm_force)
- aspm_clear_state = 1;
-}
-
void pcie_no_aspm(void)
{
- if (!aspm_force)
+ /*
+ * Disabling ASPM is intended to prevent the kernel from modifying
+ * existing hardware state, not to clear existing state. To that end:
+ * (a) set policy to POLICY_DEFAULT in order to avoid changing state
+ * (b) prevent userspace from changing policy
+ */
+ if (!aspm_force) {
+ aspm_policy = POLICY_DEFAULT;
aspm_disabled = 1;
+ }
}
/**
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index bafb3c3d4a89..5b3771a7a413 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -657,6 +657,11 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
dev_dbg(&dev->dev, "scanning [bus %02x-%02x] behind bridge, pass %d\n",
secondary, subordinate, pass);
+ if (!primary && (primary != bus->number) && secondary && subordinate) {
+ dev_warn(&dev->dev, "Primary bus is hard wired to 0\n");
+ primary = bus->number;
+ }
+
/* Check if setup is sensible at all */
if (!pass &&
(primary != bus->number || secondary <= bus->number)) {
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index cec462927317..a6b07ddad715 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2822,6 +2822,40 @@ static void __devinit fixup_ti816x_class(struct pci_dev* dev)
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_TI, 0xb800, fixup_ti816x_class);
+/*
+ * Some BIOS implementations leave the Intel GPU interrupts enabled,
+ * even though no one is handling them (f.e. i915 driver is never loaded).
+ * Additionally the interrupt destination is not set up properly
+ * and the interrupt ends up -somewhere-.
+ *
+ * These spurious interrupts are "sticky" and the kernel disables
+ * the (shared) interrupt line after 100.000+ generated interrupts.
+ *
+ * Fix it by disabling the still enabled interrupts.
+ * This resolves crashes often seen on monitor unplug.
+ */
+#define I915_DEIER_REG 0x4400c
+static void __devinit disable_igfx_irq(struct pci_dev *dev)
+{
+ void __iomem *regs = pci_iomap(dev, 0, 0);
+ if (regs == NULL) {
+ dev_warn(&dev->dev, "igfx quirk: Can't iomap PCI device\n");
+ return;
+ }
+
+ /* Check if any interrupt line is still enabled */
+ if (readl(regs + I915_DEIER_REG) != 0) {
+ dev_warn(&dev->dev, "BIOS left Intel GPU interrupts enabled; "
+ "disabling\n");
+
+ writel(0, regs + I915_DEIER_REG);
+ }
+
+ pci_iounmap(dev, regs);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq);
+
static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
struct pci_fixup *end)
{
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 749c2a16012c..1932029de48d 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -1269,10 +1269,8 @@ static int pcmcia_bus_add(struct pcmcia_socket *skt)
static int pcmcia_bus_early_resume(struct pcmcia_socket *skt)
{
- if (!verify_cis_cache(skt)) {
- pcmcia_put_socket(skt);
+ if (!verify_cis_cache(skt))
return 0;
- }
dev_dbg(&skt->dev, "cis mismatch - different card\n");
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index e1c4938b301b..2080b223c74a 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -304,6 +304,10 @@ static struct quirk_entry quirk_fujitsu_amilo_li_1718 = {
.wireless = 2,
};
+static struct quirk_entry quirk_lenovo_ideapad_s205 = {
+ .wireless = 3,
+};
+
/* The Aspire One has a dummy ACPI-WMI interface - disable it */
static struct dmi_system_id __devinitdata acer_blacklist[] = {
{
@@ -450,6 +454,24 @@ static struct dmi_system_id acer_quirks[] = {
},
.driver_data = &quirk_medion_md_98300,
},
+ {
+ .callback = dmi_matched,
+ .ident = "Lenovo Ideapad S205",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "10382LG"),
+ },
+ .driver_data = &quirk_lenovo_ideapad_s205,
+ },
+ {
+ .callback = dmi_matched,
+ .ident = "Lenovo 3000 N200",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "0687A31"),
+ },
+ .driver_data = &quirk_fujitsu_amilo_li_1718,
+ },
{}
};
@@ -542,6 +564,12 @@ struct wmi_interface *iface)
return AE_ERROR;
*value = result & 0x1;
return AE_OK;
+ case 3:
+ err = ec_read(0x78, &result);
+ if (err)
+ return AE_ERROR;
+ *value = result & 0x1;
+ return AE_OK;
default:
err = ec_read(0xA, &result);
if (err)
@@ -648,6 +676,33 @@ static acpi_status AMW0_find_mailled(void)
return AE_OK;
}
+static int AMW0_set_cap_acpi_check_device_found;
+
+static acpi_status AMW0_set_cap_acpi_check_device_cb(acpi_handle handle,
+ u32 level, void *context, void **retval)
+{
+ AMW0_set_cap_acpi_check_device_found = 1;
+ return AE_OK;
+}
+
+static const struct acpi_device_id norfkill_ids[] = {
+ { "VPC2004", 0},
+ { "IBM0068", 0},
+ { "LEN0068", 0},
+ { "SNY5001", 0}, /* sony-laptop in charge */
+ { "", 0},
+};
+
+static int AMW0_set_cap_acpi_check_device(void)
+{
+ const struct acpi_device_id *id;
+
+ for (id = norfkill_ids; id->id[0]; id++)
+ acpi_get_devices(id->id, AMW0_set_cap_acpi_check_device_cb,
+ NULL, NULL);
+ return AMW0_set_cap_acpi_check_device_found;
+}
+
static acpi_status AMW0_set_capabilities(void)
{
struct wmab_args args;
@@ -661,7 +716,9 @@ static acpi_status AMW0_set_capabilities(void)
* work.
*/
if (wmi_has_guid(AMW0_GUID2)) {
- interface->capability |= ACER_CAP_WIRELESS;
+ if ((quirks != &quirk_unknown) ||
+ !AMW0_set_cap_acpi_check_device())
+ interface->capability |= ACER_CAP_WIRELESS;
return AE_OK;
}
@@ -1265,9 +1322,15 @@ static void acer_rfkill_update(struct work_struct *ignored)
u32 state;
acpi_status status;
- status = get_u32(&state, ACER_CAP_WIRELESS);
- if (ACPI_SUCCESS(status))
- rfkill_set_sw_state(wireless_rfkill, !state);
+ if (has_cap(ACER_CAP_WIRELESS)) {
+ status = get_u32(&state, ACER_CAP_WIRELESS);
+ if (ACPI_SUCCESS(status)) {
+ if (quirks->wireless == 3)
+ rfkill_set_hw_state(wireless_rfkill, !state);
+ else
+ rfkill_set_sw_state(wireless_rfkill, !state);
+ }
+ }
if (has_cap(ACER_CAP_BLUETOOTH)) {
status = get_u32(&state, ACER_CAP_BLUETOOTH);
@@ -1334,19 +1397,24 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
static int acer_rfkill_init(struct device *dev)
{
- wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN,
- "acer-wireless", ACER_CAP_WIRELESS);
- if (IS_ERR(wireless_rfkill))
- return PTR_ERR(wireless_rfkill);
+ int err;
+
+ if (has_cap(ACER_CAP_WIRELESS)) {
+ wireless_rfkill = acer_rfkill_register(dev, RFKILL_TYPE_WLAN,
+ "acer-wireless", ACER_CAP_WIRELESS);
+ if (IS_ERR(wireless_rfkill)) {
+ err = PTR_ERR(wireless_rfkill);
+ goto error_wireless;
+ }
+ }
if (has_cap(ACER_CAP_BLUETOOTH)) {
bluetooth_rfkill = acer_rfkill_register(dev,
RFKILL_TYPE_BLUETOOTH, "acer-bluetooth",
ACER_CAP_BLUETOOTH);
if (IS_ERR(bluetooth_rfkill)) {
- rfkill_unregister(wireless_rfkill);
- rfkill_destroy(wireless_rfkill);
- return PTR_ERR(bluetooth_rfkill);
+ err = PTR_ERR(bluetooth_rfkill);
+ goto error_bluetooth;
}
}
@@ -1355,30 +1423,44 @@ static int acer_rfkill_init(struct device *dev)
RFKILL_TYPE_WWAN, "acer-threeg",
ACER_CAP_THREEG);
if (IS_ERR(threeg_rfkill)) {
- rfkill_unregister(wireless_rfkill);
- rfkill_destroy(wireless_rfkill);
- rfkill_unregister(bluetooth_rfkill);
- rfkill_destroy(bluetooth_rfkill);
- return PTR_ERR(threeg_rfkill);
+ err = PTR_ERR(threeg_rfkill);
+ goto error_threeg;
}
}
rfkill_inited = true;
- if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID))
+ if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&
+ has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))
schedule_delayed_work(&acer_rfkill_work,
round_jiffies_relative(HZ));
return 0;
+
+error_threeg:
+ if (has_cap(ACER_CAP_BLUETOOTH)) {
+ rfkill_unregister(bluetooth_rfkill);
+ rfkill_destroy(bluetooth_rfkill);
+ }
+error_bluetooth:
+ if (has_cap(ACER_CAP_WIRELESS)) {
+ rfkill_unregister(wireless_rfkill);
+ rfkill_destroy(wireless_rfkill);
+ }
+error_wireless:
+ return err;
}
static void acer_rfkill_exit(void)
{
- if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID))
+ if ((ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID)) &&
+ has_cap(ACER_CAP_WIRELESS | ACER_CAP_BLUETOOTH | ACER_CAP_THREEG))
cancel_delayed_work_sync(&acer_rfkill_work);
- rfkill_unregister(wireless_rfkill);
- rfkill_destroy(wireless_rfkill);
+ if (has_cap(ACER_CAP_WIRELESS)) {
+ rfkill_unregister(wireless_rfkill);
+ rfkill_destroy(wireless_rfkill);
+ }
if (has_cap(ACER_CAP_BLUETOOTH)) {
rfkill_unregister(bluetooth_rfkill);
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index bbd182e178cb..35dae412635d 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -127,7 +127,7 @@ MODULE_PARM_DESC(minor,
"default is -1 (automatic)");
#endif
-static int kbd_backlight; /* = 1 */
+static int kbd_backlight = 1;
module_param(kbd_backlight, int, 0444);
MODULE_PARM_DESC(kbd_backlight,
"set this to 0 to disable keyboard backlight, "
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index ca84d5099ce7..5f44b5515904 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -320,9 +320,14 @@ static int __init acpi_pnp_match(struct device *dev, void *_pnp)
{
struct acpi_device *acpi = to_acpi_device(dev);
struct pnp_dev *pnp = _pnp;
+ struct device *physical_device;
+
+ physical_device = acpi_get_physical_device(acpi->handle);
+ if (physical_device)
+ put_device(physical_device);
/* true means it matched */
- return !acpi_get_physical_device(acpi->handle)
+ return !physical_device
&& compare_pnp_id(pnp->id, acpi_device_hid(acpi));
}
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index dfbd5a6cc58b..258fef272ea7 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -295,6 +295,45 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
}
}
+#ifdef CONFIG_AMD_NB
+
+#include <asm/amd_nb.h>
+
+static void quirk_amd_mmconfig_area(struct pnp_dev *dev)
+{
+ resource_size_t start, end;
+ struct pnp_resource *pnp_res;
+ struct resource *res;
+ struct resource mmconfig_res, *mmconfig;
+
+ mmconfig = amd_get_mmconfig_range(&mmconfig_res);
+ if (!mmconfig)
+ return;
+
+ list_for_each_entry(pnp_res, &dev->resources, list) {
+ res = &pnp_res->res;
+ if (res->end < mmconfig->start || res->start > mmconfig->end ||
+ (res->start == mmconfig->start && res->end == mmconfig->end))
+ continue;
+
+ dev_info(&dev->dev, FW_BUG
+ "%pR covers only part of AMD MMCONFIG area %pR; adding more reservations\n",
+ res, mmconfig);
+ if (mmconfig->start < res->start) {
+ start = mmconfig->start;
+ end = res->start - 1;
+ pnp_add_mem_resource(dev, start, end, 0);
+ }
+ if (mmconfig->end > res->end) {
+ start = res->end + 1;
+ end = mmconfig->end;
+ pnp_add_mem_resource(dev, start, end, 0);
+ }
+ break;
+ }
+}
+#endif
+
/*
* PnP Quirks
* Cards or devices that need some tweaking due to incomplete resource info
@@ -322,6 +361,9 @@ static struct pnp_fixup pnp_fixups[] = {
/* PnP resources that might overlap PCI BARs */
{"PNP0c01", quirk_system_pci_resources},
{"PNP0c02", quirk_system_pci_resources},
+#ifdef CONFIG_AMD_NB
+ {"PNP0c01", quirk_amd_mmconfig_area},
+#endif
{""}
};
diff --git a/drivers/power/sabresd_battery.c b/drivers/power/sabresd_battery.c
index 94d7e4194f96..d7815449a9ce 100755
--- a/drivers/power/sabresd_battery.c
+++ b/drivers/power/sabresd_battery.c
@@ -55,6 +55,7 @@ struct max8903_data {
int percent;
int old_percent;
int usb_charger_online;
+ int first_delay_count;
struct power_supply bat;
struct power_supply detect_usb;
struct mutex work_lock;
@@ -68,35 +69,37 @@ typedef struct {
static int cpu_type_flag;
static int offset_discharger;
static int offset_charger;
+static int offset_usb_charger;
+
static battery_capacity chargingTable[] = {
- {4105, 99},
- {4100, 98},
- {4095, 97},
- {4085, 96},
- {4075, 95},
- {4060, 94},
- {4045, 93},
- {4030, 92},
- {4015, 91},
- {4000, 90},
- {3900, 85},
- {3790, 80},
- {3760, 75},
- {3730, 70},
- {3700, 65},
- {3680, 60},
- {3660, 55},
- {3640, 50},
- {3600, 45},
- {3550, 40},
- {3510, 35},
- {3450, 30},
- {3310, 25},
- {3240, 20},
- {3180, 15},
- {3030, 10},
- {2820, 5},
+ {4060, 99},
+ {4035, 98},
+ {4010, 97},
+ {3980, 96},
+ {3950, 95},
+ {3920, 94},
+ {3890, 93},
+ {3860, 92},
+ {3830, 91},
+ {3780, 90},
+ {3750, 85},
+ {3690, 80},
+ {3660, 75},
+ {3630, 70},
+ {3600, 65},
+ {3580, 60},
+ {3550, 55},
+ {3500, 50},
+ {3450, 45},
+ {3400, 40},
+ {3350, 35},
+ {3300, 30},
+ {3250, 25},
+ {3200, 20},
+ {3000, 15},
+ {2900, 10},
+ {2850, 5},
{2800, 0},
{0, 0}
};
@@ -166,6 +169,7 @@ static enum power_supply_property max8903_battery_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
};
extern u32 max11801_read_adc(void);
@@ -225,7 +229,12 @@ u32 calibration_voltage(struct max8903_data *data)
/* ADC offset when battery is discharger*/
volt[i] = max11801_read_adc()-offset_discharger;
} else {
- volt[i] = max11801_read_adc()-offset_charger;
+ if (data->charger_online == 1)
+ volt[i] = max11801_read_adc()-offset_charger;
+ else if (data->usb_charger_online == 1)
+ volt[i] = max11801_read_adc()-offset_usb_charger;
+ else if (data->charger_online == 1 && data->usb_charger_online == 1)
+ volt[i] = max11801_read_adc()-offset_charger;
}
}
if (cpu_type_flag == 0) {
@@ -233,7 +242,12 @@ u32 calibration_voltage(struct max8903_data *data)
/* ADC offset when battery is discharger*/
volt[i] = max11801_read_adc()-offset_discharger;
} else {
- volt[i] = max11801_read_adc()-offset_charger;
+ if (data->charger_online == 1)
+ volt[i] = max11801_read_adc()-offset_charger;
+ else if (data->usb_charger_online == 1)
+ volt[i] = max11801_read_adc()-offset_usb_charger;
+ else if (data->charger_online == 1 && data->usb_charger_online == 1)
+ volt[i] = max11801_read_adc()-offset_charger;
}
}
}
@@ -265,7 +279,7 @@ static void max8903_battery_update_status(struct max8903_data *data)
data->voltage_uV = temp_last;
}
}
- if (data->charger_online == 1) {
+ if (data->charger_online == 1 || data->usb_charger_online == 1) {
data->voltage_uV = temp;
temp_last = temp;
}
@@ -278,6 +292,16 @@ static void max8903_battery_update_status(struct max8903_data *data)
changed_flag = false;
power_supply_changed(&data->bat);
}
+ /*
+ because boot time gap between led framwork and charger
+ framwork,when system boots with charger attatched, charger
+ led framwork loses the first charger online event,add once extra
+ power_supply_changed can fix this issure
+ */
+ if (data->first_delay_count < 200) {
+ data->first_delay_count = data->first_delay_count + 1 ;
+ power_supply_changed(&data->bat);
+ }
mutex_unlock(&data->work_lock);
}
@@ -338,6 +362,14 @@ static int max8903_battery_get_property(struct power_supply *bat,
if (di->fault)
val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
break;
+ case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+ if (di->battery_status == POWER_SUPPLY_STATUS_FULL)
+ val->intval = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+ else if (di->percent <= 15)
+ val->intval = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+ else
+ val->intval = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+ break;
default:
return -EINVAL;
}
@@ -515,6 +547,22 @@ static ssize_t max8903_voltage_offset_charger_store(struct device *dev,
return count;
}
+static ssize_t max8903_voltage_offset_usb_charger_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "read offset_usb_charger:%04d\n",
+ offset_usb_charger);
+}
+
+static ssize_t max8903_voltage_offset_usb_charger_store(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ offset_usb_charger = simple_strtoul(buf, NULL, 10);
+ pr_info("read offset_charger:%04d\n", offset_usb_charger);
+ return count;
+}
+
static struct device_attribute max8903_discharger_dev_attr = {
.attr = {
.name = "max8903_ctl_offset_discharger",
@@ -533,6 +581,15 @@ static struct device_attribute max8903_charger_dev_attr = {
.store = max8903_voltage_offset_charger_store,
};
+static struct device_attribute max8903_usb_charger_dev_attr = {
+ .attr = {
+ .name = "max8903_ctl_offset_usb_charger",
+ .mode = S_IRUSR | S_IWUSR,
+ },
+ .show = max8903_voltage_offset_usb_charger_show,
+ .store = max8903_voltage_offset_usb_charger_store,
+};
+
static __devinit int max8903_probe(struct platform_device *pdev)
{
struct max8903_data *data;
@@ -553,6 +610,7 @@ static __devinit int max8903_probe(struct platform_device *pdev)
dev_err(dev, "Cannot allocate memory.\n");
return -ENOMEM;
}
+ data->first_delay_count = 0;
data->pdata = pdata;
data->dev = dev;
platform_set_drvdata(pdev, data);
@@ -734,13 +792,18 @@ static __devinit int max8903_probe(struct platform_device *pdev)
ret = device_create_file(&pdev->dev, &max8903_charger_dev_attr);
if (ret)
dev_err(&pdev->dev, "create device file failed!\n");
+ ret = device_create_file(&pdev->dev, &max8903_usb_charger_dev_attr);
+ if (ret)
+ dev_err(&pdev->dev, "create device file failed!\n");
if (cpu_type_flag == 1) {
offset_discharger = 1694;
offset_charger = 1900;
+ offset_usb_charger = 1685;
}
if (cpu_type_flag == 0) {
offset_discharger = 1464;
offset_charger = 1485;
+ offset_usb_charger = 1285;
}
max8903_charger_update_status(data);
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index d63fddb0fbb0..acda58e6ef02 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -195,7 +195,7 @@ static const unsigned int LDO12_suspend_table[] = {
};
static const unsigned int LDO13_table[] = {
- 1300000, 1800000, 2000000, 2500000, 2800000, 3000000, 0, 0,
+ 1200000, 1300000, 1800000, 2000000, 2500000, 2800000, 3000000, 0,
};
static const unsigned int LDO13_suspend_table[] = {
@@ -388,10 +388,10 @@ static struct pm8607_regulator_info pm8607_regulator_info[] = {
PM8607_LDO( 7, LDO7, 0, 3, SUPPLIES_EN12, 1),
PM8607_LDO( 8, LDO8, 0, 3, SUPPLIES_EN12, 2),
PM8607_LDO( 9, LDO9, 0, 3, SUPPLIES_EN12, 3),
- PM8607_LDO(10, LDO10, 0, 3, SUPPLIES_EN12, 4),
+ PM8607_LDO(10, LDO10, 0, 4, SUPPLIES_EN12, 4),
PM8607_LDO(12, LDO12, 0, 4, SUPPLIES_EN12, 5),
PM8607_LDO(13, VIBRATOR_SET, 1, 3, VIBRATOR_SET, 0),
- PM8607_LDO(14, LDO14, 0, 4, SUPPLIES_EN12, 6),
+ PM8607_LDO(14, LDO14, 0, 3, SUPPLIES_EN12, 6),
};
static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
index ad6628ca94f4..a8fb668c03a8 100644
--- a/drivers/regulator/max8997.c
+++ b/drivers/regulator/max8997.c
@@ -688,7 +688,7 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev,
}
new_val++;
- } while (desc->min + desc->step + new_val <= desc->max);
+ } while (desc->min + desc->step * new_val <= desc->max);
new_idx = tmp_idx;
new_val = tmp_val;
diff --git a/drivers/regulator/tps6524x-regulator.c b/drivers/regulator/tps6524x-regulator.c
index 9166aa0a9df7..229b6f4bb8b4 100644
--- a/drivers/regulator/tps6524x-regulator.c
+++ b/drivers/regulator/tps6524x-regulator.c
@@ -481,7 +481,7 @@ static int set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
if (i >= info->n_voltages)
i = info->n_voltages - 1;
- *selector = info->voltages[i];
+ *selector = i;
return write_field(hw, &info->voltage, i);
}
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index bbb6f852c5ab..636a2ec21810 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -227,11 +227,11 @@ int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
alarm->time.tm_hour = now.tm_hour;
/* For simplicity, only support date rollover for now */
- if (alarm->time.tm_mday == -1) {
+ if (alarm->time.tm_mday < 1 || alarm->time.tm_mday > 31) {
alarm->time.tm_mday = now.tm_mday;
missing = day;
}
- if (alarm->time.tm_mon == -1) {
+ if ((unsigned)alarm->time.tm_mon >= 12) {
alarm->time.tm_mon = now.tm_mon;
if (missing == none)
missing = month;
@@ -318,20 +318,6 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
}
EXPORT_SYMBOL_GPL(rtc_read_alarm);
-static int ___rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
-{
- int err;
-
- if (!rtc->ops)
- err = -ENODEV;
- else if (!rtc->ops->set_alarm)
- err = -EINVAL;
- else
- err = rtc->ops->set_alarm(rtc->dev.parent, alarm);
-
- return err;
-}
-
static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
{
struct rtc_time tm;
@@ -355,7 +341,14 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
* over right here, before we set the alarm.
*/
- return ___rtc_set_alarm(rtc, alarm);
+ if (!rtc->ops)
+ err = -ENODEV;
+ else if (!rtc->ops->set_alarm)
+ err = -EINVAL;
+ else
+ err = rtc->ops->set_alarm(rtc->dev.parent, alarm);
+
+ return err;
}
int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
@@ -771,16 +764,10 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
static void rtc_alarm_disable(struct rtc_device *rtc)
{
- struct rtc_wkalrm alarm;
- struct rtc_time tm;
-
- __rtc_read_time(rtc, &tm);
-
- alarm.time = rtc_ktime_to_tm(ktime_add(rtc_tm_to_ktime(tm),
- ktime_set(300, 0)));
- alarm.enabled = 0;
+ if (!rtc->ops || !rtc->ops->alarm_irq_enable)
+ return;
- ___rtc_set_alarm(rtc, &alarm);
+ rtc->ops->alarm_irq_enable(rtc->dev.parent, false);
}
/**
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c
index eda128fc1d38..64aedd8cc095 100644
--- a/drivers/rtc/rtc-m41t80.c
+++ b/drivers/rtc/rtc-m41t80.c
@@ -357,10 +357,19 @@ static int m41t80_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *t)
static struct rtc_class_ops m41t80_rtc_ops = {
.read_time = m41t80_rtc_read_time,
.set_time = m41t80_rtc_set_time,
+ /*
+ * XXX - m41t80 alarm functionality is reported broken.
+ * until it is fixed, don't register alarm functions.
+ *
.read_alarm = m41t80_rtc_read_alarm,
.set_alarm = m41t80_rtc_set_alarm,
+ */
.proc = m41t80_rtc_proc,
+ /*
+ * See above comment on broken alarm
+ *
.alarm_irq_enable = m41t80_rtc_alarm_irq_enable,
+ */
};
#if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE)
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
index ff1b84bd9bb5..1e80a48057e5 100644
--- a/drivers/rtc/rtc-pl031.c
+++ b/drivers/rtc/rtc-pl031.c
@@ -312,6 +312,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
int ret;
struct pl031_local *ldata;
struct rtc_class_ops *ops = id->data;
+ unsigned long time;
ret = amba_request_regions(adev, NULL);
if (ret)
@@ -339,11 +340,27 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
dev_dbg(&adev->dev, "revision = 0x%01x\n", ldata->hw_revision);
/* Enable the clockwatch on ST Variants */
- if ((ldata->hw_designer == AMBA_VENDOR_ST) &&
- (ldata->hw_revision > 1))
+ if (ldata->hw_designer == AMBA_VENDOR_ST)
writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN,
ldata->base + RTC_CR);
+ /*
+ * On ST PL031 variants, the RTC reset value does not provide correct
+ * weekday for 2000-01-01. Correct the erroneous sunday to saturday.
+ */
+ if (ldata->hw_designer == AMBA_VENDOR_ST) {
+ if (readl(ldata->base + RTC_YDR) == 0x2000) {
+ time = readl(ldata->base + RTC_DR);
+ if ((time &
+ (RTC_MON_MASK | RTC_MDAY_MASK | RTC_WDAY_MASK))
+ == 0x02120000) {
+ time = time | (0x7 << RTC_WDAY_SHIFT);
+ writel(0x2000, ldata->base + RTC_YLR);
+ writel(time, ldata->base + RTC_LR);
+ }
+ }
+ }
+
ldata->rtc = rtc_device_register("pl031", &adev->dev, ops,
THIS_MODULE);
if (IS_ERR(ldata->rtc)) {
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 30fb979d684d..cc2dd7fb289f 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -18,12 +18,12 @@
#include <linux/hdreg.h> /* HDIO_GETGEO */
#include <linux/bio.h>
#include <linux/module.h>
+#include <linux/compat.h>
#include <linux/init.h>
#include <asm/debug.h>
#include <asm/idals.h>
#include <asm/ebcdic.h>
-#include <asm/compat.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/cio.h>
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 72261e4c516d..9caeaea5d099 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -13,6 +13,7 @@
#define KMSG_COMPONENT "dasd"
#include <linux/interrupt.h>
+#include <linux/compat.h>
#include <linux/major.h>
#include <linux/fs.h>
#include <linux/blkpg.h>
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c
index f6489eb7e976..2150824303a5 100644
--- a/drivers/s390/char/fs3270.c
+++ b/drivers/s390/char/fs3270.c
@@ -14,6 +14,7 @@
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/types.h>
+#include <linux/compat.h>
#include <asm/compat.h>
#include <asm/ccwdev.h>
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
index 31a3ccbb6495..84e569c9c150 100644
--- a/drivers/s390/char/vmcp.c
+++ b/drivers/s390/char/vmcp.c
@@ -13,6 +13,7 @@
#include <linux/fs.h>
#include <linux/init.h>
+#include <linux/compat.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index e950f1ad4dd1..ec760297dd38 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -8,6 +8,7 @@
*/
#include <linux/slab.h>
+#include <linux/compat.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/uaccess.h>
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c
index fd69da3fa6b4..e2c9ac5fcb36 100644
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -2742,9 +2742,14 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
{
int cast_type = RTN_UNSPEC;
-
- if (skb_dst(skb) && skb_dst(skb)->neighbour) {
- cast_type = skb_dst(skb)->neighbour->type;
+ struct neighbour *n = NULL;
+ struct dst_entry *dst;
+
+ dst = skb_dst(skb);
+ if (dst)
+ n = dst_get_neighbour(dst);
+ if (n) {
+ cast_type = n->type;
if ((cast_type == RTN_BROADCAST) ||
(cast_type == RTN_MULTICAST) ||
(cast_type == RTN_ANYCAST))
@@ -2787,6 +2792,9 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
struct sk_buff *skb, int ipv, int cast_type)
{
+ struct neighbour *n = NULL;
+ struct dst_entry *dst;
+
memset(hdr, 0, sizeof(struct qeth_hdr));
hdr->hdr.l3.id = QETH_HEADER_TYPE_LAYER3;
hdr->hdr.l3.ext_flags = 0;
@@ -2804,13 +2812,16 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
}
hdr->hdr.l3.length = skb->len - sizeof(struct qeth_hdr);
+ dst = skb_dst(skb);
+ if (dst)
+ n = dst_get_neighbour(dst);
if (ipv == 4) {
/* IPv4 */
hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags4(cast_type);
memset(hdr->hdr.l3.dest_addr, 0, 12);
- if ((skb_dst(skb)) && (skb_dst(skb)->neighbour)) {
+ if (n) {
*((u32 *) (&hdr->hdr.l3.dest_addr[12])) =
- *((u32 *) skb_dst(skb)->neighbour->primary_key);
+ *((u32 *) n->primary_key);
} else {
/* fill in destination address used in ip header */
*((u32 *) (&hdr->hdr.l3.dest_addr[12])) =
@@ -2821,9 +2832,9 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
hdr->hdr.l3.flags = qeth_l3_get_qeth_hdr_flags6(cast_type);
if (card->info.type == QETH_CARD_TYPE_IQD)
hdr->hdr.l3.flags &= ~QETH_HDR_PASSTHRU;
- if ((skb_dst(skb)) && (skb_dst(skb)->neighbour)) {
+ if (n) {
memcpy(hdr->hdr.l3.dest_addr,
- skb_dst(skb)->neighbour->primary_key, 16);
+ n->primary_key, 16);
} else {
/* fill in destination address used in ip header */
memcpy(hdr->hdr.l3.dest_addr,
diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c
index 303dde09d294..fab2c2592a97 100644
--- a/drivers/s390/scsi/zfcp_cfdc.c
+++ b/drivers/s390/scsi/zfcp_cfdc.c
@@ -11,6 +11,7 @@
#define KMSG_COMPONENT "zfcp"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+#include <linux/compat.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/miscdevice.h>
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 2a4991d6d4d5..3a417dff1b89 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -57,6 +57,10 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdev)
{
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
+ /* if previous slave_alloc returned early, there is nothing to do */
+ if (!zfcp_sdev->port)
+ return;
+
zfcp_erp_lun_shutdown_wait(sdev, "scssd_1");
put_device(&zfcp_sdev->port->dev);
}
diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
index b2d661147a43..143f2682bdab 100644
--- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
+++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
@@ -985,7 +985,7 @@ static int init_act_open(struct cxgbi_sock *csk)
csk->saddr.sin_addr.s_addr = chba->ipv4addr;
csk->rss_qid = 0;
- csk->l2t = t3_l2t_get(t3dev, dst->neighbour, ndev);
+ csk->l2t = t3_l2t_get(t3dev, dst_get_neighbour(dst), ndev);
if (!csk->l2t) {
pr_err("NO l2t available.\n");
return -EINVAL;
diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
index f3a4cd7cf782..ae13c4993aa3 100644
--- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
+++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
@@ -1160,7 +1160,7 @@ static int init_act_open(struct cxgbi_sock *csk)
cxgbi_sock_set_flag(csk, CTPF_HAS_ATID);
cxgbi_sock_get(csk);
- csk->l2t = cxgb4_l2t_get(lldi->l2t, csk->dst->neighbour, ndev, 0);
+ csk->l2t = cxgb4_l2t_get(lldi->l2t, dst_get_neighbour(csk->dst), ndev, 0);
if (!csk->l2t) {
pr_err("%s, cannot alloc l2t.\n", ndev->name);
goto rel_resource;
diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c
index a2a9c7c6c643..77ac217ad5ce 100644
--- a/drivers/scsi/cxgbi/libcxgbi.c
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -492,7 +492,7 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr)
goto err_out;
}
dst = &rt->dst;
- ndev = dst->neighbour->dev;
+ ndev = dst_get_neighbour(dst)->dev;
if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
pr_info("multi-cast route %pI4, port %u, dev %s.\n",
@@ -506,7 +506,7 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr)
ndev = ip_dev_find(&init_net, daddr->sin_addr.s_addr);
mtu = ndev->mtu;
pr_info("rt dev %s, loopback -> %s, mtu %u.\n",
- dst->neighbour->dev->name, ndev->name, mtu);
+ dst_get_neighbour(dst)->dev->name, ndev->name, mtu);
}
cdev = cxgbi_device_find_by_netdev(ndev, &port);
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 8885b3ef369a..f829adcb3b79 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -1561,6 +1561,7 @@ static inline int fcoe_filter_frames(struct fc_lport *lport,
stats->InvalidCRCCount++;
if (stats->InvalidCRCCount < 5)
printk(KERN_WARNING "fcoe: dropping frame with CRC error\n");
+ put_cpu();
return -EINVAL;
}
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 56a9f3f676e8..58f99f44bd05 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1654,30 +1654,26 @@ static void figure_bus_target_lun(struct ctlr_info *h,
if (is_logical_dev_addr_mode(lunaddrbytes)) {
/* logical device */
- if (unlikely(is_scsi_rev_5(h))) {
- /* p1210m, logical drives lun assignments
- * match SCSI REPORT LUNS data.
+ lunid = le32_to_cpu(*((__le32 *) lunaddrbytes));
+ if (is_msa2xxx(h, device)) {
+ /* msa2xxx way, put logicals on bus 1
+ * and match target/lun numbers box
+ * reports.
*/
- lunid = le32_to_cpu(*((__le32 *) lunaddrbytes));
- *bus = 0;
- *target = 0;
- *lun = (lunid & 0x3fff) + 1;
+ *bus = 1;
+ *target = (lunid >> 16) & 0x3fff;
+ *lun = lunid & 0x00ff;
} else {
- /* not p1210m... */
- lunid = le32_to_cpu(*((__le32 *) lunaddrbytes));
- if (is_msa2xxx(h, device)) {
- /* msa2xxx way, put logicals on bus 1
- * and match target/lun numbers box
- * reports.
- */
- *bus = 1;
- *target = (lunid >> 16) & 0x3fff;
- *lun = lunid & 0x00ff;
+ if (likely(is_scsi_rev_5(h))) {
+ /* All current smart arrays (circa 2011) */
+ *bus = 0;
+ *target = 0;
+ *lun = (lunid & 0x3fff) + 1;
} else {
- /* Traditional smart array way. */
+ /* Traditional old smart array way. */
*bus = 0;
- *lun = 0;
*target = lunid & 0x3fff;
+ *lun = 0;
}
}
} else {
@@ -4037,10 +4033,10 @@ static int hpsa_request_irq(struct ctlr_info *h,
if (h->msix_vector || h->msi_vector)
rc = request_irq(h->intr[h->intr_mode], msixhandler,
- IRQF_DISABLED, h->devname, h);
+ 0, h->devname, h);
else
rc = request_irq(h->intr[h->intr_mode], intxhandler,
- IRQF_DISABLED, h->devname, h);
+ IRQF_SHARED, h->devname, h);
if (rc) {
dev_err(&h->pdev->dev, "unable to get irq %d for %s\n",
h->intr[h->intr_mode], h->devname);
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 61e0d09e2b57..71b57ec3d934 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -454,7 +454,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic
if (!orom)
orom = isci_request_oprom(pdev);
- for (i = 0; orom && i < ARRAY_SIZE(orom->ctrl); i++) {
+ for (i = 0; orom && i < num_controllers(pdev); i++) {
if (sci_oem_parameters_validate(&orom->ctrl[i])) {
dev_warn(&pdev->dev,
"[%d]: invalid oem parameters detected, falling back to firmware\n", i);
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 37cbe4d3bb9c..e68fac69504b 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -192,7 +192,14 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
phy->attached_sata_ps = dr->attached_sata_ps;
phy->attached_iproto = dr->iproto << 1;
phy->attached_tproto = dr->tproto << 1;
- memcpy(phy->attached_sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE);
+ /* help some expanders that fail to zero sas_address in the 'no
+ * device' case
+ */
+ if (phy->attached_dev_type == NO_DEVICE ||
+ phy->linkrate < SAS_LINK_RATE_1_5_GBPS)
+ memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE);
+ else
+ memcpy(phy->attached_sas_addr, dr->attached_sas_addr, SAS_ADDR_SIZE);
phy->attached_phy_id = dr->attached_phy_id;
phy->phy_change_count = dr->change_count;
phy->routing_attr = dr->routing_attr;
@@ -1632,9 +1639,17 @@ static int sas_find_bcast_phy(struct domain_device *dev, int *phy_id,
int phy_change_count = 0;
res = sas_get_phy_change_count(dev, i, &phy_change_count);
- if (res)
- goto out;
- else if (phy_change_count != ex->ex_phy[i].phy_change_count) {
+ switch (res) {
+ case SMP_RESP_PHY_VACANT:
+ case SMP_RESP_NO_PHY:
+ continue;
+ case SMP_RESP_FUNC_ACC:
+ break;
+ default:
+ return res;
+ }
+
+ if (phy_change_count != ex->ex_phy[i].phy_change_count) {
if (update)
ex->ex_phy[i].phy_change_count =
phy_change_count;
@@ -1642,8 +1657,7 @@ static int sas_find_bcast_phy(struct domain_device *dev, int *phy_id,
return 0;
}
}
-out:
- return res;
+ return 0;
}
static int sas_get_ex_change_count(struct domain_device *dev, int *ecc)
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
index 83035bd1c489..e10639bd73c3 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -66,6 +66,8 @@ static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS];
#define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */
+#define MAX_HBA_QUEUE_DEPTH 30000
+#define MAX_CHAIN_DEPTH 100000
static int max_queue_depth = -1;
module_param(max_queue_depth, int, 0);
MODULE_PARM_DESC(max_queue_depth, " max controller queue depth ");
@@ -1082,41 +1084,6 @@ _base_config_dma_addressing(struct MPT2SAS_ADAPTER *ioc, struct pci_dev *pdev)
}
/**
- * _base_save_msix_table - backup msix vector table
- * @ioc: per adapter object
- *
- * This address an errata where diag reset clears out the table
- */
-static void
-_base_save_msix_table(struct MPT2SAS_ADAPTER *ioc)
-{
- int i;
-
- if (!ioc->msix_enable || ioc->msix_table_backup == NULL)
- return;
-
- for (i = 0; i < ioc->msix_vector_count; i++)
- ioc->msix_table_backup[i] = ioc->msix_table[i];
-}
-
-/**
- * _base_restore_msix_table - this restores the msix vector table
- * @ioc: per adapter object
- *
- */
-static void
-_base_restore_msix_table(struct MPT2SAS_ADAPTER *ioc)
-{
- int i;
-
- if (!ioc->msix_enable || ioc->msix_table_backup == NULL)
- return;
-
- for (i = 0; i < ioc->msix_vector_count; i++)
- ioc->msix_table[i] = ioc->msix_table_backup[i];
-}
-
-/**
* _base_check_enable_msix - checks MSIX capabable.
* @ioc: per adapter object
*
@@ -1128,7 +1095,7 @@ _base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc)
{
int base;
u16 message_control;
- u32 msix_table_offset;
+
base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX);
if (!base) {
@@ -1141,14 +1108,8 @@ _base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc)
pci_read_config_word(ioc->pdev, base + 2, &message_control);
ioc->msix_vector_count = (message_control & 0x3FF) + 1;
- /* get msix table */
- pci_read_config_dword(ioc->pdev, base + 4, &msix_table_offset);
- msix_table_offset &= 0xFFFFFFF8;
- ioc->msix_table = (u32 *)((void *)ioc->chip + msix_table_offset);
-
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "msix is supported, "
- "vector_count(%d), table_offset(0x%08x), table(%p)\n", ioc->name,
- ioc->msix_vector_count, msix_table_offset, ioc->msix_table));
+ "vector_count(%d)\n", ioc->name, ioc->msix_vector_count));
return 0;
}
@@ -1162,8 +1123,6 @@ _base_disable_msix(struct MPT2SAS_ADAPTER *ioc)
{
if (ioc->msix_enable) {
pci_disable_msix(ioc->pdev);
- kfree(ioc->msix_table_backup);
- ioc->msix_table_backup = NULL;
ioc->msix_enable = 0;
}
}
@@ -1189,14 +1148,6 @@ _base_enable_msix(struct MPT2SAS_ADAPTER *ioc)
if (_base_check_enable_msix(ioc) != 0)
goto try_ioapic;
- ioc->msix_table_backup = kcalloc(ioc->msix_vector_count,
- sizeof(u32), GFP_KERNEL);
- if (!ioc->msix_table_backup) {
- dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation for "
- "msix_table_backup failed!!!\n", ioc->name));
- goto try_ioapic;
- }
-
memset(&entries, 0, sizeof(struct msix_entry));
r = pci_enable_msix(ioc->pdev, &entries, 1);
if (r) {
@@ -2149,8 +2100,6 @@ _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
}
if (ioc->chain_dma_pool)
pci_pool_destroy(ioc->chain_dma_pool);
- }
- if (ioc->chain_lookup) {
free_pages((ulong)ioc->chain_lookup, ioc->chain_pages);
ioc->chain_lookup = NULL;
}
@@ -2168,9 +2117,7 @@ static int
_base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
{
struct mpt2sas_facts *facts;
- u32 queue_size, queue_diff;
u16 max_sge_elements;
- u16 num_of_reply_frames;
u16 chains_needed_per_io;
u32 sz, total_sz;
u32 retry_sz;
@@ -2197,7 +2144,8 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
max_request_credit = (max_queue_depth < facts->RequestCredit)
? max_queue_depth : facts->RequestCredit;
else
- max_request_credit = facts->RequestCredit;
+ max_request_credit = min_t(u16, facts->RequestCredit,
+ MAX_HBA_QUEUE_DEPTH);
ioc->hba_queue_depth = max_request_credit;
ioc->hi_priority_depth = facts->HighPriorityCredit;
@@ -2238,50 +2186,25 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
}
ioc->chains_needed_per_io = chains_needed_per_io;
- /* reply free queue sizing - taking into account for events */
- num_of_reply_frames = ioc->hba_queue_depth + 32;
-
- /* number of replies frames can't be a multiple of 16 */
- /* decrease number of reply frames by 1 */
- if (!(num_of_reply_frames % 16))
- num_of_reply_frames--;
-
- /* calculate number of reply free queue entries
- * (must be multiple of 16)
- */
-
- /* (we know reply_free_queue_depth is not a multiple of 16) */
- queue_size = num_of_reply_frames;
- queue_size += 16 - (queue_size % 16);
- ioc->reply_free_queue_depth = queue_size;
+ /* reply free queue sizing - taking into account for 64 FW events */
+ ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64;
- /* reply descriptor post queue sizing */
- /* this size should be the number of request frames + number of reply
- * frames
- */
-
- queue_size = ioc->hba_queue_depth + num_of_reply_frames + 1;
- /* round up to 16 byte boundary */
- if (queue_size % 16)
- queue_size += 16 - (queue_size % 16);
-
- /* check against IOC maximum reply post queue depth */
- if (queue_size > facts->MaxReplyDescriptorPostQueueDepth) {
- queue_diff = queue_size -
- facts->MaxReplyDescriptorPostQueueDepth;
-
- /* round queue_diff up to multiple of 16 */
- if (queue_diff % 16)
- queue_diff += 16 - (queue_diff % 16);
-
- /* adjust hba_queue_depth, reply_free_queue_depth,
- * and queue_size
- */
- ioc->hba_queue_depth -= (queue_diff / 2);
- ioc->reply_free_queue_depth -= (queue_diff / 2);
- queue_size = facts->MaxReplyDescriptorPostQueueDepth;
+ /* align the reply post queue on the next 16 count boundary */
+ if (!ioc->reply_free_queue_depth % 16)
+ ioc->reply_post_queue_depth = ioc->reply_free_queue_depth + 16;
+ else
+ ioc->reply_post_queue_depth = ioc->reply_free_queue_depth +
+ 32 - (ioc->reply_free_queue_depth % 16);
+ if (ioc->reply_post_queue_depth >
+ facts->MaxReplyDescriptorPostQueueDepth) {
+ ioc->reply_post_queue_depth = min_t(u16,
+ (facts->MaxReplyDescriptorPostQueueDepth -
+ (facts->MaxReplyDescriptorPostQueueDepth % 16)),
+ (ioc->hba_queue_depth - (ioc->hba_queue_depth % 16)));
+ ioc->reply_free_queue_depth = ioc->reply_post_queue_depth - 16;
+ ioc->hba_queue_depth = ioc->reply_free_queue_depth - 64;
}
- ioc->reply_post_queue_depth = queue_size;
+
dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scatter gather: "
"sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), "
@@ -2367,15 +2290,12 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
"depth(%d)\n", ioc->name, ioc->request,
ioc->scsiio_depth));
- /* loop till the allocation succeeds */
- do {
- sz = ioc->chain_depth * sizeof(struct chain_tracker);
- ioc->chain_pages = get_order(sz);
- ioc->chain_lookup = (struct chain_tracker *)__get_free_pages(
- GFP_KERNEL, ioc->chain_pages);
- if (ioc->chain_lookup == NULL)
- ioc->chain_depth -= 100;
- } while (ioc->chain_lookup == NULL);
+ ioc->chain_depth = min_t(u32, ioc->chain_depth, MAX_CHAIN_DEPTH);
+ sz = ioc->chain_depth * sizeof(struct chain_tracker);
+ ioc->chain_pages = get_order(sz);
+
+ ioc->chain_lookup = (struct chain_tracker *)__get_free_pages(
+ GFP_KERNEL, ioc->chain_pages);
ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev,
ioc->request_sz, 16, 0);
if (!ioc->chain_dma_pool) {
@@ -3136,7 +3056,7 @@ _base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag)
}
pfacts = &ioc->pfacts[port];
- memset(pfacts, 0, sizeof(Mpi2PortFactsReply_t));
+ memset(pfacts, 0, sizeof(struct mpt2sas_port_facts));
pfacts->PortNumber = mpi_reply.PortNumber;
pfacts->VP_ID = mpi_reply.VP_ID;
pfacts->VF_ID = mpi_reply.VF_ID;
@@ -3178,7 +3098,7 @@ _base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
}
facts = &ioc->facts;
- memset(facts, 0, sizeof(Mpi2IOCFactsReply_t));
+ memset(facts, 0, sizeof(struct mpt2sas_facts));
facts->MsgVersion = le16_to_cpu(mpi_reply.MsgVersion);
facts->HeaderVersion = le16_to_cpu(mpi_reply.HeaderVersion);
facts->VP_ID = mpi_reply.VP_ID;
@@ -3513,9 +3433,6 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
u32 hcb_size;
printk(MPT2SAS_INFO_FMT "sending diag reset !!\n", ioc->name);
-
- _base_save_msix_table(ioc);
-
drsprintk(ioc, printk(MPT2SAS_INFO_FMT "clear interrupts\n",
ioc->name));
@@ -3611,7 +3528,6 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
goto out;
}
- _base_restore_msix_table(ioc);
printk(MPT2SAS_INFO_FMT "diag reset: SUCCESS\n", ioc->name);
return 0;
@@ -3863,7 +3779,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
goto out_free_resources;
ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts,
- sizeof(Mpi2PortFactsReply_t), GFP_KERNEL);
+ sizeof(struct mpt2sas_port_facts), GFP_KERNEL);
if (!ioc->pfacts) {
r = -ENOMEM;
goto out_free_resources;
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
index 41a57a7a5b3a..e1735f99f238 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -626,8 +626,6 @@ struct mpt2sas_port_facts {
* @wait_for_port_enable_to_complete:
* @msix_enable: flag indicating msix is enabled
* @msix_vector_count: number msix vectors
- * @msix_table: virt address to the msix table
- * @msix_table_backup: backup msix table
* @scsi_io_cb_idx: shost generated commands
* @tm_cb_idx: task management commands
* @scsih_cb_idx: scsih internal commands
@@ -768,8 +766,6 @@ struct MPT2SAS_ADAPTER {
u8 msix_enable;
u16 msix_vector_count;
- u32 *msix_table;
- u32 *msix_table_backup;
u32 ioc_reset_count;
/* internal commands, callback index */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
index 5690f09e0106..aa51195a7312 100644
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -974,8 +974,8 @@ _scsih_get_chain_buffer_tracker(struct MPT2SAS_ADAPTER *ioc, u16 smid)
spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
if (list_empty(&ioc->free_chain_list)) {
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- printk(MPT2SAS_WARN_FMT "chain buffers not available\n",
- ioc->name);
+ dfailprintk(ioc, printk(MPT2SAS_WARN_FMT "chain buffers not "
+ "available\n", ioc->name));
return NULL;
}
chain_req = list_entry(ioc->free_chain_list.next,
@@ -4145,7 +4145,7 @@ _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle)
/* insert into event log */
sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
sizeof(Mpi2EventDataSasDeviceStatusChange_t);
- event_reply = kzalloc(sz, GFP_KERNEL);
+ event_reply = kzalloc(sz, GFP_ATOMIC);
if (!event_reply) {
printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
@@ -6425,6 +6425,7 @@ _scsih_mark_responding_raid_device(struct MPT2SAS_ADAPTER *ioc, u64 wwid,
} else
sas_target_priv_data = NULL;
raid_device->responding = 1;
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
starget_printk(KERN_INFO, raid_device->starget,
"handle(0x%04x), wwid(0x%016llx)\n", handle,
(unsigned long long)raid_device->wwid);
@@ -6435,16 +6436,16 @@ _scsih_mark_responding_raid_device(struct MPT2SAS_ADAPTER *ioc, u64 wwid,
*/
_scsih_init_warpdrive_properties(ioc, raid_device);
if (raid_device->handle == handle)
- goto out;
+ return;
printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n",
raid_device->handle);
raid_device->handle = handle;
if (sas_target_priv_data)
sas_target_priv_data->handle = handle;
- goto out;
+ return;
}
}
- out:
+
spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
}
@@ -7211,6 +7212,7 @@ _scsih_remove(struct pci_dev *pdev)
}
sas_remove_host(shost);
+ mpt2sas_base_detach(ioc);
list_del(&ioc->list);
scsi_remove_host(shost);
scsi_host_put(shost);
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
index b31a8e3841d7..d4ed9eb52657 100644
--- a/drivers/scsi/osd/osd_uld.c
+++ b/drivers/scsi/osd/osd_uld.c
@@ -69,10 +69,10 @@
#ifndef SCSI_OSD_MAJOR
# define SCSI_OSD_MAJOR 260
#endif
-#define SCSI_OSD_MAX_MINOR 64
+#define SCSI_OSD_MAX_MINOR MINORMASK
static const char osd_name[] = "osd";
-static const char *osd_version_string = "open-osd 0.2.0";
+static const char *osd_version_string = "open-osd 0.2.1";
MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
MODULE_DESCRIPTION("open-osd Upper-Layer-Driver osd.ko");
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 72ab1e6da648..99fc45bb72df 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1380,16 +1380,19 @@ static int scsi_lld_busy(struct request_queue *q)
{
struct scsi_device *sdev = q->queuedata;
struct Scsi_Host *shost;
- struct scsi_target *starget;
if (!sdev)
return 0;
shost = sdev->host;
- starget = scsi_target(sdev);
- if (scsi_host_in_recovery(shost) || scsi_host_is_busy(shost) ||
- scsi_target_is_busy(starget) || scsi_device_is_busy(sdev))
+ /*
+ * Ignore host/starget busy state.
+ * Since block layer does not have a concept of fairness across
+ * multiple queues, congestion of host/starget needs to be handled
+ * in SCSI layer.
+ */
+ if (scsi_host_in_recovery(shost) || scsi_device_is_busy(sdev))
return 1;
return 0;
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index d70e91ae60af..122a5a2020ad 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -6,6 +6,7 @@
*/
#include <linux/pm_runtime.h>
+#include <linux/async.h>
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
@@ -68,6 +69,19 @@ static int scsi_bus_resume_common(struct device *dev)
return err;
}
+static int scsi_bus_prepare(struct device *dev)
+{
+ if (scsi_is_sdev_device(dev)) {
+ /* sd probing uses async_schedule. Wait until it finishes. */
+ async_synchronize_full();
+
+ } else if (scsi_is_host_device(dev)) {
+ /* Wait until async scanning is finished */
+ scsi_complete_async_scans();
+ }
+ return 0;
+}
+
static int scsi_bus_suspend(struct device *dev)
{
return scsi_bus_suspend_common(dev, PMSG_SUSPEND);
@@ -86,6 +100,7 @@ static int scsi_bus_poweroff(struct device *dev)
#else /* CONFIG_PM_SLEEP */
#define scsi_bus_resume_common NULL
+#define scsi_bus_prepare NULL
#define scsi_bus_suspend NULL
#define scsi_bus_freeze NULL
#define scsi_bus_poweroff NULL
@@ -194,6 +209,7 @@ void scsi_autopm_put_host(struct Scsi_Host *shost)
#endif /* CONFIG_PM_RUNTIME */
const struct dev_pm_ops scsi_bus_pm_ops = {
+ .prepare = scsi_bus_prepare,
.suspend = scsi_bus_suspend,
.resume = scsi_bus_resume_common,
.freeze = scsi_bus_freeze,
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 2a588955423a..5b475d0832cb 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -110,6 +110,7 @@ extern void scsi_exit_procfs(void);
#endif /* CONFIG_PROC_FS */
/* scsi_scan.c */
+extern int scsi_complete_async_scans(void);
extern int scsi_scan_host_selected(struct Scsi_Host *, unsigned int,
unsigned int, unsigned int, int);
extern void scsi_forget_host(struct Scsi_Host *);
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index b3c6d957fbd8..6e7ea4a2b7a1 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -1815,6 +1815,7 @@ static void scsi_finish_async_scan(struct async_scan_data *data)
}
spin_unlock(&async_scan_lock);
+ scsi_autopm_put_host(shost);
scsi_host_put(shost);
kfree(data);
}
@@ -1841,7 +1842,6 @@ static int do_scan_async(void *_data)
do_scsi_scan_host(shost);
scsi_finish_async_scan(data);
- scsi_autopm_put_host(shost);
return 0;
}
@@ -1869,7 +1869,7 @@ void scsi_scan_host(struct Scsi_Host *shost)
p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no);
if (IS_ERR(p))
do_scan_async(data);
- /* scsi_autopm_put_host(shost) is called in do_scan_async() */
+ /* scsi_autopm_put_host(shost) is called in scsi_finish_async_scan() */
}
EXPORT_SYMBOL(scsi_scan_host);
diff --git a/drivers/scsi/scsi_wait_scan.c b/drivers/scsi/scsi_wait_scan.c
index 74708fcaf82f..ae7814874618 100644
--- a/drivers/scsi/scsi_wait_scan.c
+++ b/drivers/scsi/scsi_wait_scan.c
@@ -12,7 +12,7 @@
#include <linux/module.h>
#include <linux/device.h>
-#include <scsi/scsi_scan.h>
+#include "scsi_priv.h"
static int __init wait_scan_init(void)
{
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 953773cb26d9..7d8b5d8d7499 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1073,6 +1073,10 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode,
SCSI_LOG_IOCTL(1, printk("sd_ioctl: disk=%s, cmd=0x%x\n",
disk->disk_name, cmd));
+ error = scsi_verify_blk_ioctl(bdev, cmd);
+ if (error < 0)
+ return error;
+
/*
* If we are in the middle of error recovery, don't let anyone
* else try and use this device. Also, if error recovery fails, it
@@ -1095,7 +1099,7 @@ static int sd_ioctl(struct block_device *bdev, fmode_t mode,
error = scsi_ioctl(sdp, cmd, p);
break;
default:
- error = scsi_cmd_ioctl(disk->queue, disk, mode, cmd, p);
+ error = scsi_cmd_blk_ioctl(bdev, mode, cmd, p);
if (error != -ENOTTY)
break;
error = scsi_ioctl(sdp, cmd, p);
@@ -1265,6 +1269,11 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode,
unsigned int cmd, unsigned long arg)
{
struct scsi_device *sdev = scsi_disk(bdev->bd_disk)->device;
+ int ret;
+
+ ret = scsi_verify_blk_ioctl(bdev, cmd);
+ if (ret < 0)
+ return -ENOIOCTLCMD;
/*
* If we are in the middle of error recovery, don't let anyone
@@ -1276,8 +1285,6 @@ static int sd_compat_ioctl(struct block_device *bdev, fmode_t mode,
return -ENODEV;
if (sdev->host->hostt->compat_ioctl) {
- int ret;
-
ret = sdev->host->hostt->compat_ioctl(sdev, cmd, (void __user *)arg);
return ret;
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index b4543f575f46..36d1ed7817eb 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -839,6 +839,10 @@ static void sym53c8xx_slave_destroy(struct scsi_device *sdev)
struct sym_lcb *lp = sym_lp(tp, sdev->lun);
unsigned long flags;
+ /* if slave_alloc returned before allocating a sym_lcb, return */
+ if (!lp)
+ return;
+
spin_lock_irqsave(np->s.host->host_lock, flags);
if (lp->busy_itlq || lp->busy_itl) {
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 2e13a14bba3f..b423fe92a785 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -318,7 +318,7 @@ struct spi_device *spi_alloc_device(struct spi_master *master)
}
spi->master = master;
- spi->dev.parent = dev;
+ spi->dev.parent = &master->dev;
spi->dev.bus = &spi_bus_type;
spi->dev.release = spidev_release;
device_initialize(&spi->dev);
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c
index d6620ad309ce..c828151c419e 100644
--- a/drivers/ssb/driver_pcicore.c
+++ b/drivers/ssb/driver_pcicore.c
@@ -516,10 +516,14 @@ static void ssb_pcicore_pcie_setup_workarounds(struct ssb_pcicore *pc)
static void ssb_pcicore_init_clientmode(struct ssb_pcicore *pc)
{
- ssb_pcicore_fix_sprom_core_index(pc);
+ struct ssb_device *pdev = pc->dev;
+ struct ssb_bus *bus = pdev->bus;
+
+ if (bus->bustype == SSB_BUSTYPE_PCI)
+ ssb_pcicore_fix_sprom_core_index(pc);
/* Disable PCI interrupts. */
- ssb_write32(pc->dev, SSB_INTVEC, 0);
+ ssb_write32(pdev, SSB_INTVEC, 0);
/* Additional PCIe always once-executed workarounds */
if (pc->dev->id.coreid == SSB_DEV_PCIE) {
diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c
index 7bb7da7959a2..63bafbb0980f 100644
--- a/drivers/staging/asus_oled/asus_oled.c
+++ b/drivers/staging/asus_oled/asus_oled.c
@@ -355,7 +355,14 @@ static void send_data(struct asus_oled_dev *odev)
static int append_values(struct asus_oled_dev *odev, uint8_t val, size_t count)
{
- while (count-- > 0 && val) {
+ odev->last_val = val;
+
+ if (val == 0) {
+ odev->buf_offs += count;
+ return 0;
+ }
+
+ while (count-- > 0) {
size_t x = odev->buf_offs % odev->width;
size_t y = odev->buf_offs / odev->width;
size_t i;
@@ -406,7 +413,6 @@ static int append_values(struct asus_oled_dev *odev, uint8_t val, size_t count)
;
}
- odev->last_val = val;
odev->buf_offs++;
}
@@ -805,10 +811,9 @@ error:
static void __exit asus_oled_exit(void)
{
+ usb_deregister(&oled_driver);
class_remove_file(oled_class, &class_attr_version.attr);
class_destroy(oled_class);
-
- usb_deregister(&oled_driver);
}
module_init(asus_oled_init);
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_bmac.c b/drivers/staging/brcm80211/brcmsmac/wlc_bmac.c
index 453492610613..934e7f9a8673 100644
--- a/drivers/staging/brcm80211/brcmsmac/wlc_bmac.c
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_bmac.c
@@ -143,7 +143,6 @@ static bool wlc_bmac_validate_chip_access(struct wlc_hw_info *wlc_hw);
static char *wlc_get_macaddr(struct wlc_hw_info *wlc_hw);
static void wlc_mhfdef(struct wlc_info *wlc, u16 *mhfs, u16 mhf2_init);
static void wlc_mctrl_write(struct wlc_hw_info *wlc_hw);
-static void wlc_bmac_mute(struct wlc_hw_info *wlc_hw, bool want, mbool flags);
static void wlc_ucode_mute_override_set(struct wlc_hw_info *wlc_hw);
static void wlc_ucode_mute_override_clear(struct wlc_hw_info *wlc_hw);
static u32 wlc_wlintrsoff(struct wlc_info *wlc);
@@ -2725,7 +2724,7 @@ void wlc_intrsrestore(struct wlc_info *wlc, u32 macintmask)
W_REG(&wlc_hw->regs->macintmask, wlc->macintmask);
}
-static void wlc_bmac_mute(struct wlc_hw_info *wlc_hw, bool on, mbool flags)
+void wlc_bmac_mute(struct wlc_hw_info *wlc_hw, bool on, mbool flags)
{
u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_bmac.h b/drivers/staging/brcm80211/brcmsmac/wlc_bmac.h
index a5dccc273ac5..a2a4e7328ee4 100644
--- a/drivers/staging/brcm80211/brcmsmac/wlc_bmac.h
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_bmac.h
@@ -103,6 +103,7 @@ extern void wlc_bmac_macphyclk_set(struct wlc_hw_info *wlc_hw, bool clk);
extern void wlc_bmac_phy_reset(struct wlc_hw_info *wlc_hw);
extern void wlc_bmac_corereset(struct wlc_hw_info *wlc_hw, u32 flags);
extern void wlc_bmac_reset(struct wlc_hw_info *wlc_hw);
+extern void wlc_bmac_mute(struct wlc_hw_info *wlc_hw, bool want, mbool flags);
extern void wlc_bmac_init(struct wlc_hw_info *wlc_hw, chanspec_t chanspec,
bool mute);
extern int wlc_bmac_up_prep(struct wlc_hw_info *wlc_hw);
diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_main.c b/drivers/staging/brcm80211/brcmsmac/wlc_main.c
index 4b4a31eff90c..99250e29461f 100644
--- a/drivers/staging/brcm80211/brcmsmac/wlc_main.c
+++ b/drivers/staging/brcm80211/brcmsmac/wlc_main.c
@@ -6145,6 +6145,7 @@ wlc_recvctl(struct wlc_info *wlc, d11rxhdr_t *rxh, struct sk_buff *p)
{
int len_mpdu;
struct ieee80211_rx_status rx_status;
+ struct ieee80211_hdr *hdr;
memset(&rx_status, 0, sizeof(rx_status));
prep_mac80211_status(wlc, rxh, p, &rx_status);
@@ -6154,6 +6155,13 @@ wlc_recvctl(struct wlc_info *wlc, d11rxhdr_t *rxh, struct sk_buff *p)
skb_pull(p, D11_PHY_HDR_LEN);
__skb_trim(p, len_mpdu);
+ /* unmute transmit */
+ if (wlc->hw->suspended_fifos) {
+ hdr = (struct ieee80211_hdr *)p->data;
+ if (ieee80211_is_beacon(hdr->frame_control))
+ wlc_bmac_mute(wlc->hw, false, 0);
+ }
+
memcpy(IEEE80211_SKB_RXCB(p), &rx_status, sizeof(rx_status));
ieee80211_rx_irqsafe(wlc->pub->ieee_hw, p);
return;
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 63e50f761828..ea8d109bb35e 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -280,7 +280,7 @@ static int do_devconfig_ioctl(struct comedi_device *dev,
if (ret == 0) {
if (!try_module_get(dev->driver->module)) {
comedi_device_detach(dev);
- return -ENOSYS;
+ ret = -ENOSYS;
}
}
diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c
index dd9a3bb6aa01..a1176d913125 100644
--- a/drivers/staging/iio/magnetometer/hmc5843.c
+++ b/drivers/staging/iio/magnetometer/hmc5843.c
@@ -520,7 +520,9 @@ static int hmc5843_detect(struct i2c_client *client,
/* Called when we have found a new HMC5843. */
static void hmc5843_init_client(struct i2c_client *client)
{
- struct hmc5843_data *data = i2c_get_clientdata(client);
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct hmc5843_data *data = iio_priv(indio_dev);
+
hmc5843_set_meas_conf(client, data->meas_conf);
hmc5843_set_rate(client, data->rate);
hmc5843_configure(client, data->operating_mode);
diff --git a/drivers/staging/lirc/lirc_serial.c b/drivers/staging/lirc/lirc_serial.c
index 805df913bb6e..21cbc9ae79c9 100644
--- a/drivers/staging/lirc/lirc_serial.c
+++ b/drivers/staging/lirc/lirc_serial.c
@@ -836,25 +836,22 @@ static int hardware_init_port(void)
return 0;
}
-static int init_port(void)
+static int __devinit lirc_serial_probe(struct platform_device *dev)
{
int i, nlow, nhigh, result;
result = request_irq(irq, irq_handler,
IRQF_DISABLED | (share_irq ? IRQF_SHARED : 0),
LIRC_DRIVER_NAME, (void *)&hardware);
-
- switch (result) {
- case -EBUSY:
- printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", irq);
- return -EBUSY;
- case -EINVAL:
- printk(KERN_ERR LIRC_DRIVER_NAME
- ": Bad irq number or handler\n");
- return -EINVAL;
- default:
- break;
- };
+ if (result < 0) {
+ if (result == -EBUSY)
+ printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n",
+ irq);
+ else if (result == -EINVAL)
+ printk(KERN_ERR LIRC_DRIVER_NAME
+ ": Bad irq number or handler\n");
+ return result;
+ }
/* Reserve io region. */
/*
@@ -875,11 +872,14 @@ static int init_port(void)
": or compile the serial port driver as module and\n");
printk(KERN_WARNING LIRC_DRIVER_NAME
": make sure this module is loaded first\n");
- return -EBUSY;
+ result = -EBUSY;
+ goto exit_free_irq;
}
- if (hardware_init_port() < 0)
- return -EINVAL;
+ if (hardware_init_port() < 0) {
+ result = -EINVAL;
+ goto exit_release_region;
+ }
/* Initialize pulse/space widths */
init_timing_params(duty_cycle, freq);
@@ -911,6 +911,28 @@ static int init_port(void)
dprintk("Interrupt %d, port %04x obtained\n", irq, io);
return 0;
+
+exit_release_region:
+ if (iommap != 0)
+ release_mem_region(iommap, 8 << ioshift);
+ else
+ release_region(io, 8);
+exit_free_irq:
+ free_irq(irq, (void *)&hardware);
+
+ return result;
+}
+
+static int __devexit lirc_serial_remove(struct platform_device *dev)
+{
+ free_irq(irq, (void *)&hardware);
+
+ if (iommap != 0)
+ release_mem_region(iommap, 8 << ioshift);
+ else
+ release_region(io, 8);
+
+ return 0;
}
static int set_use_inc(void *data)
@@ -1076,16 +1098,6 @@ static struct lirc_driver driver = {
static struct platform_device *lirc_serial_dev;
-static int __devinit lirc_serial_probe(struct platform_device *dev)
-{
- return 0;
-}
-
-static int __devexit lirc_serial_remove(struct platform_device *dev)
-{
- return 0;
-}
-
static int lirc_serial_suspend(struct platform_device *dev,
pm_message_t state)
{
@@ -1112,10 +1124,8 @@ static int lirc_serial_resume(struct platform_device *dev)
{
unsigned long flags;
- if (hardware_init_port() < 0) {
- lirc_serial_exit();
+ if (hardware_init_port() < 0)
return -EINVAL;
- }
spin_lock_irqsave(&hardware[type].lock, flags);
/* Enable Interrupt */
@@ -1188,10 +1198,6 @@ static int __init lirc_serial_init_module(void)
{
int result;
- result = lirc_serial_init();
- if (result)
- return result;
-
switch (type) {
case LIRC_HOMEBREW:
case LIRC_IRDEO:
@@ -1211,8 +1217,7 @@ static int __init lirc_serial_init_module(void)
break;
#endif
default:
- result = -EINVAL;
- goto exit_serial_exit;
+ return -EINVAL;
}
if (!softcarrier) {
switch (type) {
@@ -1228,37 +1233,26 @@ static int __init lirc_serial_init_module(void)
}
}
- result = init_port();
- if (result < 0)
- goto exit_serial_exit;
+ result = lirc_serial_init();
+ if (result)
+ return result;
+
driver.features = hardware[type].features;
driver.dev = &lirc_serial_dev->dev;
driver.minor = lirc_register_driver(&driver);
if (driver.minor < 0) {
printk(KERN_ERR LIRC_DRIVER_NAME
": register_chrdev failed!\n");
- result = -EIO;
- goto exit_release;
+ lirc_serial_exit();
+ return -EIO;
}
return 0;
-exit_release:
- release_region(io, 8);
-exit_serial_exit:
- lirc_serial_exit();
- return result;
}
static void __exit lirc_serial_exit_module(void)
{
- lirc_serial_exit();
-
- free_irq(irq, (void *)&hardware);
-
- if (iommap != 0)
- release_mem_region(iommap, 8 << ioshift);
- else
- release_region(io, 8);
lirc_unregister_driver(driver.minor);
+ lirc_serial_exit();
dprintk("cleaned up module\n");
}
diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c
index 6cb7e28c99a6..6d88d1a45f17 100644
--- a/drivers/staging/rtl8712/usb_intf.c
+++ b/drivers/staging/rtl8712/usb_intf.c
@@ -86,6 +86,7 @@ static struct usb_device_id rtl871x_usb_id_tbl[] = {
{USB_DEVICE(0x0DF6, 0x0045)},
{USB_DEVICE(0x0DF6, 0x0059)}, /* 11n mode disable */
{USB_DEVICE(0x0DF6, 0x004B)},
+ {USB_DEVICE(0x0DF6, 0x005B)},
{USB_DEVICE(0x0DF6, 0x005D)},
{USB_DEVICE(0x0DF6, 0x0063)},
/* Sweex */
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index 4b5421b391da..f7c3cfbbabac 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -905,6 +905,9 @@ static int tcm_loop_queue_data_in(struct se_cmd *se_cmd)
sc->result = SAM_STAT_GOOD;
set_host_byte(sc, DID_OK);
+ if ((se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) ||
+ (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT))
+ scsi_set_resid(sc, se_cmd->residual_count);
sc->scsi_done(sc);
return 0;
}
@@ -930,6 +933,9 @@ static int tcm_loop_queue_status(struct se_cmd *se_cmd)
sc->result = se_cmd->scsi_status;
set_host_byte(sc, DID_OK);
+ if ((se_cmd->se_cmd_flags & SCF_OVERFLOW_BIT) ||
+ (se_cmd->se_cmd_flags & SCF_UNDERFLOW_BIT))
+ scsi_set_resid(sc, se_cmd->residual_count);
sc->scsi_done(sc);
return 0;
}
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
index 86b36600acb4..c9674059213e 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -30,6 +30,7 @@
#include <linux/configfs.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
+#include <asm/unaligned.h>
#include <target/target_core_base.h>
#include <target/target_core_device.h>
@@ -238,8 +239,7 @@ int core_emulate_set_target_port_groups(struct se_cmd *cmd)
* changed.
*/
if (primary) {
- tg_pt_id = ((ptr[2] << 8) & 0xff);
- tg_pt_id |= (ptr[3] & 0xff);
+ tg_pt_id = get_unaligned_be16(ptr + 2);
/*
* Locate the matching target port group ID from
* the global tg_pt_gp list
@@ -280,8 +280,7 @@ int core_emulate_set_target_port_groups(struct se_cmd *cmd)
* the Target Port in question for the the incoming
* SET_TARGET_PORT_GROUPS op.
*/
- rtpi = ((ptr[2] << 8) & 0xff);
- rtpi |= (ptr[3] & 0xff);
+ rtpi = get_unaligned_be16(ptr + 2);
/*
* Locate the matching relative target port identifer
* for the struct se_device storage object.
diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c
index 7f19c8b7b84c..05584010e70e 100644
--- a/drivers/target/target_core_cdb.c
+++ b/drivers/target/target_core_cdb.c
@@ -84,6 +84,18 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
buf[2] = dev->transport->get_device_rev(dev);
/*
+ * NORMACA and HISUP = 0, RESPONSE DATA FORMAT = 2
+ *
+ * SPC4 says:
+ * A RESPONSE DATA FORMAT field set to 2h indicates that the
+ * standard INQUIRY data is in the format defined in this
+ * standard. Response data format values less than 2h are
+ * obsolete. Response data format values greater than 2h are
+ * reserved.
+ */
+ buf[3] = 2;
+
+ /*
* Enable SCCS and TPGS fields for Emulated ALUA
*/
if (T10_ALUA(dev->se_sub_dev)->alua_type == SPC3_ALUA_EMULATED)
@@ -94,7 +106,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
return 0;
}
- buf[7] = 0x32; /* Sync=1 and CmdQue=1 */
+ buf[7] = 0x2; /* CmdQue=1 */
/*
* Do not include vendor, product, reversion info in INQUIRY
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index b662db3a320b..98e12d31c9c2 100644
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -471,6 +471,7 @@ static int core_scsi3_pr_seq_non_holder(
case READ_MEDIA_SERIAL_NUMBER:
case REPORT_LUNS:
case REQUEST_SENSE:
+ case PERSISTENT_RESERVE_IN:
ret = 0; /*/ Allowed CDBs */
break;
default:
@@ -3079,7 +3080,7 @@ static int core_scsi3_pro_preempt(
if (!(calling_it_nexus))
core_scsi3_ua_allocate(pr_reg_nacl,
pr_res_mapped_lun, 0x2A,
- ASCQ_2AH_RESERVATIONS_PREEMPTED);
+ ASCQ_2AH_REGISTRATIONS_PREEMPTED);
}
spin_unlock(&pr_tmpl->registration_lock);
/*
@@ -3191,7 +3192,7 @@ static int core_scsi3_pro_preempt(
* additional sense code set to REGISTRATIONS PREEMPTED;
*/
core_scsi3_ua_allocate(pr_reg_nacl, pr_res_mapped_lun, 0x2A,
- ASCQ_2AH_RESERVATIONS_PREEMPTED);
+ ASCQ_2AH_REGISTRATIONS_PREEMPTED);
}
spin_unlock(&pr_tmpl->registration_lock);
/*
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 1340ffd76484..d3a7342317ea 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -5668,6 +5668,8 @@ int transport_send_check_condition_and_sense(
case TCM_SECTOR_COUNT_TOO_MANY:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* ILLEGAL REQUEST */
buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
/* INVALID COMMAND OPERATION CODE */
@@ -5676,6 +5678,7 @@ int transport_send_check_condition_and_sense(
case TCM_UNKNOWN_MODE_PAGE:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* ILLEGAL REQUEST */
buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
/* INVALID FIELD IN CDB */
@@ -5684,6 +5687,7 @@ int transport_send_check_condition_and_sense(
case TCM_CHECK_CONDITION_ABORT_CMD:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* ABORTED COMMAND */
buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
/* BUS DEVICE RESET FUNCTION OCCURRED */
@@ -5693,6 +5697,7 @@ int transport_send_check_condition_and_sense(
case TCM_INCORRECT_AMOUNT_OF_DATA:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* ABORTED COMMAND */
buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
/* WRITE ERROR */
@@ -5703,22 +5708,25 @@ int transport_send_check_condition_and_sense(
case TCM_INVALID_CDB_FIELD:
/* CURRENT ERROR */
buffer[offset] = 0x70;
- /* ABORTED COMMAND */
- buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+ /* ILLEGAL REQUEST */
+ buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
/* INVALID FIELD IN CDB */
buffer[offset+SPC_ASC_KEY_OFFSET] = 0x24;
break;
case TCM_INVALID_PARAMETER_LIST:
/* CURRENT ERROR */
buffer[offset] = 0x70;
- /* ABORTED COMMAND */
- buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+ /* ILLEGAL REQUEST */
+ buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
/* INVALID FIELD IN PARAMETER LIST */
buffer[offset+SPC_ASC_KEY_OFFSET] = 0x26;
break;
case TCM_UNEXPECTED_UNSOLICITED_DATA:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* ABORTED COMMAND */
buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
/* WRITE ERROR */
@@ -5729,6 +5737,7 @@ int transport_send_check_condition_and_sense(
case TCM_SERVICE_CRC_ERROR:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* ABORTED COMMAND */
buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
/* PROTOCOL SERVICE CRC ERROR */
@@ -5739,6 +5748,7 @@ int transport_send_check_condition_and_sense(
case TCM_SNACK_REJECTED:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* ABORTED COMMAND */
buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
/* READ ERROR */
@@ -5749,6 +5759,7 @@ int transport_send_check_condition_and_sense(
case TCM_WRITE_PROTECTED:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* DATA PROTECT */
buffer[offset+SPC_SENSE_KEY_OFFSET] = DATA_PROTECT;
/* WRITE PROTECTED */
@@ -5757,6 +5768,7 @@ int transport_send_check_condition_and_sense(
case TCM_CHECK_CONDITION_UNIT_ATTENTION:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* UNIT ATTENTION */
buffer[offset+SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
core_scsi3_ua_for_check_condition(cmd, &asc, &ascq);
@@ -5766,6 +5778,7 @@ int transport_send_check_condition_and_sense(
case TCM_CHECK_CONDITION_NOT_READY:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* Not Ready */
buffer[offset+SPC_SENSE_KEY_OFFSET] = NOT_READY;
transport_get_sense_codes(cmd, &asc, &ascq);
@@ -5776,6 +5789,7 @@ int transport_send_check_condition_and_sense(
default:
/* CURRENT ERROR */
buffer[offset] = 0x70;
+ buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
/* ILLEGAL REQUEST */
buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
/* LOGICAL UNIT COMMUNICATION FAILURE */
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c
index b2a106729d49..3c3fa84e9eff 100644
--- a/drivers/target/tcm_fc/tfc_cmd.c
+++ b/drivers/target/tcm_fc/tfc_cmd.c
@@ -371,10 +371,12 @@ static void ft_send_resp_status(struct fc_lport *lport,
fc_fill_reply_hdr(fp, rx_fp, FC_RCTL_DD_CMD_STATUS, 0);
sp = fr_seq(fp);
- if (sp)
+ if (sp) {
lport->tt.seq_send(lport, sp, fp);
- else
+ lport->tt.exch_done(sp);
+ } else {
lport->tt.frame_send(lport, fp);
+ }
}
/*
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index 220579592c20..34111486baac 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -1113,8 +1113,10 @@ static int set_serial_info(struct async_struct * info,
(new_serial.close_delay != state->close_delay) ||
(new_serial.xmit_fifo_size != state->xmit_fifo_size) ||
((new_serial.flags & ~ASYNC_USR_MASK) !=
- (state->flags & ~ASYNC_USR_MASK)))
+ (state->flags & ~ASYNC_USR_MASK))) {
+ tty_unlock();
return -EPERM;
+ }
state->flags = ((state->flags & ~ASYNC_USR_MASK) |
(new_serial.flags & ASYNC_USR_MASK));
info->flags = ((info->flags & ~ASYNC_USR_MASK) |
diff --git a/drivers/tty/moxa.c b/drivers/tty/moxa.c
index ba679ce0a774..8f82f7ab3541 100644
--- a/drivers/tty/moxa.c
+++ b/drivers/tty/moxa.c
@@ -1330,7 +1330,7 @@ static void moxa_start(struct tty_struct *tty)
if (ch == NULL)
return;
- if (!(ch->statusflags & TXSTOPPED))
+ if (!test_bit(TXSTOPPED, &ch->statusflags))
return;
MoxaPortTxEnable(ch);
diff --git a/drivers/tty/serial/8250_pci.c b/drivers/tty/serial/8250_pci.c
index ff48fdb5c0bf..21098ed99635 100644
--- a/drivers/tty/serial/8250_pci.c
+++ b/drivers/tty/serial/8250_pci.c
@@ -1459,51 +1459,61 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.vendor = PCI_VENDOR_ID_INTEL,
.device = 0x8811,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = 0x8812,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = 0x8813,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
{
.vendor = PCI_VENDOR_ID_INTEL,
.device = 0x8814,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
{
.vendor = 0x10DB,
.device = 0x8027,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
{
.vendor = 0x10DB,
.device = 0x8028,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
{
.vendor = 0x10DB,
.device = 0x8029,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
{
.vendor = 0x10DB,
.device = 0x800C,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
{
.vendor = 0x10DB,
.device = 0x800D,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
{
.vendor = 0x10DB,
.device = 0x800D,
.init = pci_eg20t_init,
+ .setup = pci_default_setup,
},
/*
* Cronyx Omega PCI (PLX-chip based)
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index 50bc5a5ac653..37db1d5898e0 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -555,7 +555,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res_mem)
port->mapbase = res_mem->start;
- else if (platp->mapbase)
+ else if (platp)
port->mapbase = platp->mapbase;
else
return -EINVAL;
@@ -563,7 +563,7 @@ static int __devinit altera_uart_probe(struct platform_device *pdev)
res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (res_irq)
port->irq = res_irq->start;
- else if (platp->irq)
+ else if (platp)
port->irq = platp->irq;
/* Check platform data first so we can override device node data */
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index f5f6831b0a64..21dc4b761eda 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1376,6 +1376,10 @@ static int pl011_startup(struct uart_port *port)
uap->port.uartclk = clk_get_rate(uap->clk);
+ /* Clear pending error and receive interrupts */
+ writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS |
+ UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR);
+
/*
* Allocate the IRQ
*/
@@ -1410,10 +1414,6 @@ static int pl011_startup(struct uart_port *port)
cr = UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
writew(cr, uap->port.membase + UART011_CR);
- /* Clear pending error interrupts */
- writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS,
- uap->port.membase + UART011_ICR);
-
/*
* initialise the old status of the modem signals
*/
@@ -1428,6 +1428,9 @@ static int pl011_startup(struct uart_port *port)
* as well.
*/
spin_lock_irq(&uap->port.lock);
+ /* Clear out any spuriously appearing RX interrupts */
+ writew(UART011_RTIS | UART011_RXIS,
+ uap->port.membase + UART011_ICR);
uap->im = UART011_RTIM;
if (!pl011_dma_rx_running(uap))
uap->im |= UART011_RXIM;
@@ -1733,9 +1736,19 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
{
struct uart_amba_port *uap = amba_ports[co->index];
unsigned int status, old_cr, new_cr;
+ unsigned long flags;
+ int locked = 1;
clk_enable(uap->clk);
+ local_irq_save(flags);
+ if (uap->port.sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+ locked = spin_trylock(&uap->port.lock);
+ else
+ spin_lock(&uap->port.lock);
+
/*
* First save the CR then disable the interrupts
*/
@@ -1755,6 +1768,10 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
} while (status & UART01x_FR_BUSY);
writew(old_cr, uap->port.membase + UART011_CR);
+ if (locked)
+ spin_unlock(&uap->port.lock);
+ local_irq_restore(flags);
+
clk_disable(uap->clk);
}
@@ -1906,6 +1923,10 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
uap->port.line = i;
pl011_dma_probe(uap);
+ /* Ensure interrupts from this UART are masked and cleared */
+ writew(0, uap->port.membase + UART011_IMSC);
+ writew(0xffff, uap->port.membase + UART011_ICR);
+
snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev));
amba_ports[i] = uap;
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index af9b7814965a..b989495c763e 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -199,8 +199,9 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
unsigned int mode;
+ unsigned long flags;
- spin_lock(&port->lock);
+ spin_lock_irqsave(&port->lock, flags);
/* Disable interrupts */
UART_PUT_IDR(port, atmel_port->tx_done_mask);
@@ -231,7 +232,7 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
/* Enable interrupts */
UART_PUT_IER(port, atmel_port->tx_done_mask);
- spin_unlock(&port->lock);
+ spin_unlock_irqrestore(&port->lock, flags);
}
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index e6c3dbd781d6..836fe2731234 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -154,10 +154,9 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id)
port->x_char = 0;
return IRQ_HANDLED;
}
- if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
- clps711xuart_stop_tx(port);
- return IRQ_HANDLED;
- }
+
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port))
+ goto disable_tx_irq;
count = port->fifosize >> 1;
do {
@@ -171,8 +170,11 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id)
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
- if (uart_circ_empty(xmit))
- clps711xuart_stop_tx(port);
+ if (uart_circ_empty(xmit)) {
+ disable_tx_irq:
+ disable_irq_nosync(TX_IRQ(port));
+ tx_enabled(port) = 0;
+ }
return IRQ_HANDLED;
}
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index beba18533371..8a66f3eeb992 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -697,6 +697,9 @@ static unsigned int imx_get_mctrl(struct uart_port *port)
if (readl(sport->port.membase + UCR2) & UCR2_CTS)
tmp |= TIOCM_RTS;
+ if (readl(sport->port.membase + UTS) & UTS_LOOP)
+ tmp |= TIOCM_LOOP;
+
return tmp;
}
@@ -707,10 +710,19 @@ static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl)
temp = readl(sport->port.membase + UCR2) & ~UCR2_CTS;
- if (mctrl & TIOCM_RTS)
+ if (mctrl & TIOCM_RTS) {
temp |= UCR2_CTS;
+ writel(temp, sport->port.membase + UCR2);
+ }
- writel(temp, sport->port.membase + UCR2);
+ if (mctrl & TIOCM_LOOP) {
+ temp = readl(sport->port.membase + UTS) & ~UTS_LOOP;
+ temp |= UTS_LOOP;
+ writel(temp, sport->port.membase + UTS);
+ } else {
+ temp = readl(sport->port.membase + UTS) & ~UTS_LOOP;
+ writel(temp, sport->port.membase + UTS);
+ }
}
/*
diff --git a/drivers/tty/serial/jsm/jsm_driver.c b/drivers/tty/serial/jsm/jsm_driver.c
index 2aaafa9c58a2..6c12d94e6d3f 100644
--- a/drivers/tty/serial/jsm/jsm_driver.c
+++ b/drivers/tty/serial/jsm/jsm_driver.c
@@ -269,6 +269,7 @@ static void jsm_io_resume(struct pci_dev *pdev)
struct jsm_board *brd = pci_get_drvdata(pdev);
pci_restore_state(pdev);
+ pci_save_state(pdev);
jsm_uart_port_init(brd);
}
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 7e02c9c344fe..5b3d063a4aa1 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -368,6 +368,8 @@ static void mxs_auart_settermios(struct uart_port *u,
writel(ctrl, u->membase + AUART_LINECTRL);
writel(ctrl2, u->membase + AUART_CTRL2);
+
+ uart_update_timeout(u, termios->c_cflag, baud);
}
static irqreturn_t mxs_auart_irq_handle(int irq, void *context)
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 902588b2a127..101eda9f1965 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -602,7 +602,8 @@ static void pch_request_dma(struct uart_port *port)
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
- dma_dev = pci_get_bus_and_slot(2, PCI_DEVFN(0xa, 0)); /* Get DMA's dev
+ dma_dev = pci_get_bus_and_slot(priv->pdev->bus->number,
+ PCI_DEVFN(0xa, 0)); /* Get DMA's dev
information */
/* Set Tx DMA */
param = &priv->param_tx;
@@ -1353,9 +1354,11 @@ static int pch_uart_verify_port(struct uart_port *port,
__func__);
return -EOPNOTSUPP;
#endif
- priv->use_dma = 1;
priv->use_dma_flag = 1;
dev_info(priv->port.dev, "PCH UART : Use DMA Mode\n");
+ if (!priv->use_dma)
+ pch_request_dma(port);
+ priv->use_dma = 1;
}
return 0;
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 5668b3eb96d8..2a106a94cdd0 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2328,6 +2328,7 @@ void uart_unregister_driver(struct uart_driver *drv)
tty_unregister_driver(p);
put_tty_driver(p);
kfree(drv->state);
+ drv->state = NULL;
drv->tty_driver = NULL;
}
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index ebd8629c108d..bead17e5634a 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -953,17 +953,20 @@ static void sci_dma_tx_complete(void *arg)
port->icount.tx += sg_dma_len(&s->sg_tx);
async_tx_ack(s->desc_tx);
- s->cookie_tx = -EINVAL;
s->desc_tx = NULL;
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
if (!uart_circ_empty(xmit)) {
+ s->cookie_tx = 0;
schedule_work(&s->work_tx);
- } else if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
- u16 ctrl = sci_in(port, SCSCR);
- sci_out(port, SCSCR, ctrl & ~SCSCR_TIE);
+ } else {
+ s->cookie_tx = -EINVAL;
+ if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
+ u16 ctrl = sci_in(port, SCSCR);
+ sci_out(port, SCSCR, ctrl & ~SCSCR_TIE);
+ }
}
spin_unlock_irqrestore(&port->lock, flags);
@@ -1225,8 +1228,10 @@ static void sci_start_tx(struct uart_port *port)
}
if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) &&
- s->cookie_tx < 0)
+ s->cookie_tx < 0) {
+ s->cookie_tx = 0;
schedule_work(&s->work_tx);
+ }
#endif
if (!s->chan_tx || port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index 33d37d230f8f..a4aaca0e014d 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -227,7 +227,6 @@ int tty_port_block_til_ready(struct tty_port *port,
int do_clocal = 0, retval;
unsigned long flags;
DEFINE_WAIT(wait);
- int cd;
/* block if port is in the process of being closed */
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
@@ -284,11 +283,14 @@ int tty_port_block_til_ready(struct tty_port *port,
retval = -ERESTARTSYS;
break;
}
- /* Probe the carrier. For devices with no carrier detect this
- will always return true */
- cd = tty_port_carrier_raised(port);
+ /*
+ * Probe the carrier. For devices with no carrier detect
+ * tty_port_carrier_raised will always return true.
+ * Never ask drivers if CLOCAL is set, this causes troubles
+ * on some hardware.
+ */
if (!(port->flags & ASYNC_CLOSING) &&
- (do_clocal || cd))
+ (do_clocal || tty_port_carrier_raised(port)))
break;
if (signal_pending(current)) {
retval = -ERESTARTSYS;
diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c
index 45d3e80156d4..f3438083a285 100644
--- a/drivers/tty/vt/consolemap.c
+++ b/drivers/tty/vt/consolemap.c
@@ -516,6 +516,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
int err = 0, err1, i;
struct uni_pagedir *p, *q;
+ /* Save original vc_unipagdir_loc in case we allocate a new one */
p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
if (p->readonly) return -EIO;
@@ -528,26 +529,57 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
err1 = con_clear_unimap(vc, NULL);
if (err1) return err1;
+ /*
+ * Since refcount was > 1, con_clear_unimap() allocated a
+ * a new uni_pagedir for this vc. Re: p != q
+ */
q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
- for (i = 0, l = 0; i < 32; i++)
+
+ /*
+ * uni_pgdir is a 32*32*64 table with rows allocated
+ * when its first entry is added. The unicode value must
+ * still be incremented for empty rows. We are copying
+ * entries from "p" (old) to "q" (new).
+ */
+ l = 0; /* unicode value */
+ for (i = 0; i < 32; i++)
if ((p1 = p->uni_pgdir[i]))
for (j = 0; j < 32; j++)
- if ((p2 = p1[j]))
+ if ((p2 = p1[j])) {
for (k = 0; k < 64; k++, l++)
if (p2[k] != 0xffff) {
+ /*
+ * Found one, copy entry for unicode
+ * l with fontpos value p2[k].
+ */
err1 = con_insert_unipair(q, l, p2[k]);
if (err1) {
p->refcount++;
*vc->vc_uni_pagedir_loc = (unsigned long)p;
con_release_unimap(q);
kfree(q);
- return err1;
+ return err1;
}
- }
- p = q;
- } else if (p == dflt)
+ }
+ } else {
+ /* Account for row of 64 empty entries */
+ l += 64;
+ }
+ else
+ /* Account for empty table */
+ l += 32 * 64;
+
+ /*
+ * Finished copying font table, set vc_uni_pagedir to new table
+ */
+ p = q;
+ } else if (p == dflt) {
dflt = NULL;
-
+ }
+
+ /*
+ * Insert user specified unicode pairs into new table.
+ */
while (ct--) {
unsigned short unicode, fontpos;
__get_user(unicode, &list->unicode);
@@ -557,11 +589,14 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
list++;
}
+ /*
+ * Merge with fontmaps of any other virtual consoles.
+ */
if (con_unify_unimap(vc, p))
return err;
for (i = 0; i <= 3; i++)
- set_inverse_transl(vc, p, i); /* Update all inverse translations */
+ set_inverse_transl(vc, p, i); /* Update inverse translations */
set_inverse_trans_unicode(vc, p);
return err;
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index 5e096f43bcea..65447c5f91d7 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -1463,7 +1463,6 @@ compat_kdfontop_ioctl(struct compat_console_font_op __user *fontop,
if (!perm && op->op != KD_FONT_OP_GET)
return -EPERM;
op->data = compat_ptr(((struct compat_console_font_op *)op)->data);
- op->flags |= KD_FONT_FLAG_OLD;
i = con_font_op(vc, op);
if (i)
return i;
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 8faa23cd74f1..158f63121434 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -554,10 +554,18 @@ static void acm_port_down(struct acm *acm)
static void acm_tty_hangup(struct tty_struct *tty)
{
- struct acm *acm = tty->driver_data;
- tty_port_hangup(&acm->port);
+ struct acm *acm;
+
mutex_lock(&open_mutex);
+ acm = tty->driver_data;
+
+ if (!acm)
+ goto out;
+
+ tty_port_hangup(&acm->port);
acm_port_down(acm);
+
+out:
mutex_unlock(&open_mutex);
}
@@ -1183,6 +1191,8 @@ made_compressed_probe:
i = device_create_file(&intf->dev, &dev_attr_wCountryCodes);
if (i < 0) {
kfree(acm->country_codes);
+ acm->country_codes = NULL;
+ acm->country_code_size = 0;
goto skip_countries;
}
@@ -1191,6 +1201,8 @@ made_compressed_probe:
if (i < 0) {
device_remove_file(&intf->dev, &dev_attr_wCountryCodes);
kfree(acm->country_codes);
+ acm->country_codes = NULL;
+ acm->country_code_size = 0;
goto skip_countries;
}
}
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 2b9ff518b509..5a244cfbeb42 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -57,6 +57,8 @@ MODULE_DEVICE_TABLE (usb, wdm_ids);
#define WDM_MAX 16
+/* CDC-WMC r1.1 requires wMaxCommand to be "at least 256 decimal (0x100)" */
+#define WDM_DEFAULT_BUFSIZE 256
static DEFINE_MUTEX(wdm_mutex);
@@ -88,7 +90,8 @@ struct wdm_device {
int count;
dma_addr_t shandle;
dma_addr_t ihandle;
- struct mutex lock;
+ struct mutex wlock;
+ struct mutex rlock;
wait_queue_head_t wait;
struct work_struct rxwork;
int werr;
@@ -105,8 +108,9 @@ static void wdm_out_callback(struct urb *urb)
spin_lock(&desc->iuspin);
desc->werr = urb->status;
spin_unlock(&desc->iuspin);
- clear_bit(WDM_IN_USE, &desc->flags);
kfree(desc->outbuf);
+ desc->outbuf = NULL;
+ clear_bit(WDM_IN_USE, &desc->flags);
wake_up(&desc->wait);
}
@@ -309,7 +313,7 @@ static ssize_t wdm_write
if (we < 0)
return -EIO;
- desc->outbuf = buf = kmalloc(count, GFP_KERNEL);
+ buf = kmalloc(count, GFP_KERNEL);
if (!buf) {
rv = -ENOMEM;
goto outnl;
@@ -323,7 +327,7 @@ static ssize_t wdm_write
}
/* concurrent writes and disconnect */
- r = mutex_lock_interruptible(&desc->lock);
+ r = mutex_lock_interruptible(&desc->wlock);
rv = -ERESTARTSYS;
if (r) {
kfree(buf);
@@ -373,10 +377,12 @@ static ssize_t wdm_write
req->wIndex = desc->inum;
req->wLength = cpu_to_le16(count);
set_bit(WDM_IN_USE, &desc->flags);
+ desc->outbuf = buf;
rv = usb_submit_urb(desc->command, GFP_KERNEL);
if (rv < 0) {
kfree(buf);
+ desc->outbuf = NULL;
clear_bit(WDM_IN_USE, &desc->flags);
dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv);
} else {
@@ -386,7 +392,7 @@ static ssize_t wdm_write
out:
usb_autopm_put_interface(desc->intf);
outnp:
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->wlock);
outnl:
return rv < 0 ? rv : count;
}
@@ -394,16 +400,17 @@ outnl:
static ssize_t wdm_read
(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
{
- int rv, cntr = 0;
+ int rv, cntr;
int i = 0;
struct wdm_device *desc = file->private_data;
- rv = mutex_lock_interruptible(&desc->lock); /*concurrent reads */
+ rv = mutex_lock_interruptible(&desc->rlock); /*concurrent reads */
if (rv < 0)
return -ERESTARTSYS;
- if (desc->length == 0) {
+ cntr = ACCESS_ONCE(desc->length);
+ if (cntr == 0) {
desc->read = 0;
retry:
if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
@@ -453,17 +460,20 @@ retry:
spin_unlock_irq(&desc->iuspin);
goto retry;
}
- clear_bit(WDM_READ, &desc->flags);
+ cntr = desc->length;
spin_unlock_irq(&desc->iuspin);
}
- cntr = count > desc->length ? desc->length : count;
+ if (cntr > count)
+ cntr = count;
rv = copy_to_user(buffer, desc->ubuf, cntr);
if (rv > 0) {
rv = -EFAULT;
goto err;
}
+ spin_lock_irq(&desc->iuspin);
+
for (i = 0; i < desc->length - cntr; i++)
desc->ubuf[i] = desc->ubuf[i + cntr];
@@ -471,10 +481,13 @@ retry:
/* in case we had outstanding data */
if (!desc->length)
clear_bit(WDM_READ, &desc->flags);
+
+ spin_unlock_irq(&desc->iuspin);
+
rv = cntr;
err:
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->rlock);
return rv;
}
@@ -498,7 +511,7 @@ static unsigned int wdm_poll(struct file *file, struct poll_table_struct *wait)
spin_lock_irqsave(&desc->iuspin, flags);
if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
- mask = POLLERR;
+ mask = POLLHUP | POLLERR;
spin_unlock_irqrestore(&desc->iuspin, flags);
goto desc_out;
}
@@ -540,7 +553,8 @@ static int wdm_open(struct inode *inode, struct file *file)
}
intf->needs_remote_wakeup = 1;
- mutex_lock(&desc->lock);
+ /* using write lock to protect desc->count */
+ mutex_lock(&desc->wlock);
if (!desc->count++) {
desc->werr = 0;
desc->rerr = 0;
@@ -553,7 +567,7 @@ static int wdm_open(struct inode *inode, struct file *file)
} else {
rv = 0;
}
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->wlock);
usb_autopm_put_interface(desc->intf);
out:
mutex_unlock(&wdm_mutex);
@@ -565,9 +579,11 @@ static int wdm_release(struct inode *inode, struct file *file)
struct wdm_device *desc = file->private_data;
mutex_lock(&wdm_mutex);
- mutex_lock(&desc->lock);
+
+ /* using write lock to protect desc->count */
+ mutex_lock(&desc->wlock);
desc->count--;
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->wlock);
if (!desc->count) {
dev_dbg(&desc->intf->dev, "wdm_release: cleanup");
@@ -630,7 +646,7 @@ static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
struct usb_cdc_dmm_desc *dmhd;
u8 *buffer = intf->altsetting->extra;
int buflen = intf->altsetting->extralen;
- u16 maxcom = 0;
+ u16 maxcom = WDM_DEFAULT_BUFSIZE;
if (!buffer)
goto out;
@@ -665,7 +681,8 @@ next_desc:
desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL);
if (!desc)
goto out;
- mutex_init(&desc->lock);
+ mutex_init(&desc->rlock);
+ mutex_init(&desc->wlock);
spin_lock_init(&desc->iuspin);
init_waitqueue_head(&desc->wait);
desc->wMaxCommand = maxcom;
@@ -716,7 +733,7 @@ next_desc:
goto err;
desc->inbuf = usb_alloc_coherent(interface_to_usbdev(intf),
- desc->bMaxPacketSize0,
+ desc->wMaxCommand,
GFP_KERNEL,
&desc->response->transfer_dma);
if (!desc->inbuf)
@@ -779,11 +796,13 @@ static void wdm_disconnect(struct usb_interface *intf)
/* to terminate pending flushes */
clear_bit(WDM_IN_USE, &desc->flags);
spin_unlock_irqrestore(&desc->iuspin, flags);
- mutex_lock(&desc->lock);
+ wake_up_all(&desc->wait);
+ mutex_lock(&desc->rlock);
+ mutex_lock(&desc->wlock);
kill_urbs(desc);
cancel_work_sync(&desc->rxwork);
- mutex_unlock(&desc->lock);
- wake_up_all(&desc->wait);
+ mutex_unlock(&desc->wlock);
+ mutex_unlock(&desc->rlock);
if (!desc->count)
cleanup(desc);
mutex_unlock(&wdm_mutex);
@@ -798,8 +817,10 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor);
/* if this is an autosuspend the caller does the locking */
- if (!(message.event & PM_EVENT_AUTO))
- mutex_lock(&desc->lock);
+ if (!(message.event & PM_EVENT_AUTO)) {
+ mutex_lock(&desc->rlock);
+ mutex_lock(&desc->wlock);
+ }
spin_lock_irq(&desc->iuspin);
if ((message.event & PM_EVENT_AUTO) &&
@@ -815,8 +836,10 @@ static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
kill_urbs(desc);
cancel_work_sync(&desc->rxwork);
}
- if (!(message.event & PM_EVENT_AUTO))
- mutex_unlock(&desc->lock);
+ if (!(message.event & PM_EVENT_AUTO)) {
+ mutex_unlock(&desc->wlock);
+ mutex_unlock(&desc->rlock);
+ }
return rv;
}
@@ -854,7 +877,8 @@ static int wdm_pre_reset(struct usb_interface *intf)
{
struct wdm_device *desc = usb_get_intfdata(intf);
- mutex_lock(&desc->lock);
+ mutex_lock(&desc->rlock);
+ mutex_lock(&desc->wlock);
kill_urbs(desc);
/*
@@ -876,7 +900,8 @@ static int wdm_post_reset(struct usb_interface *intf)
int rv;
rv = recover_from_urb_loss(desc);
- mutex_unlock(&desc->lock);
+ mutex_unlock(&desc->wlock);
+ mutex_unlock(&desc->rlock);
return 0;
}
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 0ca54e22d319..ca3c303eed81 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -292,17 +292,14 @@ static struct async *async_getcompleted(struct dev_state *ps)
static struct async *async_getpending(struct dev_state *ps,
void __user *userurb)
{
- unsigned long flags;
struct async *as;
- spin_lock_irqsave(&ps->lock, flags);
list_for_each_entry(as, &ps->async_pending, asynclist)
if (as->userurb == userurb) {
list_del_init(&as->asynclist);
- spin_unlock_irqrestore(&ps->lock, flags);
return as;
}
- spin_unlock_irqrestore(&ps->lock, flags);
+
return NULL;
}
@@ -357,6 +354,7 @@ static void cancel_bulk_urbs(struct dev_state *ps, unsigned bulk_addr)
__releases(ps->lock)
__acquires(ps->lock)
{
+ struct urb *urb;
struct async *as;
/* Mark all the pending URBs that match bulk_addr, up to but not
@@ -379,8 +377,11 @@ __acquires(ps->lock)
list_for_each_entry(as, &ps->async_pending, asynclist) {
if (as->bulk_status == AS_UNLINK) {
as->bulk_status = 0; /* Only once */
+ urb = as->urb;
+ usb_get_urb(urb);
spin_unlock(&ps->lock); /* Allow completions */
- usb_unlink_urb(as->urb);
+ usb_unlink_urb(urb);
+ usb_put_urb(urb);
spin_lock(&ps->lock);
goto rescan;
}
@@ -433,6 +434,7 @@ static void async_completed(struct urb *urb)
static void destroy_async(struct dev_state *ps, struct list_head *list)
{
+ struct urb *urb;
struct async *as;
unsigned long flags;
@@ -440,10 +442,13 @@ static void destroy_async(struct dev_state *ps, struct list_head *list)
while (!list_empty(list)) {
as = list_entry(list->next, struct async, asynclist);
list_del_init(&as->asynclist);
+ urb = as->urb;
+ usb_get_urb(urb);
/* drop the spinlock so the completion handler can run */
spin_unlock_irqrestore(&ps->lock, flags);
- usb_kill_urb(as->urb);
+ usb_kill_urb(urb);
+ usb_put_urb(urb);
spin_lock_irqsave(&ps->lock, flags);
}
spin_unlock_irqrestore(&ps->lock, flags);
@@ -1352,12 +1357,24 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg)
static int proc_unlinkurb(struct dev_state *ps, void __user *arg)
{
+ struct urb *urb;
struct async *as;
+ unsigned long flags;
+ spin_lock_irqsave(&ps->lock, flags);
as = async_getpending(ps, arg);
- if (!as)
+ if (!as) {
+ spin_unlock_irqrestore(&ps->lock, flags);
return -EINVAL;
- usb_kill_urb(as->urb);
+ }
+
+ urb = as->urb;
+ usb_get_urb(urb);
+ spin_unlock_irqrestore(&ps->lock, flags);
+
+ usb_kill_urb(urb);
+ usb_put_urb(urb);
+
return 0;
}
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index ce22f4a84ed0..aa7bbbcf9d8a 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -187,7 +187,10 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
return -ENODEV;
dev->current_state = PCI_D0;
- if (!dev->irq) {
+ /* The xHCI driver supports MSI and MSI-X,
+ * so don't fail if the BIOS doesn't provide a legacy IRQ.
+ */
+ if (!dev->irq && (driver->flags & HCD_MASK) != HCD_USB3) {
dev_err(&dev->dev,
"Found HC with no IRQ. Check BIOS/PCI %s setup!\n",
pci_name(dev));
@@ -492,6 +495,15 @@ static int hcd_pci_suspend_noirq(struct device *dev)
pci_save_state(pci_dev);
+ /*
+ * Some systems crash if an EHCI controller is in D3 during
+ * a sleep transition. We have to leave such controllers in D0.
+ */
+ if (hcd->broken_pci_sleep) {
+ dev_dbg(dev, "Staying in PCI D0\n");
+ return retval;
+ }
+
/* If the root hub is dead rather than suspended, disallow remote
* wakeup. usb_hc_died() should ensure that both hosts are marked as
* dying, so we only need to check the primary roothub.
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 39ea00bfb9c4..45e090850c93 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1387,11 +1387,10 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
ret = -EAGAIN;
else
urb->transfer_flags |= URB_DMA_MAP_SG;
- if (n != urb->num_sgs) {
- urb->num_sgs = n;
+ urb->num_mapped_sgs = n;
+ if (n != urb->num_sgs)
urb->transfer_flags |=
URB_DMA_SG_COMBINED;
- }
} else if (urb->sg) {
struct scatterlist *sg = urb->sg;
urb->transfer_dma = dma_map_page(
@@ -2436,8 +2435,10 @@ int usb_add_hcd(struct usb_hcd *hcd,
&& device_can_wakeup(&hcd->self.root_hub->dev))
dev_dbg(hcd->self.controller, "supports USB remote wakeup\n");
- /* enable irqs just before we start the controller */
- if (usb_hcd_is_primary_hcd(hcd)) {
+ /* enable irqs just before we start the controller,
+ * if the BIOS provides legacy PCI irqs.
+ */
+ if (usb_hcd_is_primary_hcd(hcd) && irqnum) {
retval = usb_hcd_request_irqs(hcd, irqnum, irqflags);
if (retval)
goto err_request_irq;
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 2932cec1c316..55a63e480adb 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -709,10 +709,26 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
if (type == HUB_INIT3)
goto init3;
- /* After a resume, port power should still be on.
+ /* The superspeed hub except for root hub has to use Hub Depth
+ * value as an offset into the route string to locate the bits
+ * it uses to determine the downstream port number. So hub driver
+ * should send a set hub depth request to superspeed hub after
+ * the superspeed hub is set configuration in initialization or
+ * reset procedure.
+ *
+ * After a resume, port power should still be on.
* For any other type of activation, turn it on.
*/
if (type != HUB_RESUME) {
+ if (hdev->parent && hub_is_superspeed(hdev)) {
+ ret = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
+ HUB_SET_DEPTH, USB_RT_HUB,
+ hdev->level - 1, 0, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
+ if (ret < 0)
+ dev_err(hub->intfdev,
+ "set hub depth failed\n");
+ }
/* Speed up system boot by using a delayed_work for the
* hub's initial power-up delays. This is pretty awkward
@@ -991,18 +1007,6 @@ static int hub_configure(struct usb_hub *hub,
goto fail;
}
- if (hub_is_superspeed(hdev) && (hdev->parent != NULL)) {
- ret = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
- HUB_SET_DEPTH, USB_RT_HUB,
- hdev->level - 1, 0, NULL, 0,
- USB_CTRL_SET_TIMEOUT);
-
- if (ret < 0) {
- message = "can't set hub depth";
- goto fail;
- }
- }
-
/* Request the entire hub descriptor.
* hub->descriptor can handle USB_MAXCHILDREN ports,
* but the hub can/will return fewer bytes here.
@@ -1644,7 +1648,6 @@ void usb_disconnect(struct usb_device **pdev)
{
struct usb_device *udev = *pdev;
int i;
- struct usb_hcd *hcd = bus_to_hcd(udev->bus);
if (!udev) {
pr_debug ("%s nodev\n", __func__);
@@ -1672,9 +1675,7 @@ void usb_disconnect(struct usb_device **pdev)
* so that the hardware is now fully quiesced.
*/
dev_dbg (&udev->dev, "unregistering device\n");
- mutex_lock(hcd->bandwidth_mutex);
usb_disable_device(udev, 0);
- mutex_unlock(hcd->bandwidth_mutex);
usb_hcd_synchronize_unlinks(udev);
usb_remove_ep_devs(&udev->ep0);
@@ -2542,7 +2543,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
struct fsl_usb2_platform_data *pdata;
pdata = hcd->self.controller->platform_data;
- if (pdata->platform_rh_resume)
+ if (pdata && pdata->platform_rh_resume)
pdata->platform_rh_resume(pdata);
}
#endif
@@ -2564,7 +2565,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
struct fsl_usb2_platform_data *pdata;
pdata = hcd->self.controller->platform_data;
- if (pdata->platform_rh_resume)
+ if (pdata && pdata->platform_rh_resume)
pdata->platform_rh_resume(pdata);
}
#endif
@@ -3244,12 +3245,12 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
pdata = (struct fsl_usb2_platform_data *)dev->platform_data;
if (dev->parent && (hdev->level == 0) && dev->type) {
- if (port1 == 1 && pdata->init)
+ if (port1 == 1 && pdata && pdata->init)
pdata->init(NULL);
}
if ((port1 == 1) && (hdev->level == 0)) {
/* Must clear HOSTDISCONDETECT when port connect change happen*/
- if (pdata->platform_set_disconnect_det)
+ if (pdata && pdata->platform_set_disconnect_det)
pdata->platform_set_disconnect_det(pdata, 0);
}
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 0b5ec234c787..1eebd45b8137 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -308,7 +308,8 @@ static void sg_complete(struct urb *urb)
retval = usb_unlink_urb(io->urbs [i]);
if (retval != -EINPROGRESS &&
retval != -ENODEV &&
- retval != -EBUSY)
+ retval != -EBUSY &&
+ retval != -EIDRM)
dev_err(&io->dev->dev,
"%s, unlink --> %d\n",
__func__, retval);
@@ -317,7 +318,6 @@ static void sg_complete(struct urb *urb)
}
spin_lock(&io->lock);
}
- urb->dev = NULL;
/* on the last completion, signal usb_sg_wait() */
io->bytes += urb->actual_length;
@@ -524,7 +524,6 @@ void usb_sg_wait(struct usb_sg_request *io)
case -ENXIO: /* hc didn't queue this one */
case -EAGAIN:
case -ENOMEM:
- io->urbs[i]->dev = NULL;
retval = 0;
yield();
break;
@@ -542,7 +541,6 @@ void usb_sg_wait(struct usb_sg_request *io)
/* fail any uncompleted urbs */
default:
- io->urbs[i]->dev = NULL;
io->urbs[i]->status = retval;
dev_dbg(&io->dev->dev, "%s, submit --> %d\n",
__func__, retval);
@@ -593,7 +591,10 @@ void usb_sg_cancel(struct usb_sg_request *io)
if (!io->urbs [i]->dev)
continue;
retval = usb_unlink_urb(io->urbs [i]);
- if (retval != -EINPROGRESS && retval != -EBUSY)
+ if (retval != -EINPROGRESS
+ && retval != -ENODEV
+ && retval != -EBUSY
+ && retval != -EIDRM)
dev_warn(&io->dev->dev, "%s, unlink --> %d\n",
__func__, retval);
}
@@ -1135,8 +1136,6 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf,
* Deallocates hcd/hardware state for the endpoints (nuking all or most
* pending urbs) and usbcore state for the interfaces, so that usbcore
* must usb_set_configuration() before any interfaces could be used.
- *
- * Must be called with hcd->bandwidth_mutex held.
*/
void usb_disable_device(struct usb_device *dev, int skip_ep0)
{
@@ -1189,7 +1188,9 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
usb_disable_endpoint(dev, i + USB_DIR_IN, false);
}
/* Remove endpoints from the host controller internal state */
+ mutex_lock(hcd->bandwidth_mutex);
usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
+ mutex_unlock(hcd->bandwidth_mutex);
/* Second pass: remove endpoint pointers */
}
for (i = skip_ep0; i < 16; ++i) {
@@ -1749,7 +1750,6 @@ free_interfaces:
/* if it's already configured, clear out old state first.
* getting rid of old interfaces means unbinding their drivers.
*/
- mutex_lock(hcd->bandwidth_mutex);
if (dev->state != USB_STATE_ADDRESS)
usb_disable_device(dev, 1); /* Skip ep0 */
@@ -1762,6 +1762,7 @@ free_interfaces:
* host controller will not allow submissions to dropped endpoints. If
* this call fails, the device state is unchanged.
*/
+ mutex_lock(hcd->bandwidth_mutex);
ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);
if (ret < 0) {
mutex_unlock(hcd->bandwidth_mutex);
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index ecf12e15a7ef..32d3adc315f5 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -117,9 +117,15 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x06a3, 0x0006), .driver_info =
USB_QUIRK_CONFIG_INTF_STRINGS },
- /* Guillemot Webcam Hercules Dualpix Exchange*/
+ /* Guillemot Webcam Hercules Dualpix Exchange (2nd ID) */
{ USB_DEVICE(0x06f8, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME },
+ /* Guillemot Webcam Hercules Dualpix Exchange*/
+ { USB_DEVICE(0x06f8, 0x3005), .driver_info = USB_QUIRK_RESET_RESUME },
+
+ /* Midiman M-Audio Keystation 88es */
+ { USB_DEVICE(0x0763, 0x0192), .driver_info = USB_QUIRK_RESET_RESUME },
+
/* M-Systems Flash Disk Pioneers */
{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 9beadf4ddded..98eb37f35364 100755
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -577,7 +577,7 @@ config USB_LANGWELL
select USB_GADGET_SELECTED
config USB_GADGET_EG20T
- boolean "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH UDC"
+ tristate "Intel EG20T PCH/OKI SEMICONDUCTOR IOH(ML7213/ML7831) UDC"
depends on PCI
select USB_GADGET_DUALSPEED
help
@@ -595,8 +595,9 @@ config USB_GADGET_EG20T
This driver also can be used for OKI SEMICONDUCTOR's ML7213 which is
for IVI(In-Vehicle Infotainment) use.
- ML7213 is companion chip for Intel Atom E6xx series.
- ML7213 is completely compatible for Intel EG20T PCH.
+ ML7831 is for general purpose use.
+ ML7213/ML7831 is companion chip for Intel Atom E6xx series.
+ ML7213/ML7831 is completely compatible for Intel EG20T PCH.
config USB_EG20T
tristate
diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c
index f7a0e7609277..048776bfdc57 100755
--- a/drivers/usb/gadget/arcotg_udc.c
+++ b/drivers/usb/gadget/arcotg_udc.c
@@ -956,7 +956,11 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
(unsigned)EP_MAX_LENGTH_TRANSFER);
if (NEED_IRAM(req->ep))
*length = min(*length, g_iram_size);
+#ifdef CONFIG_FSL_UTP
+ dtd = dma_pool_alloc_nonbufferable(udc_controller->td_pool, GFP_ATOMIC, dma);
+#else
dtd = dma_pool_alloc(udc_controller->td_pool, GFP_ATOMIC, dma);
+#endif
if (dtd == NULL)
return dtd;
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index 19fffccc370d..1cefb9f16071 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -720,7 +720,7 @@ static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value)
if (code == FUNCTIONFS_INTERFACE_REVMAP) {
struct ffs_function *func = ffs->func;
ret = func ? ffs_func_revmap_intf(func, value) : -ENODEV;
- } else if (gadget->ops->ioctl) {
+ } else if (gadget && gadget->ops->ioctl) {
ret = gadget->ops->ioctl(gadget, code, value);
} else {
ret = -ENOTTY;
diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c
index d915dbc0a28c..b2c3f55b4a32 100644
--- a/drivers/usb/gadget/f_loopback.c
+++ b/drivers/usb/gadget/f_loopback.c
@@ -373,7 +373,7 @@ int __init loopback_add(struct usb_composite_dev *cdev, bool autoresume)
/* support autoresume for remote wakeup testing */
if (autoresume)
- sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
+ loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
/* support OTG systems */
if (gadget_is_otg(cdev->gadget)) {
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 1944ebb3bcab..7405647459dc 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -2189,7 +2189,7 @@ unknown_cmnd:
common->data_size_from_cmnd = 0;
sprintf(unknown, "Unknown x%02x", common->cmnd[0]);
reply = check_command(common, common->cmnd_size,
- DATA_DIR_UNKNOWN, 0xff, 0, unknown);
+ DATA_DIR_UNKNOWN, ~0, 0, unknown);
if (reply == 0) {
common->curlun->sense_data = SS_INVALID_COMMAND;
reply = -EINVAL;
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 390d43b0e2a1..36b8c2b70150 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -2156,7 +2156,11 @@ static int send_status(struct fsg_dev *fsg)
sd = SS_INVALID_COMMAND;
} else if (sd != SS_NO_SENSE) {
DBG(fsg, "sending command-failure status\n");
+#ifdef CONFIG_FSL_UTP
+ status = USB_STATUS_PASS;
+#else
status = USB_STATUS_FAIL;
+#endif
VDBG(fsg, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;"
" info x%x\n",
SK(sd), ASC(sd), ASCQ(sd), sdinfo);
@@ -2582,7 +2586,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
fsg->data_size_from_cmnd = 0;
sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]);
if ((reply = check_command(fsg, fsg->cmnd_size,
- DATA_DIR_UNKNOWN, 0xff, 0, unknown)) == 0) {
+ DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) {
fsg->curlun->sense_data = SS_INVALID_COMMAND;
reply = -EINVAL;
}
@@ -3045,8 +3049,9 @@ static void handle_exception(struct fsg_dev *fsg)
break;
case FSG_STATE_DISCONNECT:
- for (i = 0; i < fsg->nluns; ++i)
- fsg_lun_fsync_sub(fsg->luns + i);
+ if (fsg->config != 0)
+ for (i = 0; i < fsg->nluns; ++i)
+ fsg_lun_fsync_sub(fsg->luns + i);
do_set_config(fsg, 0); // Unconfigured state
break;
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 4e4833168087..44d789d27cf3 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -717,6 +717,8 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req)
lastreq = list_entry(ep->queue.prev, struct fsl_req, queue);
lastreq->tail->next_td_ptr =
cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK);
+ /* Ensure dTD's next dtd pointer to be updated */
+ wmb();
/* Read prime bit, if 1 goto done */
if (fsl_readl(&dr_regs->endpointprime) & bitmask)
goto out;
@@ -767,7 +769,7 @@ out:
* @is_last: return flag if it is the last dTD of the request
* return: pointer to the built dTD */
static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
- dma_addr_t *dma, int *is_last)
+ dma_addr_t *dma, int *is_last, gfp_t gfp_flags)
{
u32 swap_temp;
struct ep_td_struct *dtd;
@@ -776,7 +778,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
*length = min(req->req.length - req->req.actual,
(unsigned)EP_MAX_LENGTH_TRANSFER);
- dtd = dma_pool_alloc(udc_controller->td_pool, GFP_KERNEL, dma);
+ dtd = dma_pool_alloc(udc_controller->td_pool, gfp_flags, dma);
if (dtd == NULL)
return dtd;
@@ -826,7 +828,7 @@ static struct ep_td_struct *fsl_build_dtd(struct fsl_req *req, unsigned *length,
}
/* Generate dtd chain for a request */
-static int fsl_req_to_dtd(struct fsl_req *req)
+static int fsl_req_to_dtd(struct fsl_req *req, gfp_t gfp_flags)
{
unsigned count;
int is_last;
@@ -835,7 +837,7 @@ static int fsl_req_to_dtd(struct fsl_req *req)
dma_addr_t dma;
do {
- dtd = fsl_build_dtd(req, &count, &dma, &is_last);
+ dtd = fsl_build_dtd(req, &count, &dma, &is_last, gfp_flags);
if (dtd == NULL)
return -ENOMEM;
@@ -909,13 +911,11 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
req->req.actual = 0;
req->dtd_count = 0;
- spin_lock_irqsave(&udc->lock, flags);
-
/* build dtds and push them to device queue */
- if (!fsl_req_to_dtd(req)) {
+ if (!fsl_req_to_dtd(req, gfp_flags)) {
+ spin_lock_irqsave(&udc->lock, flags);
fsl_queue_td(ep, req);
} else {
- spin_unlock_irqrestore(&udc->lock, flags);
return -ENOMEM;
}
@@ -1294,7 +1294,7 @@ static int ep0_prime_status(struct fsl_udc *udc, int direction)
ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->mapped = 1;
- if (fsl_req_to_dtd(req) == 0)
+ if (fsl_req_to_dtd(req, GFP_ATOMIC) == 0)
fsl_queue_td(ep, req);
else
return -ENOMEM;
@@ -1378,7 +1378,7 @@ static void ch9getstatus(struct fsl_udc *udc, u8 request_type, u16 value,
req->mapped = 1;
/* prime the data phase */
- if ((fsl_req_to_dtd(req) == 0))
+ if ((fsl_req_to_dtd(req, GFP_ATOMIC) == 0))
fsl_queue_td(ep, req);
else /* no mem */
goto stall;
diff --git a/drivers/usb/gadget/fsl_updater.c b/drivers/usb/gadget/fsl_updater.c
index 01b35f31cba7..39175d6d4c48 100644
--- a/drivers/usb/gadget/fsl_updater.c
+++ b/drivers/usb/gadget/fsl_updater.c
@@ -1,7 +1,7 @@
/*
* Freescale UUT driver
*
- * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright 2008-2012 Freescale Semiconductor, Inc.
* Copyright 2008-2009 Embedded Alley Solutions, Inc All Rights Reserved.
*/
@@ -71,9 +71,11 @@ static u32 count_list(struct list_head *l)
u32 count = 0;
struct list_head *tmp;
+ mutex_lock(&utp_context.lock);
list_for_each(tmp, l) {
count++;
}
+ mutex_unlock(&utp_context.lock);
return count;
}
diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c
index 80f0b605e0c6..643aa59a7b7b 100644
--- a/drivers/usb/gadget/hid.c
+++ b/drivers/usb/gadget/hid.c
@@ -69,9 +69,9 @@ static struct usb_device_descriptor device_desc = {
/* .bDeviceClass = USB_CLASS_COMM, */
/* .bDeviceSubClass = 0, */
/* .bDeviceProtocol = 0, */
- .bDeviceClass = 0xEF,
- .bDeviceSubClass = 2,
- .bDeviceProtocol = 1,
+ .bDeviceClass = USB_CLASS_PER_INTERFACE,
+ .bDeviceSubClass = 0,
+ .bDeviceProtocol = 0,
/* .bMaxPacketSize0 = f(hardware) */
/* Vendor and product id can be overridden by module parameters. */
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c
index 0e4f6886fe93..87c878b6a46c 100644
--- a/drivers/usb/gadget/inode.c
+++ b/drivers/usb/gadget/inode.c
@@ -1079,7 +1079,6 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
if (copy_to_user (buf, dev->req->buf, len))
retval = -EFAULT;
else
- /* Bug of Cancel IO 6 bytes read. */
retval = len;
clean_req (dev->gadget->ep0, dev->req);
/* NOTE userspace can't yet choose to stall */
diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c
index 68dbcc3e4cc2..1852c8a20c3d 100644
--- a/drivers/usb/gadget/pch_udc.c
+++ b/drivers/usb/gadget/pch_udc.c
@@ -320,6 +320,7 @@ struct pch_udc_ep {
* @registered: driver regsitered with system
* @suspended: driver in suspended state
* @connected: gadget driver associated
+ * @vbus_session: required vbus_session state
* @set_cfg_not_acked: pending acknowledgement 4 setup
* @waiting_zlp_ack: pending acknowledgement 4 ZLP
* @data_requests: DMA pool for data requests
@@ -346,6 +347,7 @@ struct pch_udc_dev {
registered:1,
suspended:1,
connected:1,
+ vbus_session:1,
set_cfg_not_acked:1,
waiting_zlp_ack:1;
struct pci_pool *data_requests;
@@ -363,6 +365,7 @@ struct pch_udc_dev {
#define PCI_DEVICE_ID_INTEL_EG20T_UDC 0x8808
#define PCI_VENDOR_ID_ROHM 0x10DB
#define PCI_DEVICE_ID_ML7213_IOH_UDC 0x801D
+#define PCI_DEVICE_ID_ML7831_IOH_UDC 0x8808
static const char ep0_string[] = "ep0in";
static DEFINE_SPINLOCK(udc_stall_spinlock); /* stall spin lock */
@@ -562,6 +565,29 @@ static void pch_udc_clear_disconnect(struct pch_udc_dev *dev)
}
/**
+ * pch_udc_reconnect() - This API initializes usb device controller,
+ * and clear the disconnect status.
+ * @dev: Reference to pch_udc_regs structure
+ */
+static void pch_udc_init(struct pch_udc_dev *dev);
+static void pch_udc_reconnect(struct pch_udc_dev *dev)
+{
+ pch_udc_init(dev);
+
+ /* enable device interrupts */
+ /* pch_udc_enable_interrupts() */
+ pch_udc_bit_clr(dev, UDC_DEVIRQMSK_ADDR,
+ UDC_DEVINT_UR | UDC_DEVINT_ENUM);
+
+ /* Clear the disconnect */
+ pch_udc_bit_set(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
+ pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_SD);
+ mdelay(1);
+ /* Resume USB signalling */
+ pch_udc_bit_clr(dev, UDC_DEVCTL_ADDR, UDC_DEVCTL_RES);
+}
+
+/**
* pch_udc_vbus_session() - set or clearr the disconnect status.
* @dev: Reference to pch_udc_regs structure
* @is_active: Parameter specifying the action
@@ -571,10 +597,18 @@ static void pch_udc_clear_disconnect(struct pch_udc_dev *dev)
static inline void pch_udc_vbus_session(struct pch_udc_dev *dev,
int is_active)
{
- if (is_active)
- pch_udc_clear_disconnect(dev);
- else
+ if (is_active) {
+ pch_udc_reconnect(dev);
+ dev->vbus_session = 1;
+ } else {
+ if (dev->driver && dev->driver->disconnect) {
+ spin_unlock(&dev->lock);
+ dev->driver->disconnect(&dev->gadget);
+ spin_lock(&dev->lock);
+ }
pch_udc_set_disconnect(dev);
+ dev->vbus_session = 0;
+ }
}
/**
@@ -1134,7 +1168,17 @@ static int pch_udc_pcd_pullup(struct usb_gadget *gadget, int is_on)
if (!gadget)
return -EINVAL;
dev = container_of(gadget, struct pch_udc_dev, gadget);
- pch_udc_vbus_session(dev, is_on);
+ if (is_on) {
+ pch_udc_reconnect(dev);
+ } else {
+ if (dev->driver && dev->driver->disconnect) {
+ spin_unlock(&dev->lock);
+ dev->driver->disconnect(&dev->gadget);
+ spin_lock(&dev->lock);
+ }
+ pch_udc_set_disconnect(dev);
+ }
+
return 0;
}
@@ -2338,8 +2382,11 @@ static void pch_udc_svc_ur_interrupt(struct pch_udc_dev *dev)
/* Complete request queue */
empty_req_queue(ep);
}
- if (dev->driver && dev->driver->disconnect)
+ if (dev->driver && dev->driver->disconnect) {
+ spin_unlock(&dev->lock);
dev->driver->disconnect(&dev->gadget);
+ spin_lock(&dev->lock);
+ }
}
/**
@@ -2374,6 +2421,11 @@ static void pch_udc_svc_enum_interrupt(struct pch_udc_dev *dev)
pch_udc_set_dma(dev, DMA_DIR_TX);
pch_udc_set_dma(dev, DMA_DIR_RX);
pch_udc_ep_set_rrdy(&(dev->ep[UDC_EP0OUT_IDX]));
+
+ /* enable device interrupts */
+ pch_udc_enable_interrupts(dev, UDC_DEVINT_UR | UDC_DEVINT_US |
+ UDC_DEVINT_ES | UDC_DEVINT_ENUM |
+ UDC_DEVINT_SI | UDC_DEVINT_SC);
}
/**
@@ -2475,8 +2527,24 @@ static void pch_udc_dev_isr(struct pch_udc_dev *dev, u32 dev_intr)
if (dev_intr & UDC_DEVINT_SC)
pch_udc_svc_cfg_interrupt(dev);
/* USB Suspend interrupt */
- if (dev_intr & UDC_DEVINT_US)
+ if (dev_intr & UDC_DEVINT_US) {
+ if (dev->driver
+ && dev->driver->suspend) {
+ spin_unlock(&dev->lock);
+ dev->driver->suspend(&dev->gadget);
+ spin_lock(&dev->lock);
+ }
+
+ if (dev->vbus_session == 0) {
+ if (dev->driver && dev->driver->disconnect) {
+ spin_unlock(&dev->lock);
+ dev->driver->disconnect(&dev->gadget);
+ spin_lock(&dev->lock);
+ }
+ pch_udc_reconnect(dev);
+ }
dev_dbg(&dev->pdev->dev, "USB_SUSPEND\n");
+ }
/* Clear the SOF interrupt, if enabled */
if (dev_intr & UDC_DEVINT_SOF)
dev_dbg(&dev->pdev->dev, "SOF\n");
@@ -2502,6 +2570,14 @@ static irqreturn_t pch_udc_isr(int irq, void *pdev)
dev_intr = pch_udc_read_device_interrupts(dev);
ep_intr = pch_udc_read_ep_interrupts(dev);
+ /* For a hot plug, this find that the controller is hung up. */
+ if (dev_intr == ep_intr)
+ if (dev_intr == pch_udc_readl(dev, UDC_DEVCFG_ADDR)) {
+ dev_dbg(&dev->pdev->dev, "UDC: Hung up\n");
+ /* The controller is reset */
+ pch_udc_writel(dev, UDC_SRST, UDC_SRST_ADDR);
+ return IRQ_HANDLED;
+ }
if (dev_intr)
/* Clear device interrupts */
pch_udc_write_device_interrupts(dev, dev_intr);
@@ -2915,8 +2991,10 @@ static int pch_udc_probe(struct pci_dev *pdev,
}
pch_udc = dev;
/* initialize the hardware */
- if (pch_udc_pcd_init(dev))
+ if (pch_udc_pcd_init(dev)) {
+ retval = -ENODEV;
goto finished;
+ }
if (request_irq(pdev->irq, pch_udc_isr, IRQF_SHARED, KBUILD_MODNAME,
dev)) {
dev_err(&pdev->dev, "%s: request_irq(%d) fail\n", __func__,
@@ -2971,6 +3049,11 @@ static DEFINE_PCI_DEVICE_TABLE(pch_udc_pcidev_id) = {
.class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
.class_mask = 0xffffffff,
},
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_ROHM, PCI_DEVICE_ID_ML7831_IOH_UDC),
+ .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+ .class_mask = 0xffffffff,
+ },
{ 0 },
};
diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/uvc.h
index 5b7919460fd2..01a23c1197f6 100644
--- a/drivers/usb/gadget/uvc.h
+++ b/drivers/usb/gadget/uvc.h
@@ -29,7 +29,7 @@
struct uvc_request_data
{
- unsigned int length;
+ __s32 length;
__u8 data[60];
};
diff --git a/drivers/usb/gadget/uvc_v4l2.c b/drivers/usb/gadget/uvc_v4l2.c
index 5e807f083bc8..992f66b88c81 100644
--- a/drivers/usb/gadget/uvc_v4l2.c
+++ b/drivers/usb/gadget/uvc_v4l2.c
@@ -41,7 +41,7 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data)
if (data->length < 0)
return usb_ep_set_halt(cdev->gadget->ep0);
- req->length = min(uvc->event_length, data->length);
+ req->length = min_t(unsigned int, uvc->event_length, data->length);
req->zero = data->length < uvc->event_length;
req->dma = DMA_ADDR_INVALID;
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index f380bf97e5af..fc93d57609ac 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -125,7 +125,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver,
*/
if (pdata->init && pdata->init(pdev)) {
retval = -ENODEV;
- goto err3;
+ goto err4;
}
/* Enable USB controller, 83xx or 8536 */
@@ -216,6 +216,8 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
unsigned int port_offset)
{
u32 portsc;
+ struct usb_hcd *hcd = ehci_to_hcd(ehci);
+ void __iomem *non_ehci = hcd->regs;
portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
@@ -231,6 +233,8 @@ static void ehci_fsl_setup_phy(struct ehci_hcd *ehci,
portsc |= PORT_PTS_PTW;
/* fall through */
case FSL_USB2_PHY_UTMI:
+ /* enable UTMI PHY */
+ setbits32(non_ehci + FSL_SOC_USB_CTRL, CTRL_UTMI_PHY_EN);
portsc |= PORT_PTS_UTMI;
break;
case FSL_USB2_PHY_NONE:
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index 14b9919530b1..137c5053ed35 100755
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -50,5 +50,6 @@
#define FSL_SOC_USB_PRICTRL 0x40c /* NOTE: big-endian */
#define FSL_SOC_USB_SICTRL 0x410 /* NOTE: big-endian */
#define FSL_SOC_USB_CTRL 0x500 /* NOTE: big-endian */
+#define CTRL_UTMI_PHY_EN (1<<9)
#define SNOOP_SIZE_2GB 0x1e
#endif /* _EHCI_FSL_H */
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index ffc22bf1d825..58f4472d275e 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -813,8 +813,13 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
goto dead;
}
+ /*
+ * We don't use STS_FLR, but some controllers don't like it to
+ * remain on, so mask it out along with the other status bits.
+ */
+ masked_status = status & (INTR_MASK | STS_FLR);
+
/* Shared IRQ? */
- masked_status = status & INTR_MASK;
if (!masked_status || unlikely(hcd->state == HC_STATE_HALT)) {
spin_unlock(&ehci->lock);
return IRQ_NONE;
@@ -865,7 +870,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
pcd_status = status;
/* resume root hub? */
- if (!(cmd & CMD_RUN))
+ if (hcd->state == HC_STATE_SUSPENDED)
usb_hcd_resume_root_hub(hcd);
/* get per-port change detect bits */
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index b49e65f8d89e..361bc3e7b2e8 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -434,7 +434,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
{
struct fsl_usb2_platform_data *pdata;
pdata = hcd->self.controller->platform_data;
- if (pdata->platform_rh_resume)
+ if (pdata && pdata->platform_rh_resume)
pdata->platform_rh_resume(pdata);
}
#endif
@@ -1079,7 +1079,7 @@ static int ehci_hub_control (
{
struct fsl_usb2_platform_data *pdata;
pdata = hcd->self.controller->platform_data;
- if (pdata->platform_rh_suspend)
+ if (pdata && pdata->platform_rh_suspend)
pdata->platform_rh_suspend(pdata);
}
#endif
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 1d1caa6a33fc..efb9efcffe44 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -144,6 +144,14 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
hcd->has_tt = 1;
tdi_reset(ehci);
}
+ if (pdev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK) {
+ /* EHCI #1 or #2 on 6 Series/C200 Series chipset */
+ if (pdev->device == 0x1c26 || pdev->device == 0x1c2d) {
+ ehci_info(ehci, "broken D3 during system sleep on ASUS\n");
+ hcd->broken_pci_sleep = 1;
+ device_set_wakeup_capable(&pdev->dev, false);
+ }
+ }
break;
case PCI_VENDOR_ID_TDI:
if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
@@ -357,7 +365,9 @@ static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev)
{
return pdev->class == PCI_CLASS_SERIAL_USB_EHCI &&
pdev->vendor == PCI_VENDOR_ID_INTEL &&
- pdev->device == 0x1E26;
+ (pdev->device == 0x1E26 ||
+ pdev->device == 0x8C2D ||
+ pdev->device == 0x8C26);
}
static void ehci_enable_xhci_companion(void)
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 271987952e33..e4dd26a8b2b1 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -649,7 +649,7 @@ qh_urb_transaction (
/*
* data transfer stage: buffer setup
*/
- i = urb->num_sgs;
+ i = urb->num_mapped_sgs;
if (len > 0 && i > 0) {
sg = urb->sg;
buf = sg_dma_address(sg);
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index f9cf3f04b742..23107e230530 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -389,17 +389,14 @@ ohci_shutdown (struct usb_hcd *hcd)
struct ohci_hcd *ohci;
ohci = hcd_to_ohci (hcd);
- ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
- ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
+ ohci_writel(ohci, (u32) ~0, &ohci->regs->intrdisable);
- /* If the SHUTDOWN quirk is set, don't put the controller in RESET */
- ohci->hc_control &= (ohci->flags & OHCI_QUIRK_SHUTDOWN ?
- OHCI_CTRL_RWC | OHCI_CTRL_HCFS :
- OHCI_CTRL_RWC);
- ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
+ /* Software reset, after which the controller goes into SUSPEND */
+ ohci_writel(ohci, OHCI_HCR, &ohci->regs->cmdstatus);
+ ohci_readl(ohci, &ohci->regs->cmdstatus); /* flush the writes */
+ udelay(10);
- /* flush the writes */
- (void) ohci_readl (ohci, &ohci->regs->control);
+ ohci_writel(ohci, ohci->fminterval, &ohci->regs->fminterval);
}
static int check_ed(struct ohci_hcd *ohci, struct ed *ed)
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index ad8166c681e2..bc01b064585a 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -175,28 +175,6 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
return 0;
}
-/* nVidia controllers continue to drive Reset signalling on the bus
- * even after system shutdown, wasting power. This flag tells the
- * shutdown routine to leave the controller OPERATIONAL instead of RESET.
- */
-static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd)
-{
- struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
- struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-
- /* Evidently nVidia fixed their later hardware; this is a guess at
- * the changeover point.
- */
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB 0x026d
-
- if (pdev->device < PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB) {
- ohci->flags |= OHCI_QUIRK_SHUTDOWN;
- ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
- }
-
- return 0;
-}
-
static void sb800_prefetch(struct ohci_hcd *ohci, int on)
{
struct pci_dev *pdev;
@@ -260,10 +238,6 @@ static const struct pci_device_id ohci_pci_quirks[] = {
PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399),
.driver_data = (unsigned long)ohci_quirk_amd700,
},
- {
- PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
- .driver_data = (unsigned long) ohci_quirk_nvidia_shutdown,
- },
/* FIXME for some of the early AMD 760 southbridges, OHCI
* won't work at all. blacklist them.
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 35e5fd640ce7..0795b934d00c 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -403,7 +403,6 @@ struct ohci_hcd {
#define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */
#define OHCI_QUIRK_AMD_PLL 0x200 /* AMD PLL quirk*/
#define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */
-#define OHCI_QUIRK_SHUTDOWN 0x800 /* nVidia power bug */
// there are also chip quirks/bugs in init logic
struct work_struct nec_work; /* Worker for NEC quirk */
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index a495d4899180..0757b1934da5 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -36,6 +36,7 @@
#define OHCI_INTRENABLE 0x10
#define OHCI_INTRDISABLE 0x14
#define OHCI_FMINTERVAL 0x34
+#define OHCI_HCFS (3 << 6) /* hc functional state */
#define OHCI_HCR (1 << 0) /* host controller reset */
#define OHCI_OCR (1 << 3) /* ownership change request */
#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */
@@ -465,6 +466,8 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
{
void __iomem *base;
u32 control;
+ u32 fminterval;
+ int cnt;
if (!mmio_resource_enabled(pdev, 0))
return;
@@ -497,41 +500,32 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
}
#endif
- /* reset controller, preserving RWC (and possibly IR) */
- writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
- readl(base + OHCI_CONTROL);
+ /* disable interrupts */
+ writel((u32) ~0, base + OHCI_INTRDISABLE);
- /* Some NVIDIA controllers stop working if kept in RESET for too long */
- if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) {
- u32 fminterval;
- int cnt;
+ /* Reset the USB bus, if the controller isn't already in RESET */
+ if (control & OHCI_HCFS) {
+ /* Go into RESET, preserving RWC (and possibly IR) */
+ writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
+ readl(base + OHCI_CONTROL);
- /* drive reset for at least 50 ms (7.1.7.5) */
+ /* drive bus reset for at least 50 ms (7.1.7.5) */
msleep(50);
+ }
- /* software reset of the controller, preserving HcFmInterval */
- fminterval = readl(base + OHCI_FMINTERVAL);
- writel(OHCI_HCR, base + OHCI_CMDSTATUS);
-
- /* reset requires max 10 us delay */
- for (cnt = 30; cnt > 0; --cnt) { /* ... allow extra time */
- if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0)
- break;
- udelay(1);
- }
- writel(fminterval, base + OHCI_FMINTERVAL);
+ /* software reset of the controller, preserving HcFmInterval */
+ fminterval = readl(base + OHCI_FMINTERVAL);
+ writel(OHCI_HCR, base + OHCI_CMDSTATUS);
- /* Now we're in the SUSPEND state with all devices reset
- * and wakeups and interrupts disabled
- */
+ /* reset requires max 10 us delay */
+ for (cnt = 30; cnt > 0; --cnt) { /* ... allow extra time */
+ if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0)
+ break;
+ udelay(1);
}
+ writel(fminterval, base + OHCI_FMINTERVAL);
- /*
- * disable interrupts
- */
- writel(~(u32)0, base + OHCI_INTRDISABLE);
- writel(~(u32)0, base + OHCI_INTRSTATUS);
-
+ /* Now the controller is safely in SUSPEND and nothing can wake it up */
iounmap(base);
}
@@ -717,12 +711,28 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done,
return -ETIMEDOUT;
}
-bool usb_is_intel_switchable_xhci(struct pci_dev *pdev)
+#define PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI 0x8C31
+
+bool usb_is_intel_ppt_switchable_xhci(struct pci_dev *pdev)
{
return pdev->class == PCI_CLASS_SERIAL_USB_XHCI &&
pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI;
}
+
+/* The Intel Lynx Point chipset also has switchable ports. */
+bool usb_is_intel_lpt_switchable_xhci(struct pci_dev *pdev)
+{
+ return pdev->class == PCI_CLASS_SERIAL_USB_XHCI &&
+ pdev->vendor == PCI_VENDOR_ID_INTEL &&
+ pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI;
+}
+
+bool usb_is_intel_switchable_xhci(struct pci_dev *pdev)
+{
+ return usb_is_intel_ppt_switchable_xhci(pdev) ||
+ usb_is_intel_lpt_switchable_xhci(pdev);
+}
EXPORT_SYMBOL_GPL(usb_is_intel_switchable_xhci);
/*
@@ -830,9 +840,13 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
}
}
- /* Disable any BIOS SMIs */
- writel(XHCI_LEGACY_DISABLE_SMI,
- base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
+ val = readl(base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
+ /* Mask off (turn off) any enabled SMIs */
+ val &= XHCI_LEGACY_DISABLE_SMI;
+ /* Mask all SMI events bits, RW1C */
+ val |= XHCI_LEGACY_SMI_EVENTS;
+ /* Disable any BIOS SMIs and clear all SMI events*/
+ writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
if (usb_is_intel_switchable_xhci(pdev))
usb_enable_xhci_ports(pdev);
@@ -872,6 +886,22 @@ hc_init:
static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
{
+ /* Skip Netlogic mips SoC's internal PCI USB controller.
+ * This device does not need/support EHCI/OHCI handoff
+ */
+ if (pdev->vendor == 0x184e) /* vendor Netlogic */
+ return;
+ if (pdev->class != PCI_CLASS_SERIAL_USB_UHCI &&
+ pdev->class != PCI_CLASS_SERIAL_USB_OHCI &&
+ pdev->class != PCI_CLASS_SERIAL_USB_EHCI &&
+ pdev->class != PCI_CLASS_SERIAL_USB_XHCI)
+ return;
+
+ if (pci_enable_device(pdev) < 0) {
+ dev_warn(&pdev->dev, "Can't enable PCI device, "
+ "BIOS handoff failed.\n");
+ return;
+ }
if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI)
quirk_usb_handoff_uhci(pdev);
else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI)
@@ -880,5 +910,6 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev)
quirk_usb_disable_ehci(pdev);
else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI)
quirk_usb_handoff_xhci(pdev);
+ pci_disable_device(pdev);
}
DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff);
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index 84ed28b34f93..82539913ad84 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -943,7 +943,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb,
if (usb_pipein(urb->pipe))
status |= TD_CTRL_SPD;
- i = urb->num_sgs;
+ i = urb->num_mapped_sgs;
if (len > 0 && i > 0) {
sg = urb->sg;
data = sg_dma_address(sg);
diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c
index a403b53e86b9..76083ae92138 100644
--- a/drivers/usb/host/whci/qset.c
+++ b/drivers/usb/host/whci/qset.c
@@ -443,7 +443,7 @@ static int qset_add_urb_sg(struct whc *whc, struct whc_qset *qset, struct urb *u
remaining = urb->transfer_buffer_length;
- for_each_sg(urb->sg, sg, urb->num_sgs, i) {
+ for_each_sg(urb->sg, sg, urb->num_mapped_sgs, i) {
dma_addr_t dma_addr;
size_t dma_remaining;
dma_addr_t sp, ep;
@@ -561,7 +561,7 @@ static int qset_add_urb_sg_linearize(struct whc *whc, struct whc_qset *qset,
remaining = urb->transfer_buffer_length;
- for_each_sg(urb->sg, sg, urb->num_sgs, i) {
+ for_each_sg(urb->sg, sg, urb->num_mapped_sgs, i) {
size_t len;
size_t sg_remaining;
void *orig;
diff --git a/drivers/usb/host/xhci-ext-caps.h b/drivers/usb/host/xhci-ext-caps.h
index ce5c9e51748e..4206f6bef6fb 100644
--- a/drivers/usb/host/xhci-ext-caps.h
+++ b/drivers/usb/host/xhci-ext-caps.h
@@ -62,8 +62,9 @@
/* USB Legacy Support Control and Status Register - section 7.1.2 */
/* Add this offset, plus the value of xECP in HCCPARAMS to the base address */
#define XHCI_LEGACY_CONTROL_OFFSET (0x04)
-/* bits 1:2, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */
-#define XHCI_LEGACY_DISABLE_SMI ((0x3 << 1) + (0xff << 5) + (0x7 << 17))
+/* bits 1:3, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */
+#define XHCI_LEGACY_DISABLE_SMI ((0x7 << 1) + (0xff << 5) + (0x7 << 17))
+#define XHCI_LEGACY_SMI_EVENTS (0x7 << 29)
/* command register values to disable interrupts and halt the HC */
/* start/stop HC execution - do not write unless HC is halted*/
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index ce9f974dac0f..7520ebb44548 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -75,7 +75,7 @@ static void xhci_usb2_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
*/
memset(port_removable, 0, sizeof(port_removable));
for (i = 0; i < ports; i++) {
- portsc = xhci_readl(xhci, xhci->usb3_ports[i]);
+ portsc = xhci_readl(xhci, xhci->usb2_ports[i]);
/* If a device is removable, PORTSC reports a 0, same as in the
* hub descriptor DeviceRemovable bits.
*/
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index ffeee575fd21..b455f4ca076a 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1002,26 +1002,42 @@ static unsigned int xhci_parse_exponent_interval(struct usb_device *udev,
}
/*
- * Convert bInterval expressed in frames (in 1-255 range) to exponent of
+ * Convert bInterval expressed in microframes (in 1-255 range) to exponent of
* microframes, rounded down to nearest power of 2.
*/
-static unsigned int xhci_parse_frame_interval(struct usb_device *udev,
- struct usb_host_endpoint *ep)
+static unsigned int xhci_microframes_to_exponent(struct usb_device *udev,
+ struct usb_host_endpoint *ep, unsigned int desc_interval,
+ unsigned int min_exponent, unsigned int max_exponent)
{
unsigned int interval;
- interval = fls(8 * ep->desc.bInterval) - 1;
- interval = clamp_val(interval, 3, 10);
- if ((1 << interval) != 8 * ep->desc.bInterval)
+ interval = fls(desc_interval) - 1;
+ interval = clamp_val(interval, min_exponent, max_exponent);
+ if ((1 << interval) != desc_interval)
dev_warn(&udev->dev,
"ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n",
ep->desc.bEndpointAddress,
1 << interval,
- 8 * ep->desc.bInterval);
+ desc_interval);
return interval;
}
+static unsigned int xhci_parse_microframe_interval(struct usb_device *udev,
+ struct usb_host_endpoint *ep)
+{
+ return xhci_microframes_to_exponent(udev, ep,
+ ep->desc.bInterval, 0, 15);
+}
+
+
+static unsigned int xhci_parse_frame_interval(struct usb_device *udev,
+ struct usb_host_endpoint *ep)
+{
+ return xhci_microframes_to_exponent(udev, ep,
+ ep->desc.bInterval * 8, 3, 10);
+}
+
/* Return the polling or NAK interval.
*
* The polling interval is expressed in "microframes". If xHCI's Interval field
@@ -1040,7 +1056,7 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
/* Max NAK rate */
if (usb_endpoint_xfer_control(&ep->desc) ||
usb_endpoint_xfer_bulk(&ep->desc)) {
- interval = ep->desc.bInterval;
+ interval = xhci_parse_microframe_interval(udev, ep);
break;
}
/* Fall through - SS and HS isoc/int have same decoding */
@@ -1493,11 +1509,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
int i;
/* Free the Event Ring Segment Table and the actual Event Ring */
- if (xhci->ir_set) {
- xhci_writel(xhci, 0, &xhci->ir_set->erst_size);
- xhci_write_64(xhci, 0, &xhci->ir_set->erst_base);
- xhci_write_64(xhci, 0, &xhci->ir_set->erst_dequeue);
- }
size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
if (xhci->erst.entries)
pci_free_consistent(pdev, size,
@@ -1509,7 +1520,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
xhci->event_ring = NULL;
xhci_dbg(xhci, "Freed event ring\n");
- xhci_write_64(xhci, 0, &xhci->op_regs->cmd_ring);
+ xhci->cmd_ring_reserved_trbs = 0;
if (xhci->cmd_ring)
xhci_ring_free(xhci, xhci->cmd_ring);
xhci->cmd_ring = NULL;
@@ -1538,7 +1549,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
xhci->medium_streams_pool = NULL;
xhci_dbg(xhci, "Freed medium stream array pool\n");
- xhci_write_64(xhci, 0, &xhci->op_regs->dcbaa_ptr);
if (xhci->dcbaa)
pci_free_consistent(pdev, sizeof(*xhci->dcbaa),
xhci->dcbaa, xhci->dcbaa->dma);
@@ -2107,6 +2117,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
fail:
xhci_warn(xhci, "Couldn't initialize memory\n");
+ xhci_halt(xhci);
+ xhci_reset(xhci);
xhci_mem_cleanup(xhci);
return -ENOMEM;
}
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 50e7156a7d81..39e230f2dd1b 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -123,6 +123,7 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
xhci_dbg(xhci, "QUIRK: Fresco Logic revision %u "
"has broken MSI implementation\n",
pdev->revision);
+ xhci->quirks |= XHCI_TRUST_TX_LENGTH;
}
if (pdev->vendor == PCI_VENDOR_ID_NEC)
@@ -145,6 +146,8 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
xhci->quirks |= XHCI_RESET_ON_RESUME;
xhci_dbg(xhci, "QUIRK: Resetting on resume\n");
}
+ if (pdev->vendor == PCI_VENDOR_ID_VIA)
+ xhci->quirks |= XHCI_RESET_ON_RESUME;
/* Make sure the HC is halted. */
retval = xhci_halt(xhci);
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index b4b06910f684..de3c1513fdb2 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1218,6 +1218,7 @@ static void handle_vendor_event(struct xhci_hcd *xhci,
*
* Returns a zero-based port number, which is suitable for indexing into each of
* the split roothubs' port arrays and bus state arrays.
+ * Add one to it in order to call xhci_find_slot_id_by_port.
*/
static unsigned int find_faked_portnum_from_hw_portnum(struct usb_hcd *hcd,
struct xhci_hcd *xhci, u32 port_id)
@@ -1340,7 +1341,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
temp |= PORT_LINK_STROBE | XDEV_U0;
xhci_writel(xhci, temp, port_array[faked_port_index]);
slot_id = xhci_find_slot_id_by_port(hcd, xhci,
- faked_port_index);
+ faked_port_index + 1);
if (!slot_id) {
xhci_dbg(xhci, "slot_id is zero\n");
goto cleanup;
@@ -1738,8 +1739,12 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
/* handle completion code */
switch (trb_comp_code) {
case COMP_SUCCESS:
- frame->status = 0;
- break;
+ if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
+ frame->status = 0;
+ break;
+ }
+ if ((xhci->quirks & XHCI_TRUST_TX_LENGTH))
+ trb_comp_code = COMP_SHORT_TX;
case COMP_SHORT_TX:
frame->status = td->urb->transfer_flags & URB_SHORT_NOT_OK ?
-EREMOTEIO : 0;
@@ -1755,6 +1760,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
break;
case COMP_DEV_ERR:
case COMP_STALL:
+ case COMP_TX_ERR:
frame->status = -EPROTO;
skip_td = true;
break;
@@ -1837,13 +1843,16 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
switch (trb_comp_code) {
case COMP_SUCCESS:
/* Double check that the HW transferred everything. */
- if (event_trb != td->last_trb) {
+ if (event_trb != td->last_trb ||
+ TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
xhci_warn(xhci, "WARN Successful completion "
"on short TX\n");
if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
*status = -EREMOTEIO;
else
*status = 0;
+ if ((xhci->quirks & XHCI_TRUST_TX_LENGTH))
+ trb_comp_code = COMP_SHORT_TX;
} else {
*status = 0;
}
@@ -1984,6 +1993,13 @@ static int handle_tx_event(struct xhci_hcd *xhci,
* transfer type
*/
case COMP_SUCCESS:
+ if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
+ break;
+ if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
+ trb_comp_code = COMP_SHORT_TX;
+ else
+ xhci_warn(xhci, "WARN Successful completion on short TX: "
+ "needs XHCI_TRUST_TX_LENGTH quirk?\n");
case COMP_SHORT_TX:
break;
case COMP_STOP:
@@ -2351,7 +2367,7 @@ hw_died:
u32 irq_pending;
/* Acknowledge the PCI interrupt */
irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending);
- irq_pending |= 0x3;
+ irq_pending |= IMAN_IP;
xhci_writel(xhci, irq_pending, &xhci->ir_set->irq_pending);
}
@@ -2570,7 +2586,7 @@ static unsigned int count_sg_trbs_needed(struct xhci_hcd *xhci, struct urb *urb)
struct scatterlist *sg;
sg = NULL;
- num_sgs = urb->num_sgs;
+ num_sgs = urb->num_mapped_sgs;
temp = urb->transfer_buffer_length;
xhci_dbg(xhci, "count sg list trbs: \n");
@@ -2754,7 +2770,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
return -EINVAL;
num_trbs = count_sg_trbs_needed(xhci, urb);
- num_sgs = urb->num_sgs;
+ num_sgs = urb->num_mapped_sgs;
total_packet_count = roundup(urb->transfer_buffer_length,
le16_to_cpu(urb->ep->desc.wMaxPacketSize));
@@ -3381,7 +3397,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
/* Check TD length */
if (running_total != td_len) {
xhci_err(xhci, "ISOC TD length unmatch\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto cleanup;
}
}
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 221f14e1fddb..dbba9369bb10 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -444,6 +444,11 @@ int xhci_run(struct usb_hcd *hcd)
if (ret) {
legacy_irq:
+ if (!pdev->irq) {
+ xhci_err(xhci, "No msi-x/msi found and "
+ "no IRQ in BIOS\n");
+ return -EINVAL;
+ }
/* fall back to legacy interrupt*/
ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
hcd->irq_descr, hcd);
@@ -605,11 +610,11 @@ static void xhci_save_registers(struct xhci_hcd *xhci)
xhci->s3.dev_nt = xhci_readl(xhci, &xhci->op_regs->dev_notification);
xhci->s3.dcbaa_ptr = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
xhci->s3.config_reg = xhci_readl(xhci, &xhci->op_regs->config_reg);
- xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending);
- xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control);
xhci->s3.erst_size = xhci_readl(xhci, &xhci->ir_set->erst_size);
xhci->s3.erst_base = xhci_read_64(xhci, &xhci->ir_set->erst_base);
xhci->s3.erst_dequeue = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
+ xhci->s3.irq_pending = xhci_readl(xhci, &xhci->ir_set->irq_pending);
+ xhci->s3.irq_control = xhci_readl(xhci, &xhci->ir_set->irq_control);
}
static void xhci_restore_registers(struct xhci_hcd *xhci)
@@ -618,10 +623,11 @@ static void xhci_restore_registers(struct xhci_hcd *xhci)
xhci_writel(xhci, xhci->s3.dev_nt, &xhci->op_regs->dev_notification);
xhci_write_64(xhci, xhci->s3.dcbaa_ptr, &xhci->op_regs->dcbaa_ptr);
xhci_writel(xhci, xhci->s3.config_reg, &xhci->op_regs->config_reg);
- xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending);
- xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control);
xhci_writel(xhci, xhci->s3.erst_size, &xhci->ir_set->erst_size);
xhci_write_64(xhci, xhci->s3.erst_base, &xhci->ir_set->erst_base);
+ xhci_write_64(xhci, xhci->s3.erst_dequeue, &xhci->ir_set->erst_dequeue);
+ xhci_writel(xhci, xhci->s3.irq_pending, &xhci->ir_set->irq_pending);
+ xhci_writel(xhci, xhci->s3.irq_control, &xhci->ir_set->irq_control);
}
static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci)
@@ -1568,6 +1574,7 @@ static int xhci_configure_endpoint_result(struct xhci_hcd *xhci,
/* FIXME: can we allocate more resources for the HC? */
break;
case COMP_BW_ERR:
+ case COMP_2ND_BW_ERR:
dev_warn(&udev->dev, "Not enough bandwidth "
"for new device state.\n");
ret = -ENOSPC;
@@ -2183,8 +2190,7 @@ static int xhci_calculate_streams_and_bitmask(struct xhci_hcd *xhci,
if (ret < 0)
return ret;
- max_streams = USB_SS_MAX_STREAMS(
- eps[i]->ss_ep_comp.bmAttributes);
+ max_streams = usb_ss_max_streams(&eps[i]->ss_ep_comp);
if (max_streams < (*num_streams - 1)) {
xhci_dbg(xhci, "Ep 0x%x only supports %u stream IDs.\n",
eps[i]->desc.bEndpointAddress,
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 49ce76c6b41f..25c3e26b999c 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -205,6 +205,10 @@ struct xhci_op_regs {
#define CMD_PM_INDEX (1 << 11)
/* bits 12:31 are reserved (and should be preserved on writes). */
+/* IMAN - Interrupt Management Register */
+#define IMAN_IP (1 << 1)
+#define IMAN_IE (1 << 0)
+
/* USBSTS - USB status - status bitmasks */
/* HC not running - set to 1 when run/stop bit is cleared. */
#define STS_HALT XHCI_STS_HALT
@@ -900,7 +904,6 @@ struct xhci_transfer_event {
/* Invalid Stream ID Error */
#define COMP_STRID_ERR 34
/* Secondary Bandwidth Error - may be returned by a Configure Endpoint cmd */
-/* FIXME - check for this */
#define COMP_2ND_BW_ERR 35
/* Split Transaction Error */
#define COMP_SPLIT_ERR 36
@@ -1312,6 +1315,7 @@ struct xhci_hcd {
#define XHCI_BROKEN_MSI (1 << 6)
#define XHCI_RESET_ON_RESUME (1 << 7)
#define XHCI_AMD_0x96_HOST (1 << 9)
+#define XHCI_TRUST_TX_LENGTH (1 << 10)
unsigned int num_active_eps;
unsigned int limit_active_eps;
/* There are two roothubs to keep track of bus suspend info for */
diff --git a/drivers/usb/misc/isight_firmware.c b/drivers/usb/misc/isight_firmware.c
index fe1d44319d0a..8f725f651915 100644
--- a/drivers/usb/misc/isight_firmware.c
+++ b/drivers/usb/misc/isight_firmware.c
@@ -55,8 +55,9 @@ static int isight_firmware_load(struct usb_interface *intf,
ptr = firmware->data;
+ buf[0] = 0x01;
if (usb_control_msg
- (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\1", 1,
+ (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, buf, 1,
300) != 1) {
printk(KERN_ERR
"Failed to initialise isight firmware loader\n");
@@ -100,8 +101,9 @@ static int isight_firmware_load(struct usb_interface *intf,
}
}
+ buf[0] = 0x00;
if (usb_control_msg
- (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, "\0", 1,
+ (dev, usb_sndctrlpipe(dev, 0), 0xa0, 0x40, 0xe600, 0, buf, 1,
300) != 1) {
printk(KERN_ERR "isight firmware loading completion failed\n");
ret = -ENODEV;
diff --git a/drivers/usb/misc/usbsevseg.c b/drivers/usb/misc/usbsevseg.c
index 417b8f207e8b..59689fa2f7c1 100644
--- a/drivers/usb/misc/usbsevseg.c
+++ b/drivers/usb/misc/usbsevseg.c
@@ -24,7 +24,7 @@
#define VENDOR_ID 0x0fc5
#define PRODUCT_ID 0x1227
-#define MAXLEN 6
+#define MAXLEN 8
/* table of devices that work with this driver */
static const struct usb_device_id id_table[] = {
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index bb10846affc3..5707f56d8046 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -1023,7 +1023,10 @@ test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param)
case 13: /* short read, resembling case 10 */
req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0);
/* last data packet "should" be DATA1, not DATA0 */
- len = 1024 - udev->descriptor.bMaxPacketSize0;
+ if (udev->speed == USB_SPEED_SUPER)
+ len = 1024 - 512;
+ else
+ len = 1024 - udev->descriptor.bMaxPacketSize0;
expected = -EREMOTEIO;
break;
case 14: /* short read; try to fill the last packet */
@@ -1382,11 +1385,15 @@ static int test_halt(struct usbtest_dev *tdev, int ep, struct urb *urb)
static int halt_simple(struct usbtest_dev *dev)
{
- int ep;
- int retval = 0;
- struct urb *urb;
+ int ep;
+ int retval = 0;
+ struct urb *urb;
+ struct usb_device *udev = testdev_to_usbdev(dev);
- urb = simple_alloc_urb(testdev_to_usbdev(dev), 0, 512);
+ if (udev->speed == USB_SPEED_SUPER)
+ urb = simple_alloc_urb(udev, 0, 1024);
+ else
+ urb = simple_alloc_urb(udev, 0, 512);
if (urb == NULL)
return -ENOMEM;
diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c
index ac5bfd619e62..2504694455f3 100644
--- a/drivers/usb/misc/yurex.c
+++ b/drivers/usb/misc/yurex.c
@@ -99,9 +99,7 @@ static void yurex_delete(struct kref *kref)
usb_put_dev(dev->udev);
if (dev->cntl_urb) {
usb_kill_urb(dev->cntl_urb);
- if (dev->cntl_req)
- usb_free_coherent(dev->udev, YUREX_BUF_SIZE,
- dev->cntl_req, dev->cntl_urb->setup_dma);
+ kfree(dev->cntl_req);
if (dev->cntl_buffer)
usb_free_coherent(dev->udev, YUREX_BUF_SIZE,
dev->cntl_buffer, dev->cntl_urb->transfer_dma);
@@ -234,9 +232,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
}
/* allocate buffer for control req */
- dev->cntl_req = usb_alloc_coherent(dev->udev, YUREX_BUF_SIZE,
- GFP_KERNEL,
- &dev->cntl_urb->setup_dma);
+ dev->cntl_req = kmalloc(YUREX_BUF_SIZE, GFP_KERNEL);
if (!dev->cntl_req) {
err("Could not allocate cntl_req");
goto error;
@@ -286,7 +282,7 @@ static int yurex_probe(struct usb_interface *interface, const struct usb_device_
usb_rcvintpipe(dev->udev, dev->int_in_endpointAddr),
dev->int_buffer, YUREX_BUF_SIZE, yurex_interrupt,
dev, 1);
- dev->cntl_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ dev->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
if (usb_submit_urb(dev->urb, GFP_KERNEL)) {
retval = -EIO;
err("Could not submitting URB");
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index dce7182e1dfe..a0232a77c05b 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2078,8 +2078,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
if (status < 0)
goto fail3;
- pm_runtime_put(musb->controller);
-
status = musb_init_debugfs(musb);
if (status < 0)
goto fail4;
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 548338c2147c..99ceaef23327 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -576,6 +576,15 @@ void musb_g_tx(struct musb *musb, u8 epnum)
if (request->actual == request->length) {
musb_g_giveback(musb_ep, request, 0);
+ /*
+ * In the giveback function the MUSB lock is
+ * released and acquired after sometime. During
+ * this time period the INDEX register could get
+ * changed by the gadget_queue function especially
+ * on SMP systems. Reselect the INDEX to be sure
+ * we are reading/modifying the right registers
+ */
+ musb_ep_select(mbase, epnum);
req = musb_ep->desc ? next_request(musb_ep) : NULL;
if (!req) {
dev_dbg(musb->controller, "%s idle now\n",
@@ -968,6 +977,15 @@ void musb_g_rx(struct musb *musb, u8 epnum)
}
#endif
musb_g_giveback(musb_ep, request, 0);
+ /*
+ * In the giveback function the MUSB lock is
+ * released and acquired after sometime. During
+ * this time period the INDEX register could get
+ * changed by the gadget_queue function especially
+ * on SMP systems. Reselect the INDEX to be sure
+ * we are reading/modifying the right registers
+ */
+ musb_ep_select(mbase, epnum);
req = next_request(musb_ep);
if (!req)
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index c5d4c44d0ffa..6958ab9b99be 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -295,7 +295,8 @@ static int musb_otg_notifications(struct notifier_block *nb,
static int omap2430_musb_init(struct musb *musb)
{
- u32 l, status = 0;
+ u32 l;
+ int status = 0;
struct device *dev = musb->controller;
struct musb_hdrc_platform_data *plat = dev->platform_data;
struct omap_musb_board_data *data = plat->board_data;
@@ -312,7 +313,7 @@ static int omap2430_musb_init(struct musb *musb)
status = pm_runtime_get_sync(dev);
if (status < 0) {
- dev_err(dev, "pm_runtime_get_sync FAILED");
+ dev_err(dev, "pm_runtime_get_sync FAILED %d\n", status);
goto err1;
}
@@ -464,14 +465,14 @@ static int __init omap2430_probe(struct platform_device *pdev)
goto err2;
}
+ pm_runtime_enable(&pdev->dev);
+
ret = platform_device_add(musb);
if (ret) {
dev_err(&pdev->dev, "failed to register musb device\n");
goto err2;
}
- pm_runtime_enable(&pdev->dev);
-
return 0;
err2:
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index fd67cc53545b..f2c57e051502 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -39,6 +39,8 @@ static void cp210x_get_termios(struct tty_struct *,
struct usb_serial_port *port);
static void cp210x_get_termios_port(struct usb_serial_port *port,
unsigned int *cflagp, unsigned int *baudp);
+static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *,
+ struct ktermios *);
static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *,
struct ktermios*);
static int cp210x_tiocmget(struct tty_struct *);
@@ -47,6 +49,7 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port,
unsigned int, unsigned int);
static void cp210x_break_ctl(struct tty_struct *, int);
static int cp210x_startup(struct usb_serial *);
+static void cp210x_release(struct usb_serial *);
static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
static int debug;
@@ -92,6 +95,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */
{ USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */
{ USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */
+ { USB_DEVICE(0x10C4, 0x81A9) }, /* Multiplex RC Interface */
{ USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */
{ USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */
{ USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
@@ -118,6 +122,8 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
+ { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
+ { USB_DEVICE(0x10C4, 0xEA80) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */
{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
{ USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */
@@ -133,16 +139,23 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */
{ USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */
{ USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */
+ { USB_DEVICE(0x17A8, 0x0001) }, /* Kamstrup Optical Eye/3-wire */
+ { USB_DEVICE(0x17A8, 0x0005) }, /* Kamstrup M-Bus Master MultiPort 250D */
{ USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
{ USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
{ USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
+ { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */
{ USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(usb, id_table);
+struct cp210x_port_private {
+ __u8 bInterfaceNumber;
+};
+
static struct usb_driver cp210x_driver = {
.name = "cp210x",
.probe = usb_serial_probe,
@@ -168,6 +181,7 @@ static struct usb_serial_driver cp210x_device = {
.tiocmget = cp210x_tiocmget,
.tiocmset = cp210x_tiocmset,
.attach = cp210x_startup,
+ .release = cp210x_release,
.dtr_rts = cp210x_dtr_rts
};
@@ -200,6 +214,8 @@ static struct usb_serial_driver cp210x_device = {
#define CP210X_EMBED_EVENTS 0x15
#define CP210X_GET_EVENTSTATE 0x16
#define CP210X_SET_CHARS 0x19
+#define CP210X_GET_BAUDRATE 0x1D
+#define CP210X_SET_BAUDRATE 0x1E
/* CP210X_IFC_ENABLE */
#define UART_ENABLE 0x0001
@@ -253,6 +269,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
unsigned int *data, int size)
{
struct usb_serial *serial = port->serial;
+ struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
__le32 *buf;
int result, i, length;
@@ -268,7 +285,8 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
/* Issue the request, attempting to read 'size' bytes */
result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
request, REQTYPE_DEVICE_TO_HOST, 0x0000,
- 0, buf, size, 300);
+ port_priv->bInterfaceNumber, buf, size,
+ USB_CTRL_GET_TIMEOUT);
/* Convert data into an array of integers */
for (i = 0; i < length; i++)
@@ -296,6 +314,7 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
unsigned int *data, int size)
{
struct usb_serial *serial = port->serial;
+ struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
__le32 *buf;
int result, i, length;
@@ -317,12 +336,14 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
request, REQTYPE_HOST_TO_DEVICE, 0x0000,
- 0, buf, size, 300);
+ port_priv->bInterfaceNumber, buf, size,
+ USB_CTRL_SET_TIMEOUT);
} else {
result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
request, REQTYPE_HOST_TO_DEVICE, data[0],
- 0, NULL, 0, 300);
+ port_priv->bInterfaceNumber, NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
}
kfree(buf);
@@ -353,8 +374,8 @@ static inline int cp210x_set_config_single(struct usb_serial_port *port,
* Quantises the baud rate as per AN205 Table 1
*/
static unsigned int cp210x_quantise_baudrate(unsigned int baud) {
- if (baud <= 56) baud = 0;
- else if (baud <= 300) baud = 300;
+ if (baud <= 300)
+ baud = 300;
else if (baud <= 600) baud = 600;
else if (baud <= 1200) baud = 1200;
else if (baud <= 1800) baud = 1800;
@@ -382,17 +403,15 @@ static unsigned int cp210x_quantise_baudrate(unsigned int baud) {
else if (baud <= 491520) baud = 460800;
else if (baud <= 567138) baud = 500000;
else if (baud <= 670254) baud = 576000;
- else if (baud <= 1053257) baud = 921600;
- else if (baud <= 1474560) baud = 1228800;
- else if (baud <= 2457600) baud = 1843200;
- else baud = 3686400;
+ else if (baud < 1000000)
+ baud = 921600;
+ else if (baud > 2000000)
+ baud = 2000000;
return baud;
}
static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
{
- int result;
-
dbg("%s - port %d", __func__, port->number);
if (cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_ENABLE)) {
@@ -401,13 +420,14 @@ static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
return -EPROTO;
}
- result = usb_serial_generic_open(tty, port);
- if (result)
- return result;
-
/* Configure the termios structure */
cp210x_get_termios(tty, port);
- return 0;
+
+ /* The baud rate must be initialised on cp2104 */
+ if (tty)
+ cp210x_change_speed(tty, port, NULL);
+
+ return usb_serial_generic_open(tty, port);
}
static void cp210x_close(struct usb_serial_port *port)
@@ -459,10 +479,7 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
dbg("%s - port %d", __func__, port->number);
- cp210x_get_config(port, CP210X_GET_BAUDDIV, &baud, 2);
- /* Convert to baudrate */
- if (baud)
- baud = cp210x_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud);
+ cp210x_get_config(port, CP210X_GET_BAUDRATE, &baud, 4);
dbg("%s - baud rate = %d", __func__, baud);
*baudp = baud;
@@ -576,11 +593,64 @@ static void cp210x_get_termios_port(struct usb_serial_port *port,
*cflagp = cflag;
}
+/*
+ * CP2101 supports the following baud rates:
+ *
+ * 300, 600, 1200, 1800, 2400, 4800, 7200, 9600, 14400, 19200, 28800,
+ * 38400, 56000, 57600, 115200, 128000, 230400, 460800, 921600
+ *
+ * CP2102 and CP2103 support the following additional rates:
+ *
+ * 4000, 16000, 51200, 64000, 76800, 153600, 250000, 256000, 500000,
+ * 576000
+ *
+ * The device will map a requested rate to a supported one, but the result
+ * of requests for rates greater than 1053257 is undefined (see AN205).
+ *
+ * CP2104, CP2105 and CP2110 support most rates up to 2M, 921k and 1M baud,
+ * respectively, with an error less than 1%. The actual rates are determined
+ * by
+ *
+ * div = round(freq / (2 x prescale x request))
+ * actual = freq / (2 x prescale x div)
+ *
+ * For CP2104 and CP2105 freq is 48Mhz and prescale is 4 for request <= 365bps
+ * or 1 otherwise.
+ * For CP2110 freq is 24Mhz and prescale is 4 for request <= 300bps or 1
+ * otherwise.
+ */
+static void cp210x_change_speed(struct tty_struct *tty,
+ struct usb_serial_port *port, struct ktermios *old_termios)
+{
+ u32 baud;
+
+ baud = tty->termios->c_ospeed;
+
+ /* This maps the requested rate to a rate valid on cp2102 or cp2103,
+ * or to an arbitrary rate in [1M,2M].
+ *
+ * NOTE: B0 is not implemented.
+ */
+ baud = cp210x_quantise_baudrate(baud);
+
+ dbg("%s - setting baud rate to %u", __func__, baud);
+ if (cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud,
+ sizeof(baud))) {
+ dev_warn(&port->dev, "failed to set baud rate to %u\n", baud);
+ if (old_termios)
+ baud = old_termios->c_ospeed;
+ else
+ baud = 9600;
+ }
+
+ tty_encode_baud_rate(tty, baud, baud);
+}
+
static void cp210x_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
unsigned int cflag, old_cflag;
- unsigned int baud = 0, bits;
+ unsigned int bits;
unsigned int modem_ctl[4];
dbg("%s - port %d", __func__, port->number);
@@ -591,20 +661,9 @@ static void cp210x_set_termios(struct tty_struct *tty,
tty->termios->c_cflag &= ~CMSPAR;
cflag = tty->termios->c_cflag;
old_cflag = old_termios->c_cflag;
- baud = cp210x_quantise_baudrate(tty_get_baud_rate(tty));
-
- /* If the baud rate is to be updated*/
- if (baud != tty_termios_baud_rate(old_termios) && baud != 0) {
- dbg("%s - Setting baud rate to %d baud", __func__,
- baud);
- if (cp210x_set_config_single(port, CP210X_SET_BAUDDIV,
- ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) {
- dbg("Baud rate requested not supported by device");
- baud = tty_termios_baud_rate(old_termios);
- }
- }
- /* Report back the resulting baud rate */
- tty_encode_baud_rate(tty, baud, baud);
+
+ if (tty->termios->c_ospeed != old_termios->c_ospeed)
+ cp210x_change_speed(tty, port, old_termios);
/* If the number of data bits is to be updated */
if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
@@ -784,11 +843,39 @@ static void cp210x_break_ctl (struct tty_struct *tty, int break_state)
static int cp210x_startup(struct usb_serial *serial)
{
+ struct cp210x_port_private *port_priv;
+ int i;
+
/* cp210x buffers behave strangely unless device is reset */
usb_reset_device(serial->dev);
+
+ for (i = 0; i < serial->num_ports; i++) {
+ port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
+ if (!port_priv)
+ return -ENOMEM;
+
+ memset(port_priv, 0x00, sizeof(*port_priv));
+ port_priv->bInterfaceNumber =
+ serial->interface->cur_altsetting->desc.bInterfaceNumber;
+
+ usb_set_serial_port_data(serial->port[i], port_priv);
+ }
+
return 0;
}
+static void cp210x_release(struct usb_serial *serial)
+{
+ struct cp210x_port_private *port_priv;
+ int i;
+
+ for (i = 0; i < serial->num_ports; i++) {
+ port_priv = usb_get_serial_port_data(serial->port[i]);
+ kfree(port_priv);
+ usb_set_serial_port_data(serial->port[i], NULL);
+ }
+}
+
static int __init cp210x_init(void)
{
int retval;
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index b02fd5027cce..f08d494dedbf 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -187,6 +187,7 @@ static struct usb_device_id id_table_combined [] = {
.driver_info = (kernel_ulong_t)&ftdi_8u2232c_quirk },
{ USB_DEVICE(FTDI_VID, FTDI_4232H_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_232H_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_FTX_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) },
@@ -535,6 +536,10 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_6_PID) },
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_7_PID) },
{ USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_1_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_2_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_3_PID) },
+ { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803R_4_PID) },
{ USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) },
{ USB_DEVICE(OCT_VID, OCT_US101_PID) },
{ USB_DEVICE(OCT_VID, OCT_DK201_PID) },
@@ -796,14 +801,18 @@ static struct usb_device_id id_table_combined [] = {
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID) },
{ USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
{ USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) },
{ USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) },
+ { USB_DEVICE(PI_VID, PI_E861_PID) },
{ USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },
{ USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(FTDI_VID, TI_XDS100V2_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) },
{ USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) },
{ USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) },
@@ -835,11 +844,16 @@ 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_CINTERION_MC55I_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },
{ USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(ST_VID, ST_STMCLT1030_PID),
.driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk },
+ { USB_DEVICE(FTDI_VID, FTDI_RF_R106) },
+ { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID),
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
+ { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) },
{ }, /* Optional parameter entry */
{ } /* Terminating entry */
};
@@ -862,7 +876,8 @@ static const char *ftdi_chip_name[] = {
[FT232RL] = "FT232RL",
[FT2232H] = "FT2232H",
[FT4232H] = "FT4232H",
- [FT232H] = "FT232H"
+ [FT232H] = "FT232H",
+ [FTX] = "FT-X"
};
@@ -1160,7 +1175,8 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
break;
case FT232BM: /* FT232BM chip */
case FT2232C: /* FT2232C chip */
- case FT232RL:
+ case FT232RL: /* FT232RL chip */
+ case FTX: /* FT-X series */
if (baud <= 3000000) {
__u16 product_id = le16_to_cpu(
port->serial->dev->descriptor.idProduct);
@@ -1326,8 +1342,7 @@ static int set_serial_info(struct tty_struct *tty,
goto check_and_exit;
}
- if ((new_serial.baud_base != priv->baud_base) &&
- (new_serial.baud_base < 9600)) {
+ if (new_serial.baud_base != priv->baud_base) {
mutex_unlock(&priv->cfg_lock);
return -EINVAL;
}
@@ -1447,10 +1462,14 @@ static void ftdi_determine_type(struct usb_serial_port *port)
} else if (version < 0x900) {
/* Assume it's an FT232RL */
priv->chip_type = FT232RL;
- } else {
+ } else if (version < 0x1000) {
/* Assume it's an FT232H */
priv->chip_type = FT232H;
+ } else {
+ /* Assume it's an FT-X series device */
+ priv->chip_type = FTX;
}
+
dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]);
}
@@ -1578,7 +1597,8 @@ static int create_sysfs_attrs(struct usb_serial_port *port)
priv->chip_type == FT232RL ||
priv->chip_type == FT2232H ||
priv->chip_type == FT4232H ||
- priv->chip_type == FT232H)) {
+ priv->chip_type == FT232H ||
+ priv->chip_type == FTX)) {
retval = device_create_file(&port->dev,
&dev_attr_latency_timer);
}
@@ -1600,7 +1620,8 @@ static void remove_sysfs_attrs(struct usb_serial_port *port)
priv->chip_type == FT232RL ||
priv->chip_type == FT2232H ||
priv->chip_type == FT4232H ||
- priv->chip_type == FT232H) {
+ priv->chip_type == FT232H ||
+ priv->chip_type == FTX) {
device_remove_file(&port->dev, &dev_attr_latency_timer);
}
}
@@ -1751,7 +1772,8 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial)
dbg("%s", __func__);
- if (strcmp(udev->manufacturer, "CALAO Systems") == 0)
+ if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) ||
+ (udev->product && !strcmp(udev->product, "BeagleBone/XDS100")))
return ftdi_jtag_probe(serial);
return 0;
@@ -1816,6 +1838,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
{
+ struct ktermios dummy;
struct usb_device *dev = port->serial->dev;
struct ftdi_private *priv = usb_get_serial_port_data(port);
int result;
@@ -1834,8 +1857,10 @@ static int ftdi_open(struct tty_struct *tty, struct usb_serial_port *port)
This is same behaviour as serial.c/rs_open() - Kuba */
/* ftdi_set_termios will send usb control messages */
- if (tty)
- ftdi_set_termios(tty, port, tty->termios);
+ if (tty) {
+ memset(&dummy, 0, sizeof(dummy));
+ ftdi_set_termios(tty, port, &dummy);
+ }
/* Start reading from the device */
result = usb_serial_generic_open(tty, port);
@@ -2253,6 +2278,7 @@ static int ftdi_tiocmget(struct tty_struct *tty)
case FT2232H:
case FT4232H:
case FT232H:
+ case FTX:
len = 2;
break;
default:
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
index 19584faa86f9..ed58c6fa8dbe 100644
--- a/drivers/usb/serial/ftdi_sio.h
+++ b/drivers/usb/serial/ftdi_sio.h
@@ -157,7 +157,8 @@ enum ftdi_chip_type {
FT232RL = 5,
FT2232H = 6,
FT4232H = 7,
- FT232H = 8
+ FT232H = 8,
+ FTX = 9,
};
enum ftdi_sio_baudrate {
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 055b64ef0bba..219b199eff52 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -23,12 +23,15 @@
#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
#define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */
#define FTDI_232H_PID 0x6014 /* Single channel hi-speed device */
+#define FTDI_FTX_PID 0x6015 /* FT-X series (FT201X, FT230X, FT231X, etc) */
#define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */
#define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */
/*** third-party PIDs (using FTDI_VID) ***/
+#define FTDI_LUMEL_PD12_PID 0x6002
+
/*
* Marvell OpenRD Base, Client
* http://www.open-rd.org
@@ -39,6 +42,13 @@
/* www.candapter.com Ewert Energy Systems CANdapter device */
#define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */
+/*
+ * Texas Instruments XDS100v2 JTAG / BeagleBone A3
+ * http://processors.wiki.ti.com/index.php/XDS100
+ * http://beagleboard.org/bone
+ */
+#define TI_XDS100V2_PID 0xa6d0
+
#define FTDI_NXTCAM_PID 0xABB8 /* NXTCam for Mindstorms NXT */
/* US Interface Navigator (http://www.usinterface.com/) */
@@ -90,6 +100,8 @@
#define FTDI_TACTRIX_OPENPORT_13S_PID 0xCC49 /* OpenPort 1.3 Subaru */
#define FTDI_TACTRIX_OPENPORT_13U_PID 0xCC4A /* OpenPort 1.3 Universal */
+#define FTDI_DISTORTEC_JTAG_LOCK_PICK_PID 0xCFF8
+
/* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */
/* the VID is the standard ftdi vid (FTDI_VID) */
#define FTDI_SCS_DEVICE_0_PID 0xD010 /* SCS PTC-IIusb */
@@ -525,6 +537,16 @@
#define ADI_GNICEPLUS_PID 0xF001
/*
+ * Microchip Technology, Inc.
+ *
+ * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are also used by:
+ * Hornby Elite - Digital Command Control Console
+ * http://www.hornby.com/hornby-dcc/controllers/
+ */
+#define MICROCHIP_VID 0x04D8
+#define MICROCHIP_USB_BOARD_PID 0x000A /* CDC RS-232 Emulation Demo */
+
+/*
* RATOC REX-USB60F
*/
#define RATOC_VENDOR_ID 0x0584
@@ -667,6 +689,10 @@
#define SEALEVEL_2803_6_PID 0X2863 /* SeaLINK+8 (2803) Port 6 */
#define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */
#define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */
+#define SEALEVEL_2803R_1_PID 0Xa02a /* SeaLINK+8 (2803-ROHS) Port 1+2 */
+#define SEALEVEL_2803R_2_PID 0Xa02b /* SeaLINK+8 (2803-ROHS) Port 3+4 */
+#define SEALEVEL_2803R_3_PID 0Xa02c /* SeaLINK+8 (2803-ROHS) Port 5+6 */
+#define SEALEVEL_2803R_4_PID 0Xa02d /* SeaLINK+8 (2803-ROHS) Port 7+8 */
/*
* JETI SPECTROMETER SPECBOS 1201
@@ -759,6 +785,14 @@
#define RTSYSTEMS_SERIAL_VX7_PID 0x9e52 /* Serial converter for VX-7 Radios using FT232RL */
#define RTSYSTEMS_CT29B_PID 0x9e54 /* CT29B Radio Cable */
+
+/*
+ * Physik Instrumente
+ * http://www.physikinstrumente.com/en/products/
+ */
+#define PI_VID 0x1a72 /* Vendor ID */
+#define PI_E861_PID 0x1008 /* E-861 piezo controller USB connection */
+
/*
* Bayer Ascensia Contour blood glucose meter USB-converter cable.
* http://winglucofacts.com/cables/
@@ -1168,3 +1202,16 @@
*/
/* TagTracer MIFARE*/
#define FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID 0xF7C0
+
+/*
+ * Rainforest Automation
+ */
+/* ZigBee controller */
+#define FTDI_RF_R106 0x8A28
+
+/*
+ * Product: HCP HIT GPRS modem
+ * Manufacturer: HCP d.o.o.
+ * ATI command output: Cinterion MC55i
+ */
+#define FTDI_CINTERION_MC55I_PID 0xA951
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c
index e4db5ad2bc55..9f0b2bff8ee4 100644
--- a/drivers/usb/serial/generic.c
+++ b/drivers/usb/serial/generic.c
@@ -215,8 +215,10 @@ retry:
clear_bit(i, &port->write_urbs_free);
result = usb_submit_urb(urb, GFP_ATOMIC);
if (result) {
- dev_err(&port->dev, "%s - error submitting urb: %d\n",
+ if (!port->port.console) {
+ dev_err(&port->dev, "%s - error submitting urb: %d\n",
__func__, result);
+ }
set_bit(i, &port->write_urbs_free);
spin_lock_irqsave(&port->lock, flags);
port->tx_bytes -= count;
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 0aac00afb5c8..8a90d58ee96d 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -2677,15 +2677,7 @@ cleanup:
static void edge_disconnect(struct usb_serial *serial)
{
- int i;
- struct edgeport_port *edge_port;
-
dbg("%s", __func__);
-
- for (i = 0; i < serial->num_ports; ++i) {
- edge_port = usb_get_serial_port_data(serial->port[i]);
- edge_remove_sysfs_attrs(edge_port->port);
- }
}
static void edge_release(struct usb_serial *serial)
@@ -2764,6 +2756,7 @@ static struct usb_serial_driver edgeport_1port_device = {
.disconnect = edge_disconnect,
.release = edge_release,
.port_probe = edge_create_sysfs_attrs,
+ .port_remove = edge_remove_sysfs_attrs,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
@@ -2795,6 +2788,7 @@ static struct usb_serial_driver edgeport_2port_device = {
.disconnect = edge_disconnect,
.release = edge_release,
.port_probe = edge_create_sysfs_attrs,
+ .port_remove = edge_remove_sysfs_attrs,
.ioctl = edge_ioctl,
.set_termios = edge_set_termios,
.tiocmget = edge_tiocmget,
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c
index 7b50aa122752..32575196cbf1 100644
--- a/drivers/usb/serial/mos7840.c
+++ b/drivers/usb/serial/mos7840.c
@@ -174,6 +174,7 @@
#define CLK_MULTI_REGISTER ((__u16)(0x02))
#define CLK_START_VALUE_REGISTER ((__u16)(0x03))
+#define GPIO_REGISTER ((__u16)(0x07))
#define SERIAL_LCR_DLAB ((__u16)(0x0080))
@@ -1103,14 +1104,25 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
mos7840_port->read_urb = port->read_urb;
/* set up our bulk in urb */
-
- usb_fill_bulk_urb(mos7840_port->read_urb,
- serial->dev,
- usb_rcvbulkpipe(serial->dev,
- port->bulk_in_endpointAddress),
- port->bulk_in_buffer,
- mos7840_port->read_urb->transfer_buffer_length,
- mos7840_bulk_in_callback, mos7840_port);
+ if ((serial->num_ports == 2)
+ && ((((__u16)port->number -
+ (__u16)(port->serial->minor)) % 2) != 0)) {
+ usb_fill_bulk_urb(mos7840_port->read_urb,
+ serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ (port->bulk_in_endpointAddress) + 2),
+ port->bulk_in_buffer,
+ mos7840_port->read_urb->transfer_buffer_length,
+ mos7840_bulk_in_callback, mos7840_port);
+ } else {
+ usb_fill_bulk_urb(mos7840_port->read_urb,
+ serial->dev,
+ usb_rcvbulkpipe(serial->dev,
+ port->bulk_in_endpointAddress),
+ port->bulk_in_buffer,
+ mos7840_port->read_urb->transfer_buffer_length,
+ mos7840_bulk_in_callback, mos7840_port);
+ }
dbg("mos7840_open: bulkin endpoint is %d",
port->bulk_in_endpointAddress);
@@ -1521,13 +1533,25 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port,
memcpy(urb->transfer_buffer, current_position, transfer_size);
/* fill urb with data and submit */
- usb_fill_bulk_urb(urb,
- serial->dev,
- usb_sndbulkpipe(serial->dev,
- port->bulk_out_endpointAddress),
- urb->transfer_buffer,
- transfer_size,
- mos7840_bulk_out_data_callback, mos7840_port);
+ if ((serial->num_ports == 2)
+ && ((((__u16)port->number -
+ (__u16)(port->serial->minor)) % 2) != 0)) {
+ usb_fill_bulk_urb(urb,
+ serial->dev,
+ usb_sndbulkpipe(serial->dev,
+ (port->bulk_out_endpointAddress) + 2),
+ urb->transfer_buffer,
+ transfer_size,
+ mos7840_bulk_out_data_callback, mos7840_port);
+ } else {
+ usb_fill_bulk_urb(urb,
+ serial->dev,
+ usb_sndbulkpipe(serial->dev,
+ port->bulk_out_endpointAddress),
+ urb->transfer_buffer,
+ transfer_size,
+ mos7840_bulk_out_data_callback, mos7840_port);
+ }
data1 = urb->transfer_buffer;
dbg("bulkout endpoint is %d", port->bulk_out_endpointAddress);
@@ -1840,7 +1864,7 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port,
} else {
#ifdef HW_flow_control
- / *setting h/w flow control bit to 0 */
+ /* setting h/w flow control bit to 0 */
Data = 0xb;
mos7840_port->shadowMCR = Data;
status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER,
@@ -2310,19 +2334,26 @@ static int mos7840_ioctl(struct tty_struct *tty,
static int mos7840_calc_num_ports(struct usb_serial *serial)
{
- int mos7840_num_ports = 0;
-
- dbg("numberofendpoints: cur %d, alt %d",
- (int)serial->interface->cur_altsetting->desc.bNumEndpoints,
- (int)serial->interface->altsetting->desc.bNumEndpoints);
- if (serial->interface->cur_altsetting->desc.bNumEndpoints == 5) {
- mos7840_num_ports = serial->num_ports = 2;
- } else if (serial->interface->cur_altsetting->desc.bNumEndpoints == 9) {
+ __u16 Data = 0x00;
+ int ret = 0;
+ int mos7840_num_ports;
+
+ ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ MCS_RDREQ, MCS_RD_RTYPE, 0, GPIO_REGISTER, &Data,
+ VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT);
+
+ if ((Data & 0x01) == 0) {
+ mos7840_num_ports = 2;
+ serial->num_bulk_in = 2;
+ serial->num_bulk_out = 2;
+ serial->num_ports = 2;
+ } else {
+ mos7840_num_ports = 4;
serial->num_bulk_in = 4;
serial->num_bulk_out = 4;
- mos7840_num_ports = serial->num_ports = 4;
+ serial->num_ports = 4;
}
- dbg ("mos7840_num_ports = %d", mos7840_num_ports);
+
return mos7840_num_ports;
}
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c
index 60f38d5e64fc..0a8c1e64b247 100644
--- a/drivers/usb/serial/omninet.c
+++ b/drivers/usb/serial/omninet.c
@@ -315,7 +315,7 @@ static int omninet_write_room(struct tty_struct *tty)
int room = 0; /* Default: no room */
/* FIXME: no consistent locking for write_urb_busy */
- if (wport->write_urb_busy)
+ if (!wport->write_urb_busy)
room = wport->bulk_out_size - OMNINET_HEADERLEN;
dbg("%s - returns %d", __func__, room);
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index d2becb9eb605..cbe3451cb351 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -307,6 +307,9 @@ static void option_instat_callback(struct urb *urb);
#define TELIT_VENDOR_ID 0x1bc7
#define TELIT_PRODUCT_UC864E 0x1003
#define TELIT_PRODUCT_UC864G 0x1004
+#define TELIT_PRODUCT_CC864_DUAL 0x1005
+#define TELIT_PRODUCT_CC864_SINGLE 0x1006
+#define TELIT_PRODUCT_DE910_DUAL 0x1010
/* ZTE PRODUCTS */
#define ZTE_VENDOR_ID 0x19d2
@@ -472,6 +475,21 @@ static void option_instat_callback(struct urb *urb);
#define YUGA_PRODUCT_CLU528 0x260D
#define YUGA_PRODUCT_CLU526 0x260F
+/* Viettel products */
+#define VIETTEL_VENDOR_ID 0x2262
+#define VIETTEL_PRODUCT_VT1000 0x0002
+
+/* ZD Incorporated */
+#define ZD_VENDOR_ID 0x0685
+#define ZD_PRODUCT_7000 0x7000
+
+/* LG products */
+#define LG_VENDOR_ID 0x1004
+#define LG_PRODUCT_L02C 0x618f
+
+/* MediaTek products */
+#define MEDIATEK_VENDOR_ID 0x0e8d
+
/* some devices interfaces need special handling due to a number of reasons */
enum option_blacklist_reason {
OPTION_BLACKLIST_NONE = 0,
@@ -690,6 +708,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_HIGHSPEED) },
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED3) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED4) },
{ USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_HIGHSPEED5) },
@@ -756,6 +775,9 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf1_blacklist },
@@ -776,7 +798,6 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0012, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf1_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0013, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0016, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0017, 0xff, 0xff, 0xff),
@@ -791,7 +812,6 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0024, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0025, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf1_blacklist },
- /* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0026, 0xff, 0xff, 0xff) }, */
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0028, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0029, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0030, 0xff, 0xff, 0xff) },
@@ -816,7 +836,6 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0051, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0052, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
- /* { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0053, 0xff, 0xff, 0xff) }, */
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0054, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0055, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf1_blacklist },
@@ -824,7 +843,6 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0057, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0058, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0061, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0062, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0063, 0xff, 0xff, 0xff),
@@ -834,7 +852,6 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0066, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0067, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0069, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0076, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0077, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0078, 0xff, 0xff, 0xff) },
@@ -843,6 +860,16 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0083, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0086, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0087, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0088, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0089, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0090, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0091, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0092, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0093, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0095, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0096, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0097, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0104, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0105, 0xff, 0xff, 0xff) },
@@ -863,23 +890,20 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0144, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0145, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0146, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0148, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0149, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0150, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0151, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0153, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0154, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0155, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0160, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0164, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
@@ -1054,17 +1078,27 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff,
+ 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
+
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0014, 0xff, 0xff, 0xff) }, /* ZTE CDMA products */
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0027, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0059, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0060, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff,
- 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff) },
+
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
@@ -1173,6 +1207,13 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU516) },
{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU528) },
{ USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) },
+ { USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) },
+ { USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x02, 0x01) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x00, 0x00) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x02, 0x01) }, /* MediaTek MT6276M modem & app port */
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);
@@ -1335,6 +1376,7 @@ static int option_probe(struct usb_serial *serial,
serial->interface->cur_altsetting->desc.bInterfaceNumber,
OPTION_BLACKLIST_RESERVED_IF,
(const struct option_blacklist_info *) id->driver_info))
+ return -ENODEV;
/* Don't bind network interface on Samsung GT-B3730, it is handled by a separate module */
if (serial->dev->descriptor.idVendor == SAMSUNG_VENDOR_ID &&
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index d44c669cc483..5aa7172e049f 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -424,7 +424,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
control = priv->line_control;
if ((cflag & CBAUD) == B0)
priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
- else
+ else if ((old_termios->c_cflag & CBAUD) == B0)
priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
if (control != priv->line_control) {
control = priv->line_control;
diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c
index 30b73e68a904..a34819884c1a 100644
--- a/drivers/usb/serial/qcaux.c
+++ b/drivers/usb/serial/qcaux.c
@@ -36,6 +36,7 @@
#define UTSTARCOM_PRODUCT_UM175_V1 0x3712
#define UTSTARCOM_PRODUCT_UM175_V2 0x3714
#define UTSTARCOM_PRODUCT_UM175_ALLTEL 0x3715
+#define PANTECH_PRODUCT_UML190_VZW 0x3716
#define PANTECH_PRODUCT_UML290_VZW 0x3718
/* CMOTECH devices */
@@ -67,7 +68,11 @@ static struct usb_device_id id_table[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xff, 0xff, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX, 0xff, 0xff, 0x00) },
{ USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_U520, 0xff, 0x00, 0x00) },
- { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xfe, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfd, 0xff) }, /* NMEA */
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfe, 0xff) }, /* WMC */
+ { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) }, /* DIAG */
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index b9bb24729c99..247c014a4bb0 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -23,34 +23,44 @@
static int debug;
+#define DEVICE_G1K(v, p) \
+ USB_DEVICE(v, p), .driver_info = 1
+
static const struct usb_device_id id_table[] = {
- {USB_DEVICE(0x05c6, 0x9211)}, /* Acer Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
- {USB_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */
- {USB_DEVICE(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */
- {USB_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */
- {USB_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */
- {USB_DEVICE(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */
- {USB_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */
- {USB_DEVICE(0x413c, 0x8171)}, /* Dell Gobi QDL device */
- {USB_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */
- {USB_DEVICE(0x1410, 0xa008)}, /* Novatel Gobi QDL device */
- {USB_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */
- {USB_DEVICE(0x0b05, 0x1774)}, /* Asus Gobi QDL device */
- {USB_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */
- {USB_DEVICE(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */
- {USB_DEVICE(0x1557, 0x0a80)}, /* OQO Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9008)}, /* Generic Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */
- {USB_DEVICE(0x05c6, 0x9201)}, /* Generic Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9221)}, /* Generic Gobi QDL device */
- {USB_DEVICE(0x05c6, 0x9231)}, /* Generic Gobi QDL device */
- {USB_DEVICE(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */
+ /* Gobi 1000 devices */
+ {DEVICE_G1K(0x05c6, 0x9211)}, /* Acer Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
+ {DEVICE_G1K(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */
+ {DEVICE_G1K(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */
+ {DEVICE_G1K(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */
+ {DEVICE_G1K(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */
+ {DEVICE_G1K(0x413c, 0x8172)}, /* Dell Gobi Modem device */
+ {DEVICE_G1K(0x413c, 0x8171)}, /* Dell Gobi QDL device */
+ {DEVICE_G1K(0x1410, 0xa001)}, /* Novatel Gobi Modem device */
+ {DEVICE_G1K(0x1410, 0xa008)}, /* Novatel Gobi QDL device */
+ {DEVICE_G1K(0x0b05, 0x1776)}, /* Asus Gobi Modem device */
+ {DEVICE_G1K(0x0b05, 0x1774)}, /* Asus Gobi QDL device */
+ {DEVICE_G1K(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */
+ {DEVICE_G1K(0x19d2, 0xfff2)}, /* ONDA Gobi QDL device */
+ {DEVICE_G1K(0x1557, 0x0a80)}, /* OQO Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9001)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9002)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9202)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9203)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9222)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9008)}, /* Generic Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9009)}, /* Generic Gobi Modem device */
+ {DEVICE_G1K(0x05c6, 0x9201)}, /* Generic Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9221)}, /* Generic Gobi QDL device */
+ {DEVICE_G1K(0x05c6, 0x9231)}, /* Generic Gobi QDL device */
+ {DEVICE_G1K(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */
+
+ /* Gobi 2000 devices */
+ {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi 2000 QDL device */
+ {USB_DEVICE(0x1410, 0xa011)}, /* Novatel Gobi 2000 QDL device */
+ {USB_DEVICE(0x1410, 0xa012)}, /* Novatel Gobi 2000 QDL device */
+ {USB_DEVICE(0x1410, 0xa013)}, /* Novatel Gobi 2000 QDL device */
+ {USB_DEVICE(0x1410, 0xa014)}, /* Novatel Gobi 2000 QDL device */
{USB_DEVICE(0x413c, 0x8185)}, /* Dell Gobi 2000 QDL device (N0218, VU936) */
{USB_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */
{USB_DEVICE(0x05c6, 0x9208)}, /* Generic Gobi 2000 QDL device */
@@ -85,7 +95,18 @@ static const struct usb_device_id id_table[] = {
{USB_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */
{USB_DEVICE(0x05c6, 0x9204)}, /* Gobi 2000 QDL device */
{USB_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */
+
+ /* Gobi 3000 devices */
+ {USB_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Gobi 3000 QDL */
+ {USB_DEVICE(0x05c6, 0x920c)}, /* Gobi 3000 QDL */
+ {USB_DEVICE(0x05c6, 0x920d)}, /* Gobi 3000 Composite */
+ {USB_DEVICE(0x1410, 0xa020)}, /* Novatel Gobi 3000 QDL */
+ {USB_DEVICE(0x1410, 0xa021)}, /* Novatel Gobi 3000 Composite */
+ {USB_DEVICE(0x413c, 0x8193)}, /* Dell Gobi 3000 QDL */
+ {USB_DEVICE(0x413c, 0x8194)}, /* Dell Gobi 3000 Composite */
{USB_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */
+ {USB_DEVICE(0x12D1, 0x14F0)}, /* Sony Gobi 3000 QDL */
+ {USB_DEVICE(0x12D1, 0x14F1)}, /* Sony Gobi 3000 Composite */
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, id_table);
@@ -107,8 +128,10 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
int retval = -ENODEV;
__u8 nintf;
__u8 ifnum;
+ bool is_gobi1k = id->driver_info ? true : false;
dbg("%s", __func__);
+ dbg("Is Gobi 1000 = %d", is_gobi1k);
nintf = serial->dev->actconfig->desc.bNumInterfaces;
dbg("Num Interfaces = %d", nintf);
@@ -156,15 +179,25 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
case 3:
case 4:
- /* Composite mode */
- /* ifnum == 0 is a broadband network adapter */
- if (ifnum == 1) {
- /*
- * Diagnostics Monitor (serial line 9600 8N1)
- * Qualcomm DM protocol
- * use "libqcdm" (ModemManager) for communication
- */
- dbg("Diagnostics Monitor found");
+ /* Composite mode; don't bind to the QMI/net interface as that
+ * gets handled by other drivers.
+ */
+
+ /* Gobi 1K USB layout:
+ * 0: serial port (doesn't respond)
+ * 1: serial port (doesn't respond)
+ * 2: AT-capable modem port
+ * 3: QMI/net
+ *
+ * Gobi 2K+ USB layout:
+ * 0: QMI/net
+ * 1: DM/DIAG (use libqcdm from ModemManager for communication)
+ * 2: AT-capable modem port
+ * 3: NMEA
+ */
+
+ if (ifnum == 1 && !is_gobi1k) {
+ dbg("Gobi 2K+ DM/DIAG interface found");
retval = usb_set_interface(serial->dev, ifnum, 0);
if (retval < 0) {
dev_err(&serial->dev->dev,
@@ -183,13 +216,13 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
retval = -ENODEV;
kfree(data);
}
- } else if (ifnum==3) {
+ } else if (ifnum==3 && !is_gobi1k) {
/*
* NMEA (serial line 9600 8N1)
* # echo "\$GPS_START" > /dev/ttyUSBx
* # echo "\$GPS_STOP" > /dev/ttyUSBx
*/
- dbg("NMEA GPS interface found");
+ dbg("Gobi 2K+ NMEA GPS interface found");
retval = usb_set_interface(serial->dev, ifnum, 0);
if (retval < 0) {
dev_err(&serial->dev->dev,
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index d5d136a53b61..ef71ba3960d7 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -221,7 +221,7 @@ static const struct sierra_iface_info typeB_interface_list = {
};
/* 'blacklist' of interfaces not served by this driver */
-static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11 };
+static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11, 19, 20 };
static const struct sierra_iface_info direct_ip_interface_blacklist = {
.infolen = ARRAY_SIZE(direct_ip_non_serial_ifaces),
.ifaceinfo = direct_ip_non_serial_ifaces,
@@ -298,6 +298,9 @@ static const struct usb_device_id id_table[] = {
/* Sierra Wireless HSPA Non-Composite Device */
{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)},
{ USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */
+ { USB_DEVICE(0x1199, 0x68A2), /* Sierra Wireless MC77xx in QMI mode */
+ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
+ },
{ USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */
.driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
},
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
index ea8445689c85..2856474123eb 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.c
+++ b/drivers/usb/serial/ti_usb_3410_5052.c
@@ -165,7 +165,7 @@ static unsigned int product_5052_count;
/* the array dimension is the number of default entries plus */
/* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */
/* null entry */
-static struct usb_device_id ti_id_table_3410[13+TI_EXTRA_VID_PID_COUNT+1] = {
+static struct usb_device_id ti_id_table_3410[15+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
{ USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
@@ -179,6 +179,8 @@ static struct usb_device_id ti_id_table_3410[13+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) },
+ { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) },
+ { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) },
};
static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = {
@@ -188,7 +190,7 @@ static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) },
};
-static struct usb_device_id ti_id_table_combined[17+2*TI_EXTRA_VID_PID_COUNT+1] = {
+static struct usb_device_id ti_id_table_combined[19+2*TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
{ USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) },
@@ -206,6 +208,8 @@ static struct usb_device_id ti_id_table_combined[17+2*TI_EXTRA_VID_PID_COUNT+1]
{ USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) },
{ USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) },
+ { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) },
+ { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) },
{ }
};
diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h
index 2aac1953993b..b353e7e3d480 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.h
+++ b/drivers/usb/serial/ti_usb_3410_5052.h
@@ -37,6 +37,7 @@
#define TI_5152_BOOT_PRODUCT_ID 0x5152 /* no EEPROM, no firmware */
#define TI_5052_EEPROM_PRODUCT_ID 0x505A /* EEPROM, no firmware */
#define TI_5052_FIRMWARE_PRODUCT_ID 0x505F /* firmware is running */
+#define FRI2_PRODUCT_ID 0x5053 /* Fish River Island II */
/* Multi-Tech vendor and product ids */
#define MTS_VENDOR_ID 0x06E0
@@ -49,6 +50,10 @@
#define MTS_MT9234ZBA_PRODUCT_ID 0xF115
#define MTS_MT9234ZBAOLD_PRODUCT_ID 0x0319
+/* Abbott Diabetics vendor and product ids */
+#define ABBOTT_VENDOR_ID 0x1a61
+#define ABBOTT_PRODUCT_ID 0x3410
+
/* Commands */
#define TI_GET_VERSION 0x01
#define TI_GET_PORT_STATUS 0x02
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 1c031309ab25..5d7b71b96148 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1059,6 +1059,12 @@ int usb_serial_probe(struct usb_interface *interface,
serial->attached = 1;
}
+ /* Avoid race with tty_open and serial_install by setting the
+ * disconnected flag and not clearing it until all ports have been
+ * registered.
+ */
+ serial->disconnected = 1;
+
if (get_free_serial(serial, num_ports, &minor) == NULL) {
dev_err(&interface->dev, "No more free serial devices\n");
goto probe_error;
@@ -1083,6 +1089,8 @@ int usb_serial_probe(struct usb_interface *interface,
}
}
+ serial->disconnected = 0;
+
usb_serial_console_init(debug, minor);
exit:
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 24caba79d722..591f57fcf97d 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -1885,6 +1885,13 @@ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201,
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
+/* Reported by Jesse Feddema <jdfeddema@gmail.com> */
+UNUSUAL_DEV( 0x177f, 0x0400, 0x0000, 0x0000,
+ "Yarvik",
+ "PMP400",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_BULK_IGNORE_TAG | US_FL_MAX_SECTORS_64 ),
+
/* Reported by Hans de Goede <hdegoede@redhat.com>
* These Appotech controllers are found in Picture Frames, they provide a
* (buggy) emulation of a cdrom drive which contains the windows software
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index c325e69415a1..db51ba16dc07 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -788,15 +788,19 @@ static void quiesce_and_remove_host(struct us_data *us)
struct Scsi_Host *host = us_to_host(us);
/* If the device is really gone, cut short reset delays */
- if (us->pusb_dev->state == USB_STATE_NOTATTACHED)
+ if (us->pusb_dev->state == USB_STATE_NOTATTACHED) {
set_bit(US_FLIDX_DISCONNECTING, &us->dflags);
+ wake_up(&us->delay_wait);
+ }
- /* Prevent SCSI-scanning (if it hasn't started yet)
- * and wait for the SCSI-scanning thread to stop.
+ /* Prevent SCSI scanning (if it hasn't started yet)
+ * or wait for the SCSI-scanning routine to stop.
*/
- set_bit(US_FLIDX_DONT_SCAN, &us->dflags);
- wake_up(&us->delay_wait);
- wait_for_completion(&us->scanning_done);
+ cancel_delayed_work_sync(&us->scan_dwork);
+
+ /* Balance autopm calls if scanning was cancelled */
+ if (test_bit(US_FLIDX_SCAN_PENDING, &us->dflags))
+ usb_autopm_put_interface_no_suspend(us->pusb_intf);
/* Removing the host will perform an orderly shutdown: caches
* synchronized, disks spun down, etc.
@@ -823,52 +827,28 @@ static void release_everything(struct us_data *us)
scsi_host_put(us_to_host(us));
}
-/* Thread to carry out delayed SCSI-device scanning */
-static int usb_stor_scan_thread(void * __us)
+/* Delayed-work routine to carry out SCSI-device scanning */
+static void usb_stor_scan_dwork(struct work_struct *work)
{
- struct us_data *us = (struct us_data *)__us;
+ struct us_data *us = container_of(work, struct us_data,
+ scan_dwork.work);
struct device *dev = &us->pusb_intf->dev;
- dev_dbg(dev, "device found\n");
+ dev_dbg(dev, "starting scan\n");
- set_freezable_with_signal();
- /*
- * Wait for the timeout to expire or for a disconnect
- *
- * We can't freeze in this thread or we risk causing khubd to
- * fail to freeze, but we can't be non-freezable either. Nor can
- * khubd freeze while waiting for scanning to complete as it may
- * hold the device lock, causing a hang when suspending devices.
- * So we request a fake signal when freezing and use
- * interruptible sleep to kick us out of our wait early when
- * freezing happens.
- */
- if (delay_use > 0) {
- dev_dbg(dev, "waiting for device to settle "
- "before scanning\n");
- wait_event_interruptible_timeout(us->delay_wait,
- test_bit(US_FLIDX_DONT_SCAN, &us->dflags),
- delay_use * HZ);
+ /* For bulk-only devices, determine the max LUN value */
+ if (us->protocol == USB_PR_BULK && !(us->fflags & US_FL_SINGLE_LUN)) {
+ mutex_lock(&us->dev_mutex);
+ us->max_lun = usb_stor_Bulk_max_lun(us);
+ mutex_unlock(&us->dev_mutex);
}
+ scsi_scan_host(us_to_host(us));
+ dev_dbg(dev, "scan complete\n");
- /* If the device is still connected, perform the scanning */
- if (!test_bit(US_FLIDX_DONT_SCAN, &us->dflags)) {
-
- /* For bulk-only devices, determine the max LUN value */
- if (us->protocol == USB_PR_BULK &&
- !(us->fflags & US_FL_SINGLE_LUN)) {
- mutex_lock(&us->dev_mutex);
- us->max_lun = usb_stor_Bulk_max_lun(us);
- mutex_unlock(&us->dev_mutex);
- }
- scsi_scan_host(us_to_host(us));
- dev_dbg(dev, "scan complete\n");
-
- /* Should we unbind if no devices were detected? */
- }
+ /* Should we unbind if no devices were detected? */
usb_autopm_put_interface(us->pusb_intf);
- complete_and_exit(&us->scanning_done, 0);
+ clear_bit(US_FLIDX_SCAN_PENDING, &us->dflags);
}
static unsigned int usb_stor_sg_tablesize(struct usb_interface *intf)
@@ -915,7 +895,7 @@ int usb_stor_probe1(struct us_data **pus,
init_completion(&us->cmnd_ready);
init_completion(&(us->notify));
init_waitqueue_head(&us->delay_wait);
- init_completion(&us->scanning_done);
+ INIT_DELAYED_WORK(&us->scan_dwork, usb_stor_scan_dwork);
/* Associate the us_data structure with the USB device */
result = associate_dev(us, intf);
@@ -946,7 +926,6 @@ EXPORT_SYMBOL_GPL(usb_stor_probe1);
/* Second part of general USB mass-storage probing */
int usb_stor_probe2(struct us_data *us)
{
- struct task_struct *th;
int result;
struct device *dev = &us->pusb_intf->dev;
@@ -987,20 +966,14 @@ int usb_stor_probe2(struct us_data *us)
goto BadDevice;
}
- /* Start up the thread for delayed SCSI-device scanning */
- th = kthread_create(usb_stor_scan_thread, us, "usb-stor-scan");
- if (IS_ERR(th)) {
- dev_warn(dev,
- "Unable to start the device-scanning thread\n");
- complete(&us->scanning_done);
- quiesce_and_remove_host(us);
- result = PTR_ERR(th);
- goto BadDevice;
- }
-
+ /* Submit the delayed_work for SCSI-device scanning */
usb_autopm_get_interface_no_resume(us->pusb_intf);
- wake_up_process(th);
+ set_bit(US_FLIDX_SCAN_PENDING, &us->dflags);
+ if (delay_use > 0)
+ dev_dbg(dev, "waiting for device to settle before scanning\n");
+ queue_delayed_work(system_freezable_wq, &us->scan_dwork,
+ delay_use * HZ);
return 0;
/* We come here if there are any problems */
@@ -1073,6 +1046,7 @@ static struct usb_driver usb_storage_driver = {
.id_table = usb_storage_usb_ids,
.supports_autosuspend = 1,
.soft_unbind = 1,
+ .no_dynamic_id = 1,
};
static int __init usb_stor_init(void)
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 7b0f2113632e..75f70f04f37b 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -47,6 +47,7 @@
#include <linux/blkdev.h>
#include <linux/completion.h>
#include <linux/mutex.h>
+#include <linux/workqueue.h>
#include <scsi/scsi_host.h>
struct us_data;
@@ -72,7 +73,7 @@ struct us_unusual_dev {
#define US_FLIDX_DISCONNECTING 3 /* disconnect in progress */
#define US_FLIDX_RESETTING 4 /* device reset in progress */
#define US_FLIDX_TIMED_OUT 5 /* SCSI midlayer timed out */
-#define US_FLIDX_DONT_SCAN 6 /* don't scan (disconnect) */
+#define US_FLIDX_SCAN_PENDING 6 /* scanning not yet done */
#define US_FLIDX_REDO_READ10 7 /* redo READ(10) command */
#define US_FLIDX_READ10_WORKED 8 /* previous READ(10) succeeded */
@@ -147,8 +148,8 @@ struct us_data {
/* mutual exclusion and synchronization structures */
struct completion cmnd_ready; /* to sleep thread on */
struct completion notify; /* thread begin/end */
- wait_queue_head_t delay_wait; /* wait during scan, reset */
- struct completion scanning_done; /* wait for scan thread */
+ wait_queue_head_t delay_wait; /* wait during reset */
+ struct delayed_work scan_dwork; /* for async scanning */
/* subdriver information */
void *extra; /* Any extra data */
diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c
index 2babcd4fbfc1..86685e994987 100644
--- a/drivers/uwb/hwa-rc.c
+++ b/drivers/uwb/hwa-rc.c
@@ -645,7 +645,8 @@ void hwarc_neep_cb(struct urb *urb)
dev_err(dev, "NEEP: URB error %d\n", urb->status);
}
result = usb_submit_urb(urb, GFP_ATOMIC);
- if (result < 0) {
+ if (result < 0 && result != -ENODEV && result != -EPERM) {
+ /* ignoring unrecoverable errors */
dev_err(dev, "NEEP: Can't resubmit URB (%d) resetting device\n",
result);
goto error;
diff --git a/drivers/uwb/neh.c b/drivers/uwb/neh.c
index 697e56a5bcdd..47146c894339 100644
--- a/drivers/uwb/neh.c
+++ b/drivers/uwb/neh.c
@@ -106,6 +106,7 @@ struct uwb_rc_neh {
u8 evt_type;
__le16 evt;
u8 context;
+ u8 completed;
uwb_rc_cmd_cb_f cb;
void *arg;
@@ -408,6 +409,7 @@ static void uwb_rc_neh_grok_event(struct uwb_rc *rc, struct uwb_rceb *rceb, size
struct device *dev = &rc->uwb_dev.dev;
struct uwb_rc_neh *neh;
struct uwb_rceb *notif;
+ unsigned long flags;
if (rceb->bEventContext == 0) {
notif = kmalloc(size, GFP_ATOMIC);
@@ -421,7 +423,11 @@ static void uwb_rc_neh_grok_event(struct uwb_rc *rc, struct uwb_rceb *rceb, size
} else {
neh = uwb_rc_neh_lookup(rc, rceb);
if (neh) {
- del_timer_sync(&neh->timer);
+ spin_lock_irqsave(&rc->neh_lock, flags);
+ /* to guard against a timeout */
+ neh->completed = 1;
+ del_timer(&neh->timer);
+ spin_unlock_irqrestore(&rc->neh_lock, flags);
uwb_rc_neh_cb(neh, rceb, size);
} else
dev_warn(dev, "event 0x%02x/%04x/%02x (%zu bytes): nobody cared\n",
@@ -567,6 +573,10 @@ static void uwb_rc_neh_timer(unsigned long arg)
unsigned long flags;
spin_lock_irqsave(&rc->neh_lock, flags);
+ if (neh->completed) {
+ spin_unlock_irqrestore(&rc->neh_lock, flags);
+ return;
+ }
if (neh->context)
__uwb_rc_neh_rm(rc, neh);
else
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c
index 4484c721f0f9..c2ceae4bb6ca 100644
--- a/drivers/video/atmel_lcdfb.c
+++ b/drivers/video/atmel_lcdfb.c
@@ -1085,7 +1085,7 @@ static int atmel_lcdfb_suspend(struct platform_device *pdev, pm_message_t mesg)
*/
lcdc_writel(sinfo, ATMEL_LCDC_IDR, ~0UL);
- sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_VAL);
+ sinfo->saved_lcdcon = lcdc_readl(sinfo, ATMEL_LCDC_CONTRAST_CTR);
lcdc_writel(sinfo, ATMEL_LCDC_CONTRAST_CTR, 0);
if (sinfo->atmel_lcdfb_power_control)
sinfo->atmel_lcdfb_power_control(0);
diff --git a/drivers/video/backlight/tosa_lcd.c b/drivers/video/backlight/tosa_lcd.c
index 772f6015219a..6f54f7436a97 100644
--- a/drivers/video/backlight/tosa_lcd.c
+++ b/drivers/video/backlight/tosa_lcd.c
@@ -271,7 +271,7 @@ static int tosa_lcd_resume(struct spi_device *spi)
}
#else
#define tosa_lcd_suspend NULL
-#define tosa_lcd_reume NULL
+#define tosa_lcd_resume NULL
#endif
static struct spi_driver tosa_lcd_driver = {
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index ad936295d8f4..7a41220aebdd 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1651,6 +1651,7 @@ static int do_unregister_framebuffer(struct fb_info *fb_info)
if (ret)
return -EINVAL;
+ unlink_framebuffer(fb_info);
if (fb_info->pixmap.addr &&
(fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
kfree(fb_info->pixmap.addr);
@@ -1658,7 +1659,6 @@ static int do_unregister_framebuffer(struct fb_info *fb_info)
registered_fb[i] = NULL;
num_registered_fb--;
fb_cleanup_device(fb_info);
- device_destroy(fb_class, MKDEV(FB_MAJOR, i));
event.info = fb_info;
fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
@@ -1667,6 +1667,22 @@ static int do_unregister_framebuffer(struct fb_info *fb_info)
return 0;
}
+int unlink_framebuffer(struct fb_info *fb_info)
+{
+ int i;
+
+ i = fb_info->node;
+ if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
+ return -EINVAL;
+
+ if (fb_info->dev) {
+ device_destroy(fb_class, MKDEV(FB_MAJOR, i));
+ fb_info->dev = NULL;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(unlink_framebuffer);
+
void remove_conflicting_framebuffers(struct apertures_struct *a,
const char *name, bool primary)
{
diff --git a/drivers/video/mxc/mxc_edid.c b/drivers/video/mxc/mxc_edid.c
index f86313df7dea..6f36bd47c7ec 100644
--- a/drivers/video/mxc/mxc_edid.c
+++ b/drivers/video/mxc/mxc_edid.c
@@ -281,35 +281,169 @@ int mxc_edid_parse_ext_blk(unsigned char *edid,
{
unsigned char IEEE_reg_iden[3];
unsigned char deep_color;
+ unsigned char latency_present;
+ unsigned char I_latency_present;
+ unsigned char hdmi_video_present;
+ unsigned char hdmi_3d_present;
+ unsigned char hdmi_3d_multi_present;
+ unsigned char hdmi_vic_len;
+ unsigned char hdmi_3d_len;
+ unsigned char index_inc = 0;
+ unsigned char vsd_end;
+
+ vsd_end = index + blklen;
+
IEEE_reg_iden[0] = edid[index+1];
IEEE_reg_iden[1] = edid[index+2];
IEEE_reg_iden[2] = edid[index+3];
- deep_color = edid[index+6];
+ cfg->physical_address[0] = (edid[index+4] & 0xf0) >> 4;
+ cfg->physical_address[1] = (edid[index+4] & 0x0f);
+ cfg->physical_address[2] = (edid[index+5] & 0xf0) >> 4;
+ cfg->physical_address[3] = (edid[index+5] & 0x0f);
if ((IEEE_reg_iden[0] == 0x03) &&
(IEEE_reg_iden[1] == 0x0c) &&
(IEEE_reg_iden[2] == 0x00))
cfg->hdmi_cap = 1;
- if (deep_color & 0x40)
- cfg->vsd_dc_48bit = true;
- if (deep_color & 0x20)
- cfg->vsd_dc_36bit = true;
- if (deep_color & 0x10)
- cfg->vsd_dc_30bit = true;
- if (deep_color & 0x08)
- cfg->vsd_dc_y444 = true;
- if (deep_color & 0x01)
- cfg->vsd_dvi_dual = true;
+ if (blklen > 5) {
+ deep_color = edid[index+6];
+ if (deep_color & 0x80)
+ cfg->vsd_support_ai = true;
+ if (deep_color & 0x40)
+ cfg->vsd_dc_48bit = true;
+ if (deep_color & 0x20)
+ cfg->vsd_dc_36bit = true;
+ if (deep_color & 0x10)
+ cfg->vsd_dc_30bit = true;
+ if (deep_color & 0x08)
+ cfg->vsd_dc_y444 = true;
+ if (deep_color & 0x01)
+ cfg->vsd_dvi_dual = true;
+ }
DPRINTK("VSD hdmi capability %d\n", cfg->hdmi_cap);
+ DPRINTK("VSD support ai %d\n", cfg->vsd_support_ai);
DPRINTK("VSD support deep color 48bit %d\n", cfg->vsd_dc_48bit);
DPRINTK("VSD support deep color 36bit %d\n", cfg->vsd_dc_36bit);
DPRINTK("VSD support deep color 30bit %d\n", cfg->vsd_dc_30bit);
DPRINTK("VSD support deep color y444 %d\n", cfg->vsd_dc_y444);
DPRINTK("VSD support dvi dual %d\n", cfg->vsd_dvi_dual);
- index += blklen;
+ if (blklen > 6)
+ cfg->vsd_max_tmdsclk_rate = edid[index+7] * 5;
+ DPRINTK("VSD MAX TMDS CLOCK RATE %d\n", cfg->vsd_max_tmdsclk_rate);
+
+ if (blklen > 7) {
+ latency_present = edid[index+8] >> 7;
+ I_latency_present = (edid[index+8] & 0x40) >> 6;
+ hdmi_video_present = (edid[index+8] & 0x20) >> 5;
+ cfg->vsd_cnc3 = (edid[index+8] & 0x8) >> 3;
+ cfg->vsd_cnc2 = (edid[index+8] & 0x4) >> 2;
+ cfg->vsd_cnc1 = (edid[index+8] & 0x2) >> 1;
+ cfg->vsd_cnc0 = edid[index+8] & 0x1;
+
+ DPRINTK("VSD cnc0 %d\n", cfg->vsd_cnc0);
+ DPRINTK("VSD cnc1 %d\n", cfg->vsd_cnc1);
+ DPRINTK("VSD cnc2 %d\n", cfg->vsd_cnc2);
+ DPRINTK("VSD cnc3 %d\n", cfg->vsd_cnc3);
+ DPRINTK("latency_present %d\n", latency_present);
+ DPRINTK("I_latency_present %d\n", I_latency_present);
+ DPRINTK("hdmi_video_present %d\n", hdmi_video_present);
+
+ } else {
+ index += blklen;
+ break;
+ }
+
+ index += 9;
+
+ /*latency present */
+ if (latency_present) {
+ cfg->vsd_video_latency = edid[index++];
+ cfg->vsd_audio_latency = edid[index++];
+
+ if (I_latency_present) {
+ cfg->vsd_I_video_latency = edid[index++];
+ cfg->vsd_I_audio_latency = edid[index++];
+ } else {
+ cfg->vsd_I_video_latency = cfg->vsd_video_latency;
+ cfg->vsd_I_audio_latency = cfg->vsd_audio_latency;
+ }
+
+ DPRINTK("VSD latency video_latency %d\n", cfg->vsd_video_latency);
+ DPRINTK("VSD latency audio_latency %d\n", cfg->vsd_audio_latency);
+ DPRINTK("VSD latency I_video_latency %d\n", cfg->vsd_I_video_latency);
+ DPRINTK("VSD latency I_audio_latency %d\n", cfg->vsd_I_audio_latency);
+ }
+
+ if (hdmi_video_present) {
+ hdmi_3d_present = edid[index] >> 7;
+ hdmi_3d_multi_present = (edid[index] & 0x60) >> 5;
+ index++;
+ hdmi_vic_len = (edid[index] & 0xe0) >> 5;
+ hdmi_3d_len = edid[index] & 0x1f;
+ index++;
+
+ DPRINTK("hdmi_3d_present %d\n", hdmi_3d_present);
+ DPRINTK("hdmi_3d_multi_present %d\n", hdmi_3d_multi_present);
+ DPRINTK("hdmi_vic_len %d\n", hdmi_vic_len);
+ DPRINTK("hdmi_3d_len %d\n", hdmi_3d_len);
+
+ if (hdmi_vic_len > 0) {
+ for (i = 0; i < hdmi_vic_len; i++) {
+ cfg->hdmi_vic[i] = edid[index++];
+ DPRINTK("HDMI_vic=%d\n", cfg->hdmi_vic[i]);
+ }
+ }
+
+ if (hdmi_3d_len > 0) {
+ if (hdmi_3d_present) {
+ if (hdmi_3d_multi_present == 0x1) {
+ cfg->hdmi_3d_struct_all = (edid[index] << 8) | edid[index+1];
+ index_inc = 2;
+ } else if (hdmi_3d_multi_present == 0x2) {
+ cfg->hdmi_3d_struct_all = (edid[index] << 8) | edid[index+1];
+ cfg->hdmi_3d_mask_all = (edid[index+2] << 8) | edid[index+3];
+ index_inc = 4;
+ } else
+ index_inc = 0;
+ }
+
+ DPRINTK("HDMI 3d struct all =0x%x\n", cfg->hdmi_3d_struct_all);
+ DPRINTK("HDMI 3d mask all =0x%x\n", cfg->hdmi_3d_mask_all);
+
+ /* Read 2D vic 3D_struct */
+ if ((hdmi_3d_len - index_inc) > 0) {
+ DPRINTK("Support 3D video format\n");
+ i = 0;
+ while ((hdmi_3d_len - index_inc) > 0) {
+
+ cfg->hdmi_3d_format[i].vic_order_2d = edid[index+index_inc] >> 4;
+ cfg->hdmi_3d_format[i].struct_3d = edid[index+index_inc] & 0x0f;
+ index_inc++;
+
+ if (cfg->hdmi_3d_format[i].struct_3d == 8) {
+ cfg->hdmi_3d_format[i].detail_3d = edid[index+index_inc] >> 4;
+ index_inc++;
+ } else if (cfg->hdmi_3d_format[i].struct_3d > 8) {
+ cfg->hdmi_3d_format[i].detail_3d = 0;
+ index_inc++;
+ }
+
+ DPRINTK("vic_order_2d=%d, 3d_struct=%d, 3d_detail=0x%x\n",
+ cfg->hdmi_3d_format[i].vic_order_2d,
+ cfg->hdmi_3d_format[i].struct_3d,
+ cfg->hdmi_3d_format[i].detail_3d);
+ i++;
+ }
+ }
+ index += index_inc;
+ }
+ }
+
+ index = vsd_end;
+
break;
}
case 0x1: /*Audio data block*/
@@ -363,6 +497,7 @@ int mxc_edid_parse_ext_blk(unsigned char *edid,
case 0x7: /*User extended block*/
default:
/* skip */
+ DPRINTK("Not handle block, tagcode = 0x%x\n", tagcode);
index += blklen;
break;
}
@@ -408,6 +543,7 @@ int mxc_edid_parse_ext_blk(unsigned char *edid,
return 0;
}
+EXPORT_SYMBOL(mxc_edid_parse_ext_blk);
static int mxc_edid_readblk(struct i2c_adapter *adp,
unsigned short addr, unsigned char *edid)
diff --git a/drivers/video/mxc/mxc_spdc_fb.c b/drivers/video/mxc/mxc_spdc_fb.c
index 19cbcb571ce5..0c27a32b690f 100644
--- a/drivers/video/mxc/mxc_spdc_fb.c
+++ b/drivers/video/mxc/mxc_spdc_fb.c
@@ -42,7 +42,7 @@
#define NUM_SCREENS_MIN 2
#define SPDC_DEFAULT_BPP 16
-mxc_spdc_t *g_fb_data;
+mxc_spdc_t *g_spdc_fb_data;
static int mxc_spdc_fb_send_update(struct mxcfb_update_data *upd_data,
struct fb_info *info);
@@ -1477,7 +1477,7 @@ void mxc_spdc_fb_set_waveform_modes(struct mxcfb_waveform_modes *modes,
struct fb_info *info)
{
mxc_spdc_t *fb_data = info ?
- (mxc_spdc_t *)info:g_fb_data;
+ (mxc_spdc_t *)info:g_spdc_fb_data;
mutex_lock(&fb_data->queue_mutex);
@@ -1493,7 +1493,7 @@ EXPORT_SYMBOL(mxc_spdc_fb_set_waveform_modes);
int mxc_spdc_fb_set_temperature(int temperature, struct fb_info *info)
{
mxc_spdc_t *fb_data = info ?
- (mxc_spdc_t *)info:g_fb_data;
+ (mxc_spdc_t *)info:g_spdc_fb_data;
s8 temper = (s8)(temperature & 0xFF) << 1;
mutex_lock(&fb_data->queue_mutex);
@@ -1513,7 +1513,7 @@ EXPORT_SYMBOL(mxc_spdc_fb_set_temperature);
int mxc_spdc_fb_set_auto_update(u32 auto_mode, struct fb_info *info)
{
mxc_spdc_t *fb_data = info ?
- (mxc_spdc_t *)info:g_fb_data;
+ (mxc_spdc_t *)info:g_spdc_fb_data;
dev_dbg(fb_data->dev, "Setting auto update mode to %d\n", auto_mode);
@@ -1533,7 +1533,7 @@ EXPORT_SYMBOL(mxc_spdc_fb_set_auto_update);
int mxc_spdc_fb_set_upd_scheme(u32 upd_scheme, struct fb_info *info)
{
mxc_spdc_t *fb_data = info ?
- (mxc_spdc_t *)info:g_fb_data;
+ (mxc_spdc_t *)info:g_spdc_fb_data;
dev_dbg(fb_data->dev, "Setting optimization level to %d\n", upd_scheme);
@@ -2394,7 +2394,7 @@ int mxc_spdc_fb_send_update(struct mxcfb_update_data *upd_data,
struct fb_info *info)
{
mxc_spdc_t *fb_data = info ?
- (mxc_spdc_t *)info:g_fb_data;
+ (mxc_spdc_t *)info:g_spdc_fb_data;
struct update_data_list *upd_data_list = NULL;
struct mxcfb_rect *screen_upd_region; /* Region on screen to update */
struct update_desc_list *upd_desc;
@@ -2622,7 +2622,7 @@ mxc_spdc_fb_wait_update_complete(struct mxcfb_update_marker_data *marker_data,
struct fb_info *info)
{
mxc_spdc_t *fb_data = info ?
- (mxc_spdc_t *)info:g_fb_data;
+ (mxc_spdc_t *)info:g_spdc_fb_data;
struct update_marker_data *next_marker;
struct update_marker_data *temp;
bool marker_found = false;
@@ -2685,7 +2685,7 @@ int mxc_spdc_fb_set_pwrdown_delay(u32 pwrdown_delay,
struct fb_info *info)
{
mxc_spdc_t *fb_data = info ?
- (mxc_spdc_t *)info:g_fb_data;
+ (mxc_spdc_t *)info:g_spdc_fb_data;
fb_data->pwrdown_delay = pwrdown_delay;
@@ -2696,7 +2696,7 @@ EXPORT_SYMBOL(mxc_spdc_fb_set_pwrdown_delay);
int mxc_spdc_get_pwrdown_delay(struct fb_info *info)
{
mxc_spdc_t *fb_data = info ?
- (mxc_spdc_t *)info:g_fb_data;
+ (mxc_spdc_t *)info:g_spdc_fb_data;
return fb_data->pwrdown_delay;
}
@@ -2912,7 +2912,7 @@ static int mxc_spdc_fb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
mxc_spdc_t *fb_data = info ?
- (mxc_spdc_t *)info:g_fb_data;
+ (mxc_spdc_t *)info:g_spdc_fb_data;
u_int y_bottom;
dev_dbg(info->device, "%s: var->yoffset %d, info->var.yoffset %d\n",
@@ -3980,7 +3980,7 @@ static int __devinit mxc_spdc_fb_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Unable to create file from fb_attrs\n");
/* use for spdc test */
- g_fb_data = fb_data;
+ g_spdc_fb_data = fb_data;
/* hw init */
spdc_fb_dev_init(fb_data);
diff --git a/drivers/video/mxc_hdmi.c b/drivers/video/mxc_hdmi.c
index 11aca480f254..8800b134d837 100644
--- a/drivers/video/mxc_hdmi.c
+++ b/drivers/video/mxc_hdmi.c
@@ -185,7 +185,7 @@ struct i2c_client *hdmi_i2c;
static bool hdmi_inited;
extern const struct fb_videomode mxc_cea_mode[64];
-
+extern void mxc_hdmi_cec_handle(u16 cec_stat);
#ifdef DEBUG
static void dump_fb_videomode(struct fb_videomode *m)
{
@@ -571,9 +571,9 @@ static void hdmi_video_packetize(struct mxc_hdmi *hdmi)
} else
return;
- if (!hdmi->edid_cfg.vsd_dc_48bit && !hdmi->edid_cfg.vsd_dc_36bit &&
- !hdmi->edid_cfg.vsd_dc_30bit && !hdmi->edid_cfg.vsd_dc_y444)
- color_depth = 0;
+ /* HDMI not support deep color,
+ * because IPU MAX support color depth is 24bit */
+ color_depth = 0;
/* set the packetizer registers */
val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
@@ -1043,9 +1043,9 @@ static int hdmi_phy_configure(struct mxc_hdmi *hdmi, unsigned char pRep,
/* RESISTANCE TERM 133Ohm Cfg */
hdmi_phy_i2c_write(hdmi, 0x0005, 0x19); /* TXTERM */
/* PREEMP Cgf 0.00 */
- hdmi_phy_i2c_write(hdmi, 0x8009, 0x09); /* CKSYMTXCTRL */
+ hdmi_phy_i2c_write(hdmi, 0x800d, 0x09); /* CKSYMTXCTRL */
/* TX/CK LVL 10 */
- hdmi_phy_i2c_write(hdmi, 0x0210, 0x0E); /* VLEVCTRL */
+ hdmi_phy_i2c_write(hdmi, 0x01ad, 0x0E); /* VLEVCTRL */
/* REMOVE CLK TERM */
hdmi_phy_i2c_write(hdmi, 0x8000, 0x05); /* CKCALCTRL */
@@ -1753,6 +1753,9 @@ static void hotplug_worker(struct work_struct *work)
sprintf(event_string, "EVENT=plugin");
kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
+#ifdef CONFIG_MXC_HDMI_CEC
+ mxc_hdmi_cec_handle(0x80);
+#endif
} else if (!(phy_int_pol & HDMI_PHY_HPD)) {
/* Plugout event */
@@ -1766,6 +1769,9 @@ static void hotplug_worker(struct work_struct *work)
sprintf(event_string, "EVENT=plugout");
kobject_uevent_env(&hdmi->pdev->dev.kobj, KOBJ_CHANGE, envp);
+#ifdef CONFIG_MXC_HDMI_CEC
+ mxc_hdmi_cec_handle(0x100);
+#endif
} else
dev_dbg(&hdmi->pdev->dev, "EVENT=none?\n");
@@ -1886,7 +1892,12 @@ static void mxc_hdmi_setup(struct mxc_hdmi *hdmi, unsigned long event)
hdmi->hdmi_data.video_mode.mDVI = true;
} else {
dev_dbg(&hdmi->pdev->dev, "CEA mode used vic=%d\n", hdmi->vic);
- hdmi->hdmi_data.video_mode.mDVI = false;
+ if (hdmi->edid_cfg.hdmi_cap)
+ hdmi->hdmi_data.video_mode.mDVI = false;
+ else {
+ dev_dbg(&hdmi->pdev->dev, "CEA mode vic=%d work in DVI\n", hdmi->vic);
+ hdmi->hdmi_data.video_mode.mDVI = true;
+ }
}
if ((hdmi->vic == 6) || (hdmi->vic == 7) ||
@@ -1916,14 +1927,14 @@ static void mxc_hdmi_setup(struct mxc_hdmi *hdmi, unsigned long event)
hdmi->hdmi_data.enc_out_format = RGB;
/*DVI mode not support non-RGB */
- if (!hdmi->hdmi_data.video_mode.mDVI)
- if (hdmi->edid_cfg.hdmi_cap) {
- if (hdmi->edid_cfg.cea_ycbcr444)
- hdmi->hdmi_data.enc_out_format = YCBCR444;
- else if (hdmi->edid_cfg.cea_ycbcr422)
- hdmi->hdmi_data.enc_out_format = YCBCR422_8BITS;
- }
+ if (!hdmi->hdmi_data.video_mode.mDVI) {
+ if (hdmi->edid_cfg.cea_ycbcr444)
+ hdmi->hdmi_data.enc_out_format = YCBCR444;
+ else if (hdmi->edid_cfg.cea_ycbcr422)
+ hdmi->hdmi_data.enc_out_format = YCBCR422_8BITS;
+ }
+ /* IPU not support depth color output */
hdmi->hdmi_data.enc_color_depth = 8;
hdmi->hdmi_data.pix_repet_factor = 0;
hdmi->hdmi_data.hdcp_enable = 0;
diff --git a/drivers/video/offb.c b/drivers/video/offb.c
index cb163a5397be..3251a0236d56 100644
--- a/drivers/video/offb.c
+++ b/drivers/video/offb.c
@@ -100,36 +100,32 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info)
{
struct offb_par *par = (struct offb_par *) info->par;
- int i, depth;
- u32 *pal = info->pseudo_palette;
-
- depth = info->var.bits_per_pixel;
- if (depth == 16)
- depth = (info->var.green.length == 5) ? 15 : 16;
-
- if (regno > 255 ||
- (depth == 16 && regno > 63) ||
- (depth == 15 && regno > 31))
- return 1;
-
- if (regno < 16) {
- switch (depth) {
- case 15:
- pal[regno] = (regno << 10) | (regno << 5) | regno;
- break;
- case 16:
- pal[regno] = (regno << 11) | (regno << 5) | regno;
- break;
- case 24:
- pal[regno] = (regno << 16) | (regno << 8) | regno;
- break;
- case 32:
- i = (regno << 8) | regno;
- pal[regno] = (i << 16) | i;
- break;
+
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+ u32 *pal = info->pseudo_palette;
+ u32 cr = red >> (16 - info->var.red.length);
+ u32 cg = green >> (16 - info->var.green.length);
+ u32 cb = blue >> (16 - info->var.blue.length);
+ u32 value;
+
+ if (regno >= 16)
+ return -EINVAL;
+
+ value = (cr << info->var.red.offset) |
+ (cg << info->var.green.offset) |
+ (cb << info->var.blue.offset);
+ if (info->var.transp.length > 0) {
+ u32 mask = (1 << info->var.transp.length) - 1;
+ mask <<= info->var.transp.offset;
+ value |= mask;
}
+ pal[regno] = value;
+ return 0;
}
+ if (regno > 255)
+ return -EINVAL;
+
red >>= 8;
green >>= 8;
blue >>= 8;
@@ -381,7 +377,7 @@ static void __init offb_init_fb(const char *name, const char *full_name,
int pitch, unsigned long address,
int foreign_endian, struct device_node *dp)
{
- unsigned long res_size = pitch * height * (depth + 7) / 8;
+ unsigned long res_size = pitch * height;
struct offb_par *par = &default_par;
unsigned long res_start = address;
struct fb_fix_screeninfo *fix;
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c
index b0555f4f0a78..fadd6a0836c7 100644
--- a/drivers/video/omap2/dss/hdmi.c
+++ b/drivers/video/omap2/dss/hdmi.c
@@ -29,6 +29,7 @@
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/string.h>
+#include <linux/gpio.h>
#include <video/omapdss.h>
#if defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI) || \
defined(CONFIG_SND_OMAP_SOC_OMAP4_HDMI_MODULE)
@@ -40,6 +41,9 @@
#include "hdmi.h"
#include "dss_features.h"
+#define HDMI_DEFAULT_REGN 15
+#define HDMI_DEFAULT_REGM2 1
+
static struct {
struct mutex lock;
struct omap_display_platform_data *pdata;
@@ -51,6 +55,9 @@ static struct {
u8 edid_set;
bool custom_set;
struct hdmi_config cfg;
+
+ int hpd_gpio;
+ bool phy_tx_enabled;
} hdmi;
/*
@@ -275,6 +282,47 @@ static int hdmi_pll_reset(void)
return 0;
}
+static int hdmi_check_hpd_state(void)
+{
+ unsigned long flags;
+ bool hpd;
+ int r;
+ /* this should be in ti_hdmi_4xxx_ip private data */
+ static DEFINE_SPINLOCK(phy_tx_lock);
+
+ spin_lock_irqsave(&phy_tx_lock, flags);
+
+ hpd = gpio_get_value(hdmi.hpd_gpio);
+
+ if (hpd == hdmi.phy_tx_enabled) {
+ spin_unlock_irqrestore(&phy_tx_lock, flags);
+ return 0;
+ }
+
+ if (hpd)
+ r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_TXON);
+ else
+ r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_LDOON);
+
+ if (r) {
+ DSSERR("Failed to %s PHY TX power\n",
+ hpd ? "enable" : "disable");
+ goto err;
+ }
+
+ hdmi.phy_tx_enabled = hpd;
+err:
+ spin_unlock_irqrestore(&phy_tx_lock, flags);
+ return r;
+}
+
+static irqreturn_t hpd_irq_handler(int irq, void *data)
+{
+ hdmi_check_hpd_state();
+
+ return IRQ_HANDLED;
+}
+
static int hdmi_phy_init(void)
{
u16 r = 0;
@@ -283,10 +331,6 @@ static int hdmi_phy_init(void)
if (r)
return r;
- r = hdmi_set_phy_pwr(HDMI_PHYPWRCMD_TXON);
- if (r)
- return r;
-
/*
* Read address 0 in order to get the SCP reset done completed
* Dummy access performed to make sure reset is done
@@ -308,6 +352,23 @@ static int hdmi_phy_init(void)
/* Write to phy address 3 to change the polarity control */
REG_FLD_MOD(HDMI_TXPHY_PAD_CFG_CTRL, 0x1, 27, 27);
+ r = request_threaded_irq(gpio_to_irq(hdmi.hpd_gpio),
+ NULL, hpd_irq_handler,
+ IRQF_DISABLED | IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING, "hpd", NULL);
+ if (r) {
+ DSSERR("HPD IRQ request failed\n");
+ hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF);
+ return r;
+ }
+
+ r = hdmi_check_hpd_state();
+ if (r) {
+ free_irq(gpio_to_irq(hdmi.hpd_gpio), NULL);
+ hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF);
+ return r;
+ }
+
return 0;
}
@@ -358,7 +419,9 @@ static int hdmi_pll_program(struct hdmi_pll_info *fmt)
static void hdmi_phy_off(void)
{
+ free_irq(gpio_to_irq(hdmi.hpd_gpio), NULL);
hdmi_set_phy_pwr(HDMI_PHYPWRCMD_OFF);
+ hdmi.phy_tx_enabled = false;
}
static int hdmi_core_ddc_edid(u8 *pedid, int ext)
@@ -1069,7 +1132,11 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
* Input clock is predivided by N + 1
* out put of which is reference clk
*/
- pi->regn = dssdev->clocks.hdmi.regn;
+ if (dssdev->clocks.hdmi.regn == 0)
+ pi->regn = HDMI_DEFAULT_REGN;
+ else
+ pi->regn = dssdev->clocks.hdmi.regn;
+
refclk = clkin / (pi->regn + 1);
/*
@@ -1077,7 +1144,11 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
* Multiplying by 100 to avoid fractional part removal
*/
pi->regm = (phy * 100 / (refclk)) / 100;
- pi->regm2 = dssdev->clocks.hdmi.regm2;
+
+ if (dssdev->clocks.hdmi.regm2 == 0)
+ pi->regm2 = HDMI_DEFAULT_REGM2;
+ else
+ pi->regm2 = dssdev->clocks.hdmi.regm2;
/*
* fractional multiplier is remainder of the difference between
@@ -1225,12 +1296,15 @@ void omapdss_hdmi_display_set_timing(struct omap_dss_device *dssdev)
int omapdss_hdmi_display_enable(struct omap_dss_device *dssdev)
{
+ struct omap_dss_hdmi_data *priv = dssdev->data;
int r = 0;
DSSDBG("ENTER hdmi_display_enable\n");
mutex_lock(&hdmi.lock);
+ hdmi.hpd_gpio = priv->hpd_gpio;
+
r = omap_dss_start_device(dssdev);
if (r) {
DSSERR("failed to start device\n");
diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c
index 816a4fda04f5..415e9b2f43de 100644
--- a/drivers/video/udlfb.c
+++ b/drivers/video/udlfb.c
@@ -1666,7 +1666,7 @@ static void dlfb_usb_disconnect(struct usb_interface *interface)
for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
device_remove_file(info->dev, &fb_device_attrs[i]);
device_remove_bin_file(info->dev, &edid_attr);
-
+ unlink_framebuffer(info);
usb_set_intfdata(interface, NULL);
/* if clients still have us open, will be freed on last close */
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c
index 7f8472cc993b..881358859d83 100644
--- a/drivers/video/uvesafb.c
+++ b/drivers/video/uvesafb.c
@@ -815,8 +815,15 @@ static int __devinit uvesafb_vbe_init(struct fb_info *info)
par->pmi_setpal = pmi_setpal;
par->ypan = ypan;
- if (par->pmi_setpal || par->ypan)
- uvesafb_vbe_getpmi(task, par);
+ if (par->pmi_setpal || par->ypan) {
+ if (__supported_pte_mask & _PAGE_NX) {
+ par->pmi_setpal = par->ypan = 0;
+ printk(KERN_WARNING "uvesafb: NX protection is actively."
+ "We have better not to use the PMI.\n");
+ } else {
+ uvesafb_vbe_getpmi(task, par);
+ }
+ }
#else
/* The protected mode interface is not available on non-x86. */
par->pmi_setpal = par->ypan = 0;
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index 8cb26855bfed..d4ab797cf756 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -216,6 +216,7 @@ static int __devinit cru_detect(unsigned long map_entry,
cmn_regs.u1.reax = CRU_BIOS_SIGNATURE_VALUE;
+ set_memory_x((unsigned long)bios32_map, 2);
asminline_call(&cmn_regs, bios32_entrypoint);
if (cmn_regs.u1.ral != 0) {
@@ -233,8 +234,11 @@ static int __devinit cru_detect(unsigned long map_entry,
if ((physical_bios_base + physical_bios_offset)) {
cru_rom_addr =
ioremap(cru_physical_address, cru_length);
- if (cru_rom_addr)
+ if (cru_rom_addr) {
+ set_memory_x((unsigned long)cru_rom_addr & PAGE_MASK,
+ (cru_length + PAGE_SIZE - 1) >> PAGE_SHIFT);
retval = 0;
+ }
}
printk(KERN_DEBUG "hpwdt: CRU Base Address: 0x%lx\n",
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index ad2a40fefc6c..e4de28b42848 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -33,7 +33,9 @@
#include <linux/uaccess.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
+#include <linux/interrupt.h>
#include <mach/hardware.h>
+#include <mach/irqs.h>
#define DRIVER_NAME "imx2-wdt"
@@ -43,14 +45,21 @@
#define IMX2_WDT_WCR_WDE (1 << 2) /* -> Watchdog Enable */
#define IMX2_WDT_WCR_WDZST (1 << 0) /* -> Watchdog timer Suspend */
+
#define IMX2_WDT_WSR 0x02 /* Service Register */
#define IMX2_WDT_SEQ1 0x5555 /* -> service sequence 1 */
#define IMX2_WDT_SEQ2 0xAAAA /* -> service sequence 2 */
+#define IMX2_WDT_WICR 0x06 /*Interrupt Control Register*/
+#define IMX2_WDT_WICR_WIE (1 << 15) /* -> Interrupt Enable */
+#define IMX2_WDT_WICR_WTIS (1 << 14) /* -> Interrupt Status */
+#define IMX2_WDT_WICR_WICT (0xFF << 0) /* -> Watchdog Interrupt Timeout Field */
+
#define IMX2_WDT_MAX_TIME 128
#define IMX2_WDT_DEFAULT_TIME 60 /* in seconds */
#define WDOG_SEC_TO_COUNT(s) ((s * 2 - 1) << 8)
+#define WDOG_SEC_TO_PRECOUNT(s) (s * 2) /* set WDOG pre timeout count*/
#define IMX2_WDT_STATUS_OPEN 0
#define IMX2_WDT_STATUS_STARTED 1
@@ -60,6 +69,7 @@ static struct {
struct clk *clk;
void __iomem *base;
unsigned timeout;
+ unsigned pretimeout;
unsigned long status;
struct timer_list timer; /* Pings the watchdog when closed */
} imx2_wdt;
@@ -79,7 +89,7 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default="
static const struct watchdog_info imx2_wdt_info = {
.identity = "imx2+ watchdog",
- .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+ .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_PRETIMEOUT,
};
static inline void imx2_wdt_setup(void)
@@ -148,6 +158,38 @@ static void imx2_wdt_set_timeout(int new_timeout)
__raw_writew(val, imx2_wdt.base + IMX2_WDT_WCR);
}
+
+static int imx2_wdt_check_pretimeout_set(void)
+{
+ u16 val = __raw_readw(imx2_wdt.base + IMX2_WDT_WICR);
+ return (val & IMX2_WDT_WICR_WIE) ? 1 : 0;
+}
+
+static void imx2_wdt_set_pretimeout(int new_timeout)
+{
+ u16 val = __raw_readw(imx2_wdt.base + IMX2_WDT_WICR);
+
+ /* set the new pre-timeout value in the WSR */
+ val &= ~IMX2_WDT_WICR_WICT;
+ val |= WDOG_SEC_TO_PRECOUNT(new_timeout);
+
+ if (!imx2_wdt_check_pretimeout_set())
+ val |= IMX2_WDT_WICR_WIE; /*enable*/
+ __raw_writew(val, imx2_wdt.base + IMX2_WDT_WICR);
+}
+
+static irqreturn_t imx2_wdt_isr(int irq, void *dev_id)
+{
+ u16 val = __raw_readw(imx2_wdt.base + IMX2_WDT_WICR);
+ if (val & IMX2_WDT_WICR_WTIS) {
+ /*clear interrupt status bit*/
+ __raw_writew(val, imx2_wdt.base + IMX2_WDT_WICR);
+ printk(KERN_INFO "watchdog pre-timeout:%d, %d Seconds remained\n", \
+ imx2_wdt.pretimeout, imx2_wdt.timeout-imx2_wdt.pretimeout);
+ }
+ return IRQ_HANDLED;
+}
+
static int imx2_wdt_open(struct inode *inode, struct file *file)
{
if (test_and_set_bit(IMX2_WDT_STATUS_OPEN, &imx2_wdt.status))
@@ -205,6 +247,17 @@ static long imx2_wdt_ioctl(struct file *file, unsigned int cmd,
case WDIOC_GETTIMEOUT:
return put_user(imx2_wdt.timeout, p);
+ case WDIOC_SETPRETIMEOUT:
+ if (get_user(new_value, p))
+ return -EFAULT;
+ if ((new_value < 0) || (new_value >= imx2_wdt.timeout))
+ return -EINVAL;
+ imx2_wdt_set_pretimeout(new_value);
+ imx2_wdt.pretimeout = new_value;
+
+ case WDIOC_GETPRETIMEOUT:
+ return put_user(imx2_wdt.pretimeout, p);
+
default:
return -ENOTTY;
}
@@ -251,6 +304,7 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
{
int ret;
int res_size;
+ int irq;
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -259,6 +313,12 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
return -ENODEV;
}
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "can't get device irq number\n");
+ return -ENODEV;
+ }
+
res_size = resource_size(res);
if (!devm_request_mem_region(&pdev->dev, res->start, res_size,
res->name)) {
@@ -279,6 +339,12 @@ static int __init imx2_wdt_probe(struct platform_device *pdev)
return PTR_ERR(imx2_wdt.clk);
}
+ ret = request_irq(irq, imx2_wdt_isr, 0, pdev->name, NULL);
+ if (ret) {
+ dev_err(&pdev->dev, "can't claim irq %d\n", irq);
+ goto fail;
+ }
+
imx2_wdt.timeout = clamp_t(unsigned, timeout, 1, IMX2_WDT_MAX_TIME);
if (imx2_wdt.timeout != timeout)
dev_warn(&pdev->dev, "Initial timeout out of range! "
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index f914b26cf0c2..b4e830eb3f26 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -664,7 +664,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
vma->vm_flags |= VM_RESERVED|VM_DONTEXPAND;
if (use_ptemod)
- vma->vm_flags |= VM_DONTCOPY|VM_PFNMAP;
+ vma->vm_flags |= VM_DONTCOPY;
vma->vm_private_data = map;
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index 84f317e0cc2e..fd60dffeb0fc 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -162,7 +162,7 @@ void __init xen_swiotlb_init(int verbose)
/*
* Get IO TLB memory from any location.
*/
- xen_io_tlb_start = alloc_bootmem(bytes);
+ xen_io_tlb_start = alloc_bootmem_pages(PAGE_ALIGN(bytes));
if (!xen_io_tlb_start)
panic("Cannot allocate SWIOTLB buffer");
diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c
index b6a2690c9d49..560f2176aa6c 100644
--- a/drivers/xen/xenbus/xenbus_probe_frontend.c
+++ b/drivers/xen/xenbus/xenbus_probe_frontend.c
@@ -132,7 +132,7 @@ static int read_backend_details(struct xenbus_device *xendev)
return xenbus_read_otherend_details(xendev, "backend-id", "backend");
}
-static int is_device_connecting(struct device *dev, void *data)
+static int is_device_connecting(struct device *dev, void *data, bool ignore_nonessential)
{
struct xenbus_device *xendev = to_xenbus_device(dev);
struct device_driver *drv = data;
@@ -149,16 +149,41 @@ static int is_device_connecting(struct device *dev, void *data)
if (drv && (dev->driver != drv))
return 0;
+ if (ignore_nonessential) {
+ /* With older QEMU, for PVonHVM guests the guest config files
+ * could contain: vfb = [ 'vnc=1, vnclisten=0.0.0.0']
+ * which is nonsensical as there is no PV FB (there can be
+ * a PVKB) running as HVM guest. */
+
+ if ((strncmp(xendev->nodename, "device/vkbd", 11) == 0))
+ return 0;
+
+ if ((strncmp(xendev->nodename, "device/vfb", 10) == 0))
+ return 0;
+ }
xendrv = to_xenbus_driver(dev->driver);
return (xendev->state < XenbusStateConnected ||
(xendev->state == XenbusStateConnected &&
xendrv->is_ready && !xendrv->is_ready(xendev)));
}
+static int essential_device_connecting(struct device *dev, void *data)
+{
+ return is_device_connecting(dev, data, true /* ignore PV[KBB+FB] */);
+}
+static int non_essential_device_connecting(struct device *dev, void *data)
+{
+ return is_device_connecting(dev, data, false);
+}
-static int exists_connecting_device(struct device_driver *drv)
+static int exists_essential_connecting_device(struct device_driver *drv)
{
return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
- is_device_connecting);
+ essential_device_connecting);
+}
+static int exists_non_essential_connecting_device(struct device_driver *drv)
+{
+ return bus_for_each_dev(&xenbus_frontend.bus, NULL, drv,
+ non_essential_device_connecting);
}
static int print_device_status(struct device *dev, void *data)
@@ -189,6 +214,23 @@ static int print_device_status(struct device *dev, void *data)
/* We only wait for device setup after most initcalls have run. */
static int ready_to_wait_for_devices;
+static bool wait_loop(unsigned long start, unsigned int max_delay,
+ unsigned int *seconds_waited)
+{
+ if (time_after(jiffies, start + (*seconds_waited+5)*HZ)) {
+ if (!*seconds_waited)
+ printk(KERN_WARNING "XENBUS: Waiting for "
+ "devices to initialise: ");
+ *seconds_waited += 5;
+ printk("%us...", max_delay - *seconds_waited);
+ if (*seconds_waited == max_delay)
+ return true;
+ }
+
+ schedule_timeout_interruptible(HZ/10);
+
+ return false;
+}
/*
* On a 5-minute timeout, wait for all devices currently configured. We need
* to do this to guarantee that the filesystems and / or network devices
@@ -212,19 +254,14 @@ static void wait_for_devices(struct xenbus_driver *xendrv)
if (!ready_to_wait_for_devices || !xen_domain())
return;
- while (exists_connecting_device(drv)) {
- if (time_after(jiffies, start + (seconds_waited+5)*HZ)) {
- if (!seconds_waited)
- printk(KERN_WARNING "XENBUS: Waiting for "
- "devices to initialise: ");
- seconds_waited += 5;
- printk("%us...", 300 - seconds_waited);
- if (seconds_waited == 300)
- break;
- }
-
- schedule_timeout_interruptible(HZ/10);
- }
+ while (exists_non_essential_connecting_device(drv))
+ if (wait_loop(start, 30, &seconds_waited))
+ break;
+
+ /* Skips PVKB and PVFB check.*/
+ while (exists_essential_connecting_device(drv))
+ if (wait_loop(start, 270, &seconds_waited))
+ break;
if (seconds_waited)
printk("\n");
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c
index 5534690075af..daee5db4bef8 100644
--- a/drivers/xen/xenbus/xenbus_xs.c
+++ b/drivers/xen/xenbus/xenbus_xs.c
@@ -801,6 +801,12 @@ static int process_msg(void)
goto out;
}
+ if (msg->hdr.len > XENSTORE_PAYLOAD_MAX) {
+ kfree(msg);
+ err = -EINVAL;
+ goto out;
+ }
+
body = kmalloc(msg->hdr.len + 1, GFP_NOIO | __GFP_HIGH);
if (body == NULL) {
kfree(msg);
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index 5a9b6843bac1..1f3624d3b24f 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -109,7 +109,7 @@ struct afs_call {
unsigned reply_size; /* current size of reply */
unsigned first_offset; /* offset into mapping[first] */
unsigned last_to; /* amount of mapping[last] */
- unsigned short offset; /* offset into received data store */
+ unsigned offset; /* offset into received data store */
unsigned char unmarshall; /* unmarshalling phase */
bool incoming; /* T if incoming call */
bool send_pages; /* T if data from mapping should be sent */
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
index e45a323aebb4..8ad8c2a0703a 100644
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -314,6 +314,7 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
struct msghdr msg;
struct kvec iov[1];
int ret;
+ struct sk_buff *skb;
_enter("%x,{%d},", addr->s_addr, ntohs(call->port));
@@ -380,6 +381,8 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
error_do_abort:
rxrpc_kernel_abort_call(rxcall, RX_USER_ABORT);
+ while ((skb = skb_dequeue(&call->rx_queue)))
+ afs_free_skb(skb);
rxrpc_kernel_end_call(rxcall);
call->rxcall = NULL;
error_kill_call:
diff --git a/fs/aio.c b/fs/aio.c
index e29ec485af25..278ed7dc71bb 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -228,12 +228,6 @@ static void __put_ioctx(struct kioctx *ctx)
call_rcu(&ctx->rcu_head, ctx_rcu_free);
}
-static inline void get_ioctx(struct kioctx *kioctx)
-{
- BUG_ON(atomic_read(&kioctx->users) <= 0);
- atomic_inc(&kioctx->users);
-}
-
static inline int try_get_ioctx(struct kioctx *kioctx)
{
return atomic_inc_not_zero(&kioctx->users);
@@ -273,7 +267,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
mm = ctx->mm = current->mm;
atomic_inc(&mm->mm_count);
- atomic_set(&ctx->users, 1);
+ atomic_set(&ctx->users, 2);
spin_lock_init(&ctx->ctx_lock);
spin_lock_init(&ctx->ring_info.ring_lock);
init_waitqueue_head(&ctx->wait);
@@ -527,11 +521,16 @@ static void aio_fput_routine(struct work_struct *data)
fput(req->ki_filp);
/* Link the iocb into the context's free list */
+ rcu_read_lock();
spin_lock_irq(&ctx->ctx_lock);
really_put_req(ctx, req);
+ /*
+ * at that point ctx might've been killed, but actual
+ * freeing is RCU'd
+ */
spin_unlock_irq(&ctx->ctx_lock);
+ rcu_read_unlock();
- put_ioctx(ctx);
spin_lock_irq(&fput_lock);
}
spin_unlock_irq(&fput_lock);
@@ -562,7 +561,6 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
* this function will be executed w/out any aio kthread wakeup.
*/
if (unlikely(!fput_atomic(req->ki_filp))) {
- get_ioctx(ctx);
spin_lock(&fput_lock);
list_add(&req->ki_list, &fput_head);
spin_unlock(&fput_lock);
@@ -1256,10 +1254,10 @@ SYSCALL_DEFINE2(io_setup, unsigned, nr_events, aio_context_t __user *, ctxp)
ret = PTR_ERR(ioctx);
if (!IS_ERR(ioctx)) {
ret = put_user(ioctx->user_id, ctxp);
- if (!ret)
+ if (!ret) {
+ put_ioctx(ioctx);
return 0;
-
- get_ioctx(ioctx); /* io_destroy() expects us to hold a ref */
+ }
io_destroy(ioctx);
}
@@ -1397,6 +1395,10 @@ static ssize_t aio_setup_vectored_rw(int type, struct kiocb *kiocb, bool compat)
if (ret < 0)
goto out;
+ ret = rw_verify_area(type, kiocb->ki_filp, &kiocb->ki_pos, ret);
+ if (ret < 0)
+ goto out;
+
kiocb->ki_nr_segs = kiocb->ki_nbytes;
kiocb->ki_cur_seg = 0;
/* ki_nbytes/left now reflect bytes instead of segs */
@@ -1408,11 +1410,17 @@ out:
return ret;
}
-static ssize_t aio_setup_single_vector(struct kiocb *kiocb)
+static ssize_t aio_setup_single_vector(int type, struct file * file, struct kiocb *kiocb)
{
+ int bytes;
+
+ bytes = rw_verify_area(type, file, &kiocb->ki_pos, kiocb->ki_left);
+ if (bytes < 0)
+ return bytes;
+
kiocb->ki_iovec = &kiocb->ki_inline_vec;
kiocb->ki_iovec->iov_base = kiocb->ki_buf;
- kiocb->ki_iovec->iov_len = kiocb->ki_left;
+ kiocb->ki_iovec->iov_len = bytes;
kiocb->ki_nr_segs = 1;
kiocb->ki_cur_seg = 0;
return 0;
@@ -1437,10 +1445,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
if (unlikely(!access_ok(VERIFY_WRITE, kiocb->ki_buf,
kiocb->ki_left)))
break;
- ret = security_file_permission(file, MAY_READ);
- if (unlikely(ret))
- break;
- ret = aio_setup_single_vector(kiocb);
+ ret = aio_setup_single_vector(READ, file, kiocb);
if (ret)
break;
ret = -EINVAL;
@@ -1455,10 +1460,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
if (unlikely(!access_ok(VERIFY_READ, kiocb->ki_buf,
kiocb->ki_left)))
break;
- ret = security_file_permission(file, MAY_WRITE);
- if (unlikely(ret))
- break;
- ret = aio_setup_single_vector(kiocb);
+ ret = aio_setup_single_vector(WRITE, file, kiocb);
if (ret)
break;
ret = -EINVAL;
@@ -1469,9 +1471,6 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
ret = -EBADF;
if (unlikely(!(file->f_mode & FMODE_READ)))
break;
- ret = security_file_permission(file, MAY_READ);
- if (unlikely(ret))
- break;
ret = aio_setup_vectored_rw(READ, kiocb, compat);
if (ret)
break;
@@ -1483,9 +1482,6 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
ret = -EBADF;
if (unlikely(!(file->f_mode & FMODE_WRITE)))
break;
- ret = security_file_permission(file, MAY_WRITE);
- if (unlikely(ret))
- break;
ret = aio_setup_vectored_rw(WRITE, kiocb, compat);
if (ret)
break;
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 475f9c597cb7..756d3286bee5 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -278,6 +278,17 @@ int autofs4_fill_super(struct super_block *, void *, int);
struct autofs_info *autofs4_new_ino(struct autofs_sb_info *);
void autofs4_clean_ino(struct autofs_info *);
+static inline int autofs_prepare_pipe(struct file *pipe)
+{
+ if (!pipe->f_op || !pipe->f_op->write)
+ return -EINVAL;
+ if (!S_ISFIFO(pipe->f_dentry->d_inode->i_mode))
+ return -EINVAL;
+ /* We want a packet pipe */
+ pipe->f_flags |= O_DIRECT;
+ return 0;
+}
+
/* Queue management functions */
int autofs4_wait(struct autofs_sb_info *,struct dentry *, enum autofs_notify);
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c
index 509fe1eb66ae..de542716245e 100644
--- a/fs/autofs4/dev-ioctl.c
+++ b/fs/autofs4/dev-ioctl.c
@@ -376,7 +376,7 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp,
err = -EBADF;
goto out;
}
- if (!pipe->f_op || !pipe->f_op->write) {
+ if (autofs_prepare_pipe(pipe) < 0) {
err = -EPIPE;
fput(pipe);
goto out;
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 180fa2425e49..7c26678e2cac 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -292,7 +292,7 @@ int autofs4_fill_super(struct super_block *s, void *data, int silent)
printk("autofs: could not open pipe file descriptor\n");
goto fail_dput;
}
- if (!pipe->f_op || !pipe->f_op->write)
+ if (autofs_prepare_pipe(pipe) < 0)
goto fail_fput;
sbi->pipe = pipe;
sbi->pipefd = pipefd;
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 25435987d6ae..813ea10fdde3 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -90,7 +90,7 @@ static int autofs4_write(struct file *file, const void *addr, int bytes)
return (bytes > 0);
}
-
+
static void autofs4_notify_daemon(struct autofs_sb_info *sbi,
struct autofs_wait_queue *wq,
int type)
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 9ba2ac755a7e..618493e44ae0 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1422,7 +1422,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
for (i = 1; i < view->n; ++i) {
const struct user_regset *regset = &view->regsets[i];
do_thread_regset_writeback(t->task, regset);
- if (regset->core_note_type &&
+ if (regset->core_note_type && regset->get &&
(!regset->active || regset->active(t->task, regset))) {
int ret;
size_t size = regset->n * regset->size;
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 34503ba6c077..a580028e2fb8 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -64,7 +64,7 @@ static void bdev_inode_switch_bdi(struct inode *inode,
spin_unlock(&inode_wb_list_lock);
}
-static sector_t max_block(struct block_device *bdev)
+sector_t blkdev_max_block(struct block_device *bdev)
{
sector_t retval = ~((sector_t)0);
loff_t sz = i_size_read(bdev->bd_inode);
@@ -135,7 +135,7 @@ static int
blkdev_get_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh, int create)
{
- if (iblock >= max_block(I_BDEV(inode))) {
+ if (iblock >= blkdev_max_block(I_BDEV(inode))) {
if (create)
return -EIO;
@@ -157,7 +157,7 @@ static int
blkdev_get_blocks(struct inode *inode, sector_t iblock,
struct buffer_head *bh, int create)
{
- sector_t end_block = max_block(I_BDEV(inode));
+ sector_t end_block = blkdev_max_block(I_BDEV(inode));
unsigned long max_blocks = bh->b_size >> inode->i_blkbits;
if ((iblock + max_blocks) > end_block) {
@@ -1149,8 +1149,12 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
* The latter is necessary to prevent ghost
* partitions on a removed medium.
*/
- if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM))
- rescan_partitions(disk, bdev);
+ if (bdev->bd_invalidated) {
+ if (!ret)
+ rescan_partitions(disk, bdev);
+ else if (ret == -ENOMEDIUM)
+ invalidate_partitions(disk, bdev);
+ }
if (ret)
goto out_clear;
} else {
@@ -1180,8 +1184,12 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
if (bdev->bd_disk->fops->open)
ret = bdev->bd_disk->fops->open(bdev, mode);
/* the same as first opener case, read comment there */
- if (bdev->bd_invalidated && (!ret || ret == -ENOMEDIUM))
- rescan_partitions(bdev->bd_disk, bdev);
+ if (bdev->bd_invalidated) {
+ if (!ret)
+ rescan_partitions(bdev->bd_disk, bdev);
+ else if (ret == -ENOMEDIUM)
+ invalidate_partitions(bdev->bd_disk, bdev);
+ }
if (ret)
goto out_unlock_bdev;
}
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 3b859a3e6a0e..66179bcb16f6 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1972,7 +1972,7 @@ BTRFS_SETGET_STACK_FUNCS(root_last_snapshot, struct btrfs_root_item,
static inline bool btrfs_root_readonly(struct btrfs_root *root)
{
- return root->root_item.flags & BTRFS_ROOT_SUBVOL_RDONLY;
+ return (root->root_item.flags & cpu_to_le64(BTRFS_ROOT_SUBVOL_RDONLY)) != 0;
}
/* struct btrfs_super_block */
diff --git a/fs/buffer.c b/fs/buffer.c
index 1a80b048ade8..330cbce11413 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -968,6 +968,7 @@ init_page_buffers(struct page *page, struct block_device *bdev,
struct buffer_head *head = page_buffers(page);
struct buffer_head *bh = head;
int uptodate = PageUptodate(page);
+ sector_t end_block = blkdev_max_block(I_BDEV(bdev->bd_inode));
do {
if (!buffer_mapped(bh)) {
@@ -976,7 +977,8 @@ init_page_buffers(struct page *page, struct block_device *bdev,
bh->b_blocknr = block;
if (uptodate)
set_buffer_uptodate(bh);
- set_buffer_mapped(bh);
+ if (block < end_block)
+ set_buffer_mapped(bh);
}
block++;
bh = bh->b_this_page;
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 6255fa812c7a..7cb9dd225318 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -43,6 +43,7 @@
#define CIFS_MIN_RCV_POOL 4
+#define MAX_REOPEN_ATT 5 /* these many maximum attempts to reopen a file */
/*
* default attribute cache timeout (jiffies)
*/
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index cb85825c741c..b7758094770c 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3004,7 +3004,7 @@ cifs_get_volume_info(char *mount_data, const char *devname)
int
cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
{
- int rc = 0;
+ int rc;
int xid;
struct cifs_ses *pSesInfo;
struct cifs_tcon *tcon;
@@ -3033,6 +3033,7 @@ try_mount_again:
FreeXid(xid);
}
#endif
+ rc = 0;
tcon = NULL;
pSesInfo = NULL;
srvTcp = NULL;
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 16cdd6da227a..ed5c07b0cdb1 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -583,10 +583,26 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
* If either that or op not supported returned, follow
* the normal lookup.
*/
- if ((rc == 0) || (rc == -ENOENT))
+ switch (rc) {
+ case 0:
+ /*
+ * The server may allow us to open things like
+ * FIFOs, but the client isn't set up to deal
+ * with that. If it's not a regular file, just
+ * close it and proceed as if it were a normal
+ * lookup.
+ */
+ if (newInode && !S_ISREG(newInode->i_mode)) {
+ CIFSSMBClose(xid, pTcon, fileHandle);
+ break;
+ }
+ case -ENOENT:
posix_open = true;
- else if ((rc == -EINVAL) || (rc != -EOPNOTSUPP))
+ case -EOPNOTSUPP:
+ break;
+ default:
pTcon->broken_posix_open = true;
+ }
}
if (!posix_open)
rc = cifs_get_inode_info_unix(&newInode, full_path,
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index a9b4a24f2a16..9040cb0695cd 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -973,10 +973,11 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
bool fsuid_only)
{
- struct cifsFileInfo *open_file;
+ struct cifsFileInfo *open_file, *inv_file = NULL;
struct cifs_sb_info *cifs_sb;
bool any_available = false;
int rc;
+ unsigned int refind = 0;
/* Having a null inode here (because mapping->host was set to zero by
the VFS or MM) should not happen but we had reports of on oops (due to
@@ -996,40 +997,25 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
spin_lock(&cifs_file_list_lock);
refind_writable:
+ if (refind > MAX_REOPEN_ATT) {
+ spin_unlock(&cifs_file_list_lock);
+ return NULL;
+ }
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
if (!any_available && open_file->pid != current->tgid)
continue;
if (fsuid_only && open_file->uid != current_fsuid())
continue;
if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
- cifsFileInfo_get(open_file);
-
if (!open_file->invalidHandle) {
/* found a good writable file */
+ cifsFileInfo_get(open_file);
spin_unlock(&cifs_file_list_lock);
return open_file;
+ } else {
+ if (!inv_file)
+ inv_file = open_file;
}
-
- spin_unlock(&cifs_file_list_lock);
-
- /* Had to unlock since following call can block */
- rc = cifs_reopen_file(open_file, false);
- if (!rc)
- return open_file;
-
- /* if it fails, try another handle if possible */
- cFYI(1, "wp failed on reopen file");
- cifsFileInfo_put(open_file);
-
- spin_lock(&cifs_file_list_lock);
-
- /* else we simply continue to the next entry. Thus
- we do not loop on reopen errors. If we
- can not reopen the file, for example if we
- reconnected to a server with another client
- racing to delete or lock the file we would not
- make progress if we restarted before the beginning
- of the loop here. */
}
}
/* couldn't find useable FH with same pid, try any available */
@@ -1037,7 +1023,30 @@ refind_writable:
any_available = true;
goto refind_writable;
}
+
+ if (inv_file) {
+ any_available = false;
+ cifsFileInfo_get(inv_file);
+ }
+
spin_unlock(&cifs_file_list_lock);
+
+ if (inv_file) {
+ rc = cifs_reopen_file(inv_file, false);
+ if (!rc)
+ return inv_file;
+ else {
+ spin_lock(&cifs_file_list_lock);
+ list_move_tail(&inv_file->flist,
+ &cifs_inode->openFileList);
+ spin_unlock(&cifs_file_list_lock);
+ cifsFileInfo_put(inv_file);
+ spin_lock(&cifs_file_list_lock);
+ ++refind;
+ goto refind_writable;
+ }
+ }
+
return NULL;
}
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index d3e619692ee0..0cfae19129bd 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -244,16 +244,15 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses,
/* copy user */
/* BB what about null user mounts - check that we do this BB */
/* copy user */
- if (ses->user_name != NULL)
+ if (ses->user_name != NULL) {
strncpy(bcc_ptr, ses->user_name, MAX_USERNAME_SIZE);
+ bcc_ptr += strnlen(ses->user_name, MAX_USERNAME_SIZE);
+ }
/* else null user mount */
-
- bcc_ptr += strnlen(ses->user_name, MAX_USERNAME_SIZE);
*bcc_ptr = 0;
bcc_ptr++; /* account for null termination */
/* copy domain */
-
if (ses->domainName != NULL) {
strncpy(bcc_ptr, ses->domainName, 256);
bcc_ptr += strnlen(ses->domainName, 256);
diff --git a/fs/dcache.c b/fs/dcache.c
index d2f8feb75da1..0b51cfc9291a 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -241,6 +241,7 @@ static void dentry_lru_add(struct dentry *dentry)
static void __dentry_lru_del(struct dentry *dentry)
{
list_del_init(&dentry->d_lru);
+ dentry->d_flags &= ~DCACHE_SHRINK_LIST;
dentry->d_sb->s_nr_dentry_unused--;
dentry_stat.nr_unused--;
}
@@ -753,6 +754,7 @@ relock:
spin_unlock(&dentry->d_lock);
} else {
list_move_tail(&dentry->d_lru, &tmp);
+ dentry->d_flags |= DCACHE_SHRINK_LIST;
spin_unlock(&dentry->d_lock);
if (!--cnt)
break;
@@ -1144,14 +1146,18 @@ resume:
/*
* move only zero ref count dentries to the end
* of the unused list for prune_dcache
+ *
+ * Those which are presently on the shrink list, being processed
+ * by shrink_dentry_list(), shouldn't be moved. Otherwise the
+ * loop in shrink_dcache_parent() might not make any progress
+ * and loop forever.
*/
- if (!dentry->d_count) {
+ if (dentry->d_count) {
+ dentry_lru_del(dentry);
+ } else if (!(dentry->d_flags & DCACHE_SHRINK_LIST)) {
dentry_lru_move_tail(dentry);
found++;
- } else {
- dentry_lru_del(dentry);
}
-
/*
* We can return to the caller if we have found some (this
* ensures forward progress). We'll be coming back to find
@@ -2427,6 +2433,7 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
if (d_ancestor(alias, dentry)) {
/* Check for loops */
actual = ERR_PTR(-ELOOP);
+ spin_unlock(&inode->i_lock);
} else if (IS_ROOT(alias)) {
/* Is this an anonymous mountpoint that we
* could splice into our tree? */
@@ -2436,7 +2443,7 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
goto found;
} else {
/* Nope, but we must(!) avoid directory
- * aliasing */
+ * aliasing. This drops inode->i_lock */
actual = __d_unalias(inode, dentry, alias);
}
write_sequnlock(&rename_lock);
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c
index 7cf5c3e9c17f..c6602d245176 100644
--- a/fs/ecryptfs/crypto.c
+++ b/fs/ecryptfs/crypto.c
@@ -417,17 +417,6 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page,
(unsigned long long)(extent_base + extent_offset), rc);
goto out;
}
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "Encrypting extent "
- "with iv:\n");
- ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes);
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes before "
- "encryption:\n");
- ecryptfs_dump_hex((char *)
- (page_address(page)
- + (extent_offset * crypt_stat->extent_size)),
- 8);
- }
rc = ecryptfs_encrypt_page_offset(crypt_stat, enc_extent_page, 0,
page, (extent_offset
* crypt_stat->extent_size),
@@ -440,14 +429,6 @@ static int ecryptfs_encrypt_extent(struct page *enc_extent_page,
goto out;
}
rc = 0;
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "Encrypt extent [0x%.16llx]; "
- "rc = [%d]\n",
- (unsigned long long)(extent_base + extent_offset), rc);
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes after "
- "encryption:\n");
- ecryptfs_dump_hex((char *)(page_address(enc_extent_page)), 8);
- }
out:
return rc;
}
@@ -543,17 +524,6 @@ static int ecryptfs_decrypt_extent(struct page *page,
(unsigned long long)(extent_base + extent_offset), rc);
goto out;
}
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "Decrypting extent "
- "with iv:\n");
- ecryptfs_dump_hex(extent_iv, crypt_stat->iv_bytes);
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes before "
- "decryption:\n");
- ecryptfs_dump_hex((char *)
- (page_address(enc_extent_page)
- + (extent_offset * crypt_stat->extent_size)),
- 8);
- }
rc = ecryptfs_decrypt_page_offset(crypt_stat, page,
(extent_offset
* crypt_stat->extent_size),
@@ -567,16 +537,6 @@ static int ecryptfs_decrypt_extent(struct page *page,
goto out;
}
rc = 0;
- if (unlikely(ecryptfs_verbosity > 0)) {
- ecryptfs_printk(KERN_DEBUG, "Decrypt extent [0x%.16llx]; "
- "rc = [%d]\n",
- (unsigned long long)(extent_base + extent_offset), rc);
- ecryptfs_printk(KERN_DEBUG, "First 8 bytes after "
- "decryption:\n");
- ecryptfs_dump_hex((char *)(page_address(page)
- + (extent_offset
- * crypt_stat->extent_size)), 8);
- }
out:
return rc;
}
@@ -1618,7 +1578,8 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
rc = ecryptfs_read_xattr_region(page_virt, ecryptfs_inode);
if (rc) {
printk(KERN_DEBUG "Valid eCryptfs headers not found in "
- "file header region or xattr region\n");
+ "file header region or xattr region, inode %lu\n",
+ ecryptfs_inode->i_ino);
rc = -EINVAL;
goto out;
}
@@ -1627,7 +1588,8 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
ECRYPTFS_DONT_VALIDATE_HEADER_SIZE);
if (rc) {
printk(KERN_DEBUG "Valid eCryptfs headers not found in "
- "file xattr region either\n");
+ "file xattr region either, inode %lu\n",
+ ecryptfs_inode->i_ino);
rc = -EINVAL;
}
if (crypt_stat->mount_crypt_stat->flags
@@ -1638,7 +1600,8 @@ int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry)
"crypto metadata only in the extended attribute "
"region, but eCryptfs was mounted without "
"xattr support enabled. eCryptfs will not treat "
- "this like an encrypted file.\n");
+ "this like an encrypted file, inode %lu\n",
+ ecryptfs_inode->i_ino);
rc = -EINVAL;
}
}
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
index 4a4fad7fb851..2717329386d8 100644
--- a/fs/ecryptfs/inode.c
+++ b/fs/ecryptfs/inode.c
@@ -854,18 +854,6 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
size_t num_zeros = (PAGE_CACHE_SIZE
- (ia->ia_size & ~PAGE_CACHE_MASK));
-
- /*
- * XXX(truncate) this should really happen at the begginning
- * of ->setattr. But the code is too messy to that as part
- * of a larger patch. ecryptfs is also totally missing out
- * on the inode_change_ok check at the beginning of
- * ->setattr while would include this.
- */
- rc = inode_newsize_ok(inode, ia->ia_size);
- if (rc)
- goto out;
-
if (!(crypt_stat->flags & ECRYPTFS_ENCRYPTED)) {
truncate_setsize(inode, ia->ia_size);
lower_ia->ia_size = ia->ia_size;
@@ -915,6 +903,28 @@ out:
return rc;
}
+static int ecryptfs_inode_newsize_ok(struct inode *inode, loff_t offset)
+{
+ struct ecryptfs_crypt_stat *crypt_stat;
+ loff_t lower_oldsize, lower_newsize;
+
+ crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
+ lower_oldsize = upper_size_to_lower_size(crypt_stat,
+ i_size_read(inode));
+ lower_newsize = upper_size_to_lower_size(crypt_stat, offset);
+ if (lower_newsize > lower_oldsize) {
+ /*
+ * The eCryptfs inode and the new *lower* size are mixed here
+ * because we may not have the lower i_mutex held and/or it may
+ * not be appropriate to call inode_newsize_ok() with inodes
+ * from other filesystems.
+ */
+ return inode_newsize_ok(inode, lower_newsize);
+ }
+
+ return 0;
+}
+
/**
* ecryptfs_truncate
* @dentry: The ecryptfs layer dentry
@@ -931,6 +941,10 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length)
struct iattr lower_ia = { .ia_valid = 0 };
int rc;
+ rc = ecryptfs_inode_newsize_ok(dentry->d_inode, new_length);
+ if (rc)
+ return rc;
+
rc = truncate_upper(dentry, &ia, &lower_ia);
if (!rc && lower_ia.ia_valid & ATTR_SIZE) {
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
@@ -1012,6 +1026,16 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
}
}
mutex_unlock(&crypt_stat->cs_mutex);
+
+ rc = inode_change_ok(inode, ia);
+ if (rc)
+ goto out;
+ if (ia->ia_valid & ATTR_SIZE) {
+ rc = ecryptfs_inode_newsize_ok(inode, ia->ia_size);
+ if (rc)
+ goto out;
+ }
+
if (S_ISREG(inode->i_mode)) {
rc = filemap_write_and_wait(inode->i_mapping);
if (rc)
@@ -1095,6 +1119,8 @@ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value,
}
rc = vfs_setxattr(lower_dentry, name, value, size, flags);
+ if (!rc)
+ fsstack_copy_attr_all(dentry->d_inode, lower_dentry->d_inode);
out:
return rc;
}
diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c
index 940a82e63dc3..0dc5a3d554a4 100644
--- a/fs/ecryptfs/miscdev.c
+++ b/fs/ecryptfs/miscdev.c
@@ -409,11 +409,47 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
ssize_t sz = 0;
char *data;
uid_t euid = current_euid();
+ unsigned char packet_size_peek[3];
int rc;
- if (count == 0)
+ if (count == 0) {
goto out;
+ } else if (count == (1 + 4)) {
+ /* Likely a harmless MSG_HELO or MSG_QUIT - no packet length */
+ goto memdup;
+ } else if (count < (1 + 4 + 1)
+ || count > (1 + 4 + 2 + sizeof(struct ecryptfs_message) + 4
+ + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES)) {
+ printk(KERN_WARNING "%s: Acceptable packet size range is "
+ "[%d-%lu], but amount of data written is [%zu].",
+ __func__, (1 + 4 + 1),
+ (1 + 4 + 2 + sizeof(struct ecryptfs_message) + 4
+ + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES), count);
+ return -EINVAL;
+ }
+
+ if (copy_from_user(packet_size_peek, (buf + 1 + 4),
+ sizeof(packet_size_peek))) {
+ printk(KERN_WARNING "%s: Error while inspecting packet size\n",
+ __func__);
+ return -EFAULT;
+ }
+
+ rc = ecryptfs_parse_packet_length(packet_size_peek, &packet_size,
+ &packet_size_length);
+ if (rc) {
+ printk(KERN_WARNING "%s: Error parsing packet length; "
+ "rc = [%d]\n", __func__, rc);
+ return rc;
+ }
+
+ if ((1 + 4 + packet_size_length + packet_size) != count) {
+ printk(KERN_WARNING "%s: Invalid packet size [%zu]\n", __func__,
+ packet_size);
+ return -EINVAL;
+ }
+memdup:
data = memdup_user(buf, count);
if (IS_ERR(data)) {
printk(KERN_ERR "%s: memdup_user returned error [%ld]\n",
@@ -435,23 +471,7 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf,
}
memcpy(&counter_nbo, &data[i], 4);
seq = be32_to_cpu(counter_nbo);
- i += 4;
- rc = ecryptfs_parse_packet_length(&data[i], &packet_size,
- &packet_size_length);
- if (rc) {
- printk(KERN_WARNING "%s: Error parsing packet length; "
- "rc = [%d]\n", __func__, rc);
- goto out_free;
- }
- i += packet_size_length;
- if ((1 + 4 + packet_size_length + packet_size) != count) {
- printk(KERN_WARNING "%s: (1 + packet_size_length([%zd])"
- " + packet_size([%zd]))([%zd]) != "
- "count([%zd]). Invalid packet format.\n",
- __func__, packet_size_length, packet_size,
- (1 + packet_size_length + packet_size), count);
- goto out_free;
- }
+ i += 4 + packet_size_length;
rc = ecryptfs_miscdev_response(&data[i], packet_size,
euid, current_user_ns(),
task_pid(current), seq);
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c
index 3745f7c2b9c2..608c1c3fde1b 100644
--- a/fs/ecryptfs/read_write.c
+++ b/fs/ecryptfs/read_write.c
@@ -130,13 +130,18 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
pgoff_t ecryptfs_page_idx = (pos >> PAGE_CACHE_SHIFT);
size_t start_offset_in_page = (pos & ~PAGE_CACHE_MASK);
size_t num_bytes = (PAGE_CACHE_SIZE - start_offset_in_page);
- size_t total_remaining_bytes = ((offset + size) - pos);
+ loff_t total_remaining_bytes = ((offset + size) - pos);
+
+ if (fatal_signal_pending(current)) {
+ rc = -EINTR;
+ break;
+ }
if (num_bytes > total_remaining_bytes)
num_bytes = total_remaining_bytes;
if (pos < offset) {
/* remaining zeros to write, up to destination offset */
- size_t total_remaining_zeros = (offset - pos);
+ loff_t total_remaining_zeros = (offset - pos);
if (num_bytes > total_remaining_zeros)
num_bytes = total_remaining_zeros;
@@ -193,15 +198,19 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset,
}
pos += num_bytes;
}
- if ((offset + size) > ecryptfs_file_size) {
- i_size_write(ecryptfs_inode, (offset + size));
+ if (pos > ecryptfs_file_size) {
+ i_size_write(ecryptfs_inode, pos);
if (crypt_stat->flags & ECRYPTFS_ENCRYPTED) {
- rc = ecryptfs_write_inode_size_to_metadata(
+ int rc2;
+
+ rc2 = ecryptfs_write_inode_size_to_metadata(
ecryptfs_inode);
- if (rc) {
+ if (rc2) {
printk(KERN_ERR "Problem with "
"ecryptfs_write_inode_size_to_metadata; "
- "rc = [%d]\n", rc);
+ "rc = [%d]\n", rc2);
+ if (!rc)
+ rc = rc2;
goto out;
}
}
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 2acaf60f4e4d..35a852a2682f 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -197,6 +197,12 @@ struct eventpoll {
/* The user that created the eventpoll descriptor */
struct user_struct *user;
+
+ struct file *file;
+
+ /* used to optimize loop detection check */
+ int visited;
+ struct list_head visited_list_link;
};
/* Wait structure used by the poll hooks */
@@ -255,6 +261,15 @@ static struct kmem_cache *epi_cache __read_mostly;
/* Slab cache used to allocate "struct eppoll_entry" */
static struct kmem_cache *pwq_cache __read_mostly;
+/* Visited nodes during ep_loop_check(), so we can unset them when we finish */
+static LIST_HEAD(visited_list);
+
+/*
+ * List of files with newly added links, where we may need to limit the number
+ * of emanating paths. Protected by the epmutex.
+ */
+static LIST_HEAD(tfile_check_list);
+
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
@@ -276,6 +291,12 @@ ctl_table epoll_table[] = {
};
#endif /* CONFIG_SYSCTL */
+static const struct file_operations eventpoll_fops;
+
+static inline int is_file_epoll(struct file *f)
+{
+ return f->f_op == &eventpoll_fops;
+}
/* Setup the structure that is used as key for the RB tree */
static inline void ep_set_ffd(struct epoll_filefd *ffd,
@@ -299,6 +320,11 @@ static inline int ep_is_linked(struct list_head *p)
return !list_empty(p);
}
+static inline struct eppoll_entry *ep_pwq_from_wait(wait_queue_t *p)
+{
+ return container_of(p, struct eppoll_entry, wait);
+}
+
/* Get the "struct epitem" from a wait queue pointer */
static inline struct epitem *ep_item_from_wait(wait_queue_t *p)
{
@@ -446,6 +472,18 @@ static void ep_poll_safewake(wait_queue_head_t *wq)
put_cpu();
}
+static void ep_remove_wait_queue(struct eppoll_entry *pwq)
+{
+ wait_queue_head_t *whead;
+
+ rcu_read_lock();
+ /* If it is cleared by POLLFREE, it should be rcu-safe */
+ whead = rcu_dereference(pwq->whead);
+ if (whead)
+ remove_wait_queue(whead, &pwq->wait);
+ rcu_read_unlock();
+}
+
/*
* This function unregisters poll callbacks from the associated file
* descriptor. Must be called with "mtx" held (or "epmutex" if called from
@@ -460,7 +498,7 @@ static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi)
pwq = list_first_entry(lsthead, struct eppoll_entry, llink);
list_del(&pwq->llink);
- remove_wait_queue(pwq->whead, &pwq->wait);
+ ep_remove_wait_queue(pwq);
kmem_cache_free(pwq_cache, pwq);
}
}
@@ -711,12 +749,6 @@ static const struct file_operations eventpoll_fops = {
.llseek = noop_llseek,
};
-/* Fast test to see if the file is an evenpoll file */
-static inline int is_file_epoll(struct file *f)
-{
- return f->f_op == &eventpoll_fops;
-}
-
/*
* This is called from eventpoll_release() to unlink files from the eventpoll
* interface. We need to have this facility to cleanup correctly files that are
@@ -827,6 +859,17 @@ static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *k
struct epitem *epi = ep_item_from_wait(wait);
struct eventpoll *ep = epi->ep;
+ if ((unsigned long)key & POLLFREE) {
+ ep_pwq_from_wait(wait)->whead = NULL;
+ /*
+ * whead = NULL above can race with ep_remove_wait_queue()
+ * which can do another remove_wait_queue() after us, so we
+ * can't use __remove_wait_queue(). whead->lock is held by
+ * the caller.
+ */
+ list_del_init(&wait->task_list);
+ }
+
spin_lock_irqsave(&ep->lock, flags);
/*
@@ -926,6 +969,103 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi)
rb_insert_color(&epi->rbn, &ep->rbr);
}
+
+
+#define PATH_ARR_SIZE 5
+/*
+ * These are the number paths of length 1 to 5, that we are allowing to emanate
+ * from a single file of interest. For example, we allow 1000 paths of length
+ * 1, to emanate from each file of interest. This essentially represents the
+ * potential wakeup paths, which need to be limited in order to avoid massive
+ * uncontrolled wakeup storms. The common use case should be a single ep which
+ * is connected to n file sources. In this case each file source has 1 path
+ * of length 1. Thus, the numbers below should be more than sufficient. These
+ * path limits are enforced during an EPOLL_CTL_ADD operation, since a modify
+ * and delete can't add additional paths. Protected by the epmutex.
+ */
+static const int path_limits[PATH_ARR_SIZE] = { 1000, 500, 100, 50, 10 };
+static int path_count[PATH_ARR_SIZE];
+
+static int path_count_inc(int nests)
+{
+ /* Allow an arbitrary number of depth 1 paths */
+ if (nests == 0)
+ return 0;
+
+ if (++path_count[nests] > path_limits[nests])
+ return -1;
+ return 0;
+}
+
+static void path_count_init(void)
+{
+ int i;
+
+ for (i = 0; i < PATH_ARR_SIZE; i++)
+ path_count[i] = 0;
+}
+
+static int reverse_path_check_proc(void *priv, void *cookie, int call_nests)
+{
+ int error = 0;
+ struct file *file = priv;
+ struct file *child_file;
+ struct epitem *epi;
+
+ list_for_each_entry(epi, &file->f_ep_links, fllink) {
+ child_file = epi->ep->file;
+ if (is_file_epoll(child_file)) {
+ if (list_empty(&child_file->f_ep_links)) {
+ if (path_count_inc(call_nests)) {
+ error = -1;
+ break;
+ }
+ } else {
+ error = ep_call_nested(&poll_loop_ncalls,
+ EP_MAX_NESTS,
+ reverse_path_check_proc,
+ child_file, child_file,
+ current);
+ }
+ if (error != 0)
+ break;
+ } else {
+ printk(KERN_ERR "reverse_path_check_proc: "
+ "file is not an ep!\n");
+ }
+ }
+ return error;
+}
+
+/**
+ * reverse_path_check - The tfile_check_list is list of file *, which have
+ * links that are proposed to be newly added. We need to
+ * make sure that those added links don't add too many
+ * paths such that we will spend all our time waking up
+ * eventpoll objects.
+ *
+ * Returns: Returns zero if the proposed links don't create too many paths,
+ * -1 otherwise.
+ */
+static int reverse_path_check(void)
+{
+ int length = 0;
+ int error = 0;
+ struct file *current_file;
+
+ /* let's call this for all tfiles */
+ list_for_each_entry(current_file, &tfile_check_list, f_tfile_llink) {
+ length++;
+ path_count_init();
+ error = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
+ reverse_path_check_proc, current_file,
+ current_file, current);
+ if (error)
+ break;
+ }
+ return error;
+}
+
/*
* Must be called with "mtx" held.
*/
@@ -987,6 +1127,11 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
*/
ep_rbtree_insert(ep, epi);
+ /* now check if we've created too many backpaths */
+ error = -EINVAL;
+ if (reverse_path_check())
+ goto error_remove_epi;
+
/* We have to drop the new item inside our item list to keep track of it */
spin_lock_irqsave(&ep->lock, flags);
@@ -1011,6 +1156,14 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
return 0;
+error_remove_epi:
+ spin_lock(&tfile->f_lock);
+ if (ep_is_linked(&epi->fllink))
+ list_del_init(&epi->fllink);
+ spin_unlock(&tfile->f_lock);
+
+ rb_erase(&epi->rbn, &ep->rbr);
+
error_unregister:
ep_unregister_pollwait(ep, epi);
@@ -1275,18 +1428,36 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
int error = 0;
struct file *file = priv;
struct eventpoll *ep = file->private_data;
+ struct eventpoll *ep_tovisit;
struct rb_node *rbp;
struct epitem *epi;
mutex_lock_nested(&ep->mtx, call_nests + 1);
+ ep->visited = 1;
+ list_add(&ep->visited_list_link, &visited_list);
for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) {
epi = rb_entry(rbp, struct epitem, rbn);
if (unlikely(is_file_epoll(epi->ffd.file))) {
+ ep_tovisit = epi->ffd.file->private_data;
+ if (ep_tovisit->visited)
+ continue;
error = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
- ep_loop_check_proc, epi->ffd.file,
- epi->ffd.file->private_data, current);
+ ep_loop_check_proc, epi->ffd.file,
+ ep_tovisit, current);
if (error != 0)
break;
+ } else {
+ /*
+ * If we've reached a file that is not associated with
+ * an ep, then we need to check if the newly added
+ * links are going to add too many wakeup paths. We do
+ * this by adding it to the tfile_check_list, if it's
+ * not already there, and calling reverse_path_check()
+ * during ep_insert().
+ */
+ if (list_empty(&epi->ffd.file->f_tfile_llink))
+ list_add(&epi->ffd.file->f_tfile_llink,
+ &tfile_check_list);
}
}
mutex_unlock(&ep->mtx);
@@ -1307,8 +1478,31 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
*/
static int ep_loop_check(struct eventpoll *ep, struct file *file)
{
- return ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
+ int ret;
+ struct eventpoll *ep_cur, *ep_next;
+
+ ret = ep_call_nested(&poll_loop_ncalls, EP_MAX_NESTS,
ep_loop_check_proc, file, ep, current);
+ /* clear visited list */
+ list_for_each_entry_safe(ep_cur, ep_next, &visited_list,
+ visited_list_link) {
+ ep_cur->visited = 0;
+ list_del(&ep_cur->visited_list_link);
+ }
+ return ret;
+}
+
+static void clear_tfile_check_list(void)
+{
+ struct file *file;
+
+ /* first clear the tfile_check_list */
+ while (!list_empty(&tfile_check_list)) {
+ file = list_first_entry(&tfile_check_list, struct file,
+ f_tfile_llink);
+ list_del_init(&file->f_tfile_llink);
+ }
+ INIT_LIST_HEAD(&tfile_check_list);
}
/*
@@ -1316,8 +1510,9 @@ static int ep_loop_check(struct eventpoll *ep, struct file *file)
*/
SYSCALL_DEFINE1(epoll_create1, int, flags)
{
- int error;
+ int error, fd;
struct eventpoll *ep = NULL;
+ struct file *file;
/* Check the EPOLL_* constant for consistency. */
BUILD_BUG_ON(EPOLL_CLOEXEC != O_CLOEXEC);
@@ -1334,11 +1529,25 @@ SYSCALL_DEFINE1(epoll_create1, int, flags)
* Creates all the items needed to setup an eventpoll file. That is,
* a file structure and a free file descriptor.
*/
- error = anon_inode_getfd("[eventpoll]", &eventpoll_fops, ep,
+ fd = get_unused_fd_flags(O_RDWR | (flags & O_CLOEXEC));
+ if (fd < 0) {
+ error = fd;
+ goto out_free_ep;
+ }
+ file = anon_inode_getfile("[eventpoll]", &eventpoll_fops, ep,
O_RDWR | (flags & O_CLOEXEC));
- if (error < 0)
- ep_free(ep);
-
+ if (IS_ERR(file)) {
+ error = PTR_ERR(file);
+ goto out_free_fd;
+ }
+ fd_install(fd, file);
+ ep->file = file;
+ return fd;
+
+out_free_fd:
+ put_unused_fd(fd);
+out_free_ep:
+ ep_free(ep);
return error;
}
@@ -1404,21 +1613,27 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
/*
* When we insert an epoll file descriptor, inside another epoll file
* descriptor, there is the change of creating closed loops, which are
- * better be handled here, than in more critical paths.
+ * better be handled here, than in more critical paths. While we are
+ * checking for loops we also determine the list of files reachable
+ * and hang them on the tfile_check_list, so we can check that we
+ * haven't created too many possible wakeup paths.
*
- * We hold epmutex across the loop check and the insert in this case, in
- * order to prevent two separate inserts from racing and each doing the
- * insert "at the same time" such that ep_loop_check passes on both
- * before either one does the insert, thereby creating a cycle.
+ * We need to hold the epmutex across both ep_insert and ep_remove
+ * b/c we want to make sure we are looking at a coherent view of
+ * epoll network.
*/
- if (unlikely(is_file_epoll(tfile) && op == EPOLL_CTL_ADD)) {
+ if (op == EPOLL_CTL_ADD || op == EPOLL_CTL_DEL) {
mutex_lock(&epmutex);
did_lock_epmutex = 1;
- error = -ELOOP;
- if (ep_loop_check(ep, tfile) != 0)
- goto error_tgt_fput;
}
-
+ if (op == EPOLL_CTL_ADD) {
+ if (is_file_epoll(tfile)) {
+ error = -ELOOP;
+ if (ep_loop_check(ep, tfile) != 0)
+ goto error_tgt_fput;
+ } else
+ list_add(&tfile->f_tfile_llink, &tfile_check_list);
+ }
mutex_lock_nested(&ep->mtx, 0);
@@ -1437,6 +1652,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
error = ep_insert(ep, &epds, tfile, fd);
} else
error = -EEXIST;
+ clear_tfile_check_list();
break;
case EPOLL_CTL_DEL:
if (epi)
@@ -1455,7 +1671,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
mutex_unlock(&ep->mtx);
error_tgt_fput:
- if (unlikely(did_lock_epmutex))
+ if (did_lock_epmutex)
mutex_unlock(&epmutex);
fput(tfile);
diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
index bfc2dc43681d..0b3da7cc8aba 100644
--- a/fs/ext3/ialloc.c
+++ b/fs/ext3/ialloc.c
@@ -561,8 +561,12 @@ got:
if (IS_DIRSYNC(inode))
handle->h_sync = 1;
if (insert_inode_locked(inode) < 0) {
- err = -EINVAL;
- goto fail_drop;
+ /*
+ * Likely a bitmap corruption causing inode to be allocated
+ * twice.
+ */
+ err = -EIO;
+ goto fail;
}
spin_lock(&sbi->s_next_gen_lock);
inode->i_generation = sbi->s_next_generation++;
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 3451d23c3bae..db9ba1a3f7f8 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -1568,7 +1568,13 @@ static int ext3_ordered_writepage(struct page *page,
int err;
J_ASSERT(PageLocked(page));
- WARN_ON_ONCE(IS_RDONLY(inode));
+ /*
+ * We don't want to warn for emergency remount. The condition is
+ * ordered to avoid dereferencing inode->i_sb in non-error case to
+ * avoid slow-downs.
+ */
+ WARN_ON_ONCE(IS_RDONLY(inode) &&
+ !(EXT3_SB(inode->i_sb)->s_mount_state & EXT3_ERROR_FS));
/*
* We give up here if we're reentered, because it might be for a
@@ -1642,7 +1648,13 @@ static int ext3_writeback_writepage(struct page *page,
int err;
J_ASSERT(PageLocked(page));
- WARN_ON_ONCE(IS_RDONLY(inode));
+ /*
+ * We don't want to warn for emergency remount. The condition is
+ * ordered to avoid dereferencing inode->i_sb in non-error case to
+ * avoid slow-downs.
+ */
+ WARN_ON_ONCE(IS_RDONLY(inode) &&
+ !(EXT3_SB(inode->i_sb)->s_mount_state & EXT3_ERROR_FS));
if (ext3_journal_current_handle())
goto out_fail;
@@ -1684,7 +1696,13 @@ static int ext3_journalled_writepage(struct page *page,
int err;
J_ASSERT(PageLocked(page));
- WARN_ON_ONCE(IS_RDONLY(inode));
+ /*
+ * We don't want to warn for emergency remount. The condition is
+ * ordered to avoid dereferencing inode->i_sb in non-error case to
+ * avoid slow-downs.
+ */
+ WARN_ON_ONCE(IS_RDONLY(inode) &&
+ !(EXT3_SB(inode->i_sb)->s_mount_state & EXT3_ERROR_FS));
if (ext3_journal_current_handle())
goto no_write;
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
index 5802fa1dab18..95af6f878501 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -261,43 +261,45 @@ static inline void ext4_update_inode_fsync_trans(handle_t *handle,
/* super.c */
int ext4_force_commit(struct super_block *sb);
-static inline int ext4_should_journal_data(struct inode *inode)
+/*
+ * Ext4 inode journal modes
+ */
+#define EXT4_INODE_JOURNAL_DATA_MODE 0x01 /* journal data mode */
+#define EXT4_INODE_ORDERED_DATA_MODE 0x02 /* ordered data mode */
+#define EXT4_INODE_WRITEBACK_DATA_MODE 0x04 /* writeback data mode */
+
+static inline int ext4_inode_journal_mode(struct inode *inode)
{
if (EXT4_JOURNAL(inode) == NULL)
- return 0;
- if (!S_ISREG(inode->i_mode))
- return 1;
- if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
- return 1;
- if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
- return 1;
- return 0;
+ return EXT4_INODE_WRITEBACK_DATA_MODE; /* writeback */
+ /* We do not support data journalling with delayed allocation */
+ if (!S_ISREG(inode->i_mode) ||
+ test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
+ return EXT4_INODE_JOURNAL_DATA_MODE; /* journal data */
+ if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
+ !test_opt(inode->i_sb, DELALLOC))
+ return EXT4_INODE_JOURNAL_DATA_MODE; /* journal data */
+ if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
+ return EXT4_INODE_ORDERED_DATA_MODE; /* ordered */
+ if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
+ return EXT4_INODE_WRITEBACK_DATA_MODE; /* writeback */
+ else
+ BUG();
+}
+
+static inline int ext4_should_journal_data(struct inode *inode)
+{
+ return ext4_inode_journal_mode(inode) & EXT4_INODE_JOURNAL_DATA_MODE;
}
static inline int ext4_should_order_data(struct inode *inode)
{
- if (EXT4_JOURNAL(inode) == NULL)
- return 0;
- if (!S_ISREG(inode->i_mode))
- return 0;
- if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
- return 0;
- if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
- return 1;
- return 0;
+ return ext4_inode_journal_mode(inode) & EXT4_INODE_ORDERED_DATA_MODE;
}
static inline int ext4_should_writeback_data(struct inode *inode)
{
- if (EXT4_JOURNAL(inode) == NULL)
- return 1;
- if (!S_ISREG(inode->i_mode))
- return 0;
- if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
- return 0;
- if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
- return 1;
- return 0;
+ return ext4_inode_journal_mode(inode) & EXT4_INODE_WRITEBACK_DATA_MODE;
}
/*
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index f3aacb32059f..611647b28a4d 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -341,6 +341,8 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext)
ext4_fsblk_t block = ext4_ext_pblock(ext);
int len = ext4_ext_get_actual_len(ext);
+ if (len == 0)
+ return 0;
return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len);
}
@@ -2844,7 +2846,7 @@ static int ext4_split_extent_at(handle_t *handle,
if (err)
goto fix_extent_len;
/* update the extent length and mark as initialized */
- ex->ee_len = cpu_to_le32(ee_len);
+ ex->ee_len = cpu_to_le16(ee_len);
ext4_ext_try_to_merge(inode, path, ex);
err = ext4_ext_dirty(handle, inode, path + depth);
goto out;
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 21bb2f61e502..412469b241a8 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -1021,8 +1021,12 @@ got:
if (IS_DIRSYNC(inode))
ext4_handle_sync(handle);
if (insert_inode_locked(inode) < 0) {
- err = -EINVAL;
- goto fail_drop;
+ /*
+ * Likely a bitmap corruption causing inode to be allocated
+ * twice.
+ */
+ err = -EIO;
+ goto fail;
}
spin_lock(&sbi->s_next_gen_lock);
inode->i_generation = sbi->s_next_generation++;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index af0906080fd8..c1e6a7263893 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3212,13 +3212,14 @@ static int ext4_da_write_end(struct file *file,
int write_mode = (int)(unsigned long)fsdata;
if (write_mode == FALL_BACK_TO_NONDELALLOC) {
- if (ext4_should_order_data(inode)) {
+ switch (ext4_inode_journal_mode(inode)) {
+ case EXT4_INODE_ORDERED_DATA_MODE:
return ext4_ordered_write_end(file, mapping, pos,
len, copied, page, fsdata);
- } else if (ext4_should_writeback_data(inode)) {
+ case EXT4_INODE_WRITEBACK_DATA_MODE:
return ext4_writeback_write_end(file, mapping, pos,
len, copied, page, fsdata);
- } else {
+ default:
BUG();
}
}
@@ -3510,12 +3511,17 @@ static ssize_t ext4_ind_direct_IO(int rw, struct kiocb *iocb,
}
retry:
- if (rw == READ && ext4_should_dioread_nolock(inode))
+ if (rw == READ && ext4_should_dioread_nolock(inode)) {
+ if (unlikely(!list_empty(&ei->i_completed_io_list))) {
+ mutex_lock(&inode->i_mutex);
+ ext4_flush_completed_IO(inode);
+ mutex_unlock(&inode->i_mutex);
+ }
ret = __blockdev_direct_IO(rw, iocb, inode,
inode->i_sb->s_bdev, iov,
offset, nr_segs,
ext4_get_block, NULL, NULL, 0);
- else {
+ } else {
ret = blockdev_direct_IO(rw, iocb, inode,
inode->i_sb->s_bdev, iov,
offset, nr_segs,
@@ -3913,18 +3919,25 @@ static const struct address_space_operations ext4_da_aops = {
void ext4_set_aops(struct inode *inode)
{
- if (ext4_should_order_data(inode) &&
- test_opt(inode->i_sb, DELALLOC))
- inode->i_mapping->a_ops = &ext4_da_aops;
- else if (ext4_should_order_data(inode))
- inode->i_mapping->a_ops = &ext4_ordered_aops;
- else if (ext4_should_writeback_data(inode) &&
- test_opt(inode->i_sb, DELALLOC))
- inode->i_mapping->a_ops = &ext4_da_aops;
- else if (ext4_should_writeback_data(inode))
- inode->i_mapping->a_ops = &ext4_writeback_aops;
- else
+ switch (ext4_inode_journal_mode(inode)) {
+ case EXT4_INODE_ORDERED_DATA_MODE:
+ if (test_opt(inode->i_sb, DELALLOC))
+ inode->i_mapping->a_ops = &ext4_da_aops;
+ else
+ inode->i_mapping->a_ops = &ext4_ordered_aops;
+ break;
+ case EXT4_INODE_WRITEBACK_DATA_MODE:
+ if (test_opt(inode->i_sb, DELALLOC))
+ inode->i_mapping->a_ops = &ext4_da_aops;
+ else
+ inode->i_mapping->a_ops = &ext4_writeback_aops;
+ break;
+ case EXT4_INODE_JOURNAL_DATA_MODE:
inode->i_mapping->a_ops = &ext4_journalled_aops;
+ break;
+ default:
+ BUG();
+ }
}
/*
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 808c554e773f..4cbe1c2c9968 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -35,7 +35,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
handle_t *handle = NULL;
int err, migrate = 0;
struct ext4_iloc iloc;
- unsigned int oldflags;
+ unsigned int oldflags, mask, i;
unsigned int jflag;
if (!inode_owner_or_capable(inode))
@@ -112,9 +112,14 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (err)
goto flags_err;
- flags = flags & EXT4_FL_USER_MODIFIABLE;
- flags |= oldflags & ~EXT4_FL_USER_MODIFIABLE;
- ei->i_flags = flags;
+ for (i = 0, mask = 1; i < 32; i++, mask <<= 1) {
+ if (!(mask & EXT4_FL_USER_MODIFIABLE))
+ continue;
+ if (mask & flags)
+ ext4_set_inode_flag(inode, i);
+ else
+ ext4_clear_inode_flag(inode, i);
+ }
ext4_set_inode_flags(inode);
inode->i_ctime = ext4_current_time(inode);
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 0f1be7f16376..b6adf68a5c02 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -2528,6 +2528,9 @@ int ext4_mb_release(struct super_block *sb)
struct ext4_sb_info *sbi = EXT4_SB(sb);
struct kmem_cache *cachep = get_groupinfo_cache(sb->s_blocksize_bits);
+ if (sbi->s_proc)
+ remove_proc_entry("mb_groups", sbi->s_proc);
+
if (sbi->s_group_info) {
for (i = 0; i < ngroups; i++) {
grinfo = ext4_get_group_info(sb, i);
@@ -2575,8 +2578,6 @@ int ext4_mb_release(struct super_block *sb)
}
free_percpu(sbi->s_locality_groups);
- if (sbi->s_proc)
- remove_proc_entry("mb_groups", sbi->s_proc);
return 0;
}
@@ -4583,6 +4584,7 @@ do_more:
*/
new_entry = kmem_cache_alloc(ext4_free_ext_cachep, GFP_NOFS);
if (!new_entry) {
+ ext4_mb_unload_buddy(&e4b);
err = -ENOMEM;
goto error_return;
}
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 7aa77f049173..113b10768445 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -433,6 +433,7 @@ void __ext4_error(struct super_block *sb, const char *function,
printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: comm %s: %pV\n",
sb->s_id, function, line, current->comm, &vaf);
va_end(args);
+ save_error_info(sb, function, line);
ext4_handle_error(sb);
}
@@ -1957,17 +1958,16 @@ static int ext4_fill_flex_info(struct super_block *sb)
struct ext4_group_desc *gdp = NULL;
ext4_group_t flex_group_count;
ext4_group_t flex_group;
- int groups_per_flex = 0;
+ unsigned int groups_per_flex = 0;
size_t size;
int i;
sbi->s_log_groups_per_flex = sbi->s_es->s_log_groups_per_flex;
- groups_per_flex = 1 << sbi->s_log_groups_per_flex;
-
- if (groups_per_flex < 2) {
+ if (sbi->s_log_groups_per_flex < 1 || sbi->s_log_groups_per_flex > 31) {
sbi->s_log_groups_per_flex = 0;
return 1;
}
+ groups_per_flex = 1 << sbi->s_log_groups_per_flex;
/* We allocate both existing and potentially added groups */
flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) +
@@ -3619,7 +3619,8 @@ no_journal:
goto failed_mount4;
}
- ext4_setup_super(sb, es, sb->s_flags & MS_RDONLY);
+ if (ext4_setup_super(sb, es, sb->s_flags & MS_RDONLY))
+ sb->s_flags |= MS_RDONLY;
/* determine the minimum size of new large inodes, if present */
if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE) {
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 19fe4e3d39ec..c2865cc3101e 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -487,18 +487,19 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode,
ext4_free_blocks(handle, inode, bh, 0, 1,
EXT4_FREE_BLOCKS_METADATA |
EXT4_FREE_BLOCKS_FORGET);
+ unlock_buffer(bh);
} else {
le32_add_cpu(&BHDR(bh)->h_refcount, -1);
+ if (ce)
+ mb_cache_entry_release(ce);
+ unlock_buffer(bh);
error = ext4_handle_dirty_metadata(handle, inode, bh);
if (IS_SYNC(inode))
ext4_handle_sync(handle);
dquot_free_block(inode, 1);
ea_bdebug(bh, "refcount now=%d; releasing",
le32_to_cpu(BHDR(bh)->h_refcount));
- if (ce)
- mb_cache_entry_release(ce);
}
- unlock_buffer(bh);
out:
ext4_std_error(inode->i_sb, error);
return;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index d50160714595..c04a025c677f 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -858,6 +858,7 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat,
if (stat) {
generic_fillattr(inode, stat);
stat->mode = fi->orig_i_mode;
+ stat->ino = fi->orig_ino;
}
}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index b788becada76..f6215501097d 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -82,6 +82,9 @@ struct fuse_inode {
preserve the original mode */
mode_t orig_i_mode;
+ /** 64 bit inode number */
+ u64 orig_ino;
+
/** Version of last attribute change */
u64 attr_version;
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 38f84cd48b67..69a1e0f04f44 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -91,6 +91,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb)
fi->nlookup = 0;
fi->attr_version = 0;
fi->writectr = 0;
+ fi->orig_ino = 0;
INIT_LIST_HEAD(&fi->write_files);
INIT_LIST_HEAD(&fi->queued_writes);
INIT_LIST_HEAD(&fi->writepages);
@@ -140,6 +141,18 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data)
return 0;
}
+/*
+ * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down
+ * so that it will fit.
+ */
+static ino_t fuse_squash_ino(u64 ino64)
+{
+ ino_t ino = (ino_t) ino64;
+ if (sizeof(ino_t) < sizeof(u64))
+ ino ^= ino64 >> (sizeof(u64) - sizeof(ino_t)) * 8;
+ return ino;
+}
+
void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
u64 attr_valid)
{
@@ -149,7 +162,7 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
fi->attr_version = ++fc->attr_version;
fi->i_time = attr_valid;
- inode->i_ino = attr->ino;
+ inode->i_ino = fuse_squash_ino(attr->ino);
inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777);
inode->i_nlink = attr->nlink;
inode->i_uid = attr->uid;
@@ -175,6 +188,8 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr,
fi->orig_i_mode = inode->i_mode;
if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS))
inode->i_mode &= ~S_ISVTX;
+
+ fi->orig_ino = attr->ino;
}
void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
diff --git a/fs/hfsplus/catalog.c b/fs/hfsplus/catalog.c
index b4ba1b319333..408073ae7a27 100644
--- a/fs/hfsplus/catalog.c
+++ b/fs/hfsplus/catalog.c
@@ -360,6 +360,10 @@ int hfsplus_rename_cat(u32 cnid,
err = hfs_brec_find(&src_fd);
if (err)
goto out;
+ if (src_fd.entrylength > sizeof(entry) || src_fd.entrylength < 0) {
+ err = -EIO;
+ goto out;
+ }
hfs_bnode_read(src_fd.bnode, &entry, src_fd.entryoffset,
src_fd.entrylength);
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 4df5059c25da..159f5ebf519a 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -146,6 +146,11 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
filp->f_pos++;
/* fall through */
case 1:
+ if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) {
+ err = -EIO;
+ goto out;
+ }
+
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
fd.entrylength);
if (be16_to_cpu(entry.type) != HFSPLUS_FOLDER_THREAD) {
@@ -177,6 +182,12 @@ static int hfsplus_readdir(struct file *filp, void *dirent, filldir_t filldir)
err = -EIO;
goto out;
}
+
+ if (fd.entrylength > sizeof(entry) || fd.entrylength < 0) {
+ err = -EIO;
+ goto out;
+ }
+
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
fd.entrylength);
type = be16_to_cpu(entry.type);
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 7aafeb8fa300..8b0c87530b04 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -238,17 +238,10 @@ static ssize_t hugetlbfs_read(struct file *filp, char __user *buf,
loff_t isize;
ssize_t retval = 0;
- mutex_lock(&inode->i_mutex);
-
/* validate length */
if (len == 0)
goto out;
- isize = i_size_read(inode);
- if (!isize)
- goto out;
-
- end_index = (isize - 1) >> huge_page_shift(h);
for (;;) {
struct page *page;
unsigned long nr, ret;
@@ -256,18 +249,21 @@ static ssize_t hugetlbfs_read(struct file *filp, char __user *buf,
/* nr is the maximum number of bytes to copy from this page */
nr = huge_page_size(h);
+ isize = i_size_read(inode);
+ if (!isize)
+ goto out;
+ end_index = (isize - 1) >> huge_page_shift(h);
if (index >= end_index) {
if (index > end_index)
goto out;
nr = ((isize - 1) & ~huge_page_mask(h)) + 1;
- if (nr <= offset) {
+ if (nr <= offset)
goto out;
- }
}
nr = nr - offset;
/* Find the page */
- page = find_get_page(mapping, index);
+ page = find_lock_page(mapping, index);
if (unlikely(page == NULL)) {
/*
* We have a HOLE, zero out the user-buffer for the
@@ -279,17 +275,18 @@ static ssize_t hugetlbfs_read(struct file *filp, char __user *buf,
else
ra = 0;
} else {
+ unlock_page(page);
+
/*
* We have the page, copy it to user space buffer.
*/
ra = hugetlbfs_read_actor(page, offset, buf, len, nr);
ret = ra;
+ page_cache_release(page);
}
if (ra < 0) {
if (retval == 0)
retval = ra;
- if (page)
- page_cache_release(page);
goto out;
}
@@ -299,16 +296,12 @@ static ssize_t hugetlbfs_read(struct file *filp, char __user *buf,
index += offset >> huge_page_shift(h);
offset &= ~huge_page_mask(h);
- if (page)
- page_cache_release(page);
-
/* short read or no more work */
if ((ret != nr) || (len == 0))
break;
}
out:
*ppos = ((loff_t)index << huge_page_shift(h)) + offset;
- mutex_unlock(&inode->i_mutex);
return retval;
}
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index eef6979821a4..36c2e800e734 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -683,7 +683,7 @@ start_journal_io:
if (commit_transaction->t_need_data_flush &&
(journal->j_fs_dev != journal->j_dev) &&
(journal->j_flags & JBD2_BARRIER))
- blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL);
+ blkdev_issue_flush(journal->j_fs_dev, GFP_NOFS, NULL);
/* Done it all: now write the commit record asynchronously. */
if (JBD2_HAS_INCOMPAT_FEATURE(journal,
@@ -819,7 +819,7 @@ wait_for_iobuf:
if (JBD2_HAS_INCOMPAT_FEATURE(journal,
JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT) &&
journal->j_flags & JBD2_BARRIER) {
- blkdev_issue_flush(journal->j_dev, GFP_KERNEL, NULL);
+ blkdev_issue_flush(journal->j_dev, GFP_NOFS, NULL);
}
if (err)
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index 2d7109414cdd..9baa39ea6be2 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -1902,6 +1902,8 @@ zap_buffer_unlocked:
clear_buffer_mapped(bh);
clear_buffer_req(bh);
clear_buffer_new(bh);
+ clear_buffer_delay(bh);
+ clear_buffer_unwritten(bh);
bh->b_bdev = NULL;
return may_free;
}
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 31dce611337c..4bbd5211bb32 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -225,8 +225,8 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
return 0;
D1(printk(KERN_DEBUG "No progress from erasing blocks; doing GC anyway\n"));
- spin_lock(&c->erase_completion_lock);
mutex_lock(&c->alloc_sem);
+ spin_lock(&c->erase_completion_lock);
}
/* First, work out which block we're garbage-collecting */
diff --git a/fs/lockd/clnt4xdr.c b/fs/lockd/clnt4xdr.c
index f848b52c67b1..046bb77c6013 100644
--- a/fs/lockd/clnt4xdr.c
+++ b/fs/lockd/clnt4xdr.c
@@ -241,7 +241,7 @@ static int decode_nlm4_stat(struct xdr_stream *xdr, __be32 *stat)
p = xdr_inline_decode(xdr, 4);
if (unlikely(p == NULL))
goto out_overflow;
- if (unlikely(*p > nlm4_failed))
+ if (unlikely(ntohl(*p) > ntohl(nlm4_failed)))
goto out_bad_xdr;
*stat = *p;
return 0;
diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c
index 180ac34feb9a..36057cedac62 100644
--- a/fs/lockd/clntxdr.c
+++ b/fs/lockd/clntxdr.c
@@ -236,7 +236,7 @@ static int decode_nlm_stat(struct xdr_stream *xdr,
p = xdr_inline_decode(xdr, 4);
if (unlikely(p == NULL))
goto out_overflow;
- if (unlikely(*p > nlm_lck_denied_grace_period))
+ if (unlikely(ntohl(*p) > ntohl(nlm_lck_denied_grace_period)))
goto out_enum;
*stat = *p;
return 0;
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index abfff9d7979d..1743064cd0ce 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -440,7 +440,7 @@ static int param_set_##name(const char *val, struct kernel_param *kp) \
__typeof__(type) num = which_strtol(val, &endp, 0); \
if (endp == val || *endp || num < (min) || num > (max)) \
return -EINVAL; \
- *((int *) kp->arg) = num; \
+ *((type *) kp->arg) = num; \
return 0; \
}
diff --git a/fs/namei.c b/fs/namei.c
index f7593c0899d1..16bda6cd602d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2109,7 +2109,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
/* sayonara */
error = complete_walk(nd);
if (error)
- return ERR_PTR(-ECHILD);
+ return ERR_PTR(error);
error = -ENOTDIR;
if (nd->flags & LOOKUP_DIRECTORY) {
@@ -2208,7 +2208,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
/* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */
error = complete_walk(nd);
if (error)
- goto exit;
+ return ERR_PTR(error);
error = -EISDIR;
if (S_ISDIR(nd->inode->i_mode))
goto exit;
diff --git a/fs/namespace.c b/fs/namespace.c
index edc1c4aef757..b3d8f51c6fa3 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1244,8 +1244,9 @@ void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill)
list_del_init(&p->mnt_expire);
list_del_init(&p->mnt_list);
__touch_mnt_namespace(p->mnt_ns);
+ if (p->mnt_ns)
+ __mnt_make_shortterm(p);
p->mnt_ns = NULL;
- __mnt_make_shortterm(p);
list_del_init(&p->mnt_child);
if (p->mnt_parent != p) {
p->mnt_parent->mnt_ghosts++;
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index aaa09e948a9c..b5c826e17b6a 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -324,7 +324,7 @@ validate_seqid(struct nfs4_slot_table *tbl, struct cb_sequenceargs * args)
dprintk("%s enter. slotid %d seqid %d\n",
__func__, args->csa_slotid, args->csa_sequenceid);
- if (args->csa_slotid > NFS41_BC_MAX_CALLBACKS)
+ if (args->csa_slotid >= NFS41_BC_MAX_CALLBACKS)
return htonl(NFS4ERR_BADSLOT);
slot = tbl->slots + args->csa_slotid;
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 321a66bc3846..ecabbd8f6ee5 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -466,6 +466,17 @@ static void nfs_delegation_run_state_manager(struct nfs_client *clp)
nfs4_schedule_state_manager(clp);
}
+void nfs_remove_bad_delegation(struct inode *inode)
+{
+ struct nfs_delegation *delegation;
+
+ delegation = nfs_detach_delegation(NFS_I(inode), NFS_SERVER(inode));
+ if (delegation) {
+ nfs_inode_find_state_and_recover(inode, &delegation->stateid);
+ nfs_free_delegation(delegation);
+ }
+}
+
/**
* nfs_expire_all_delegation_types
* @clp: client to process
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index d9322e490c56..691a79609184 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -45,6 +45,7 @@ void nfs_expire_unreferenced_delegations(struct nfs_client *clp);
void nfs_handle_cb_pathdown(struct nfs_client *clp);
int nfs_client_return_marked_delegations(struct nfs_client *clp);
int nfs_delegations_present(struct nfs_client *clp);
+void nfs_remove_bad_delegation(struct inode *inode);
void nfs_delegation_mark_reclaim(struct nfs_client *clp);
void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index c4a69833dd0d..e1c1365ba832 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -209,6 +209,7 @@ struct nfs4_exception {
long timeout;
int retry;
struct nfs4_state *state;
+ struct inode *inode;
};
struct nfs4_state_recovery_ops {
@@ -344,6 +345,8 @@ extern void nfs4_put_open_state(struct nfs4_state *);
extern void nfs4_close_state(struct path *, struct nfs4_state *, fmode_t);
extern void nfs4_close_sync(struct path *, struct nfs4_state *, fmode_t);
extern void nfs4_state_set_mode_locked(struct nfs4_state *, fmode_t);
+extern void nfs_inode_find_state_and_recover(struct inode *inode,
+ const nfs4_stateid *stateid);
extern void nfs4_schedule_lease_recovery(struct nfs_client *);
extern void nfs4_schedule_state_manager(struct nfs_client *);
extern void nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a2a7d0a8daff..b7a7e5fe4019 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -94,6 +94,8 @@ static int nfs4_map_errors(int err)
case -NFS4ERR_BADOWNER:
case -NFS4ERR_BADNAME:
return -EINVAL;
+ case -NFS4ERR_SHARE_DENIED:
+ return -EACCES;
default:
dprintk("%s could not handle NFSv4 error %d\n",
__func__, -err);
@@ -254,15 +256,28 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
{
struct nfs_client *clp = server->nfs_client;
struct nfs4_state *state = exception->state;
+ struct inode *inode = exception->inode;
int ret = errorcode;
exception->retry = 0;
switch(errorcode) {
case 0:
return 0;
+ case -NFS4ERR_OPENMODE:
+ if (nfs_have_delegation(inode, FMODE_READ)) {
+ nfs_inode_return_delegation(inode);
+ exception->retry = 1;
+ return 0;
+ }
+ if (state == NULL)
+ break;
+ nfs4_schedule_stateid_recovery(server, state);
+ goto wait_on_recovery;
+ case -NFS4ERR_DELEG_REVOKED:
case -NFS4ERR_ADMIN_REVOKED:
case -NFS4ERR_BAD_STATEID:
- case -NFS4ERR_OPENMODE:
+ if (state != NULL)
+ nfs_remove_bad_delegation(state->inode);
if (state == NULL)
break;
nfs4_schedule_stateid_recovery(server, state);
@@ -1305,8 +1320,11 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state
* The show must go on: exit, but mark the
* stateid as needing recovery.
*/
+ case -NFS4ERR_DELEG_REVOKED:
case -NFS4ERR_ADMIN_REVOKED:
case -NFS4ERR_BAD_STATEID:
+ nfs_inode_find_state_and_recover(state->inode,
+ stateid);
nfs4_schedule_stateid_recovery(server, state);
case -EKEYEXPIRED:
/*
@@ -1755,6 +1773,7 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, fmode_t fmode, in
nfs_setattr_update_inode(state->inode, sattr);
nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr);
}
+ nfs_revalidate_inode(server, state->inode);
nfs4_opendata_put(opendata);
nfs4_put_state_owner(sp);
*res = state;
@@ -1862,7 +1881,10 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
struct nfs4_state *state)
{
struct nfs_server *server = NFS_SERVER(inode);
- struct nfs4_exception exception = { };
+ struct nfs4_exception exception = {
+ .state = state,
+ .inode = inode,
+ };
int err;
do {
err = nfs4_handle_exception(server,
@@ -3678,8 +3700,11 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
if (task->tk_status >= 0)
return 0;
switch(task->tk_status) {
+ case -NFS4ERR_DELEG_REVOKED:
case -NFS4ERR_ADMIN_REVOKED:
case -NFS4ERR_BAD_STATEID:
+ if (state != NULL)
+ nfs_remove_bad_delegation(state->inode);
case -NFS4ERR_OPENMODE:
if (state == NULL)
break;
@@ -4402,7 +4427,9 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
{
struct nfs_server *server = NFS_SERVER(state->inode);
- struct nfs4_exception exception = { };
+ struct nfs4_exception exception = {
+ .inode = state->inode,
+ };
int err;
do {
@@ -4420,7 +4447,9 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request
static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request)
{
struct nfs_server *server = NFS_SERVER(state->inode);
- struct nfs4_exception exception = { };
+ struct nfs4_exception exception = {
+ .inode = state->inode,
+ };
int err;
err = nfs4_set_lock_state(state, request);
@@ -4484,7 +4513,10 @@ out:
static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
{
- struct nfs4_exception exception = { };
+ struct nfs4_exception exception = {
+ .state = state,
+ .inode = state->inode,
+ };
int err;
do {
@@ -4529,6 +4561,20 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
if (state == NULL)
return -ENOLCK;
+ /*
+ * Don't rely on the VFS having checked the file open mode,
+ * since it won't do this for flock() locks.
+ */
+ switch (request->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) {
+ case F_RDLCK:
+ if (!(filp->f_mode & FMODE_READ))
+ return -EBADF;
+ break;
+ case F_WRLCK:
+ if (!(filp->f_mode & FMODE_WRITE))
+ return -EBADF;
+ }
+
do {
status = nfs4_proc_setlk(state, cmd, request);
if ((status != -EAGAIN) || IS_SETLK(cmd))
@@ -4577,6 +4623,7 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
* The show must go on: exit, but mark the
* stateid as needing recovery.
*/
+ case -NFS4ERR_DELEG_REVOKED:
case -NFS4ERR_ADMIN_REVOKED:
case -NFS4ERR_BAD_STATEID:
case -NFS4ERR_OPENMODE:
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index e97dd219f84f..c6e2769f65bb 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1069,6 +1069,33 @@ void nfs4_schedule_stateid_recovery(const struct nfs_server *server, struct nfs4
nfs4_schedule_state_manager(clp);
}
+void nfs_inode_find_state_and_recover(struct inode *inode,
+ const nfs4_stateid *stateid)
+{
+ struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
+ struct nfs_inode *nfsi = NFS_I(inode);
+ struct nfs_open_context *ctx;
+ struct nfs4_state *state;
+ bool found = false;
+
+ spin_lock(&inode->i_lock);
+ list_for_each_entry(ctx, &nfsi->open_files, list) {
+ state = ctx->state;
+ if (state == NULL)
+ continue;
+ if (!test_bit(NFS_DELEGATED_STATE, &state->flags))
+ continue;
+ if (memcmp(state->stateid.data, stateid->data, sizeof(state->stateid.data)) != 0)
+ continue;
+ nfs4_state_mark_reclaim_nograce(clp, state);
+ found = true;
+ }
+ spin_unlock(&inode->i_lock);
+ if (found)
+ nfs4_schedule_state_manager(clp);
+}
+
+
static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_recovery_ops *ops)
{
struct inode *inode = state->inode;
@@ -1519,16 +1546,16 @@ void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags)
{
if (!flags)
return;
- else if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED)
+ if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED)
nfs41_handle_server_reboot(clp);
- else if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED |
+ if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED |
SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED |
SEQ4_STATUS_ADMIN_STATE_REVOKED |
SEQ4_STATUS_LEASE_MOVED))
nfs41_handle_state_revoked(clp);
- else if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED)
+ if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED)
nfs41_handle_recallable_state_revoked(clp);
- else if (flags & (SEQ4_STATUS_CB_PATH_DOWN |
+ if (flags & (SEQ4_STATUS_CB_PATH_DOWN |
SEQ4_STATUS_BACKCHANNEL_FAULT |
SEQ4_STATUS_CB_PATH_DOWN_SESSION))
nfs41_handle_cb_path_down(clp);
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c
index 1d1dc1ee3943..75fe694d78de 100644
--- a/fs/nfs/objlayout/objio_osd.c
+++ b/fs/nfs/objlayout/objio_osd.c
@@ -1006,7 +1006,8 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio,
static struct pnfs_layoutdriver_type objlayout_type = {
.id = LAYOUT_OSD2_OBJECTS,
.name = "LAYOUT_OSD2_OBJECTS",
- .flags = PNFS_LAYOUTRET_ON_SETATTR,
+ .flags = PNFS_LAYOUTRET_ON_SETATTR |
+ PNFS_LAYOUTRET_ON_ERROR,
.alloc_layout_hdr = objlayout_alloc_layout_hdr,
.free_layout_hdr = objlayout_free_layout_hdr,
diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c
index 1d06f8e2adea..fefa1224aff3 100644
--- a/fs/nfs/objlayout/objlayout.c
+++ b/fs/nfs/objlayout/objlayout.c
@@ -294,9 +294,11 @@ objlayout_read_done(struct objlayout_io_state *state, ssize_t status, bool sync)
dprintk("%s: Begin status=%zd eof=%d\n", __func__, status, eof);
rdata = state->rpcdata;
rdata->task.tk_status = status;
- if (status >= 0) {
+ if (likely(status >= 0)) {
rdata->res.count = status;
rdata->res.eof = eof;
+ } else {
+ rdata->pnfs_error = status;
}
objlayout_iodone(state);
/* must not use state after this point */
@@ -380,15 +382,17 @@ objlayout_write_done(struct objlayout_io_state *state, ssize_t status,
wdata = state->rpcdata;
state->status = status;
wdata->task.tk_status = status;
- if (status >= 0) {
+ if (likely(status >= 0)) {
wdata->res.count = status;
wdata->verf.committed = state->committed;
dprintk("%s: Return status %d committed %d\n",
__func__, wdata->task.tk_status,
wdata->verf.committed);
- } else
+ } else {
+ wdata->pnfs_error = status;
dprintk("%s: Return status %d\n",
__func__, wdata->task.tk_status);
+ }
objlayout_iodone(state);
/* must not use state after this point */
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 36d2a29bfbed..99518872f42c 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1119,6 +1119,14 @@ pnfs_ld_write_done(struct nfs_write_data *data)
data->mds_ops->rpc_release(data);
return 0;
}
+ if (NFS_SERVER(data->inode)->pnfs_curr_ld->flags &
+ PNFS_LAYOUTRET_ON_ERROR) {
+ /* Don't lo_commit on error, Server will needs to
+ * preform a file recovery.
+ */
+ clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(data->inode)->flags);
+ pnfs_return_layout(data->inode);
+ }
dprintk("%s: pnfs_error=%d, retry via MDS\n", __func__,
data->pnfs_error);
@@ -1167,6 +1175,10 @@ pnfs_ld_read_done(struct nfs_read_data *data)
return 0;
}
+ if (NFS_SERVER(data->inode)->pnfs_curr_ld->flags &
+ PNFS_LAYOUTRET_ON_ERROR)
+ pnfs_return_layout(data->inode);
+
dprintk("%s: pnfs_error=%d, retry via MDS\n", __func__,
data->pnfs_error);
status = nfs_initiate_read(data, NFS_CLIENT(data->inode),
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 9d147d963bd9..bb8b3247f29c 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -68,6 +68,7 @@ enum {
enum layoutdriver_policy_flags {
/* Should the pNFS client commit and return the layout upon a setattr */
PNFS_LAYOUTRET_ON_SETATTR = 1 << 0,
+ PNFS_LAYOUTRET_ON_ERROR = 1 << 1,
};
struct nfs4_deviceid_node;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 858d31be29c8..8e7b61d5829a 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -904,10 +904,24 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(unsigned int ve
data->auth_flavor_len = 1;
data->version = version;
data->minorversion = 0;
+ security_init_mnt_opts(&data->lsm_opts);
}
return data;
}
+static void nfs_free_parsed_mount_data(struct nfs_parsed_mount_data *data)
+{
+ if (data) {
+ kfree(data->client_address);
+ kfree(data->mount_server.hostname);
+ kfree(data->nfs_server.export_path);
+ kfree(data->nfs_server.hostname);
+ kfree(data->fscache_uniq);
+ security_free_mnt_opts(&data->lsm_opts);
+ kfree(data);
+ }
+}
+
/*
* Sanity-check a server address provided by the mount command.
*
@@ -2218,9 +2232,7 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
data = nfs_alloc_parsed_mount_data(NFS_DEFAULT_VERSION);
mntfh = nfs_alloc_fhandle();
if (data == NULL || mntfh == NULL)
- goto out_free_fh;
-
- security_init_mnt_opts(&data->lsm_opts);
+ goto out;
/* Validate the mount data */
error = nfs_validate_mount_data(raw_data, data, mntfh, dev_name);
@@ -2232,8 +2244,6 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
#ifdef CONFIG_NFS_V4
if (data->version == 4) {
mntroot = nfs4_try_mount(flags, dev_name, data);
- kfree(data->client_address);
- kfree(data->nfs_server.export_path);
goto out;
}
#endif /* CONFIG_NFS_V4 */
@@ -2284,13 +2294,8 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
s->s_flags |= MS_ACTIVE;
out:
- kfree(data->nfs_server.hostname);
- kfree(data->mount_server.hostname);
- kfree(data->fscache_uniq);
- security_free_mnt_opts(&data->lsm_opts);
-out_free_fh:
+ nfs_free_parsed_mount_data(data);
nfs_free_fhandle(mntfh);
- kfree(data);
return mntroot;
out_err_nosb:
@@ -2613,9 +2618,7 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags,
mntfh = nfs_alloc_fhandle();
if (data == NULL || mntfh == NULL)
- goto out_free_fh;
-
- security_init_mnt_opts(&data->lsm_opts);
+ goto out;
/* Get a volume representation */
server = nfs4_create_server(data, mntfh);
@@ -2663,13 +2666,10 @@ nfs4_remote_mount(struct file_system_type *fs_type, int flags,
s->s_flags |= MS_ACTIVE;
- security_free_mnt_opts(&data->lsm_opts);
nfs_free_fhandle(mntfh);
return mntroot;
out:
- security_free_mnt_opts(&data->lsm_opts);
-out_free_fh:
nfs_free_fhandle(mntfh);
return ERR_PTR(error);
@@ -2694,11 +2694,15 @@ static struct vfsmount *nfs_do_root_mount(struct file_system_type *fs_type,
char *root_devname;
size_t len;
- len = strlen(hostname) + 3;
+ len = strlen(hostname) + 5;
root_devname = kmalloc(len, GFP_KERNEL);
if (root_devname == NULL)
return ERR_PTR(-ENOMEM);
- snprintf(root_devname, len, "%s:/", hostname);
+ /* Does hostname needs to be enclosed in brackets? */
+ if (strchr(hostname, ':'))
+ snprintf(root_devname, len, "[%s]:/", hostname);
+ else
+ snprintf(root_devname, len, "%s:/", hostname);
root_mnt = vfs_kern_mount(fs_type, flags, root_devname, data);
kfree(root_devname);
return root_mnt;
@@ -2855,7 +2859,7 @@ static struct dentry *nfs4_mount(struct file_system_type *fs_type,
data = nfs_alloc_parsed_mount_data(4);
if (data == NULL)
- goto out_free_data;
+ goto out;
/* Validate the mount data */
error = nfs4_validate_mount_data(raw_data, data, dev_name);
@@ -2869,12 +2873,7 @@ static struct dentry *nfs4_mount(struct file_system_type *fs_type,
error = PTR_ERR(res);
out:
- kfree(data->client_address);
- kfree(data->nfs_server.export_path);
- kfree(data->nfs_server.hostname);
- kfree(data->fscache_uniq);
-out_free_data:
- kfree(data);
+ nfs_free_parsed_mount_data(data);
dprintk("<-- nfs4_mount() = %d%s\n", error,
error != 0 ? " [error]" : "");
return res;
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index b9566e46219f..4b470f6043ec 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -88,7 +88,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
struct svc_expkey key;
struct svc_expkey *ek = NULL;
- if (mesg[mlen-1] != '\n')
+ if (mlen < 1 || mesg[mlen-1] != '\n')
return -EINVAL;
mesg[mlen-1] = 0;
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 08c6e36ab2eb..43f46cd9edea 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -803,13 +803,13 @@ encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name,
return p;
}
-static int
+static __be32
compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
const char *name, int namlen)
{
struct svc_export *exp;
struct dentry *dparent, *dchild;
- int rv = 0;
+ __be32 rv = nfserr_noent;
dparent = cd->fh.fh_dentry;
exp = cd->fh.fh_export;
@@ -817,26 +817,20 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
if (isdotent(name, namlen)) {
if (namlen == 2) {
dchild = dget_parent(dparent);
- if (dchild == dparent) {
- /* filesystem root - cannot return filehandle for ".." */
- dput(dchild);
- return -ENOENT;
- }
+ /* filesystem root - cannot return filehandle for ".." */
+ if (dchild == dparent)
+ goto out;
} else
dchild = dget(dparent);
} else
dchild = lookup_one_len(name, dparent, namlen);
if (IS_ERR(dchild))
- return -ENOENT;
- rv = -ENOENT;
+ return rv;
if (d_mountpoint(dchild))
goto out;
- rv = fh_compose(fhp, exp, dchild, &cd->fh);
- if (rv)
- goto out;
if (!dchild->d_inode)
goto out;
- rv = 0;
+ rv = fh_compose(fhp, exp, dchild, &cd->fh);
out:
dput(dchild);
return rv;
@@ -845,7 +839,7 @@ out:
static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen)
{
struct svc_fh fh;
- int err;
+ __be32 err;
fh_init(&fh, NFS3_FHSIZE);
err = compose_entry_fh(cd, &fh, name, namlen);
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 0b8830c9de73..d06a02c1b1a3 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -812,6 +812,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
struct nfsd4_setattr *setattr)
{
__be32 status = nfs_ok;
+ int err;
if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
nfs4_lock_state();
@@ -823,9 +824,9 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
return status;
}
}
- status = mnt_want_write(cstate->current_fh.fh_export->ex_path.mnt);
- if (status)
- return status;
+ err = mnt_want_write(cstate->current_fh.fh_export->ex_path.mnt);
+ if (err)
+ return nfserrno(err);
status = nfs_ok;
status = check_attr_support(rqstp, cstate, setattr->sa_bmval,
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index ecd8152965ee..92f7eb7c5863 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -3956,16 +3956,14 @@ out:
* vfs_test_lock. (Arguably perhaps test_lock should be done with an
* inode operation.)
*/
-static int nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock)
+static __be32 nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock)
{
struct file *file;
- int err;
-
- err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
- if (err)
- return err;
- err = vfs_test_lock(file, lock);
- nfsd_close(file);
+ __be32 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
+ if (!err) {
+ err = nfserrno(vfs_test_lock(file, lock));
+ nfsd_close(file);
+ }
return err;
}
@@ -3978,7 +3976,6 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
{
struct inode *inode;
struct file_lock file_lock;
- int error;
__be32 status;
if (locks_in_grace())
@@ -4030,12 +4027,10 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
nfs4_transform_lock_offset(&file_lock);
- status = nfs_ok;
- error = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock);
- if (error) {
- status = nfserrno(error);
+ status = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock);
+ if (status)
goto out;
- }
+
if (file_lock.fl_type != F_UNLCK) {
status = nfserr_denied;
nfs4_set_lock_denied(&file_lock, &lockt->lt_denied);
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index 41d6743d303c..3e654273cfc2 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -842,6 +842,19 @@ long nilfs_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
case FS_IOC32_GETVERSION:
cmd = FS_IOC_GETVERSION;
break;
+ case NILFS_IOCTL_CHANGE_CPMODE:
+ case NILFS_IOCTL_DELETE_CHECKPOINT:
+ case NILFS_IOCTL_GET_CPINFO:
+ case NILFS_IOCTL_GET_CPSTAT:
+ case NILFS_IOCTL_GET_SUINFO:
+ case NILFS_IOCTL_GET_SUSTAT:
+ case NILFS_IOCTL_GET_VINFO:
+ case NILFS_IOCTL_GET_BDESCS:
+ case NILFS_IOCTL_CLEAN_SEGMENTS:
+ case NILFS_IOCTL_SYNC:
+ case NILFS_IOCTL_RESIZE:
+ case NILFS_IOCTL_SET_ALLOC_RANGE:
+ break;
default:
return -ENOIOCTLCMD;
}
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index d32714094375..35a89708b635 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -515,6 +515,7 @@ static int nilfs_load_super_block(struct the_nilfs *nilfs,
brelse(sbh[1]);
sbh[1] = NULL;
sbp[1] = NULL;
+ valid[1] = 0;
swp = 0;
}
if (!valid[swp]) {
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index 252ab1f6452b..42ed195771f1 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -135,9 +135,6 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
mark->flags &= ~FSNOTIFY_MARK_FLAG_ALIVE;
- /* 1 from caller and 1 for being on i_list/g_list */
- BUG_ON(atomic_read(&mark->refcnt) < 2);
-
spin_lock(&group->mark_lock);
if (mark->flags & FSNOTIFY_MARK_FLAG_INODE) {
@@ -182,6 +179,11 @@ void fsnotify_destroy_mark(struct fsnotify_mark *mark)
iput(inode);
/*
+ * We don't necessarily have a ref on mark from caller so the above iput
+ * may have already destroyed it. Don't touch from now on.
+ */
+
+ /*
* it's possible that this group tried to destroy itself, but this
* this mark was simultaneously being freed by inode. If that's the
* case, we finish freeing the group here.
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index ed553c60de82..76c8165deed9 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -1134,7 +1134,7 @@ static int ocfs2_adjust_rightmost_branch(handle_t *handle,
}
el = path_leaf_el(path);
- rec = &el->l_recs[le32_to_cpu(el->l_next_free_rec) - 1];
+ rec = &el->l_recs[le16_to_cpu(el->l_next_free_rec) - 1];
ocfs2_adjust_rightmost_records(handle, et, path, rec);
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
index ebfd3825f12a..15d29ccefd4f 100644
--- a/fs/ocfs2/refcounttree.c
+++ b/fs/ocfs2/refcounttree.c
@@ -1036,14 +1036,14 @@ static int ocfs2_get_refcount_cpos_end(struct ocfs2_caching_info *ci,
tmp_el = left_path->p_node[subtree_root].el;
blkno = left_path->p_node[subtree_root+1].bh->b_blocknr;
- for (i = 0; i < le32_to_cpu(tmp_el->l_next_free_rec); i++) {
+ for (i = 0; i < le16_to_cpu(tmp_el->l_next_free_rec); i++) {
if (le64_to_cpu(tmp_el->l_recs[i].e_blkno) == blkno) {
*cpos_end = le32_to_cpu(tmp_el->l_recs[i+1].e_cpos);
break;
}
}
- BUG_ON(i == le32_to_cpu(tmp_el->l_next_free_rec));
+ BUG_ON(i == le16_to_cpu(tmp_el->l_next_free_rec));
out:
ocfs2_free_path(left_path);
@@ -1468,7 +1468,7 @@ static int ocfs2_divide_leaf_refcount_block(struct buffer_head *ref_leaf_bh,
trace_ocfs2_divide_leaf_refcount_block(
(unsigned long long)ref_leaf_bh->b_blocknr,
- le32_to_cpu(rl->rl_count), le32_to_cpu(rl->rl_used));
+ le16_to_cpu(rl->rl_count), le16_to_cpu(rl->rl_used));
/*
* XXX: Improvement later.
@@ -2411,7 +2411,7 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb,
rb = (struct ocfs2_refcount_block *)
prev_bh->b_data;
- if (le64_to_cpu(rb->rf_records.rl_used) +
+ if (le16_to_cpu(rb->rf_records.rl_used) +
recs_add >
le16_to_cpu(rb->rf_records.rl_count))
ref_blocks++;
@@ -2476,7 +2476,7 @@ static int ocfs2_calc_refcount_meta_credits(struct super_block *sb,
if (prev_bh) {
rb = (struct ocfs2_refcount_block *)prev_bh->b_data;
- if (le64_to_cpu(rb->rf_records.rl_used) + recs_add >
+ if (le16_to_cpu(rb->rf_records.rl_used) + recs_add >
le16_to_cpu(rb->rf_records.rl_count))
ref_blocks++;
@@ -3629,7 +3629,7 @@ int ocfs2_refcounted_xattr_delete_need(struct inode *inode,
* one will split a refcount rec, so totally we need
* clusters * 2 new refcount rec.
*/
- if (le64_to_cpu(rb->rf_records.rl_used) + clusters * 2 >
+ if (le16_to_cpu(rb->rf_records.rl_used) + clusters * 2 >
le16_to_cpu(rb->rf_records.rl_count))
ref_blocks++;
diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c
index ba5d97e4a73e..f169da4624fd 100644
--- a/fs/ocfs2/suballoc.c
+++ b/fs/ocfs2/suballoc.c
@@ -600,7 +600,7 @@ static void ocfs2_bg_alloc_cleanup(handle_t *handle,
ret = ocfs2_free_clusters(handle, cluster_ac->ac_inode,
cluster_ac->ac_bh,
le64_to_cpu(rec->e_blkno),
- le32_to_cpu(rec->e_leaf_clusters));
+ le16_to_cpu(rec->e_leaf_clusters));
if (ret)
mlog_errno(ret);
/* Try all the clusters to free */
@@ -1628,7 +1628,7 @@ static int ocfs2_bg_discontig_fix_by_rec(struct ocfs2_suballoc_result *res,
{
unsigned int bpc = le16_to_cpu(cl->cl_bpc);
unsigned int bitoff = le32_to_cpu(rec->e_cpos) * bpc;
- unsigned int bitcount = le32_to_cpu(rec->e_leaf_clusters) * bpc;
+ unsigned int bitcount = le16_to_cpu(rec->e_leaf_clusters) * bpc;
if (res->sr_bit_offset < bitoff)
return 0;
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index a0a041dfa0fd..811960a5ef6f 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -550,17 +550,11 @@ static bool disk_unlock_native_capacity(struct gendisk *disk)
}
}
-int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
+static int drop_partitions(struct gendisk *disk, struct block_device *bdev)
{
- struct parsed_partitions *state = NULL;
struct disk_part_iter piter;
struct hd_struct *part;
- int p, highest, res;
-rescan:
- if (state && !IS_ERR(state)) {
- kfree(state);
- state = NULL;
- }
+ int res;
if (bdev->bd_part_count)
return -EBUSY;
@@ -573,6 +567,24 @@ rescan:
delete_partition(disk, part->partno);
disk_part_iter_exit(&piter);
+ return 0;
+}
+
+int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
+{
+ struct parsed_partitions *state = NULL;
+ struct hd_struct *part;
+ int p, highest, res;
+rescan:
+ if (state && !IS_ERR(state)) {
+ kfree(state);
+ state = NULL;
+ }
+
+ res = drop_partitions(disk, bdev);
+ if (res)
+ return res;
+
if (disk->fops->revalidate_disk)
disk->fops->revalidate_disk(disk);
check_disk_size_change(disk, bdev);
@@ -676,6 +688,26 @@ rescan:
return 0;
}
+int invalidate_partitions(struct gendisk *disk, struct block_device *bdev)
+{
+ int res;
+
+ if (!bdev->bd_invalidated)
+ return 0;
+
+ res = drop_partitions(disk, bdev);
+ if (res)
+ return res;
+
+ set_capacity(disk, 0);
+ check_disk_size_change(disk, bdev);
+ bdev->bd_invalidated = 0;
+ /* tell userspace that the media / partition table may have changed */
+ kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE);
+
+ return 0;
+}
+
unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p)
{
struct address_space *mapping = bdev->bd_inode->i_mapping;
diff --git a/fs/pipe.c b/fs/pipe.c
index da42f7db50de..0499a96287ad 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -345,6 +345,16 @@ static const struct pipe_buf_operations anon_pipe_buf_ops = {
.get = generic_pipe_buf_get,
};
+static const struct pipe_buf_operations packet_pipe_buf_ops = {
+ .can_merge = 0,
+ .map = generic_pipe_buf_map,
+ .unmap = generic_pipe_buf_unmap,
+ .confirm = generic_pipe_buf_confirm,
+ .release = anon_pipe_buf_release,
+ .steal = generic_pipe_buf_steal,
+ .get = generic_pipe_buf_get,
+};
+
static ssize_t
pipe_read(struct kiocb *iocb, const struct iovec *_iov,
unsigned long nr_segs, loff_t pos)
@@ -406,6 +416,13 @@ redo:
ret += chars;
buf->offset += chars;
buf->len -= chars;
+
+ /* Was it a packet buffer? Clean up and exit */
+ if (buf->flags & PIPE_BUF_FLAG_PACKET) {
+ total_len = chars;
+ buf->len = 0;
+ }
+
if (!buf->len) {
buf->ops = NULL;
ops->release(pipe, buf);
@@ -458,6 +475,11 @@ redo:
return ret;
}
+static inline int is_packetized(struct file *file)
+{
+ return (file->f_flags & O_DIRECT) != 0;
+}
+
static ssize_t
pipe_write(struct kiocb *iocb, const struct iovec *_iov,
unsigned long nr_segs, loff_t ppos)
@@ -592,6 +614,11 @@ redo2:
buf->ops = &anon_pipe_buf_ops;
buf->offset = 0;
buf->len = chars;
+ buf->flags = 0;
+ if (is_packetized(filp)) {
+ buf->ops = &packet_pipe_buf_ops;
+ buf->flags = PIPE_BUF_FLAG_PACKET;
+ }
pipe->nrbufs = ++bufs;
pipe->tmp_page = NULL;
@@ -1012,7 +1039,7 @@ struct file *create_write_pipe(int flags)
goto err_dentry;
f->f_mapping = inode->i_mapping;
- f->f_flags = O_WRONLY | (flags & O_NONBLOCK);
+ f->f_flags = O_WRONLY | (flags & (O_NONBLOCK | O_DIRECT));
f->f_version = 0;
return f;
@@ -1056,7 +1083,7 @@ int do_pipe_flags(int *fd, int flags)
int error;
int fdw, fdr;
- if (flags & ~(O_CLOEXEC | O_NONBLOCK))
+ if (flags & ~(O_CLOEXEC | O_NONBLOCK | O_DIRECT))
return -EINVAL;
fw = create_write_pipe(flags);
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 845c1d210ef1..bfa13ac6738a 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -200,65 +200,7 @@ static int proc_root_link(struct inode *inode, struct path *path)
return result;
}
-static struct mm_struct *__check_mem_permission(struct task_struct *task)
-{
- struct mm_struct *mm;
-
- mm = get_task_mm(task);
- if (!mm)
- return ERR_PTR(-EINVAL);
-
- /*
- * A task can always look at itself, in case it chooses
- * to use system calls instead of load instructions.
- */
- if (task == current)
- return mm;
-
- /*
- * If current is actively ptrace'ing, and would also be
- * permitted to freshly attach with ptrace now, permit it.
- */
- if (task_is_stopped_or_traced(task)) {
- int match;
- rcu_read_lock();
- match = (tracehook_tracer_task(task) == current);
- rcu_read_unlock();
- if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH))
- return mm;
- }
-
- /*
- * No one else is allowed.
- */
- mmput(mm);
- return ERR_PTR(-EPERM);
-}
-
-/*
- * If current may access user memory in @task return a reference to the
- * corresponding mm, otherwise ERR_PTR.
- */
-static struct mm_struct *check_mem_permission(struct task_struct *task)
-{
- struct mm_struct *mm;
- int err;
-
- /*
- * Avoid racing if task exec's as we might get a new mm but validate
- * against old credentials.
- */
- err = mutex_lock_killable(&task->signal->cred_guard_mutex);
- if (err)
- return ERR_PTR(err);
-
- mm = __check_mem_permission(task);
- mutex_unlock(&task->signal->cred_guard_mutex);
-
- return mm;
-}
-
-struct mm_struct *mm_for_maps(struct task_struct *task)
+static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
{
struct mm_struct *mm;
int err;
@@ -279,6 +221,11 @@ struct mm_struct *mm_for_maps(struct task_struct *task)
return mm;
}
+struct mm_struct *mm_for_maps(struct task_struct *task)
+{
+ return mm_access(task, PTRACE_MODE_READ);
+}
+
static int proc_pid_cmdline(struct task_struct *task, char * buffer)
{
int res = 0;
@@ -823,136 +770,99 @@ static const struct file_operations proc_single_file_operations = {
static int mem_open(struct inode* inode, struct file* file)
{
- file->private_data = (void*)((long)current->self_exec_id);
- /* OK to pass negative loff_t, we can catch out-of-range */
- file->f_mode |= FMODE_UNSIGNED_OFFSET;
- return 0;
-}
-
-static ssize_t mem_read(struct file * file, char __user * buf,
- size_t count, loff_t *ppos)
-{
struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
- char *page;
- unsigned long src = *ppos;
- int ret = -ESRCH;
struct mm_struct *mm;
if (!task)
- goto out_no_task;
+ return -ESRCH;
- ret = -ENOMEM;
- page = (char *)__get_free_page(GFP_TEMPORARY);
- if (!page)
- goto out;
+ mm = mm_access(task, PTRACE_MODE_ATTACH);
+ put_task_struct(task);
- mm = check_mem_permission(task);
- ret = PTR_ERR(mm);
if (IS_ERR(mm))
- goto out_free;
-
- ret = -EIO;
-
- if (file->private_data != (void*)((long)current->self_exec_id))
- goto out_put;
-
- ret = 0;
-
- while (count > 0) {
- int this_len, retval;
-
- this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
- retval = access_remote_vm(mm, src, page, this_len, 0);
- if (!retval) {
- if (!ret)
- ret = -EIO;
- break;
- }
+ return PTR_ERR(mm);
- if (copy_to_user(buf, page, retval)) {
- ret = -EFAULT;
- break;
- }
-
- ret += retval;
- src += retval;
- buf += retval;
- count -= retval;
+ if (mm) {
+ /* ensure this mm_struct can't be freed */
+ atomic_inc(&mm->mm_count);
+ /* but do not pin its memory */
+ mmput(mm);
}
- *ppos = src;
-out_put:
- mmput(mm);
-out_free:
- free_page((unsigned long) page);
-out:
- put_task_struct(task);
-out_no_task:
- return ret;
-}
+ /* OK to pass negative loff_t, we can catch out-of-range */
+ file->f_mode |= FMODE_UNSIGNED_OFFSET;
+ file->private_data = mm;
-#define mem_write NULL
+ return 0;
+}
-#ifndef mem_write
-/* This is a security hazard */
-static ssize_t mem_write(struct file * file, const char __user *buf,
- size_t count, loff_t *ppos)
+static ssize_t mem_rw(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos, int write)
{
- int copied;
+ struct mm_struct *mm = file->private_data;
+ unsigned long addr = *ppos;
+ ssize_t copied;
char *page;
- struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
- unsigned long dst = *ppos;
- struct mm_struct *mm;
- copied = -ESRCH;
- if (!task)
- goto out_no_task;
+ if (!mm)
+ return 0;
- copied = -ENOMEM;
page = (char *)__get_free_page(GFP_TEMPORARY);
if (!page)
- goto out_task;
-
- mm = check_mem_permission(task);
- copied = PTR_ERR(mm);
- if (IS_ERR(mm))
- goto out_free;
-
- copied = -EIO;
- if (file->private_data != (void *)((long)current->self_exec_id))
- goto out_mm;
+ return -ENOMEM;
copied = 0;
+ if (!atomic_inc_not_zero(&mm->mm_users))
+ goto free;
+
while (count > 0) {
- int this_len, retval;
+ int this_len = min_t(int, count, PAGE_SIZE);
- this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
- if (copy_from_user(page, buf, this_len)) {
+ if (write && copy_from_user(page, buf, this_len)) {
copied = -EFAULT;
break;
}
- retval = access_remote_vm(mm, dst, page, this_len, 1);
- if (!retval) {
+
+ this_len = access_remote_vm(mm, addr, page, this_len, write);
+ if (!this_len) {
if (!copied)
copied = -EIO;
break;
}
- copied += retval;
- buf += retval;
- dst += retval;
- count -= retval;
+
+ if (!write && copy_to_user(buf, page, this_len)) {
+ copied = -EFAULT;
+ break;
+ }
+
+ buf += this_len;
+ addr += this_len;
+ copied += this_len;
+ count -= this_len;
}
- *ppos = dst;
+ *ppos = addr;
-out_mm:
mmput(mm);
-out_free:
+free:
free_page((unsigned long) page);
-out_task:
- put_task_struct(task);
-out_no_task:
return copied;
}
+
+static ssize_t mem_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return mem_rw(file, buf, count, ppos, 0);
+}
+
+#define mem_write NULL
+
+#ifndef mem_write
+/* This is a security hazard */
+static ssize_t mem_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ return mem_rw(file, (char __user*)buf, count, ppos, 1);
+}
#endif
loff_t mem_lseek(struct file *file, loff_t offset, int orig)
@@ -971,11 +881,20 @@ loff_t mem_lseek(struct file *file, loff_t offset, int orig)
return file->f_pos;
}
+static int mem_release(struct inode *inode, struct file *file)
+{
+ struct mm_struct *mm = file->private_data;
+ if (mm)
+ mmdrop(mm);
+ return 0;
+}
+
static const struct file_operations proc_mem_operations = {
.llseek = mem_lseek,
.read = mem_read,
.write = mem_write,
.open = mem_open,
+ .release = mem_release,
};
static ssize_t environ_read(struct file *file, char __user *buf,
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
index be177f702acb..d6c078ea1489 100644
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -54,7 +54,7 @@ static struct dentry *proc_ns_instantiate(struct inode *dir,
ei->ns_ops = ns_ops;
ei->ns = ns;
- dentry->d_op = &pid_dentry_operations;
+ d_set_d_op(dentry, &pid_dentry_operations);
d_add(dentry, inode);
/* Close the race of the process dying before we return the dentry */
if (pid_revalidate(dentry, NULL))
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index c7d4ee663f14..55a1f494711c 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -407,6 +407,9 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
} else {
spin_unlock(&walk->mm->page_table_lock);
}
+
+ if (pmd_trans_unstable(pmd))
+ return 0;
/*
* The mmap_sem held all the way back in m_start() is what
* keeps khugepaged out of here and from collapsing things
@@ -505,6 +508,8 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
struct page *page;
split_huge_page_pmd(walk->mm, pmd);
+ if (pmd_trans_unstable(pmd))
+ return 0;
pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
for (; addr != end; pte++, addr += PAGE_SIZE) {
@@ -516,6 +521,9 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
if (!page)
continue;
+ if (PageReserved(page))
+ continue;
+
/* Clear accessed and referenced bits. */
ptep_test_and_clear_young(vma, addr, pte);
ClearPageReferenced(page);
@@ -665,6 +673,8 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
int err = 0;
split_huge_page_pmd(walk->mm, pmd);
+ if (pmd_trans_unstable(pmd))
+ return 0;
/* find the first VMA at or above 'addr' */
vma = find_vma(walk->mm, addr);
@@ -956,6 +966,8 @@ static int gather_pte_stats(pmd_t *pmd, unsigned long addr,
spin_unlock(&walk->mm->page_table_lock);
}
+ if (pmd_trans_unstable(pmd))
+ return 0;
orig_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
do {
struct page *page = can_gather_numa_stats(*pte, md->vma, addr);
diff --git a/fs/proc/uptime.c b/fs/proc/uptime.c
index 766b1d456050..29166ecd03ae 100644
--- a/fs/proc/uptime.c
+++ b/fs/proc/uptime.c
@@ -11,15 +11,20 @@ static int uptime_proc_show(struct seq_file *m, void *v)
{
struct timespec uptime;
struct timespec idle;
+ cputime64_t idletime;
+ u64 nsec;
+ u32 rem;
int i;
- cputime_t idletime = cputime_zero;
+ idletime = 0;
for_each_possible_cpu(i)
idletime = cputime64_add(idletime, kstat_cpu(i).cpustat.idle);
do_posix_clock_monotonic_gettime(&uptime);
monotonic_to_bootbased(&uptime);
- cputime_to_timespec(idletime, &idle);
+ nsec = cputime64_to_jiffies64(idletime) * TICK_NSEC;
+ idle.tv_sec = div_u64_rem(nsec, NSEC_PER_SEC, &rem);
+ idle.tv_nsec = rem;
seq_printf(m, "%lu.%02lu %lu.%02lu\n",
(unsigned long) uptime.tv_sec,
(uptime.tv_nsec / (NSEC_PER_SEC / 100)),
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index aa91089162cb..f19dfbf60002 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -453,16 +453,20 @@ int remove_save_link(struct inode *inode, int truncate)
static void reiserfs_kill_sb(struct super_block *s)
{
if (REISERFS_SB(s)) {
- if (REISERFS_SB(s)->xattr_root) {
- d_invalidate(REISERFS_SB(s)->xattr_root);
- dput(REISERFS_SB(s)->xattr_root);
- REISERFS_SB(s)->xattr_root = NULL;
- }
- if (REISERFS_SB(s)->priv_root) {
- d_invalidate(REISERFS_SB(s)->priv_root);
- dput(REISERFS_SB(s)->priv_root);
- REISERFS_SB(s)->priv_root = NULL;
- }
+ /*
+ * Force any pending inode evictions to occur now. Any
+ * inodes to be removed that have extended attributes
+ * associated with them need to clean them up before
+ * we can release the extended attribute root dentries.
+ * shrink_dcache_for_umount will BUG if we don't release
+ * those before it's called so ->put_super is too late.
+ */
+ shrink_dcache_sb(s);
+
+ dput(REISERFS_SB(s)->xattr_root);
+ REISERFS_SB(s)->xattr_root = NULL;
+ dput(REISERFS_SB(s)->priv_root);
+ REISERFS_SB(s)->priv_root = NULL;
}
kill_block_super(s);
@@ -1164,7 +1168,8 @@ static void handle_quota_files(struct super_block *s, char **qf_names,
kfree(REISERFS_SB(s)->s_qf_names[i]);
REISERFS_SB(s)->s_qf_names[i] = qf_names[i];
}
- REISERFS_SB(s)->s_jquota_fmt = *qfmt;
+ if (*qfmt)
+ REISERFS_SB(s)->s_jquota_fmt = *qfmt;
}
#endif
diff --git a/fs/signalfd.c b/fs/signalfd.c
index 492465b451dd..7ae2a574cb25 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -30,6 +30,21 @@
#include <linux/signalfd.h>
#include <linux/syscalls.h>
+void signalfd_cleanup(struct sighand_struct *sighand)
+{
+ wait_queue_head_t *wqh = &sighand->signalfd_wqh;
+ /*
+ * The lockless check can race with remove_wait_queue() in progress,
+ * but in this case its caller should run under rcu_read_lock() and
+ * sighand_cachep is SLAB_DESTROY_BY_RCU, we can safely return.
+ */
+ if (likely(!waitqueue_active(wqh)))
+ return;
+
+ /* wait_queue_t->func(POLLFREE) should do remove_wait_queue() */
+ wake_up_poll(wqh, POLLHUP | POLLFREE);
+}
+
struct signalfd_ctx {
sigset_t sigmask;
};
diff --git a/fs/splice.c b/fs/splice.c
index aa866d309695..9d890085f9ba 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -31,6 +31,7 @@
#include <linux/uio.h>
#include <linux/security.h>
#include <linux/gfp.h>
+#include <linux/socket.h>
/*
* Attempt to steal a page from a pipe buffer. This should perhaps go into
@@ -691,7 +692,9 @@ static int pipe_to_sendpage(struct pipe_inode_info *pipe,
if (!likely(file->f_op && file->f_op->sendpage))
return -EINVAL;
- more = (sd->flags & SPLICE_F_MORE) || sd->len < sd->total_len;
+ more = (sd->flags & SPLICE_F_MORE) ? MSG_MORE : 0;
+ if (sd->len < sd->total_len)
+ more |= MSG_SENDPAGE_NOTLAST;
return file->f_op->sendpage(file, buf->page, buf->offset,
sd->len, &pos, more);
}
diff --git a/fs/super.c b/fs/super.c
index ab3d672db0de..caf4dfa28eed 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -1009,6 +1009,8 @@ int freeze_super(struct super_block *sb)
printk(KERN_ERR
"VFS:Filesystem freeze failed\n");
sb->s_frozen = SB_UNFROZEN;
+ smp_wmb();
+ wake_up(&sb->s_wait_unfrozen);
deactivate_locked_super(sb);
return ret;
}
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 0a12eb89cd32..a494413e4865 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -136,12 +136,13 @@ static int sysfs_sd_setsecdata(struct sysfs_dirent *sd, void **secdata, u32 *sec
void *old_secdata;
size_t old_secdata_len;
- iattrs = sd->s_iattr;
- if (!iattrs)
- iattrs = sysfs_init_inode_attrs(sd);
- if (!iattrs)
- return -ENOMEM;
+ if (!sd->s_iattr) {
+ sd->s_iattr = sysfs_init_inode_attrs(sd);
+ if (!sd->s_iattr)
+ return -ENOMEM;
+ }
+ iattrs = sd->s_iattr;
old_secdata = iattrs->ia_secdata;
old_secdata_len = iattrs->ia_secdata_len;
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index a811ac4a26bb..fd75b635daeb 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -121,20 +121,21 @@ const char *dbg_key_str1(const struct ubifs_info *c,
const union ubifs_key *key);
/*
- * DBGKEY macros require @dbg_lock to be held, which it is in the dbg message
- * macros.
+ * TODO: these macros are now broken because there is no locking around them
+ * and we use a global buffer for the key string. This means that in case of
+ * concurrent execution we will end up with incorrect and messy key strings.
*/
#define DBGKEY(key) dbg_key_str0(c, (key))
#define DBGKEY1(key) dbg_key_str1(c, (key))
-#define ubifs_dbg_msg(type, fmt, ...) do { \
- spin_lock(&dbg_lock); \
- pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__); \
- spin_unlock(&dbg_lock); \
-} while (0)
+#define ubifs_dbg_msg(type, fmt, ...) \
+ pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__)
/* Just a debugging messages not related to any specific UBIFS subsystem */
-#define dbg_msg(fmt, ...) ubifs_dbg_msg("msg", fmt, ##__VA_ARGS__)
+#define dbg_msg(fmt, ...) \
+ printk(KERN_DEBUG "UBIFS DBG (pid %d): %s: " fmt "\n", current->pid, \
+ __func__, ##__VA_ARGS__)
+
/* General messages */
#define dbg_gen(fmt, ...) ubifs_dbg_msg("gen", fmt, ##__VA_ARGS__)
/* Additional journal messages */
diff --git a/fs/udf/file.c b/fs/udf/file.c
index 2a346bb1d9f5..3438b0000413 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -125,7 +125,6 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
err = udf_expand_file_adinicb(inode);
if (err) {
udf_debug("udf_expand_adinicb: err=%d\n", err);
- up_write(&iinfo->i_data_sem);
return err;
}
} else {
@@ -133,9 +132,10 @@ static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
iinfo->i_lenAlloc = pos + count;
else
iinfo->i_lenAlloc = inode->i_size;
+ up_write(&iinfo->i_data_sem);
}
- }
- up_write(&iinfo->i_data_sem);
+ } else
+ up_write(&iinfo->i_data_sem);
retval = generic_file_aio_write(iocb, iov, nr_segs, ppos);
if (retval > 0)
@@ -201,12 +201,10 @@ out:
static int udf_release_file(struct inode *inode, struct file *filp)
{
if (filp->f_mode & FMODE_WRITE) {
- mutex_lock(&inode->i_mutex);
down_write(&UDF_I(inode)->i_data_sem);
udf_discard_prealloc(inode);
udf_truncate_tail_extent(inode);
up_write(&UDF_I(inode)->i_data_sem);
- mutex_unlock(&inode->i_mutex);
}
return 0;
}
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 1d1358ed80c1..262050f2eb6c 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -145,6 +145,12 @@ const struct address_space_operations udf_aops = {
.bmap = udf_bmap,
};
+/*
+ * Expand file stored in ICB to a normal one-block-file
+ *
+ * This function requires i_data_sem for writing and releases it.
+ * This function requires i_mutex held
+ */
int udf_expand_file_adinicb(struct inode *inode)
{
struct page *page;
@@ -163,9 +169,15 @@ int udf_expand_file_adinicb(struct inode *inode)
iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
/* from now on we have normal address_space methods */
inode->i_data.a_ops = &udf_aops;
+ up_write(&iinfo->i_data_sem);
mark_inode_dirty(inode);
return 0;
}
+ /*
+ * Release i_data_sem so that we can lock a page - page lock ranks
+ * above i_data_sem. i_mutex still protects us against file changes.
+ */
+ up_write(&iinfo->i_data_sem);
page = find_or_create_page(inode->i_mapping, 0, GFP_NOFS);
if (!page)
@@ -181,6 +193,7 @@ int udf_expand_file_adinicb(struct inode *inode)
SetPageUptodate(page);
kunmap(page);
}
+ down_write(&iinfo->i_data_sem);
memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0x00,
iinfo->i_lenAlloc);
iinfo->i_lenAlloc = 0;
@@ -190,17 +203,20 @@ int udf_expand_file_adinicb(struct inode *inode)
iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
/* from now on we have normal address_space methods */
inode->i_data.a_ops = &udf_aops;
+ up_write(&iinfo->i_data_sem);
err = inode->i_data.a_ops->writepage(page, &udf_wbc);
if (err) {
/* Restore everything back so that we don't lose data... */
lock_page(page);
kaddr = kmap(page);
+ down_write(&iinfo->i_data_sem);
memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr,
inode->i_size);
kunmap(page);
unlock_page(page);
iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB;
inode->i_data.a_ops = &udf_adinicb_aops;
+ up_write(&iinfo->i_data_sem);
}
page_cache_release(page);
mark_inode_dirty(inode);
@@ -1105,10 +1121,9 @@ int udf_setsize(struct inode *inode, loff_t newsize)
if (bsize <
(udf_file_entry_alloc_offset(inode) + newsize)) {
err = udf_expand_file_adinicb(inode);
- if (err) {
- up_write(&iinfo->i_data_sem);
+ if (err)
return err;
- }
+ down_write(&iinfo->i_data_sem);
} else
iinfo->i_lenAlloc = newsize;
}
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 7b27b063ff6d..7f0e18aa25d4 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -1830,6 +1830,12 @@ static void udf_close_lvid(struct super_block *sb)
le16_to_cpu(lvid->descTag.descCRCLength)));
lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag);
+ /*
+ * We set buffer uptodate unconditionally here to avoid spurious
+ * warnings from mark_buffer_dirty() when previous EIO has marked
+ * the buffer as !uptodate
+ */
+ set_buffer_uptodate(bh);
mark_buffer_dirty(bh);
sbi->s_lvid_dirty = 0;
mutex_unlock(&sbi->s_alloc_mutex);
diff --git a/fs/xfs/linux-2.6/xfs_acl.c b/fs/xfs/linux-2.6/xfs_acl.c
index 4b9fb915d445..f86e03487866 100644
--- a/fs/xfs/linux-2.6/xfs_acl.c
+++ b/fs/xfs/linux-2.6/xfs_acl.c
@@ -39,7 +39,7 @@ xfs_acl_from_disk(struct xfs_acl *aclp)
struct posix_acl_entry *acl_e;
struct posix_acl *acl;
struct xfs_acl_entry *ace;
- int count, i;
+ unsigned int count, i;
count = be32_to_cpu(aclp->acl_cnt);
if (count > XFS_ACL_MAX_ENTRIES)
diff --git a/fs/xfs/linux-2.6/xfs_discard.c b/fs/xfs/linux-2.6/xfs_discard.c
index 244e797dae32..572494faf262 100644
--- a/fs/xfs/linux-2.6/xfs_discard.c
+++ b/fs/xfs/linux-2.6/xfs_discard.c
@@ -68,7 +68,7 @@ xfs_trim_extents(
* Look up the longest btree in the AGF and start with it.
*/
error = xfs_alloc_lookup_le(cur, 0,
- XFS_BUF_TO_AGF(agbp)->agf_longest, &i);
+ be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_longest), &i);
if (error)
goto out_del_cursor;
@@ -84,7 +84,7 @@ xfs_trim_extents(
if (error)
goto out_del_cursor;
XFS_WANT_CORRUPTED_GOTO(i == 1, out_del_cursor);
- ASSERT(flen <= XFS_BUF_TO_AGF(agbp)->agf_longest);
+ ASSERT(flen <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_longest));
/*
* Too small? Give up.
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 28de70b91220..e6ac98c112e3 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -871,27 +871,6 @@ xfs_fs_dirty_inode(
}
STATIC int
-xfs_log_inode(
- struct xfs_inode *ip)
-{
- struct xfs_mount *mp = ip->i_mount;
- struct xfs_trans *tp;
- int error;
-
- tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS);
- error = xfs_trans_reserve(tp, 0, XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0);
- if (error) {
- xfs_trans_cancel(tp, 0);
- return error;
- }
-
- xfs_ilock(ip, XFS_ILOCK_EXCL);
- xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);
- xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
- return xfs_trans_commit(tp, 0);
-}
-
-STATIC int
xfs_fs_write_inode(
struct inode *inode,
struct writeback_control *wbc)
@@ -904,10 +883,8 @@ xfs_fs_write_inode(
if (XFS_FORCED_SHUTDOWN(mp))
return -XFS_ERROR(EIO);
- if (!ip->i_update_core)
- return 0;
- if (wbc->sync_mode == WB_SYNC_ALL) {
+ if (wbc->sync_mode == WB_SYNC_ALL || wbc->for_kupdate) {
/*
* Make sure the inode has made it it into the log. Instead
* of forcing it all the way to stable storage using a
@@ -916,11 +893,14 @@ xfs_fs_write_inode(
* of synchronous log foces dramatically.
*/
xfs_ioend_wait(ip);
- error = xfs_log_inode(ip);
+ error = xfs_log_dirty_inode(ip, NULL, 0);
if (error)
goto out;
return 0;
} else {
+ if (!ip->i_update_core)
+ return 0;
+
/*
* We make this non-blocking if the inode is contended, return
* EAGAIN to indicate to the caller that they did not succeed.
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index b69688d0776e..2f277a04d67d 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -336,6 +336,32 @@ xfs_sync_fsdata(
return xfs_bwrite(mp, bp);
}
+int
+xfs_log_dirty_inode(
+ struct xfs_inode *ip,
+ struct xfs_perag *pag,
+ int flags)
+{
+ struct xfs_mount *mp = ip->i_mount;
+ struct xfs_trans *tp;
+ int error;
+
+ if (!ip->i_update_core)
+ return 0;
+
+ tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS);
+ error = xfs_trans_reserve(tp, 0, XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0);
+ if (error) {
+ xfs_trans_cancel(tp, 0);
+ return error;
+ }
+
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL);
+ xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+ return xfs_trans_commit(tp, 0);
+}
+
/*
* When remounting a filesystem read-only or freezing the filesystem, we have
* two phases to execute. This first phase is syncing the data before we
@@ -365,6 +391,17 @@ xfs_quiesce_data(
/* push and block till complete */
xfs_sync_data(mp, SYNC_WAIT);
+
+ /*
+ * Log all pending size and timestamp updates. The vfs writeback
+ * code is supposed to do this, but due to its overagressive
+ * livelock detection it will skip inodes where appending writes
+ * were written out in the first non-blocking sync phase if their
+ * completion took long enough that it happened after taking the
+ * timestamp for the cut-off in the blocking phase.
+ */
+ xfs_inode_ag_iterator(mp, xfs_log_dirty_inode, 0);
+
xfs_qm_sync(mp, SYNC_WAIT);
/* write superblock and hoover up shutdown errors */
diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h
index e3a6ad27415f..ef5b2ce42982 100644
--- a/fs/xfs/linux-2.6/xfs_sync.h
+++ b/fs/xfs/linux-2.6/xfs_sync.h
@@ -42,6 +42,8 @@ void xfs_quiesce_attr(struct xfs_mount *mp);
void xfs_flush_inodes(struct xfs_inode *ip);
+int xfs_log_dirty_inode(struct xfs_inode *ip, struct xfs_perag *pag, int flags);
+
int xfs_reclaim_inodes(struct xfs_mount *mp, int mode);
void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 3631783b2b53..ca752f05c31c 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -356,9 +356,20 @@ xfs_iget_cache_miss(
BUG();
}
- spin_lock(&pag->pag_ici_lock);
+ /*
+ * These values must be set before inserting the inode into the radix
+ * tree as the moment it is inserted a concurrent lookup (allowed by the
+ * RCU locking mechanism) can find it and that lookup must see that this
+ * is an inode currently under construction (i.e. that XFS_INEW is set).
+ * The ip->i_flags_lock that protects the XFS_INEW flag forms the
+ * memory barrier that ensures this detection works correctly at lookup
+ * time.
+ */
+ ip->i_udquot = ip->i_gdquot = NULL;
+ xfs_iflags_set(ip, XFS_INEW);
/* insert the new inode */
+ spin_lock(&pag->pag_ici_lock);
error = radix_tree_insert(&pag->pag_ici_root, agino, ip);
if (unlikely(error)) {
WARN_ON(error != -EEXIST);
@@ -366,11 +377,6 @@ xfs_iget_cache_miss(
error = EAGAIN;
goto out_preload_end;
}
-
- /* These values _must_ be set before releasing the radix tree lock! */
- ip->i_udquot = ip->i_gdquot = NULL;
- xfs_iflags_set(ip, XFS_INEW);
-
spin_unlock(&pag->pag_ici_lock);
radix_tree_preload_end();
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 04142caedb2b..b75fd67ca376 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -3159,37 +3159,26 @@ xlog_recover_process_iunlinks(
*/
continue;
}
+ /*
+ * Unlock the buffer so that it can be acquired in the normal
+ * course of the transaction to truncate and free each inode.
+ * Because we are not racing with anyone else here for the AGI
+ * buffer, we don't even need to hold it locked to read the
+ * initial unlinked bucket entries out of the buffer. We keep
+ * buffer reference though, so that it stays pinned in memory
+ * while we need the buffer.
+ */
agi = XFS_BUF_TO_AGI(agibp);
+ xfs_buf_unlock(agibp);
for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) {
agino = be32_to_cpu(agi->agi_unlinked[bucket]);
while (agino != NULLAGINO) {
- /*
- * Release the agi buffer so that it can
- * be acquired in the normal course of the
- * transaction to truncate and free the inode.
- */
- xfs_buf_relse(agibp);
-
agino = xlog_recover_process_one_iunlink(mp,
agno, agino, bucket);
-
- /*
- * Reacquire the agibuffer and continue around
- * the loop. This should never fail as we know
- * the buffer was good earlier on.
- */
- error = xfs_read_agi(mp, NULL, agno, &agibp);
- ASSERT(error == 0);
- agi = XFS_BUF_TO_AGI(agibp);
}
}
-
- /*
- * Release the buffer for the current agi so we can
- * go on to the next one.
- */
- xfs_buf_relse(agibp);
+ xfs_buf_rele(agibp);
}
mp->m_dmevmask = mp_dmevmask;
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 6cc4d41fb0db..59509ae0b273 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -554,7 +554,8 @@ xfs_readlink(
__func__, (unsigned long long) ip->i_ino,
(long long) pathlen);
ASSERT(0);
- return XFS_ERROR(EFSCORRUPTED);
+ error = XFS_ERROR(EFSCORRUPTED);
+ goto out;
}
diff --git a/include/acpi/acpi_numa.h b/include/acpi/acpi_numa.h
index 173972672175..451823cb8837 100644
--- a/include/acpi/acpi_numa.h
+++ b/include/acpi/acpi_numa.h
@@ -15,6 +15,7 @@ extern int pxm_to_node(int);
extern int node_to_pxm(int);
extern void __acpi_map_pxm_to_node(int, int);
extern int acpi_map_pxm_to_node(int);
+extern unsigned char acpi_srat_revision;
#endif /* CONFIG_ACPI_NUMA */
#endif /* __ACP_NUMA_H */
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 76bff2bff15e..831924a1bbd8 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -425,6 +425,8 @@ extern void untrack_pfn_vma(struct vm_area_struct *vma, unsigned long pfn,
unsigned long size);
#endif
+#ifdef CONFIG_MMU
+
#ifndef CONFIG_TRANSPARENT_HUGEPAGE
static inline int pmd_trans_huge(pmd_t pmd)
{
@@ -441,7 +443,84 @@ static inline int pmd_write(pmd_t pmd)
return 0;
}
#endif /* __HAVE_ARCH_PMD_WRITE */
+#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+
+#ifndef pmd_read_atomic
+static inline pmd_t pmd_read_atomic(pmd_t *pmdp)
+{
+ /*
+ * Depend on compiler for an atomic pmd read. NOTE: this is
+ * only going to work, if the pmdval_t isn't larger than
+ * an unsigned long.
+ */
+ return *pmdp;
+}
+#endif
+
+/*
+ * This function is meant to be used by sites walking pagetables with
+ * the mmap_sem hold in read mode to protect against MADV_DONTNEED and
+ * transhuge page faults. MADV_DONTNEED can convert a transhuge pmd
+ * into a null pmd and the transhuge page fault can convert a null pmd
+ * into an hugepmd or into a regular pmd (if the hugepage allocation
+ * fails). While holding the mmap_sem in read mode the pmd becomes
+ * stable and stops changing under us only if it's not null and not a
+ * transhuge pmd. When those races occurs and this function makes a
+ * difference vs the standard pmd_none_or_clear_bad, the result is
+ * undefined so behaving like if the pmd was none is safe (because it
+ * can return none anyway). The compiler level barrier() is critically
+ * important to compute the two checks atomically on the same pmdval.
+ *
+ * For 32bit kernels with a 64bit large pmd_t this automatically takes
+ * care of reading the pmd atomically to avoid SMP race conditions
+ * against pmd_populate() when the mmap_sem is hold for reading by the
+ * caller (a special atomic read not done by "gcc" as in the generic
+ * version above, is also needed when THP is disabled because the page
+ * fault can populate the pmd from under us).
+ */
+static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd)
+{
+ pmd_t pmdval = pmd_read_atomic(pmd);
+ /*
+ * The barrier will stabilize the pmdval in a register or on
+ * the stack so that it will stop changing under the code.
+ */
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+ barrier();
#endif
+ if (pmd_none(pmdval))
+ return 1;
+ if (unlikely(pmd_bad(pmdval))) {
+ if (!pmd_trans_huge(pmdval))
+ pmd_clear_bad(pmd);
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * This is a noop if Transparent Hugepage Support is not built into
+ * the kernel. Otherwise it is equivalent to
+ * pmd_none_or_trans_huge_or_clear_bad(), and shall only be called in
+ * places that already verified the pmd is not none and they want to
+ * walk ptes while holding the mmap sem in read mode (write mode don't
+ * need this). If THP is not enabled, the pmd can't go away under the
+ * code even if MADV_DONTNEED runs, but if THP is enabled we need to
+ * run a pmd_trans_unstable before walking the ptes after
+ * split_huge_page_pmd returns (because it may have run when the pmd
+ * become null, but then a page fault can map in a THP and not a
+ * regular page).
+ */
+static inline int pmd_trans_unstable(pmd_t *pmd)
+{
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+ return pmd_none_or_trans_huge_or_clear_bad(pmd);
+#else
+ return 0;
+#endif
+}
+
+#endif /* CONFIG_MMU */
#endif /* !__ASSEMBLY__ */
diff --git a/include/asm-generic/poll.h b/include/asm-generic/poll.h
index 44bce836d350..9ce7f44aebd2 100644
--- a/include/asm-generic/poll.h
+++ b/include/asm-generic/poll.h
@@ -28,6 +28,8 @@
#define POLLRDHUP 0x2000
#endif
+#define POLLFREE 0x4000 /* currently only for epoll */
+
struct pollfd {
int fd;
short events;
diff --git a/include/asm-generic/statfs.h b/include/asm-generic/statfs.h
index 0fd28e028de1..c749af9c0983 100644
--- a/include/asm-generic/statfs.h
+++ b/include/asm-generic/statfs.h
@@ -15,7 +15,7 @@ typedef __kernel_fsid_t fsid_t;
* with a 10' pole.
*/
#ifndef __statfs_word
-#if BITS_PER_LONG == 64
+#if __BITS_PER_LONG == 64
#define __statfs_word long
#else
#define __statfs_word __u32
diff --git a/include/asm-generic/unistd.h b/include/asm-generic/unistd.h
index 4f76959397fa..5518963e38b0 100644
--- a/include/asm-generic/unistd.h
+++ b/include/asm-generic/unistd.h
@@ -218,7 +218,7 @@ __SC_COMP(__NR_pwritev, sys_pwritev, compat_sys_pwritev)
/* fs/sendfile.c */
#define __NR3264_sendfile 71
-__SC_3264(__NR3264_sendfile, sys_sendfile64, sys_sendfile)
+__SYSCALL(__NR3264_sendfile, sys_sendfile64)
/* fs/select.c */
#define __NR_pselect6 72
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 738b3a5faa12..40aaebf50af7 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1323,6 +1323,7 @@ extern int drm_getmagic(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int drm_authmagic(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+extern int drm_remove_magic(struct drm_master *master, drm_magic_t magic);
/* Cache management (drm_cache.c) */
void drm_clflush_pages(struct page *pages[], unsigned long num_pages);
diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h
index 14b6cd022284..4306811f8a14 100644
--- a/include/drm/drm_pciids.h
+++ b/include/drm/drm_pciids.h
@@ -181,6 +181,7 @@
{0x1002, 0x6747, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6748, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6749, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x674A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6758, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
@@ -198,6 +199,7 @@
{0x1002, 0x6767, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6768, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6770, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6771, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6778, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6779, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
diff --git a/include/linux/ahci_platform.h b/include/linux/ahci_platform.h
index be3d9a77d6ed..73a25005d88a 100644
--- a/include/linux/ahci_platform.h
+++ b/include/linux/ahci_platform.h
@@ -23,6 +23,8 @@ struct ata_port_info;
struct ahci_platform_data {
int (*init)(struct device *dev, void __iomem *addr);
void (*exit)(struct device *dev);
+ int (*suspend)(struct device *dev);
+ int (*resume)(struct device *dev);
const struct ata_port_info *ata_port_info;
unsigned int force_port_map;
unsigned int mask_port_map;
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index a3ef66a2a083..fc8a3ffce320 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -50,6 +50,26 @@ static inline unsigned long hweight_long(unsigned long w)
}
/**
+ * rol64 - rotate a 64-bit value left
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u64 rol64(__u64 word, unsigned int shift)
+{
+ return (word << shift) | (word >> (64 - shift));
+}
+
+/**
+ * ror64 - rotate a 64-bit value right
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u64 ror64(__u64 word, unsigned int shift)
+{
+ return (word >> shift) | (word << (64 - shift));
+}
+
+/**
* rol32 - rotate a 32-bit value left
* @word: value to rotate
* @shift: bits to roll
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 1a23722e8878..1b130216ccd4 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -670,6 +670,9 @@ extern int blk_insert_cloned_request(struct request_queue *q,
struct request *rq);
extern void blk_delay_queue(struct request_queue *, unsigned long);
extern void blk_recount_segments(struct request_queue *, struct bio *);
+extern int scsi_verify_blk_ioctl(struct block_device *, unsigned int);
+extern int scsi_cmd_blk_ioctl(struct block_device *, fmode_t,
+ unsigned int, void __user *);
extern int scsi_cmd_ioctl(struct request_queue *, struct gendisk *, fmode_t,
unsigned int, void __user *);
extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t,
@@ -798,9 +801,6 @@ extern void blk_unprep_request(struct request *);
*/
extern struct request_queue *blk_init_queue_node(request_fn_proc *rfn,
spinlock_t *lock, int node_id);
-extern struct request_queue *blk_init_allocated_queue_node(struct request_queue *,
- request_fn_proc *,
- spinlock_t *, int node_id);
extern struct request_queue *blk_init_queue(request_fn_proc *, spinlock_t *);
extern struct request_queue *blk_init_allocated_queue(struct request_queue *,
request_fn_proc *, spinlock_t *);
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 846bb1792572..edaf3900f6bc 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -561,5 +561,9 @@ extern ssize_t compat_rw_copy_check_uvector(int type,
extern void __user *compat_alloc_user_space(unsigned long len);
+#else
+
+#define is_compat_task() (0)
+
#endif /* CONFIG_COMPAT */
#endif /* _LINUX_COMPAT_H */
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 8f848e462b25..f13bb6dd156f 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -207,6 +207,7 @@ struct dentry_operations {
#define DCACHE_CANT_MOUNT 0x0100
#define DCACHE_GENOCIDE 0x0200
+#define DCACHE_SHRINK_LIST 0x0400
#define DCACHE_OP_HASH 0x1000
#define DCACHE_OP_COMPARE 0x2000
diff --git a/include/linux/dmapool.h b/include/linux/dmapool.h
index 022e34fcbd1b..450950163272 100644
--- a/include/linux/dmapool.h
+++ b/include/linux/dmapool.h
@@ -22,6 +22,11 @@ void dma_pool_destroy(struct dma_pool *pool);
void *dma_pool_alloc(struct dma_pool *pool, gfp_t mem_flags,
dma_addr_t *handle);
+#ifdef CONFIG_FSL_UTP
+void *dma_pool_alloc_nonbufferable(struct dma_pool *pool, gfp_t mem_flags,
+ dma_addr_t *handle);
+#endif
+
void dma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t addr);
/*
diff --git a/include/linux/efi.h b/include/linux/efi.h
index e376270cd26e..e0ce165aa59a 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -347,7 +347,18 @@ extern int __init efi_setup_pcdp_console(char *);
#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001
#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002
#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004
-
+#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x0000000000000008
+#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x0000000000000010
+#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x0000000000000020
+#define EFI_VARIABLE_APPEND_WRITE 0x0000000000000040
+
+#define EFI_VARIABLE_MASK (EFI_VARIABLE_NON_VOLATILE | \
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | \
+ EFI_VARIABLE_RUNTIME_ACCESS | \
+ EFI_VARIABLE_HARDWARE_ERROR_RECORD | \
+ EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \
+ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \
+ EFI_VARIABLE_APPEND_WRITE)
/*
* EFI Device Path information
*/
diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h
index f362733186a5..657ab55beda0 100644
--- a/include/linux/eventpoll.h
+++ b/include/linux/eventpoll.h
@@ -61,6 +61,7 @@ struct file;
static inline void eventpoll_init_file(struct file *file)
{
INIT_LIST_HEAD(&file->f_ep_links);
+ INIT_LIST_HEAD(&file->f_tfile_llink);
}
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 6a8274877171..f9d013d09bc7 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -997,6 +997,7 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf,
/* drivers/video/fbmem.c */
extern int register_framebuffer(struct fb_info *fb_info);
extern int unregister_framebuffer(struct fb_info *fb_info);
+extern int unlink_framebuffer(struct fb_info *fb_info);
extern void remove_conflicting_framebuffers(struct apertures_struct *a,
const char *name, bool primary);
extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7b17db7c5a6e..96b10354c741 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -969,6 +969,7 @@ struct file {
#ifdef CONFIG_EPOLL
/* Used by fs/eventpoll.c to link all the hooks to this file */
struct list_head f_ep_links;
+ struct list_head f_tfile_llink;
#endif /* #ifdef CONFIG_EPOLL */
struct address_space *f_mapping;
#ifdef CONFIG_DEBUG_WRITECOUNT
@@ -2028,6 +2029,7 @@ extern void unregister_blkdev(unsigned int, const char *);
extern struct block_device *bdget(dev_t);
extern struct block_device *bdgrab(struct block_device *bdev);
extern void bd_set_size(struct block_device *, loff_t size);
+extern sector_t blkdev_max_block(struct block_device *bdev);
extern void bd_forget(struct inode *inode);
extern void bdput(struct block_device *);
extern void invalidate_bdev(struct block_device *);
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 300d7582006e..7a1ce1816441 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -221,12 +221,6 @@ static inline void part_pack_uuid(const u8 *uuid_str, u8 *to)
}
}
-static inline char *part_unpack_uuid(const u8 *uuid, char *out)
-{
- sprintf(out, "%pU", uuid);
- return out;
-}
-
static inline int disk_max_parts(struct gendisk *disk)
{
if (disk->flags & GENHD_FL_EXT_DEVT)
@@ -594,6 +588,7 @@ extern char *disk_name (struct gendisk *hd, int partno, char *buf);
extern int disk_expand_part_tbl(struct gendisk *disk, int target);
extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev);
+extern int invalidate_partitions(struct gendisk *disk, struct block_device *bdev);
extern struct hd_struct * __must_check add_partition(struct gendisk *disk,
int partno, sector_t start,
sector_t len, int flags,
diff --git a/include/linux/i2c/twl4030-madc.h b/include/linux/i2c/twl4030-madc.h
index 6427d298fbfc..530e11ba0738 100644
--- a/include/linux/i2c/twl4030-madc.h
+++ b/include/linux/i2c/twl4030-madc.h
@@ -129,6 +129,10 @@ enum sample_type {
#define REG_BCICTL2 0x024
#define TWL4030_BCI_ITHSENS 0x007
+/* Register and bits for GPBR1 register */
+#define TWL4030_REG_GPBR1 0x0c
+#define TWL4030_GPBR1_MADC_HFCLK_EN (1 << 7)
+
struct twl4030_madc_user_parms {
int channel;
int average;
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 47e8dbea85c8..da3e76d00105 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -77,6 +77,19 @@
} \
)
+/*
+ * Multiplies an integer by a fraction, while avoiding unnecessary
+ * overflow or loss of precision.
+ */
+#define mult_frac(x, numer, denom)( \
+{ \
+ typeof(x) quot = (x) / (denom); \
+ typeof(x) rem = (x) % (denom); \
+ (quot * (numer)) + ((rem * (numer)) / (denom)); \
+} \
+)
+
+
#define _RET_IP_ (unsigned long)__builtin_return_address(0)
#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; })
diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h
index 10ca03d0a250..f7192fb4237f 100644
--- a/include/linux/kgdb.h
+++ b/include/linux/kgdb.h
@@ -63,7 +63,8 @@ enum kgdb_bptype {
BP_HARDWARE_BREAKPOINT,
BP_WRITE_WATCHPOINT,
BP_READ_WATCHPOINT,
- BP_ACCESS_WATCHPOINT
+ BP_ACCESS_WATCHPOINT,
+ BP_POKE_BREAKPOINT,
};
enum kgdb_bpstate {
@@ -207,8 +208,8 @@ extern void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc);
/* Optional functions. */
extern int kgdb_validate_break_address(unsigned long addr);
-extern int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr);
-extern int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle);
+extern int kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt);
+extern int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt);
/**
* kgdb_arch_late - Perform any architecture specific initalization.
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 31ebb59cbd2f..82d5476e69cc 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -554,6 +554,7 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id);
#ifdef CONFIG_IOMMU_API
int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot);
+void kvm_iommu_unmap_pages(struct kvm *kvm, struct kvm_memory_slot *slot);
int kvm_iommu_map_guest(struct kvm *kvm);
int kvm_iommu_unmap_guest(struct kvm *kvm);
int kvm_assign_device(struct kvm *kvm,
@@ -567,6 +568,11 @@ static inline int kvm_iommu_map_pages(struct kvm *kvm,
return 0;
}
+static inline void kvm_iommu_unmap_pages(struct kvm *kvm,
+ struct kvm_memory_slot *slot)
+{
+}
+
static inline int kvm_iommu_map_guest(struct kvm *kvm)
{
return -ENODEV;
diff --git a/include/linux/lglock.h b/include/linux/lglock.h
index f549056fb20b..87f402ccec55 100644
--- a/include/linux/lglock.h
+++ b/include/linux/lglock.h
@@ -22,6 +22,7 @@
#include <linux/spinlock.h>
#include <linux/lockdep.h>
#include <linux/percpu.h>
+#include <linux/cpu.h>
/* can make br locks by using local lock for read side, global lock for write */
#define br_lock_init(name) name##_lock_init()
@@ -72,9 +73,31 @@
#define DEFINE_LGLOCK(name) \
\
+ DEFINE_SPINLOCK(name##_cpu_lock); \
+ cpumask_t name##_cpus __read_mostly; \
DEFINE_PER_CPU(arch_spinlock_t, name##_lock); \
DEFINE_LGLOCK_LOCKDEP(name); \
\
+ static int \
+ name##_lg_cpu_callback(struct notifier_block *nb, \
+ unsigned long action, void *hcpu) \
+ { \
+ switch (action & ~CPU_TASKS_FROZEN) { \
+ case CPU_UP_PREPARE: \
+ spin_lock(&name##_cpu_lock); \
+ cpu_set((unsigned long)hcpu, name##_cpus); \
+ spin_unlock(&name##_cpu_lock); \
+ break; \
+ case CPU_UP_CANCELED: case CPU_DEAD: \
+ spin_lock(&name##_cpu_lock); \
+ cpu_clear((unsigned long)hcpu, name##_cpus); \
+ spin_unlock(&name##_cpu_lock); \
+ } \
+ return NOTIFY_OK; \
+ } \
+ static struct notifier_block name##_lg_cpu_notifier = { \
+ .notifier_call = name##_lg_cpu_callback, \
+ }; \
void name##_lock_init(void) { \
int i; \
LOCKDEP_INIT_MAP(&name##_lock_dep_map, #name, &name##_lock_key, 0); \
@@ -83,6 +106,11 @@
lock = &per_cpu(name##_lock, i); \
*lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; \
} \
+ register_hotcpu_notifier(&name##_lg_cpu_notifier); \
+ get_online_cpus(); \
+ for_each_online_cpu(i) \
+ cpu_set(i, name##_cpus); \
+ put_online_cpus(); \
} \
EXPORT_SYMBOL(name##_lock_init); \
\
@@ -124,9 +152,9 @@
\
void name##_global_lock_online(void) { \
int i; \
- preempt_disable(); \
+ spin_lock(&name##_cpu_lock); \
rwlock_acquire(&name##_lock_dep_map, 0, 0, _RET_IP_); \
- for_each_online_cpu(i) { \
+ for_each_cpu(i, &name##_cpus) { \
arch_spinlock_t *lock; \
lock = &per_cpu(name##_lock, i); \
arch_spin_lock(lock); \
@@ -137,12 +165,12 @@
void name##_global_unlock_online(void) { \
int i; \
rwlock_release(&name##_lock_dep_map, 1, _RET_IP_); \
- for_each_online_cpu(i) { \
+ for_each_cpu(i, &name##_cpus) { \
arch_spinlock_t *lock; \
lock = &per_cpu(name##_lock, i); \
arch_spin_unlock(lock); \
} \
- preempt_enable(); \
+ spin_unlock(&name##_cpu_lock); \
} \
EXPORT_SYMBOL(name##_global_unlock_online); \
\
diff --git a/include/linux/math64.h b/include/linux/math64.h
index 23fcdfcba81b..b8ba85544721 100644
--- a/include/linux/math64.h
+++ b/include/linux/math64.h
@@ -6,6 +6,8 @@
#if BITS_PER_LONG == 64
+#define div64_long(x,y) div64_s64((x),(y))
+
/**
* div_u64_rem - unsigned 64bit divide with 32bit divisor with remainder
*
@@ -45,6 +47,8 @@ static inline s64 div64_s64(s64 dividend, s64 divisor)
#elif BITS_PER_LONG == 32
+#define div64_long(x,y) div_s64((x),(y))
+
#ifndef div_u64_rem
static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
{
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 50940da6adf3..313a00eca40e 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -119,6 +119,8 @@ struct zone_reclaim_stat*
mem_cgroup_get_reclaim_stat_from_page(struct page *page);
extern void mem_cgroup_print_oom_info(struct mem_cgroup *memcg,
struct task_struct *p);
+extern void mem_cgroup_replace_page_cache(struct page *oldpage,
+ struct page *newpage);
#ifdef CONFIG_CGROUP_MEM_RES_CTLR_SWAP
extern int do_swap_account;
@@ -370,6 +372,10 @@ static inline
void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx)
{
}
+static inline void mem_cgroup_replace_page_cache(struct page *oldpage,
+ struct page *newpage)
+{
+}
#endif /* CONFIG_CGROUP_MEM_CONT */
#if !defined(CONFIG_CGROUP_MEM_RES_CTLR) || !defined(CONFIG_DEBUG_VM)
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 08ff27886af6..35a2672f1664 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -299,6 +299,7 @@ struct mmc_host {
unsigned int sdio_irqs;
struct task_struct *sdio_irq_thread;
+ bool sdio_irq_pending;
atomic_t sdio_irq_thread_abort;
mmc_pm_flag_t pm_flags; /* requested pm features */
@@ -374,6 +375,7 @@ extern void mmc_request_done(struct mmc_host *, struct mmc_request *);
static inline void mmc_signal_sdio_irq(struct mmc_host *host)
{
host->ops->enable_sdio_irq(host, 0);
+ host->sdio_irq_pending = true;
wake_up_process(host->sdio_irq_thread);
}
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 0ddc45c80aac..056c45b0072e 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1452,15 +1452,6 @@ static inline bool netdev_uses_dsa_tags(struct net_device *dev)
return 0;
}
-#ifndef CONFIG_NET_NS
-static inline void skb_set_dev(struct sk_buff *skb, struct net_device *dev)
-{
- skb->dev = dev;
-}
-#else /* CONFIG_NET_NS */
-void skb_set_dev(struct sk_buff *skb, struct net_device *dev);
-#endif
-
static inline bool netdev_uses_trailer_tags(struct net_device *dev)
{
#ifdef CONFIG_NET_DSA_TAG_TRAILER
diff --git a/include/linux/pci-aspm.h b/include/linux/pci-aspm.h
index 7cea7b6c1413..c8320144fe79 100644
--- a/include/linux/pci-aspm.h
+++ b/include/linux/pci-aspm.h
@@ -29,7 +29,7 @@ extern void pcie_aspm_pm_state_change(struct pci_dev *pdev);
extern void pcie_aspm_powersave_config_link(struct pci_dev *pdev);
extern void pci_disable_link_state(struct pci_dev *pdev, int state);
extern void pci_disable_link_state_locked(struct pci_dev *pdev, int state);
-extern void pcie_clear_aspm(void);
+extern void pcie_clear_aspm(struct pci_bus *bus);
extern void pcie_no_aspm(void);
#else
static inline void pcie_aspm_init_link_state(struct pci_dev *pdev)
@@ -47,7 +47,7 @@ static inline void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
static inline void pci_disable_link_state(struct pci_dev *pdev, int state)
{
}
-static inline void pcie_clear_aspm(void)
+static inline void pcie_clear_aspm(struct pci_bus *bus)
{
}
static inline void pcie_no_aspm(void)
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
index e8840964aca1..dad7d9a4abce 100644
--- a/include/linux/pci_regs.h
+++ b/include/linux/pci_regs.h
@@ -392,7 +392,7 @@
#define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */
#define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCI/PCI-X Bridge */
#define PCI_EXP_TYPE_RC_END 0x9 /* Root Complex Integrated Endpoint */
-#define PCI_EXP_TYPE_RC_EC 0x10 /* Root Complex Event Collector */
+#define PCI_EXP_TYPE_RC_EC 0xa /* Root Complex Event Collector */
#define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */
#define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */
#define PCI_EXP_DEVCAP 4 /* Device capabilities */
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index 77257c92155a..0072a5366e97 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -8,6 +8,7 @@
#define PIPE_BUF_FLAG_LRU 0x01 /* page is on the LRU */
#define PIPE_BUF_FLAG_ATOMIC 0x02 /* was atomically mapped */
#define PIPE_BUF_FLAG_GIFT 0x04 /* page is a gift */
+#define PIPE_BUF_FLAG_PACKET 0x08 /* read() as a packet */
/**
* struct pipe_buffer - a linux kernel pipe buffer
diff --git a/include/linux/proportions.h b/include/linux/proportions.h
index cf793bbbd05e..22653d7c3f8d 100644
--- a/include/linux/proportions.h
+++ b/include/linux/proportions.h
@@ -81,7 +81,11 @@ void prop_inc_percpu(struct prop_descriptor *pd, struct prop_local_percpu *pl)
* Limit the time part in order to ensure there are some bits left for the
* cycle counter and fraction multiply.
*/
+#if BITS_PER_LONG == 32
#define PROP_MAX_SHIFT (3*BITS_PER_LONG/4)
+#else
+#define PROP_MAX_SHIFT (BITS_PER_LONG/2)
+#endif
#define PROP_FRAC_SHIFT (BITS_PER_LONG - PROP_MAX_SHIFT - 1)
#define PROP_FRAC_BASE (1UL << PROP_FRAC_SHIFT)
diff --git a/include/linux/regset.h b/include/linux/regset.h
index 8abee6556223..686f37327a49 100644
--- a/include/linux/regset.h
+++ b/include/linux/regset.h
@@ -335,8 +335,11 @@ static inline int copy_regset_to_user(struct task_struct *target,
{
const struct user_regset *regset = &view->regsets[setno];
+ if (!regset->get)
+ return -EOPNOTSUPP;
+
if (!access_ok(VERIFY_WRITE, data, size))
- return -EIO;
+ return -EFAULT;
return regset->get(target, regset, offset, size, NULL, data);
}
@@ -358,8 +361,11 @@ static inline int copy_regset_from_user(struct task_struct *target,
{
const struct user_regset *regset = &view->regsets[setno];
+ if (!regset->set)
+ return -EOPNOTSUPP;
+
if (!access_ok(VERIFY_READ, data, size))
- return -EIO;
+ return -EFAULT;
return regset->set(target, regset, offset, size, NULL, data);
}
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index c6db9fb33c44..bb1fac5b8ee8 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -141,7 +141,7 @@ static inline unsigned __read_seqcount_begin(const seqcount_t *s)
unsigned ret;
repeat:
- ret = s->sequence;
+ ret = ACCESS_ONCE(s->sequence);
if (unlikely(ret & 1)) {
cpu_relax();
goto repeat;
diff --git a/include/linux/signalfd.h b/include/linux/signalfd.h
index 3ff4961da9b5..247399b2979a 100644
--- a/include/linux/signalfd.h
+++ b/include/linux/signalfd.h
@@ -61,13 +61,16 @@ static inline void signalfd_notify(struct task_struct *tsk, int sig)
wake_up(&tsk->sighand->signalfd_wqh);
}
+extern void signalfd_cleanup(struct sighand_struct *sighand);
+
#else /* CONFIG_SIGNALFD */
static inline void signalfd_notify(struct task_struct *tsk, int sig) { }
+static inline void signalfd_cleanup(struct sighand_struct *sighand) { }
+
#endif /* CONFIG_SIGNALFD */
#endif /* __KERNEL__ */
#endif /* _LINUX_SIGNALFD_H */
-
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index b920a72a7a9a..37b643bd680e 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1370,6 +1370,16 @@ static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
}
#endif /* NET_SKBUFF_DATA_USES_OFFSET */
+static inline void skb_mac_header_rebuild(struct sk_buff *skb)
+{
+ if (skb_mac_header_was_set(skb)) {
+ const unsigned char *old_mac = skb_mac_header(skb);
+
+ skb_set_mac_header(skb, -skb->mac_len);
+ memmove(skb_mac_header(skb), old_mac, skb->mac_len);
+ }
+}
+
static inline int skb_checksum_start_offset(const struct sk_buff *skb)
{
return skb->csum_start - skb_headroom(skb);
@@ -1623,8 +1633,6 @@ static inline int __skb_cow(struct sk_buff *skb, unsigned int headroom,
{
int delta = 0;
- if (headroom < NET_SKB_PAD)
- headroom = NET_SKB_PAD;
if (headroom > skb_headroom(skb))
delta = headroom - skb_headroom(skb);
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 4ef98e422fde..635c2136ce3e 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -261,7 +261,7 @@ struct ucred {
#define MSG_NOSIGNAL 0x4000 /* Do not generate SIGPIPE */
#define MSG_MORE 0x8000 /* Sender will send more */
#define MSG_WAITFORONE 0x10000 /* recvmmsg(): block until 1+ packets avail */
-
+#define MSG_SENDPAGE_NOTLAST 0x20000 /* sendpage() internal : not the last page */
#define MSG_EOF MSG_FIN
#define MSG_CMSG_CLOEXEC 0x40000000 /* Set close_on_exit for file
diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
index 85c50b40759d..c84e9741cb2a 100644
--- a/include/linux/sunrpc/svcsock.h
+++ b/include/linux/sunrpc/svcsock.h
@@ -34,7 +34,7 @@ struct svc_sock {
/*
* Function prototypes.
*/
-void svc_close_all(struct list_head *);
+void svc_close_all(struct svc_serv *);
int svc_recv(struct svc_rqst *, long);
int svc_send(struct svc_rqst *);
void svc_drop(struct svc_rqst *);
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 73c7df489607..b08e04cf202b 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1202,6 +1202,7 @@ struct urb {
void *transfer_buffer; /* (in) associated data buffer */
dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */
struct scatterlist *sg; /* (in) scatter gather buffer list */
+ int num_mapped_sgs; /* (internal) mapped sg entries */
int num_sgs; /* (in) number of entries in the sg list */
u32 transfer_buffer_length; /* (in) data buffer length */
u32 actual_length; /* (return) actual transfer length */
diff --git a/include/linux/usb/ch11.h b/include/linux/usb/ch11.h
index 4ebaf0824179..1eb735b53fc4 100644
--- a/include/linux/usb/ch11.h
+++ b/include/linux/usb/ch11.h
@@ -62,12 +62,6 @@
#define USB_PORT_FEAT_TEST 21
#define USB_PORT_FEAT_INDICATOR 22
#define USB_PORT_FEAT_C_PORT_L1 23
-#define USB_PORT_FEAT_C_PORT_LINK_STATE 25
-#define USB_PORT_FEAT_C_PORT_CONFIG_ERROR 26
-#define USB_PORT_FEAT_PORT_REMOTE_WAKE_MASK 27
-#define USB_PORT_FEAT_BH_PORT_RESET 28
-#define USB_PORT_FEAT_C_BH_PORT_RESET 29
-#define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT 30
/*
* Port feature selectors added by USB 3.0 spec.
@@ -76,8 +70,8 @@
#define USB_PORT_FEAT_LINK_STATE 5
#define USB_PORT_FEAT_U1_TIMEOUT 23
#define USB_PORT_FEAT_U2_TIMEOUT 24
-#define USB_PORT_FEAT_C_LINK_STATE 25
-#define USB_PORT_FEAT_C_CONFIG_ERR 26
+#define USB_PORT_FEAT_C_PORT_LINK_STATE 25
+#define USB_PORT_FEAT_C_PORT_CONFIG_ERROR 26
#define USB_PORT_FEAT_REMOTE_WAKE_MASK 27
#define USB_PORT_FEAT_BH_PORT_RESET 28
#define USB_PORT_FEAT_C_BH_PORT_RESET 29
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h
index 0fd3fbdd8283..cf65b5cff722 100644
--- a/include/linux/usb/ch9.h
+++ b/include/linux/usb/ch9.h
@@ -583,8 +583,26 @@ struct usb_ss_ep_comp_descriptor {
} __attribute__ ((packed));
#define USB_DT_SS_EP_COMP_SIZE 6
+
/* Bits 4:0 of bmAttributes if this is a bulk endpoint */
-#define USB_SS_MAX_STREAMS(p) (1 << ((p) & 0x1f))
+static inline int
+usb_ss_max_streams(const struct usb_ss_ep_comp_descriptor *comp)
+{
+ int max_streams;
+
+ if (!comp)
+ return 0;
+
+ max_streams = comp->bmAttributes & 0x1f;
+
+ if (!max_streams)
+ return 0;
+
+ max_streams = 1 << max_streams;
+
+ return max_streams;
+}
+
/* Bits 1:0 of bmAttributes if this is an isoc endpoint */
#define USB_SS_MULT(p) (1 + ((p) & 0x3))
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index c0ecc5a2ef9e..32ba8c55b3a4 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -128,6 +128,8 @@ struct usb_hcd {
unsigned wireless:1; /* Wireless USB HCD */
unsigned authorized_default:1;
unsigned has_tt:1; /* Integrated TT in root hub */
+ unsigned broken_pci_sleep:1; /* Don't put the
+ controller in PCI-D3 for system sleep */
int irq; /* irq allocated */
void __iomem *regs; /* device memory/io */
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index 605b0aa8d852..76f439647c4b 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -191,7 +191,8 @@ extern void usbnet_cdc_status(struct usbnet *, struct urb *);
enum skb_state {
illegal = 0,
tx_start, tx_done,
- rx_start, rx_done, rx_cleanup
+ rx_start, rx_done, rx_cleanup,
+ unlink_start
};
struct skb_data { /* skb->cb is one of these */
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 8a4c309d2344..eeeda13b4d53 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -1075,6 +1075,7 @@ struct v4l2_querymenu {
#define V4L2_CTRL_FLAG_NEXT_CTRL 0x80000000
/* User-class control IDs defined by V4L2 */
+#define V4L2_CID_MAX_CTRLS 1024
#define V4L2_CID_BASE (V4L2_CTRL_CLASS_USER | 0x900)
#define V4L2_CID_USER_BASE V4L2_CID_BASE
/* IDs reserved for driver specific controls */
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index f584aba78ca9..6c56a14a70d9 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -289,12 +289,16 @@ enum {
*
* system_freezable_wq is equivalent to system_wq except that it's
* freezable.
+ *
+ * system_nrt_freezable_wq is equivalent to system_nrt_wq except that
+ * it's freezable.
*/
extern struct workqueue_struct *system_wq;
extern struct workqueue_struct *system_long_wq;
extern struct workqueue_struct *system_nrt_wq;
extern struct workqueue_struct *system_unbound_wq;
extern struct workqueue_struct *system_freezable_wq;
+extern struct workqueue_struct *system_nrt_freezable_wq;
extern struct workqueue_struct *
__alloc_workqueue_key(const char *name, unsigned int flags, int max_active,
diff --git a/include/net/arp.h b/include/net/arp.h
index 91f0568a04ef..fb0eb9048b19 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -16,6 +16,7 @@ extern void arp_send(int type, int ptype, __be32 dest_ip,
const unsigned char *dest_hw,
const unsigned char *src_hw, const unsigned char *th);
extern int arp_bind_neighbour(struct dst_entry *dst);
+extern struct neighbour *__arp_bind_neighbour(struct dst_entry *dst, __be32 nexthop);
extern int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir);
extern void arp_ifdown(struct net_device *dev);
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 0489b8b90fe7..a2049c618022 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -84,6 +84,7 @@ enum {
HCI_SERVICE_CACHE,
HCI_LINK_KEYS,
HCI_DEBUG_KEYS,
+ HCI_UNREGISTER,
HCI_RESET,
};
diff --git a/include/net/dst.h b/include/net/dst.h
index e12ddfb9eb16..7907ff15e0fd 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -37,7 +37,7 @@ struct dst_entry {
unsigned long _metrics;
unsigned long expires;
struct dst_entry *path;
- struct neighbour *neighbour;
+ struct neighbour __rcu *_neighbour;
struct hh_cache *hh;
#ifdef CONFIG_XFRM
struct xfrm_state *xfrm;
@@ -78,6 +78,7 @@ struct dst_entry {
#define DST_NOHASH 0x0008
#define DST_NOCACHE 0x0010
#define DST_NOCOUNT 0x0020
+#define DST_XFRM_TUNNEL 0x0100
union {
struct dst_entry *next;
struct rtable __rcu *rt_next;
@@ -86,6 +87,21 @@ struct dst_entry {
};
};
+static inline struct neighbour *dst_get_neighbour(struct dst_entry *dst)
+{
+ return rcu_dereference(dst->_neighbour);
+}
+
+static inline struct neighbour *dst_get_neighbour_raw(struct dst_entry *dst)
+{
+ return rcu_dereference_raw(dst->_neighbour);
+}
+
+static inline void dst_set_neighbour(struct dst_entry *dst, struct neighbour *neigh)
+{
+ rcu_assign_pointer(dst->_neighbour, neigh);
+}
+
extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old);
extern const u32 dst_default_metrics[RTAX_MAX];
@@ -371,8 +387,14 @@ static inline void dst_rcu_free(struct rcu_head *head)
static inline void dst_confirm(struct dst_entry *dst)
{
- if (dst)
- neigh_confirm(dst->neighbour);
+ if (dst) {
+ struct neighbour *n;
+
+ rcu_read_lock();
+ n = dst_get_neighbour(dst);
+ neigh_confirm(n);
+ rcu_read_unlock();
+ }
}
static inline void dst_link_failure(struct sk_buff *skb)
diff --git a/include/net/flow.h b/include/net/flow.h
index 32359fdc7e73..e37cfda9c0ff 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -90,6 +90,16 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif,
fl4->fl4_dport = dport;
fl4->fl4_sport = sport;
}
+
+/* Reset some input parameters after previous lookup */
+static inline void flowi4_update_output(struct flowi4 *fl4, int oif, __u8 tos,
+ __be32 daddr, __be32 saddr)
+{
+ fl4->flowi4_oif = oif;
+ fl4->flowi4_tos = tos;
+ fl4->daddr = daddr;
+ fl4->saddr = saddr;
+}
struct flowi6 {
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index caaff5f5f39f..14dd9c789924 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -31,6 +31,7 @@
/** struct ip_options - IP Options
*
* @faddr - Saved first hop address
+ * @nexthop - Saved nexthop address in LSRR and SSRR
* @is_data - Options in __data, rather than skb
* @is_strictroute - Strict source route
* @srr_is_hit - Packet destination addr was our one
@@ -41,6 +42,7 @@
*/
struct ip_options {
__be32 faddr;
+ __be32 nexthop;
unsigned char optlen;
unsigned char srr;
unsigned char rr;
diff --git a/include/net/netns/generic.h b/include/net/netns/generic.h
index 3419bf5cd154..d55f43443335 100644
--- a/include/net/netns/generic.h
+++ b/include/net/netns/generic.h
@@ -41,6 +41,7 @@ static inline void *net_generic(const struct net *net, int id)
ptr = ng->ptr[id - 1];
rcu_read_unlock();
+ BUG_ON(!ptr);
return ptr;
}
#endif
diff --git a/include/net/route.h b/include/net/route.h
index db7b3432f07c..5d7aae4ab2ee 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -270,6 +270,7 @@ static inline struct rtable *ip_route_connect(struct flowi4 *fl4,
if (IS_ERR(rt))
return rt;
ip_rt_put(rt);
+ flowi4_update_output(fl4, oif, tos, fl4->daddr, fl4->saddr);
}
security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
return ip_route_output_flow(net, fl4, sk);
@@ -284,6 +285,9 @@ static inline struct rtable *ip_route_newports(struct flowi4 *fl4, struct rtable
fl4->fl4_dport = dport;
fl4->fl4_sport = sport;
ip_rt_put(rt);
+ flowi4_update_output(fl4, sk->sk_bound_dev_if,
+ RT_CONN_FLAGS(sk), fl4->daddr,
+ fl4->saddr);
security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
return ip_route_output_flow(sock_net(sk), fl4, sk);
}
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index b931f021d7ab..f1fbe2d5e055 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -219,9 +219,16 @@ struct tcf_proto {
struct qdisc_skb_cb {
unsigned int pkt_len;
- long data[];
+ unsigned char data[24];
};
+static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz)
+{
+ struct qdisc_skb_cb *qcb;
+ BUILD_BUG_ON(sizeof(skb->cb) < sizeof(unsigned int) + sz);
+ BUILD_BUG_ON(sizeof(qcb->data) < sz);
+}
+
static inline int qdisc_qlen(struct Qdisc *q)
{
return q->q.qlen;
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index b2c2366676a7..f686066087d5 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -700,4 +700,17 @@ static inline void sctp_v4_map_v6(union sctp_addr *addr)
addr->v6.sin6_addr.s6_addr32[2] = htonl(0x0000ffff);
}
+/* The cookie is always 0 since this is how it's used in the
+ * pmtu code.
+ */
+static inline struct dst_entry *sctp_transport_dst_check(struct sctp_transport *t)
+{
+ if (t->dst && !dst_check(t->dst, 0)) {
+ dst_release(t->dst);
+ t->dst = NULL;
+ }
+
+ return t->dst;
+}
+
#endif /* __net_sctp_h__ */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 7df327a6d564..c3884214c600 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -236,6 +236,9 @@ extern struct sctp_globals {
* bits is an indicator of when to send and window update SACK.
*/
int rwnd_update_shift;
+
+ /* Threshold for autoclose timeout, in seconds. */
+ unsigned long max_autoclose;
} sctp_globals;
#define sctp_rto_initial (sctp_globals.rto_initial)
@@ -271,6 +274,7 @@ extern struct sctp_globals {
#define sctp_auth_enable (sctp_globals.auth_enable)
#define sctp_checksum_disable (sctp_globals.checksum_disable)
#define sctp_rwnd_upd_shift (sctp_globals.rwnd_update_shift)
+#define sctp_max_autoclose (sctp_globals.max_autoclose)
/* SCTP Socket type: UDP or TCP style. */
typedef enum {
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 561ac99def5a..0fe667901ed3 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -36,6 +36,7 @@
#define TRANSPORT_SENSE_BUFFER SCSI_SENSE_BUFFERSIZE
/* Used by transport_send_check_condition_and_sense() */
#define SPC_SENSE_KEY_OFFSET 2
+#define SPC_ADD_SENSE_LEN_OFFSET 7
#define SPC_ASC_KEY_OFFSET 12
#define SPC_ASCQ_KEY_OFFSET 13
#define TRANSPORT_IQN_LEN 224
diff --git a/include/trace/events/writeback.h b/include/trace/events/writeback.h
index 4e249b927eaa..9b60c6fc6df7 100644
--- a/include/trace/events/writeback.h
+++ b/include/trace/events/writeback.h
@@ -23,7 +23,10 @@ DECLARE_EVENT_CLASS(writeback_work_class,
__field(int, for_background)
),
TP_fast_assign(
- strncpy(__entry->name, dev_name(bdi->dev), 32);
+ struct device *dev = bdi->dev;
+ if (!dev)
+ dev = default_backing_dev_info.dev;
+ strncpy(__entry->name, dev_name(dev), 32);
__entry->nr_pages = work->nr_pages;
__entry->sb_dev = work->sb ? work->sb->s_dev : 0;
__entry->sync_mode = work->sync_mode;
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
index 892b97f8e157..c0d8014f5ccc 100644
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -514,6 +514,11 @@ struct omap_dss_device {
int (*get_backlight)(struct omap_dss_device *dssdev);
};
+struct omap_dss_hdmi_data
+{
+ int hpd_gpio;
+};
+
struct omap_dss_driver {
struct device_driver driver;
diff --git a/include/xen/interface/io/xs_wire.h b/include/xen/interface/io/xs_wire.h
index 99fcffb372d1..454ee2629238 100644
--- a/include/xen/interface/io/xs_wire.h
+++ b/include/xen/interface/io/xs_wire.h
@@ -84,4 +84,7 @@ struct xenstore_domain_interface {
XENSTORE_RING_IDX rsp_cons, rsp_prod;
};
+/* Violating this is very bad. See docs/misc/xenstore.txt. */
+#define XENSTORE_PAYLOAD_MAX 4096
+
#endif /* _XS_WIRE_H */
diff --git a/init/do_mounts.c b/init/do_mounts.c
index c0851a8e030c..8959eb32e095 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -360,15 +360,42 @@ out:
}
#ifdef CONFIG_ROOT_NFS
+
+#define NFSROOT_TIMEOUT_MIN 5
+#define NFSROOT_TIMEOUT_MAX 30
+#define NFSROOT_RETRY_MAX 5
+
static int __init mount_nfs_root(void)
{
char *root_dev, *root_data;
+ unsigned int timeout;
+ int try, err;
- if (nfs_root_data(&root_dev, &root_data) != 0)
- return 0;
- if (do_mount_root(root_dev, "nfs", root_mountflags, root_data) != 0)
+ err = nfs_root_data(&root_dev, &root_data);
+ if (err != 0)
return 0;
- return 1;
+
+ /*
+ * The server or network may not be ready, so try several
+ * times. Stop after a few tries in case the client wants
+ * to fall back to other boot methods.
+ */
+ timeout = NFSROOT_TIMEOUT_MIN;
+ for (try = 1; ; try++) {
+ err = do_mount_root(root_dev, "nfs",
+ root_mountflags, root_data);
+ if (err == 0)
+ return 1;
+ if (try > NFSROOT_RETRY_MAX)
+ break;
+
+ /* Wait, in case the server refused us immediately */
+ ssleep(timeout);
+ timeout <<= 1;
+ if (timeout > NFSROOT_TIMEOUT_MAX)
+ timeout = NFSROOT_TIMEOUT_MAX;
+ }
+ return 0;
}
#endif
@@ -405,7 +432,7 @@ void __init change_floppy(char *fmt, ...)
void __init mount_root(void)
{
#ifdef CONFIG_ROOT_NFS
- if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
+ if (ROOT_DEV == Root_NFS) {
if (mount_nfs_root())
return;
diff --git a/init/main.c b/init/main.c
index d7211faed2ad..841e344d366e 100644
--- a/init/main.c
+++ b/init/main.c
@@ -549,9 +549,6 @@ asmlinkage void __init start_kernel(void)
early_boot_irqs_disabled = false;
local_irq_enable();
- /* Interrupts are enabled now so all GFP allocations are safe. */
- gfp_allowed_mask = __GFP_BITS_MASK;
-
kmem_cache_init_late();
/*
@@ -783,6 +780,10 @@ static int __init kernel_init(void * unused)
* Wait until kthreadd is all set-up.
*/
wait_for_completion(&kthreadd_done);
+
+ /* Now the scheduler is fully set up and can do blocking allocations */
+ gfp_allowed_mask = __GFP_BITS_MASK;
+
/*
* init can allocate pages on any node
*/
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 241b74a307de..5083a09a9b6d 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1176,10 +1176,10 @@ static int parse_cgroupfs_options(char *data, struct cgroup_sb_opts *opts)
/*
* If the 'all' option was specified select all the subsystems,
- * otherwise 'all, 'none' and a subsystem name options were not
- * specified, let's default to 'all'
+ * otherwise if 'none', 'name=' and a subsystem name options
+ * were not specified, let's default to 'all'
*/
- if (all_ss || (!all_ss && !one_ss && !opts->none)) {
+ if (all_ss || (!one_ss && !opts->none && !opts->name)) {
for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
struct cgroup_subsys *ss = subsys[i];
if (ss == NULL)
@@ -2105,11 +2105,6 @@ int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader)
continue;
/* get old css_set pointer */
task_lock(tsk);
- if (tsk->flags & PF_EXITING) {
- /* ignore this task if it's going away */
- task_unlock(tsk);
- continue;
- }
oldcg = tsk->cgroups;
get_css_set(oldcg);
task_unlock(tsk);
diff --git a/kernel/compat.c b/kernel/compat.c
index fc9eb093acd5..3507c936e5f9 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -318,25 +318,54 @@ asmlinkage long compat_sys_sigpending(compat_old_sigset_t __user *set)
#ifdef __ARCH_WANT_SYS_SIGPROCMASK
-asmlinkage long compat_sys_sigprocmask(int how, compat_old_sigset_t __user *set,
- compat_old_sigset_t __user *oset)
+/*
+ * sys_sigprocmask SIG_SETMASK sets the first (compat) word of the
+ * blocked set of signals to the supplied signal set
+ */
+static inline void compat_sig_setmask(sigset_t *blocked, compat_sigset_word set)
{
- old_sigset_t s;
- long ret;
- mm_segment_t old_fs;
+ memcpy(blocked->sig, &set, sizeof(set));
+}
- if (set && get_user(s, set))
- return -EFAULT;
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- ret = sys_sigprocmask(how,
- set ? (old_sigset_t __user *) &s : NULL,
- oset ? (old_sigset_t __user *) &s : NULL);
- set_fs(old_fs);
- if (ret == 0)
- if (oset)
- ret = put_user(s, oset);
- return ret;
+asmlinkage long compat_sys_sigprocmask(int how,
+ compat_old_sigset_t __user *nset,
+ compat_old_sigset_t __user *oset)
+{
+ old_sigset_t old_set, new_set;
+ sigset_t new_blocked;
+
+ old_set = current->blocked.sig[0];
+
+ if (nset) {
+ if (get_user(new_set, nset))
+ return -EFAULT;
+ new_set &= ~(sigmask(SIGKILL) | sigmask(SIGSTOP));
+
+ new_blocked = current->blocked;
+
+ switch (how) {
+ case SIG_BLOCK:
+ sigaddsetmask(&new_blocked, new_set);
+ break;
+ case SIG_UNBLOCK:
+ sigdelsetmask(&new_blocked, new_set);
+ break;
+ case SIG_SETMASK:
+ compat_sig_setmask(&new_blocked, new_set);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ set_current_blocked(&new_blocked);
+ }
+
+ if (oset) {
+ if (put_user(old_set, oset))
+ return -EFAULT;
+ }
+
+ return 0;
}
#endif
diff --git a/kernel/cred.c b/kernel/cred.c
index 174fa84eca30..3a55ea4fa983 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -385,6 +385,8 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
struct cred *new;
int ret;
+ p->replacement_session_keyring = NULL;
+
if (
#ifdef CONFIG_KEYS
!p->cred->thread_keyring &&
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
index bad6786dee88..5ee24d106320 100644
--- a/kernel/debug/debug_core.c
+++ b/kernel/debug/debug_core.c
@@ -157,37 +157,39 @@ early_param("nokgdbroundup", opt_nokgdbroundup);
* Weak aliases for breakpoint management,
* can be overriden by architectures when needed:
*/
-int __weak kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
+int __weak kgdb_arch_set_breakpoint(struct kgdb_bkpt *bpt)
{
int err;
- err = probe_kernel_read(saved_instr, (char *)addr, BREAK_INSTR_SIZE);
+ err = probe_kernel_read(bpt->saved_instr, (char *)bpt->bpt_addr,
+ BREAK_INSTR_SIZE);
if (err)
return err;
-
- return probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr,
- BREAK_INSTR_SIZE);
+ err = probe_kernel_write((char *)bpt->bpt_addr,
+ arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
+ return err;
}
-int __weak kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
+int __weak kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
{
- return probe_kernel_write((char *)addr,
- (char *)bundle, BREAK_INSTR_SIZE);
+ return probe_kernel_write((char *)bpt->bpt_addr,
+ (char *)bpt->saved_instr, BREAK_INSTR_SIZE);
}
int __weak kgdb_validate_break_address(unsigned long addr)
{
- char tmp_variable[BREAK_INSTR_SIZE];
+ struct kgdb_bkpt tmp;
int err;
- /* Validate setting the breakpoint and then removing it. In the
+ /* Validate setting the breakpoint and then removing it. If the
* remove fails, the kernel needs to emit a bad message because we
* are deep trouble not being able to put things back the way we
* found them.
*/
- err = kgdb_arch_set_breakpoint(addr, tmp_variable);
+ tmp.bpt_addr = addr;
+ err = kgdb_arch_set_breakpoint(&tmp);
if (err)
return err;
- err = kgdb_arch_remove_breakpoint(addr, tmp_variable);
+ err = kgdb_arch_remove_breakpoint(&tmp);
if (err)
printk(KERN_ERR "KGDB: Critical breakpoint error, kernel "
"memory destroyed at: %lx", addr);
@@ -231,7 +233,6 @@ static void kgdb_flush_swbreak_addr(unsigned long addr)
*/
int dbg_activate_sw_breakpoints(void)
{
- unsigned long addr;
int error;
int ret = 0;
int i;
@@ -240,16 +241,15 @@ int dbg_activate_sw_breakpoints(void)
if (kgdb_break[i].state != BP_SET)
continue;
- addr = kgdb_break[i].bpt_addr;
- error = kgdb_arch_set_breakpoint(addr,
- kgdb_break[i].saved_instr);
+ error = kgdb_arch_set_breakpoint(&kgdb_break[i]);
if (error) {
ret = error;
- printk(KERN_INFO "KGDB: BP install failed: %lx", addr);
+ printk(KERN_INFO "KGDB: BP install failed: %lx",
+ kgdb_break[i].bpt_addr);
continue;
}
- kgdb_flush_swbreak_addr(addr);
+ kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr);
kgdb_break[i].state = BP_ACTIVE;
}
return ret;
@@ -298,7 +298,6 @@ int dbg_set_sw_break(unsigned long addr)
int dbg_deactivate_sw_breakpoints(void)
{
- unsigned long addr;
int error;
int ret = 0;
int i;
@@ -306,15 +305,14 @@ int dbg_deactivate_sw_breakpoints(void)
for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
if (kgdb_break[i].state != BP_ACTIVE)
continue;
- addr = kgdb_break[i].bpt_addr;
- error = kgdb_arch_remove_breakpoint(addr,
- kgdb_break[i].saved_instr);
+ error = kgdb_arch_remove_breakpoint(&kgdb_break[i]);
if (error) {
- printk(KERN_INFO "KGDB: BP remove failed: %lx\n", addr);
+ printk(KERN_INFO "KGDB: BP remove failed: %lx\n",
+ kgdb_break[i].bpt_addr);
ret = error;
}
- kgdb_flush_swbreak_addr(addr);
+ kgdb_flush_swbreak_addr(kgdb_break[i].bpt_addr);
kgdb_break[i].state = BP_SET;
}
return ret;
@@ -348,7 +346,6 @@ int kgdb_isremovedbreak(unsigned long addr)
int dbg_remove_all_break(void)
{
- unsigned long addr;
int error;
int i;
@@ -356,12 +353,10 @@ int dbg_remove_all_break(void)
for (i = 0; i < KGDB_MAX_BREAKPOINTS; i++) {
if (kgdb_break[i].state != BP_ACTIVE)
goto setundefined;
- addr = kgdb_break[i].bpt_addr;
- error = kgdb_arch_remove_breakpoint(addr,
- kgdb_break[i].saved_instr);
+ error = kgdb_arch_remove_breakpoint(&kgdb_break[i]);
if (error)
printk(KERN_ERR "KGDB: breakpoint remove failed: %lx\n",
- addr);
+ kgdb_break[i].bpt_addr);
setundefined:
kgdb_break[i].state = BP_UNDEFINED;
}
diff --git a/kernel/exit.c b/kernel/exit.c
index f2b321bae440..303bed2966b6 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -1553,8 +1553,15 @@ static int wait_consider_task(struct wait_opts *wo, int ptrace,
}
/* dead body doesn't have much to contribute */
- if (p->exit_state == EXIT_DEAD)
+ if (unlikely(p->exit_state == EXIT_DEAD)) {
+ /*
+ * But do not ignore this task until the tracer does
+ * wait_task_zombie()->do_notify_parent().
+ */
+ if (likely(!ptrace) && unlikely(ptrace_reparented(p)))
+ wo->notask_error = 0;
return 0;
+ }
/* slay zombie? */
if (p->exit_state == EXIT_ZOMBIE) {
diff --git a/kernel/fork.c b/kernel/fork.c
index 4e4b34465118..fa6030d9c59b 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -48,6 +48,7 @@
#include <linux/audit.h>
#include <linux/memcontrol.h>
#include <linux/ftrace.h>
+#include <linux/proc_fs.h>
#include <linux/profile.h>
#include <linux/rmap.h>
#include <linux/ksm.h>
@@ -67,6 +68,7 @@
#include <linux/user-return-notifier.h>
#include <linux/oom.h>
#include <linux/khugepaged.h>
+#include <linux/signalfd.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
@@ -933,8 +935,10 @@ static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)
void __cleanup_sighand(struct sighand_struct *sighand)
{
- if (atomic_dec_and_test(&sighand->count))
+ if (atomic_dec_and_test(&sighand->count)) {
+ signalfd_cleanup(sighand);
kmem_cache_free(sighand_cachep, sighand);
+ }
}
@@ -1391,6 +1395,8 @@ bad_fork_cleanup_io:
if (p->io_context)
exit_io_context(p);
bad_fork_cleanup_namespaces:
+ if (unlikely(clone_flags & CLONE_NEWPID))
+ pid_ns_release_proc(p->nsproxy->pid_ns);
exit_task_namespaces(p);
bad_fork_cleanup_mm:
if (p->mm) {
diff --git a/kernel/hung_task.c b/kernel/hung_task.c
index ea640120ab86..e972276f12ff 100644
--- a/kernel/hung_task.c
+++ b/kernel/hung_task.c
@@ -74,11 +74,17 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
/*
* Ensure the task is not frozen.
- * Also, when a freshly created task is scheduled once, changes
- * its state to TASK_UNINTERRUPTIBLE without having ever been
- * switched out once, it musn't be checked.
+ * Also, skip vfork and any other user process that freezer should skip.
*/
- if (unlikely(t->flags & PF_FROZEN || !switch_count))
+ if (unlikely(t->flags & (PF_FROZEN | PF_FREEZER_SKIP)))
+ return;
+
+ /*
+ * When a freshly created task is scheduled once, changes its state to
+ * TASK_UNINTERRUPTIBLE without having ever been switched out once, it
+ * musn't be checked.
+ */
+ if (unlikely(!switch_count))
return;
if (switch_count != t->last_switch_count) {
diff --git a/kernel/irq/autoprobe.c b/kernel/irq/autoprobe.c
index 342d8f44e401..0119b9d467ae 100644
--- a/kernel/irq/autoprobe.c
+++ b/kernel/irq/autoprobe.c
@@ -53,7 +53,7 @@ unsigned long probe_irq_on(void)
if (desc->irq_data.chip->irq_set_type)
desc->irq_data.chip->irq_set_type(&desc->irq_data,
IRQ_TYPE_PROBE);
- irq_startup(desc);
+ irq_startup(desc, false);
}
raw_spin_unlock_irq(&desc->lock);
}
@@ -70,7 +70,7 @@ unsigned long probe_irq_on(void)
raw_spin_lock_irq(&desc->lock);
if (!desc->action && irq_settings_can_probe(desc)) {
desc->istate |= IRQS_AUTODETECT | IRQS_WAITING;
- if (irq_startup(desc))
+ if (irq_startup(desc, false))
desc->istate |= IRQS_PENDING;
}
raw_spin_unlock_irq(&desc->lock);
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index dc5114b4c16c..990965ec5d0b 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -61,8 +61,7 @@ int irq_set_irq_type(unsigned int irq, unsigned int type)
return -EINVAL;
type &= IRQ_TYPE_SENSE_MASK;
- if (type != IRQ_TYPE_NONE)
- ret = __irq_set_trigger(desc, irq, type);
+ ret = __irq_set_trigger(desc, irq, type);
irq_put_desc_busunlock(desc, flags);
return ret;
}
@@ -157,19 +156,22 @@ static void irq_state_set_masked(struct irq_desc *desc)
irqd_set(&desc->irq_data, IRQD_IRQ_MASKED);
}
-int irq_startup(struct irq_desc *desc)
+int irq_startup(struct irq_desc *desc, bool resend)
{
+ int ret = 0;
+
irq_state_clr_disabled(desc);
desc->depth = 0;
if (desc->irq_data.chip->irq_startup) {
- int ret = desc->irq_data.chip->irq_startup(&desc->irq_data);
+ ret = desc->irq_data.chip->irq_startup(&desc->irq_data);
irq_state_clr_masked(desc);
- return ret;
+ } else {
+ irq_enable(desc);
}
-
- irq_enable(desc);
- return 0;
+ if (resend)
+ check_irq_resend(desc, desc->irq_data.irq);
+ return ret;
}
void irq_shutdown(struct irq_desc *desc)
@@ -312,6 +314,24 @@ out_unlock:
}
EXPORT_SYMBOL_GPL(handle_simple_irq);
+/*
+ * Called unconditionally from handle_level_irq() and only for oneshot
+ * interrupts from handle_fasteoi_irq()
+ */
+static void cond_unmask_irq(struct irq_desc *desc)
+{
+ /*
+ * We need to unmask in the following cases:
+ * - Standard level irq (IRQF_ONESHOT is not set)
+ * - Oneshot irq which did not wake the thread (caused by a
+ * spurious interrupt or a primary handler handling it
+ * completely).
+ */
+ if (!irqd_irq_disabled(&desc->irq_data) &&
+ irqd_irq_masked(&desc->irq_data) && !desc->threads_oneshot)
+ unmask_irq(desc);
+}
+
/**
* handle_level_irq - Level type irq handler
* @irq: the interrupt number
@@ -344,8 +364,8 @@ handle_level_irq(unsigned int irq, struct irq_desc *desc)
handle_irq_event(desc);
- if (!irqd_irq_disabled(&desc->irq_data) && !(desc->istate & IRQS_ONESHOT))
- unmask_irq(desc);
+ cond_unmask_irq(desc);
+
out_unlock:
raw_spin_unlock(&desc->lock);
}
@@ -399,6 +419,9 @@ handle_fasteoi_irq(unsigned int irq, struct irq_desc *desc)
preflow_handler(desc);
handle_irq_event(desc);
+ if (desc->istate & IRQS_ONESHOT)
+ cond_unmask_irq(desc);
+
out_eoi:
desc->irq_data.chip->irq_eoi(&desc->irq_data);
out_unlock:
@@ -575,7 +598,7 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
irq_settings_set_noprobe(desc);
irq_settings_set_norequest(desc);
irq_settings_set_nothread(desc);
- irq_startup(desc);
+ irq_startup(desc, true);
}
out:
irq_put_desc_busunlock(desc, flags);
diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 6546431447d7..62efdc44b643 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -67,7 +67,7 @@ extern int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp);
extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume);
-extern int irq_startup(struct irq_desc *desc);
+extern int irq_startup(struct irq_desc *desc, bool resend);
extern void irq_shutdown(struct irq_desc *desc);
extern void irq_enable(struct irq_desc *desc);
extern void irq_disable(struct irq_desc *desc);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index a1aadab09aab..df8136fff8cc 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -770,7 +770,7 @@ static int irq_thread(void *data)
struct irqaction *action);
int wake;
- if (force_irqthreads & test_bit(IRQTF_FORCED_THREAD,
+ if (force_irqthreads && test_bit(IRQTF_FORCED_THREAD,
&action->thread_flags))
handler_fn = irq_forced_thread_fn;
else
@@ -976,6 +976,11 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
/* add new interrupt at end of irq queue */
do {
+ /*
+ * Or all existing action->thread_mask bits,
+ * so we can find the next zero bit for this
+ * new action.
+ */
thread_mask |= old->thread_mask;
old_ptr = &old->next;
old = *old_ptr;
@@ -984,14 +989,41 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
}
/*
- * Setup the thread mask for this irqaction. Unlikely to have
- * 32 resp 64 irqs sharing one line, but who knows.
+ * Setup the thread mask for this irqaction for ONESHOT. For
+ * !ONESHOT irqs the thread mask is 0 so we can avoid a
+ * conditional in irq_wake_thread().
*/
- if (new->flags & IRQF_ONESHOT && thread_mask == ~0UL) {
- ret = -EBUSY;
- goto out_mask;
+ if (new->flags & IRQF_ONESHOT) {
+ /*
+ * Unlikely to have 32 resp 64 irqs sharing one line,
+ * but who knows.
+ */
+ if (thread_mask == ~0UL) {
+ ret = -EBUSY;
+ goto out_mask;
+ }
+ /*
+ * The thread_mask for the action is or'ed to
+ * desc->thread_active to indicate that the
+ * IRQF_ONESHOT thread handler has been woken, but not
+ * yet finished. The bit is cleared when a thread
+ * completes. When all threads of a shared interrupt
+ * line have completed desc->threads_active becomes
+ * zero and the interrupt line is unmasked. See
+ * handle.c:irq_wake_thread() for further information.
+ *
+ * If no thread is woken by primary (hard irq context)
+ * interrupt handlers, then desc->threads_active is
+ * also checked for zero to unmask the irq line in the
+ * affected hard irq flow handlers
+ * (handle_[fasteoi|level]_irq).
+ *
+ * The new action gets the first zero bit of
+ * thread_mask assigned. See the loop above which or's
+ * all existing action->thread_mask bits.
+ */
+ new->thread_mask = 1 << ffz(thread_mask);
}
- new->thread_mask = 1 << ffz(thread_mask);
if (!shared) {
init_waitqueue_head(&desc->wait_for_threads);
@@ -1018,7 +1050,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
desc->istate |= IRQS_ONESHOT;
if (irq_settings_can_autoenable(desc))
- irq_startup(desc);
+ irq_startup(desc, true);
else
/* Undo nested disables: */
desc->depth = 1;
diff --git a/kernel/irq/migration.c b/kernel/irq/migration.c
index 47420908fba0..c3c89751b327 100644
--- a/kernel/irq/migration.c
+++ b/kernel/irq/migration.c
@@ -43,12 +43,16 @@ void irq_move_masked_irq(struct irq_data *idata)
* masking the irqs.
*/
if (likely(cpumask_any_and(desc->pending_mask, cpu_online_mask)
- < nr_cpu_ids))
- if (!chip->irq_set_affinity(&desc->irq_data,
- desc->pending_mask, false)) {
+ < nr_cpu_ids)) {
+ int ret = chip->irq_set_affinity(&desc->irq_data,
+ desc->pending_mask, false);
+ switch (ret) {
+ case IRQ_SET_MASK_OK:
cpumask_copy(desc->irq_data.affinity, desc->pending_mask);
+ case IRQ_SET_MASK_OK_NOCOPY:
irq_set_thread_affinity(desc);
}
+ }
cpumask_clear(desc->pending_mask);
}
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 77981813a1e7..f1dcde499f69 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1077,6 +1077,7 @@ void __kprobes kprobe_flush_task(struct task_struct *tk)
/* Early boot. kretprobe_table_locks not yet initialized. */
return;
+ INIT_HLIST_HEAD(&empty_rp);
hash = hash_ptr(tk, KPROBE_HASH_BITS);
head = &kretprobe_inst_table[hash];
kretprobe_table_lock(hash, &flags);
@@ -1085,7 +1086,6 @@ void __kprobes kprobe_flush_task(struct task_struct *tk)
recycle_rp_inst(ri, &empty_rp);
}
kretprobe_table_unlock(hash, &flags);
- INIT_HLIST_HEAD(&empty_rp);
hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
hlist_del(&ri->hlist);
kfree(ri);
@@ -1660,8 +1660,12 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p,
ri->rp = rp;
ri->task = current;
- if (rp->entry_handler && rp->entry_handler(ri, regs))
+ if (rp->entry_handler && rp->entry_handler(ri, regs)) {
+ spin_lock_irqsave(&rp->lock, flags);
+ hlist_add_head(&ri->hlist, &rp->free_instances);
+ spin_unlock_irqrestore(&rp->lock, flags);
return 0;
+ }
arch_prepare_kretprobe(ri, regs);
diff --git a/kernel/module.c b/kernel/module.c
index 795bdc7f5c3f..b9d0667efe62 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2290,8 +2290,7 @@ static int copy_and_check(struct load_info *info,
return -ENOEXEC;
/* Suck in entire file: we'll want most of it. */
- /* vmalloc barfs on "unusual" numbers. Check here */
- if (len > 64 * 1024 * 1024 || (hdr = vmalloc(len)) == NULL)
+ if ((hdr = vmalloc(len)) == NULL)
return -ENOMEM;
if (copy_from_user(hdr, umod, len) != 0) {
diff --git a/kernel/panic.c b/kernel/panic.c
index a136da2f3968..564c7bc6ecbd 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -242,8 +242,16 @@ void add_taint(unsigned flag)
* Also we want to keep up lockdep for staging development and
* post-warning case.
*/
- if (flag != TAINT_CRAP && flag != TAINT_WARN && __debug_locks_off())
- printk(KERN_WARNING "Disabling lock debugging due to kernel taint\n");
+ switch (flag) {
+ case TAINT_CRAP:
+ case TAINT_WARN:
+ case TAINT_FIRMWARE_WORKAROUND:
+ break;
+
+ default:
+ if (__debug_locks_off())
+ printk(KERN_WARNING "Disabling lock debugging due to kernel taint\n");
+ }
set_bit(flag, &tainted_mask);
}
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 8f7b1db1ece1..8884c27682f5 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -623,7 +623,7 @@ int hibernate(void)
/* Allocate memory management structures */
error = create_basic_memory_bitmaps();
if (error)
- goto Exit;
+ goto Enable_umh;
printk(KERN_INFO "PM: Syncing filesystems ... ");
sys_sync();
@@ -631,7 +631,7 @@ int hibernate(void)
error = prepare_processes();
if (error)
- goto Finish;
+ goto Free_bitmaps;
if (hibernation_test(TEST_FREEZER))
goto Thaw;
@@ -663,8 +663,9 @@ int hibernate(void)
Thaw:
thaw_processes();
- Finish:
+ Free_bitmaps:
free_basic_memory_bitmaps();
+ Enable_umh:
usermodehelper_enable();
Exit:
pm_notifier_call_chain(PM_POST_HIBERNATION);
diff --git a/kernel/printk.c b/kernel/printk.c
index dc5aefe0b995..24146142bc01 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -369,8 +369,10 @@ static int check_syslog_permissions(int type, bool from_file)
return 0;
/* For historical reasons, accept CAP_SYS_ADMIN too, with a warning */
if (capable(CAP_SYS_ADMIN)) {
- WARN_ONCE(1, "Attempt to access syslog with CAP_SYS_ADMIN "
- "but no CAP_SYSLOG (deprecated).\n");
+ printk_once(KERN_WARNING "%s (%d): "
+ "Attempt to access syslog with CAP_SYS_ADMIN "
+ "but no CAP_SYSLOG (deprecated).\n",
+ current->comm, task_pid_nr(current));
return 0;
}
return -EPERM;
diff --git a/kernel/relay.c b/kernel/relay.c
index 859ea5a9605f..2c242fb2368b 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -164,10 +164,14 @@ depopulate:
*/
static struct rchan_buf *relay_create_buf(struct rchan *chan)
{
- struct rchan_buf *buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL);
- if (!buf)
+ struct rchan_buf *buf;
+
+ if (chan->n_subbufs > UINT_MAX / sizeof(size_t *))
return NULL;
+ buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL);
+ if (!buf)
+ return NULL;
buf->padding = kmalloc(chan->n_subbufs * sizeof(size_t *), GFP_KERNEL);
if (!buf->padding)
goto free_buf;
@@ -574,6 +578,8 @@ struct rchan *relay_open(const char *base_filename,
if (!(subbuf_size && n_subbufs))
return NULL;
+ if (subbuf_size > UINT_MAX / n_subbufs)
+ return NULL;
chan = kzalloc(sizeof(struct rchan), GFP_KERNEL);
if (!chan)
diff --git a/kernel/sched.c b/kernel/sched.c
index 62948763bc8b..2da88acde924 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -3393,13 +3393,10 @@ calc_load_n(unsigned long load, unsigned long exp,
* 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)
+static void calc_global_nohz(void)
{
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
@@ -3411,31 +3408,25 @@ static void calc_global_nohz(unsigned long ticks)
atomic_long_add(delta, &calc_load_tasks);
/*
- * If we were idle for multiple load cycles, apply them.
+ * It could be the one fold was all it took, we done!
*/
- if (ticks >= LOAD_FREQ) {
- n = ticks / LOAD_FREQ;
+ if (time_before(jiffies, calc_load_update + 10))
+ return;
- active = atomic_long_read(&calc_load_tasks);
- active = active > 0 ? active * FIXED_1 : 0;
+ /*
+ * Catch-up, fold however many we are behind still
+ */
+ delta = jiffies - calc_load_update - 10;
+ n = 1 + (delta / LOAD_FREQ);
- 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);
+ active = atomic_long_read(&calc_load_tasks);
+ active = active > 0 ? active * FIXED_1 : 0;
- calc_load_update += n * LOAD_FREQ;
- }
+ 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);
- /*
- * 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.
- */
+ calc_load_update += n * LOAD_FREQ;
}
#else
static void calc_load_account_idle(struct rq *this_rq)
@@ -3447,7 +3438,7 @@ static inline long calc_load_fold_idle(void)
return 0;
}
-static void calc_global_nohz(unsigned long ticks)
+static void calc_global_nohz(void)
{
}
#endif
@@ -3475,8 +3466,6 @@ void calc_global_load(unsigned long ticks)
{
long active;
- calc_global_nohz(ticks);
-
if (time_before(jiffies, calc_load_update + 10))
return;
@@ -3488,6 +3477,16 @@ void calc_global_load(unsigned long ticks)
avenrun[2] = calc_load(avenrun[2], EXP_15, active);
calc_load_update += LOAD_FREQ;
+
+ /*
+ * Account one period with whatever state we found before
+ * folding in the nohz state and ageing the entire idle period.
+ *
+ * This avoids loosing a sample when we go idle between
+ * calc_load_account_active() (10 ticks ago) and now and thus
+ * under-accounting.
+ */
+ calc_global_nohz();
}
/*
@@ -7222,11 +7221,8 @@ int sched_domain_level_max;
static int __init setup_relax_domain_level(char *str)
{
- unsigned long val;
-
- val = simple_strtoul(str, NULL, 0);
- if (val < sched_domain_level_max)
- default_relax_domain_level = val;
+ if (kstrtoint(str, 0, &default_relax_domain_level))
+ pr_warn("Unable to set relax_domain_level\n");
return 1;
}
@@ -7419,7 +7415,6 @@ struct sched_domain *build_sched_domain(struct sched_domain_topology_level *tl,
if (!sd)
return child;
- set_domain_attribute(sd, attr);
cpumask_and(sched_domain_span(sd), cpu_map, tl->mask(cpu));
if (child) {
sd->level = child->level + 1;
@@ -7427,6 +7422,7 @@ struct sched_domain *build_sched_domain(struct sched_domain_topology_level *tl,
child->parent = sd;
}
sd->child = child;
+ set_domain_attribute(sd, attr);
return sd;
}
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
index 17f2319d5e4f..ac79f9e34fd2 100644
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -1390,6 +1390,11 @@ static int push_rt_task(struct rq *rq)
if (!next_task)
return 0;
+#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
+ if (unlikely(task_running(rq, next_task)))
+ return 0;
+#endif
+
retry:
if (unlikely(next_task == rq->curr)) {
WARN_ON(1);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index ea468b1232ac..5b6afb27e8b2 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -173,7 +173,7 @@ static int proc_taint(struct ctl_table *table, int write,
#endif
#ifdef CONFIG_PRINTK
-static int proc_dmesg_restrict(struct ctl_table *table, int write,
+static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos);
#endif
@@ -710,7 +710,7 @@ static struct ctl_table kern_table[] = {
.data = &dmesg_restrict,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = proc_dointvec_minmax,
+ .proc_handler = proc_dointvec_minmax_sysadmin,
.extra1 = &zero,
.extra2 = &one,
},
@@ -719,7 +719,7 @@ static struct ctl_table kern_table[] = {
.data = &kptr_restrict,
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = proc_dmesg_restrict,
+ .proc_handler = proc_dointvec_minmax_sysadmin,
.extra1 = &zero,
.extra2 = &two,
},
@@ -2424,7 +2424,7 @@ static int proc_taint(struct ctl_table *table, int write,
}
#ifdef CONFIG_PRINTK
-static int proc_dmesg_restrict(struct ctl_table *table, int write,
+static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
if (write && !capable(CAP_SYS_ADMIN))
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
index 3b8e028b9601..e055e8b533ce 100644
--- a/kernel/sysctl_binary.c
+++ b/kernel/sysctl_binary.c
@@ -1354,7 +1354,7 @@ static ssize_t binary_sysctl(const int *name, int nlen,
fput(file);
out_putname:
- putname(pathname);
+ __putname(pathname);
out:
return result;
}
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index f6117a4c7cb8..4b85a7a72526 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -275,7 +275,7 @@ static inline s64 ntp_update_offset_fll(s64 offset64, long secs)
time_status |= STA_MODE;
- return div_s64(offset64 << (NTP_SCALE_SHIFT - SHIFT_FLL), secs);
+ return div64_long(offset64 << (NTP_SCALE_SHIFT - SHIFT_FLL), secs);
}
static void ntp_update_offset(long offset)
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
index 8b3b01452248..032f1934cc99 100644
--- a/kernel/time/tick-sched.c
+++ b/kernel/time/tick-sched.c
@@ -484,9 +484,9 @@ static void tick_nohz_restart(struct tick_sched *ts, ktime_t now)
hrtimer_get_expires(&ts->sched_timer), 0))
break;
}
- /* Update jiffies and reread time */
- tick_do_update_jiffies64(now);
+ /* Reread time and update jiffies */
now = ktime_get();
+ tick_do_update_jiffies64(now);
}
}
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index ef9271b69b4f..9f8e2e11020a 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -952,7 +952,7 @@ struct ftrace_func_probe {
};
enum {
- FTRACE_ENABLE_CALLS = (1 << 0),
+ FTRACE_UPDATE_CALLS = (1 << 0),
FTRACE_DISABLE_CALLS = (1 << 1),
FTRACE_UPDATE_TRACE_FUNC = (1 << 2),
FTRACE_START_FUNC_RET = (1 << 3),
@@ -1182,8 +1182,14 @@ alloc_and_copy_ftrace_hash(int size_bits, struct ftrace_hash *hash)
return NULL;
}
+static void
+ftrace_hash_rec_disable(struct ftrace_ops *ops, int filter_hash);
+static void
+ftrace_hash_rec_enable(struct ftrace_ops *ops, int filter_hash);
+
static int
-ftrace_hash_move(struct ftrace_hash **dst, struct ftrace_hash *src)
+ftrace_hash_move(struct ftrace_ops *ops, int enable,
+ struct ftrace_hash **dst, struct ftrace_hash *src)
{
struct ftrace_func_entry *entry;
struct hlist_node *tp, *tn;
@@ -1193,9 +1199,16 @@ ftrace_hash_move(struct ftrace_hash **dst, struct ftrace_hash *src)
unsigned long key;
int size = src->count;
int bits = 0;
+ int ret;
int i;
/*
+ * Remove the current set, update the hash and add
+ * them back.
+ */
+ ftrace_hash_rec_disable(ops, enable);
+
+ /*
* If the new source is empty, just free dst and assign it
* the empty_hash.
*/
@@ -1215,9 +1228,10 @@ ftrace_hash_move(struct ftrace_hash **dst, struct ftrace_hash *src)
if (bits > FTRACE_HASH_MAX_BITS)
bits = FTRACE_HASH_MAX_BITS;
+ ret = -ENOMEM;
new_hash = alloc_ftrace_hash(bits);
if (!new_hash)
- return -ENOMEM;
+ goto out;
size = 1 << src->size_bits;
for (i = 0; i < size; i++) {
@@ -1236,7 +1250,16 @@ ftrace_hash_move(struct ftrace_hash **dst, struct ftrace_hash *src)
rcu_assign_pointer(*dst, new_hash);
free_ftrace_hash_rcu(old_hash);
- return 0;
+ ret = 0;
+ out:
+ /*
+ * Enable regardless of ret:
+ * On success, we enable the new hash.
+ * On failure, we re-enable the original hash.
+ */
+ ftrace_hash_rec_enable(ops, enable);
+
+ return ret;
}
/*
@@ -1498,7 +1521,7 @@ int ftrace_text_reserved(void *start, void *end)
static int
-__ftrace_replace_code(struct dyn_ftrace *rec, int enable)
+__ftrace_replace_code(struct dyn_ftrace *rec, int update)
{
unsigned long ftrace_addr;
unsigned long flag = 0UL;
@@ -1506,17 +1529,17 @@ __ftrace_replace_code(struct dyn_ftrace *rec, int enable)
ftrace_addr = (unsigned long)FTRACE_ADDR;
/*
- * If we are enabling tracing:
+ * If we are updating calls:
*
* If the record has a ref count, then we need to enable it
* because someone is using it.
*
* Otherwise we make sure its disabled.
*
- * If we are disabling tracing, then disable all records that
+ * If we are disabling calls, then disable all records that
* are enabled.
*/
- if (enable && (rec->flags & ~FTRACE_FL_MASK))
+ if (update && (rec->flags & ~FTRACE_FL_MASK))
flag = FTRACE_FL_ENABLED;
/* If the state of this record hasn't changed, then do nothing */
@@ -1532,7 +1555,7 @@ __ftrace_replace_code(struct dyn_ftrace *rec, int enable)
return ftrace_make_nop(NULL, rec, ftrace_addr);
}
-static void ftrace_replace_code(int enable)
+static void ftrace_replace_code(int update)
{
struct dyn_ftrace *rec;
struct ftrace_page *pg;
@@ -1546,7 +1569,7 @@ static void ftrace_replace_code(int enable)
if (rec->flags & FTRACE_FL_FREE)
continue;
- failed = __ftrace_replace_code(rec, enable);
+ failed = __ftrace_replace_code(rec, update);
if (failed) {
ftrace_bug(failed, rec->ip);
/* Stop processing */
@@ -1596,7 +1619,7 @@ static int __ftrace_modify_code(void *data)
{
int *command = data;
- if (*command & FTRACE_ENABLE_CALLS)
+ if (*command & FTRACE_UPDATE_CALLS)
ftrace_replace_code(1);
else if (*command & FTRACE_DISABLE_CALLS)
ftrace_replace_code(0);
@@ -1652,7 +1675,7 @@ static int ftrace_startup(struct ftrace_ops *ops, int command)
return -ENODEV;
ftrace_start_up++;
- command |= FTRACE_ENABLE_CALLS;
+ command |= FTRACE_UPDATE_CALLS;
/* ops marked global share the filter hashes */
if (ops->flags & FTRACE_OPS_FL_GLOBAL) {
@@ -1704,8 +1727,7 @@ static void ftrace_shutdown(struct ftrace_ops *ops, int command)
if (ops != &global_ops || !global_start_up)
ops->flags &= ~FTRACE_OPS_FL_ENABLED;
- if (!ftrace_start_up)
- command |= FTRACE_DISABLE_CALLS;
+ command |= FTRACE_UPDATE_CALLS;
if (saved_ftrace_func != ftrace_trace_function) {
saved_ftrace_func = ftrace_trace_function;
@@ -1727,7 +1749,7 @@ static void ftrace_startup_sysctl(void)
saved_ftrace_func = NULL;
/* ftrace_start_up is true if we want ftrace running */
if (ftrace_start_up)
- ftrace_run_update_code(FTRACE_ENABLE_CALLS);
+ ftrace_run_update_code(FTRACE_UPDATE_CALLS);
}
static void ftrace_shutdown_sysctl(void)
@@ -2877,7 +2899,11 @@ ftrace_set_regex(struct ftrace_ops *ops, unsigned char *buf, int len,
ftrace_match_records(hash, buf, len);
mutex_lock(&ftrace_lock);
- ret = ftrace_hash_move(orig_hash, hash);
+ ret = ftrace_hash_move(ops, enable, orig_hash, hash);
+ if (!ret && ops->flags & FTRACE_OPS_FL_ENABLED
+ && ftrace_enabled)
+ ftrace_run_update_code(FTRACE_UPDATE_CALLS);
+
mutex_unlock(&ftrace_lock);
mutex_unlock(&ftrace_regex_lock);
@@ -3060,18 +3086,12 @@ ftrace_regex_release(struct inode *inode, struct file *file)
orig_hash = &iter->ops->notrace_hash;
mutex_lock(&ftrace_lock);
- /*
- * Remove the current set, update the hash and add
- * them back.
- */
- ftrace_hash_rec_disable(iter->ops, filter_hash);
- ret = ftrace_hash_move(orig_hash, iter->hash);
- if (!ret) {
- ftrace_hash_rec_enable(iter->ops, filter_hash);
- if (iter->ops->flags & FTRACE_OPS_FL_ENABLED
- && ftrace_enabled)
- ftrace_run_update_code(FTRACE_ENABLE_CALLS);
- }
+ ret = ftrace_hash_move(iter->ops, filter_hash,
+ orig_hash, iter->hash);
+ if (!ret && (iter->ops->flags & FTRACE_OPS_FL_ENABLED)
+ && ftrace_enabled)
+ ftrace_run_update_code(FTRACE_UPDATE_CALLS);
+
mutex_unlock(&ftrace_lock);
}
free_ftrace_hash(iter->hash);
diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h
index e32744c84d94..1fe81eef1ce4 100644
--- a/kernel/trace/trace_entries.h
+++ b/kernel/trace/trace_entries.h
@@ -156,6 +156,12 @@ FTRACE_ENTRY_DUP(wakeup, ctx_switch_entry,
#define FTRACE_STACK_ENTRIES 8
+#ifndef CONFIG_64BIT
+# define IP_FMT "%08lx"
+#else
+# define IP_FMT "%016lx"
+#endif
+
FTRACE_ENTRY(kernel_stack, stack_entry,
TRACE_STACK,
@@ -164,8 +170,9 @@ FTRACE_ENTRY(kernel_stack, stack_entry,
__array( unsigned long, caller, FTRACE_STACK_ENTRIES )
),
- F_printk("\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n"
- "\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n",
+ F_printk("\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n"
+ "\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n"
+ "\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n",
__entry->caller[0], __entry->caller[1], __entry->caller[2],
__entry->caller[3], __entry->caller[4], __entry->caller[5],
__entry->caller[6], __entry->caller[7])
@@ -180,8 +187,9 @@ FTRACE_ENTRY(user_stack, userstack_entry,
__array( unsigned long, caller, FTRACE_STACK_ENTRIES )
),
- F_printk("\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n"
- "\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n\t=> (%08lx)\n",
+ F_printk("\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n"
+ "\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n"
+ "\t=> (" IP_FMT ")\n\t=> (" IP_FMT ")\n",
__entry->caller[0], __entry->caller[1], __entry->caller[2],
__entry->caller[3], __entry->caller[4], __entry->caller[5],
__entry->caller[6], __entry->caller[7])
diff --git a/kernel/trace/trace_export.c b/kernel/trace/trace_export.c
index bbeec31e0ae3..ad4000c71be0 100644
--- a/kernel/trace/trace_export.c
+++ b/kernel/trace/trace_export.c
@@ -150,7 +150,7 @@ ftrace_define_fields_##name(struct ftrace_event_call *event_call) \
#define __dynamic_array(type, item)
#undef F_printk
-#define F_printk(fmt, args...) #fmt ", " __stringify(args)
+#define F_printk(fmt, args...) __stringify(fmt) ", " __stringify(args)
#undef FTRACE_ENTRY
#define FTRACE_ENTRY(call, struct_name, etype, tstruct, print) \
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index aec02b6a1c4a..ee1845b8d690 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -252,11 +252,13 @@ struct workqueue_struct *system_long_wq __read_mostly;
struct workqueue_struct *system_nrt_wq __read_mostly;
struct workqueue_struct *system_unbound_wq __read_mostly;
struct workqueue_struct *system_freezable_wq __read_mostly;
+struct workqueue_struct *system_nrt_freezable_wq __read_mostly;
EXPORT_SYMBOL_GPL(system_wq);
EXPORT_SYMBOL_GPL(system_long_wq);
EXPORT_SYMBOL_GPL(system_nrt_wq);
EXPORT_SYMBOL_GPL(system_unbound_wq);
EXPORT_SYMBOL_GPL(system_freezable_wq);
+EXPORT_SYMBOL_GPL(system_nrt_freezable_wq);
#define CREATE_TRACE_POINTS
#include <trace/events/workqueue.h>
@@ -1212,8 +1214,13 @@ static void worker_enter_idle(struct worker *worker)
} else
wake_up_all(&gcwq->trustee_wait);
- /* sanity check nr_running */
- WARN_ON_ONCE(gcwq->nr_workers == gcwq->nr_idle &&
+ /*
+ * Sanity check nr_running. Because trustee releases gcwq->lock
+ * between setting %WORKER_ROGUE and zapping nr_running, the
+ * warning may trigger spuriously. Check iff trustee is idle.
+ */
+ WARN_ON_ONCE(gcwq->trustee_state == TRUSTEE_DONE &&
+ gcwq->nr_workers == gcwq->nr_idle &&
atomic_read(get_gcwq_nr_running(gcwq->cpu)));
}
@@ -3796,8 +3803,11 @@ static int __init init_workqueues(void)
WQ_UNBOUND_MAX_ACTIVE);
system_freezable_wq = alloc_workqueue("events_freezable",
WQ_FREEZABLE, 0);
+ system_nrt_freezable_wq = alloc_workqueue("events_nrt_freezable",
+ WQ_NON_REENTRANT | WQ_FREEZABLE, 0);
BUG_ON(!system_wq || !system_long_wq || !system_nrt_wq ||
- !system_unbound_wq || !system_freezable_wq);
+ !system_unbound_wq || !system_freezable_wq ||
+ !system_nrt_freezable_wq);
return 0;
}
early_initcall(init_workqueues);
diff --git a/lib/btree.c b/lib/btree.c
index 2a34392bcecc..297124d4d8da 100644
--- a/lib/btree.c
+++ b/lib/btree.c
@@ -319,8 +319,8 @@ void *btree_get_prev(struct btree_head *head, struct btree_geo *geo,
if (head->height == 0)
return NULL;
-retry:
longcpy(key, __key, geo->keylen);
+retry:
dec_key(geo, key);
node = head->node;
@@ -351,7 +351,7 @@ retry:
}
miss:
if (retry_key) {
- __key = retry_key;
+ longcpy(key, retry_key, geo->keylen);
retry_key = NULL;
goto retry;
}
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index ad72a03ce5e9..6d40244e8010 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -29,16 +29,17 @@
u64 uevent_seqnum;
char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH;
-static DEFINE_SPINLOCK(sequence_lock);
#ifdef CONFIG_NET
struct uevent_sock {
struct list_head list;
struct sock *sk;
};
static LIST_HEAD(uevent_sock_list);
-static DEFINE_MUTEX(uevent_sock_mutex);
#endif
+/* This lock protects uevent_seqnum and uevent_sock_list */
+static DEFINE_MUTEX(uevent_sock_mutex);
+
/* the strings here must match the enum in include/linux/kobject.h */
static const char *kobject_actions[] = {
[KOBJ_ADD] = "add",
@@ -136,7 +137,6 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
struct kobject *top_kobj;
struct kset *kset;
const struct kset_uevent_ops *uevent_ops;
- u64 seq;
int i = 0;
int retval = 0;
#ifdef CONFIG_NET
@@ -243,17 +243,16 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
else if (action == KOBJ_REMOVE)
kobj->state_remove_uevent_sent = 1;
+ mutex_lock(&uevent_sock_mutex);
/* we will send an event, so request a new sequence number */
- spin_lock(&sequence_lock);
- seq = ++uevent_seqnum;
- spin_unlock(&sequence_lock);
- retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)seq);
- if (retval)
+ retval = add_uevent_var(env, "SEQNUM=%llu", (unsigned long long)++uevent_seqnum);
+ if (retval) {
+ mutex_unlock(&uevent_sock_mutex);
goto exit;
+ }
#if defined(CONFIG_NET)
/* send netlink message */
- mutex_lock(&uevent_sock_mutex);
list_for_each_entry(ue_sk, &uevent_sock_list, list) {
struct sock *uevent_sock = ue_sk->sk;
struct sk_buff *skb;
@@ -287,8 +286,8 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
} else
retval = -ENOMEM;
}
- mutex_unlock(&uevent_sock_mutex);
#endif
+ mutex_unlock(&uevent_sock_mutex);
/* call uevent_helper, usually only enabled during early boot */
if (uevent_helper[0] && !kobj_usermode_filter(kobj)) {
diff --git a/mm/bootmem.c b/mm/bootmem.c
index 01d5a4b3dd0c..9686c4e3f80d 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -768,14 +768,13 @@ void * __init alloc_bootmem_section(unsigned long size,
unsigned long section_nr)
{
bootmem_data_t *bdata;
- unsigned long pfn, goal, limit;
+ unsigned long pfn, goal;
pfn = section_nr_to_pfn(section_nr);
goal = pfn << PAGE_SHIFT;
- limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT;
bdata = &bootmem_node_data[early_pfn_to_nid(pfn)];
- return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, limit);
+ return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, 0);
}
#endif
diff --git a/mm/compaction.c b/mm/compaction.c
index 6cc604bd5649..c4bc5acf865d 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -320,12 +320,34 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
} else if (!locked)
spin_lock_irq(&zone->lru_lock);
+ /*
+ * migrate_pfn does not necessarily start aligned to a
+ * pageblock. Ensure that pfn_valid is called when moving
+ * into a new MAX_ORDER_NR_PAGES range in case of large
+ * memory holes within the zone
+ */
+ if ((low_pfn & (MAX_ORDER_NR_PAGES - 1)) == 0) {
+ if (!pfn_valid(low_pfn)) {
+ low_pfn += MAX_ORDER_NR_PAGES - 1;
+ continue;
+ }
+ }
+
if (!pfn_valid_within(low_pfn))
continue;
nr_scanned++;
- /* Get the page and skip if free */
+ /*
+ * Get the page and ensure the page is within the same zone.
+ * See the comment in isolate_freepages about overlapping
+ * nodes. It is deliberate that the new zone lock is not taken
+ * as memory compaction should not move pages between nodes.
+ */
page = pfn_to_page(low_pfn);
+ if (page_zone(page) != zone)
+ continue;
+
+ /* Skip if free */
if (PageBuddy(page))
continue;
diff --git a/mm/dmapool.c b/mm/dmapool.c
index 03bf3bb4519a..98798f414cb9 100644
--- a/mm/dmapool.c
+++ b/mm/dmapool.c
@@ -212,6 +212,32 @@ static void pool_initialise_page(struct dma_pool *pool, struct dma_page *page)
} while (offset < pool->allocation);
}
+#ifdef CONFIG_FSL_UTP
+static struct dma_page *pool_alloc_page_nonbufferable(struct dma_pool *pool, gfp_t mem_flags)
+{
+ struct dma_page *page;
+
+ page = kmalloc(sizeof(*page), mem_flags);
+ if (!page)
+ return NULL;
+ page->vaddr = dma_alloc_noncacheable(pool->dev, pool->allocation,
+ &page->dma, mem_flags);
+ if (page->vaddr) {
+#ifdef DMAPOOL_DEBUG
+ memset(page->vaddr, POOL_POISON_FREED, pool->allocation);
+#endif
+ pool_initialise_page(pool, page);
+ list_add(&page->page_list, &pool->page_list);
+ page->in_use = 0;
+ page->offset = 0;
+ } else {
+ kfree(page);
+ page = NULL;
+ }
+ return page;
+}
+#endif
+
static struct dma_page *pool_alloc_page(struct dma_pool *pool, gfp_t mem_flags)
{
struct dma_page *page;
@@ -353,6 +379,68 @@ void *dma_pool_alloc(struct dma_pool *pool, gfp_t mem_flags,
}
EXPORT_SYMBOL(dma_pool_alloc);
+#ifdef CONFIG_FSL_UTP
+/**
+ * dma_pool_alloc_nonbufferable - get a block of consistent memory
+ * @pool: dma pool that will produce the block
+ * @mem_flags: GFP_* bitmask
+ * @handle: pointer to dma address of block
+ *
+ * This returns the kernel virtual address of a currently unused block,
+ * and reports its dma address through the handle.
+ * If such a memory block can't be allocated, %NULL is returned.
+ */
+void *dma_pool_alloc_nonbufferable(struct dma_pool *pool, gfp_t mem_flags,
+ dma_addr_t *handle)
+{
+ unsigned long flags;
+ struct dma_page *page;
+ size_t offset;
+ void *retval;
+
+ might_sleep_if(mem_flags & __GFP_WAIT);
+
+ spin_lock_irqsave(&pool->lock, flags);
+ restart:
+ list_for_each_entry(page, &pool->page_list, page_list) {
+ if (page->offset < pool->allocation)
+ goto ready;
+ }
+ page = pool_alloc_page_nonbufferable(pool, GFP_ATOMIC);
+ if (!page) {
+ if (mem_flags & __GFP_WAIT) {
+ DECLARE_WAITQUEUE(wait, current);
+
+ __set_current_state(TASK_UNINTERRUPTIBLE);
+ __add_wait_queue(&pool->waitq, &wait);
+ spin_unlock_irqrestore(&pool->lock, flags);
+
+ schedule_timeout(POOL_TIMEOUT_JIFFIES);
+
+ spin_lock_irqsave(&pool->lock, flags);
+ __remove_wait_queue(&pool->waitq, &wait);
+ goto restart;
+ }
+ retval = NULL;
+ goto done;
+ }
+
+ ready:
+ page->in_use++;
+ offset = page->offset;
+ page->offset = *(int *)(page->vaddr + offset);
+ retval = offset + page->vaddr;
+ *handle = offset + page->dma;
+#ifdef DMAPOOL_DEBUG
+ memset(retval, POOL_POISON_ALLOCATED, pool->size);
+#endif
+ done:
+ spin_unlock_irqrestore(&pool->lock, flags);
+ return retval;
+}
+EXPORT_SYMBOL(dma_pool_alloc_nonbufferable);
+#endif
+
static struct dma_page *pool_find_page(struct dma_pool *pool, dma_addr_t dma)
{
struct dma_page *page;
diff --git a/mm/filemap.c b/mm/filemap.c
index a8251a8d3457..b7d860390f34 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -396,24 +396,11 @@ EXPORT_SYMBOL(filemap_write_and_wait_range);
int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask)
{
int error;
- struct mem_cgroup *memcg = NULL;
VM_BUG_ON(!PageLocked(old));
VM_BUG_ON(!PageLocked(new));
VM_BUG_ON(new->mapping);
- /*
- * This is not page migration, but prepare_migration and
- * end_migration does enough work for charge replacement.
- *
- * In the longer term we probably want a specialized function
- * for moving the charge from old to new in a more efficient
- * manner.
- */
- error = mem_cgroup_prepare_migration(old, new, &memcg, gfp_mask);
- if (error)
- return error;
-
error = radix_tree_preload(gfp_mask & ~__GFP_HIGHMEM);
if (!error) {
struct address_space *mapping = old->mapping;
@@ -435,13 +422,12 @@ int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask)
if (PageSwapBacked(new))
__inc_zone_page_state(new, NR_SHMEM);
spin_unlock_irq(&mapping->tree_lock);
+ /* mem_cgroup codes must not be called under tree_lock */
+ mem_cgroup_replace_page_cache(old, new);
radix_tree_preload_end();
if (freepage)
freepage(old);
page_cache_release(old);
- mem_cgroup_end_migration(memcg, old, new, true);
- } else {
- mem_cgroup_end_migration(memcg, old, new, false);
}
return error;
@@ -1393,15 +1379,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
unsigned long seg = 0;
size_t count;
loff_t *ppos = &iocb->ki_pos;
- struct blk_plug plug;
count = 0;
retval = generic_segment_checks(iov, &nr_segs, &count, VERIFY_WRITE);
if (retval)
return retval;
- blk_start_plug(&plug);
-
/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */
if (filp->f_flags & O_DIRECT) {
loff_t size;
@@ -1417,8 +1400,12 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
retval = filemap_write_and_wait_range(mapping, pos,
pos + iov_length(iov, nr_segs) - 1);
if (!retval) {
+ struct blk_plug plug;
+
+ blk_start_plug(&plug);
retval = mapping->a_ops->direct_IO(READ, iocb,
iov, pos, nr_segs);
+ blk_finish_plug(&plug);
}
if (retval > 0) {
*ppos = pos + retval;
@@ -1474,7 +1461,6 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
break;
}
out:
- blk_finish_plug(&plug);
return retval;
}
EXPORT_SYMBOL(generic_file_aio_read);
@@ -1807,7 +1793,7 @@ repeat:
page = __page_cache_alloc(gfp | __GFP_COLD);
if (!page)
return ERR_PTR(-ENOMEM);
- err = add_to_page_cache_lru(page, mapping, index, GFP_KERNEL);
+ err = add_to_page_cache_lru(page, mapping, index, gfp);
if (unlikely(err)) {
page_cache_release(page);
if (err == -EEXIST)
@@ -1904,10 +1890,7 @@ static struct page *wait_on_page_read(struct page *page)
* @gfp: the page allocator flags to use if allocating
*
* This is the same as "read_mapping_page(mapping, index, NULL)", but with
- * any new page allocations done using the specified allocation flags. Note
- * that the Radix tree operations will still use GFP_KERNEL, so you can't
- * expect to do this atomically or anything like that - but you can pass in
- * other page requirements.
+ * any new page allocations done using the specified allocation flags.
*
* If the page does not get brought uptodate, return -EIO.
*/
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index 93356cd12828..dee94297f392 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -263,7 +263,12 @@ found:
xip_pfn);
if (err == -ENOMEM)
return VM_FAULT_OOM;
- BUG_ON(err);
+ /*
+ * err == -EBUSY is fine, we've raced against another thread
+ * that faulted-in the same page
+ */
+ if (err != -EBUSY)
+ BUG_ON(err);
return VM_FAULT_NOPAGE;
} else {
int err, ret = VM_FAULT_OOM;
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index cc5acf9998b0..8cc11dda6a74 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -641,6 +641,7 @@ static int __do_huge_pmd_anonymous_page(struct mm_struct *mm,
set_pmd_at(mm, haddr, pmd, entry);
prepare_pmd_huge_pte(pgtable, mm);
add_mm_counter(mm, MM_ANONPAGES, HPAGE_PMD_NR);
+ mm->nr_ptes++;
spin_unlock(&mm->page_table_lock);
}
@@ -759,6 +760,7 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm,
pmd = pmd_mkold(pmd_wrprotect(pmd));
set_pmd_at(dst_mm, addr, dst_pmd, pmd);
prepare_pmd_huge_pte(pgtable, dst_mm);
+ dst_mm->nr_ptes++;
ret = 0;
out_unlock:
@@ -857,7 +859,6 @@ static int do_huge_pmd_wp_page_fallback(struct mm_struct *mm,
}
kfree(pages);
- mm->nr_ptes++;
smp_wmb(); /* make pte visible before pmd */
pmd_populate(mm, pmd, pgtable);
page_remove_rmap(page);
@@ -1016,6 +1017,7 @@ int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
VM_BUG_ON(page_mapcount(page) < 0);
add_mm_counter(tlb->mm, MM_ANONPAGES, -HPAGE_PMD_NR);
VM_BUG_ON(!PageHead(page));
+ tlb->mm->nr_ptes--;
spin_unlock(&tlb->mm->page_table_lock);
tlb_remove_page(tlb, page);
pte_free(tlb->mm, pgtable);
@@ -1310,7 +1312,6 @@ static int __split_huge_page_map(struct page *page,
pte_unmap(pte);
}
- mm->nr_ptes++;
smp_wmb(); /* make pte visible before pmd */
/*
* Up to this point the pmd is present and huge and
@@ -1925,7 +1926,6 @@ static void collapse_huge_page(struct mm_struct *mm,
set_pmd_at(mm, address, pmd, _pmd);
update_mmu_cache(vma, address, entry);
prepare_pmd_huge_pte(pgtable, mm);
- mm->nr_ptes--;
spin_unlock(&mm->page_table_lock);
#ifndef CONFIG_NUMA
@@ -2020,7 +2020,7 @@ static void collect_mm_slot(struct mm_slot *mm_slot)
{
struct mm_struct *mm = mm_slot->mm;
- VM_BUG_ON(!spin_is_locked(&khugepaged_mm_lock));
+ VM_BUG_ON(NR_CPUS != 1 && !spin_is_locked(&khugepaged_mm_lock));
if (khugepaged_test_exit(mm)) {
/* free mm_slot */
@@ -2048,7 +2048,7 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages,
int progress = 0;
VM_BUG_ON(!pages);
- VM_BUG_ON(!spin_is_locked(&khugepaged_mm_lock));
+ VM_BUG_ON(NR_CPUS != 1 && !spin_is_locked(&khugepaged_mm_lock));
if (khugepaged_scan.mm_slot)
mm_slot = khugepaged_scan.mm_slot;
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 80936a118c38..05f8fd425f69 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -901,7 +901,6 @@ retry:
h->resv_huge_pages += delta;
ret = 0;
- spin_unlock(&hugetlb_lock);
/* Free the needed pages to the hugetlb pool */
list_for_each_entry_safe(page, tmp, &surplus_list, lru) {
if ((--needed) < 0)
@@ -915,6 +914,7 @@ retry:
VM_BUG_ON(page_count(page));
enqueue_huge_page(h, page);
}
+ spin_unlock(&hugetlb_lock);
/* Free unnecessary surplus pages to the buddy allocator */
free:
@@ -2060,6 +2060,15 @@ static void hugetlb_vm_op_open(struct vm_area_struct *vma)
kref_get(&reservations->refs);
}
+static void resv_map_put(struct vm_area_struct *vma)
+{
+ struct resv_map *reservations = vma_resv_map(vma);
+
+ if (!reservations)
+ return;
+ kref_put(&reservations->refs, resv_map_release);
+}
+
static void hugetlb_vm_op_close(struct vm_area_struct *vma)
{
struct hstate *h = hstate_vma(vma);
@@ -2075,7 +2084,7 @@ static void hugetlb_vm_op_close(struct vm_area_struct *vma)
reserve = (end - start) -
region_count(&reservations->regions, start, end);
- kref_put(&reservations->refs, resv_map_release);
+ resv_map_put(vma);
if (reserve) {
hugetlb_acct_memory(h, -reserve);
@@ -2398,7 +2407,6 @@ retry_avoidcopy:
if (outside_reserve) {
BUG_ON(huge_pte_none(pte));
if (unmap_ref_private(mm, vma, old_page, address)) {
- BUG_ON(page_count(old_page) != 1);
BUG_ON(huge_pte_none(pte));
spin_lock(&mm->page_table_lock);
goto retry_avoidcopy;
@@ -2679,6 +2687,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
* so no worry about deadlock.
*/
page = pte_page(entry);
+ get_page(page);
if (page != pagecache_page)
lock_page(page);
@@ -2710,6 +2719,7 @@ out_page_table_lock:
}
if (page != pagecache_page)
unlock_page(page);
+ put_page(page);
out_mutex:
mutex_unlock(&hugetlb_instantiation_mutex);
@@ -2876,12 +2886,16 @@ int hugetlb_reserve_pages(struct inode *inode,
set_vma_resv_flags(vma, HPAGE_RESV_OWNER);
}
- if (chg < 0)
- return chg;
+ if (chg < 0) {
+ ret = chg;
+ goto out_err;
+ }
/* There must be enough filesystem quota for the mapping */
- if (hugetlb_get_quota(inode->i_mapping, chg))
- return -ENOSPC;
+ if (hugetlb_get_quota(inode->i_mapping, chg)) {
+ ret = -ENOSPC;
+ goto out_err;
+ }
/*
* Check enough hugepages are available for the reservation.
@@ -2890,7 +2904,7 @@ int hugetlb_reserve_pages(struct inode *inode,
ret = hugetlb_acct_memory(h, chg);
if (ret < 0) {
hugetlb_put_quota(inode->i_mapping, chg);
- return ret;
+ goto out_err;
}
/*
@@ -2907,6 +2921,10 @@ int hugetlb_reserve_pages(struct inode *inode,
if (!vma || vma->vm_flags & VM_MAYSHARE)
region_add(&inode->i_mapping->private_list, from, to);
return 0;
+out_err:
+ if (vma)
+ resv_map_put(vma);
+ return ret;
}
void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed)
diff --git a/mm/madvise.c b/mm/madvise.c
index 2221491ed503..deabe5f603ad 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -13,6 +13,7 @@
#include <linux/hugetlb.h>
#include <linux/sched.h>
#include <linux/ksm.h>
+#include <linux/file.h>
/*
* Any behaviour which results in changes to the vma->vm_flags needs to
@@ -197,14 +198,16 @@ static long madvise_remove(struct vm_area_struct *vma,
struct address_space *mapping;
loff_t offset, endoff;
int error;
+ struct file *f;
*prev = NULL; /* tell sys_madvise we drop mmap_sem */
if (vma->vm_flags & (VM_LOCKED|VM_NONLINEAR|VM_HUGETLB))
return -EINVAL;
- if (!vma->vm_file || !vma->vm_file->f_mapping
- || !vma->vm_file->f_mapping->host) {
+ f = vma->vm_file;
+
+ if (!f || !f->f_mapping || !f->f_mapping->host) {
return -EINVAL;
}
@@ -218,9 +221,16 @@ static long madvise_remove(struct vm_area_struct *vma,
endoff = (loff_t)(end - vma->vm_start - 1)
+ ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
- /* vmtruncate_range needs to take i_mutex and i_alloc_sem */
+ /*
+ * vmtruncate_range may need to take i_mutex and i_alloc_sem.
+ * We need to explicitly grab a reference because the vma (and
+ * hence the vma's reference to the file) can go away as soon as
+ * we drop mmap_sem.
+ */
+ get_file(f);
up_read(&current->mm->mmap_sem);
error = vmtruncate_range(mapping->host, offset, endoff);
+ fput(f);
down_read(&current->mm->mmap_sem);
return error;
}
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 59ac5d6de478..ffb99b4e7527 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3422,6 +3422,50 @@ int mem_cgroup_shmem_charge_fallback(struct page *page,
return ret;
}
+/*
+ * At replace page cache, newpage is not under any memcg but it's on
+ * LRU. So, this function doesn't touch res_counter but handles LRU
+ * in correct way. Both pages are locked so we cannot race with uncharge.
+ */
+void mem_cgroup_replace_page_cache(struct page *oldpage,
+ struct page *newpage)
+{
+ struct mem_cgroup *memcg;
+ struct page_cgroup *pc;
+ struct zone *zone;
+ enum charge_type type = MEM_CGROUP_CHARGE_TYPE_CACHE;
+ unsigned long flags;
+
+ if (mem_cgroup_disabled())
+ return;
+
+ pc = lookup_page_cgroup(oldpage);
+ /* fix accounting on old pages */
+ lock_page_cgroup(pc);
+ memcg = pc->mem_cgroup;
+ mem_cgroup_charge_statistics(memcg, PageCgroupCache(pc), -1);
+ ClearPageCgroupUsed(pc);
+ unlock_page_cgroup(pc);
+
+ if (PageSwapBacked(oldpage))
+ type = MEM_CGROUP_CHARGE_TYPE_SHMEM;
+
+ zone = page_zone(newpage);
+ pc = lookup_page_cgroup(newpage);
+ /*
+ * Even if newpage->mapping was NULL before starting replacement,
+ * the newpage may be on LRU(or pagevec for LRU) already. We lock
+ * LRU while we overwrite pc->mem_cgroup.
+ */
+ spin_lock_irqsave(&zone->lru_lock, flags);
+ if (PageLRU(newpage))
+ del_page_from_lru_list(zone, newpage, page_lru(newpage));
+ __mem_cgroup_commit_charge(memcg, newpage, 1, pc, type);
+ if (PageLRU(newpage))
+ add_page_to_lru_list(zone, newpage, page_lru(newpage));
+ spin_unlock_irqrestore(&zone->lru_lock, flags);
+}
+
#ifdef CONFIG_DEBUG_VM
static struct page_cgroup *lookup_page_cgroup_used(struct page *page)
{
@@ -4514,6 +4558,9 @@ static void mem_cgroup_usage_unregister_event(struct cgroup *cgrp,
*/
BUG_ON(!thresholds);
+ if (!thresholds->primary)
+ goto unlock;
+
usage = mem_cgroup_usage(memcg, type == _MEMSWAP);
/* Check if a threshold crossed before removing */
@@ -4558,11 +4605,17 @@ static void mem_cgroup_usage_unregister_event(struct cgroup *cgrp,
swap_buffers:
/* Swap primary and spare array */
thresholds->spare = thresholds->primary;
+ /* If all events are unregistered, free the spare array */
+ if (!new) {
+ kfree(thresholds->spare);
+ thresholds->spare = NULL;
+ }
+
rcu_assign_pointer(thresholds->primary, new);
/* To be sure that nobody uses thresholds */
synchronize_rcu();
-
+unlock:
mutex_unlock(&memcg->thresholds_lock);
}
@@ -4963,9 +5016,9 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
int cpu;
enable_swap_cgroup();
parent = NULL;
- root_mem_cgroup = mem;
if (mem_cgroup_soft_limit_tree_init())
goto free_out;
+ root_mem_cgroup = mem;
for_each_possible_cpu(cpu) {
struct memcg_stock_pcp *stock =
&per_cpu(memcg_stock, cpu);
@@ -5004,7 +5057,6 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
return &mem->css;
free_out:
__mem_cgroup_free(mem);
- root_mem_cgroup = NULL;
return ERR_PTR(error);
}
@@ -5244,6 +5296,8 @@ static int mem_cgroup_count_precharge_pte_range(pmd_t *pmd,
spinlock_t *ptl;
split_huge_page_pmd(walk->mm, pmd);
+ if (pmd_trans_unstable(pmd))
+ return 0;
pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
for (; addr != end; pte++, addr += PAGE_SIZE)
@@ -5405,6 +5459,8 @@ static int mem_cgroup_move_charge_pte_range(pmd_t *pmd,
spinlock_t *ptl;
split_huge_page_pmd(walk->mm, pmd);
+ if (pmd_trans_unstable(pmd))
+ return 0;
retry:
pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
for (; addr != end; addr += PAGE_SIZE) {
diff --git a/mm/memory.c b/mm/memory.c
index 95a77998ab51..d49b58aba4ae 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1228,16 +1228,24 @@ static inline unsigned long zap_pmd_range(struct mmu_gather *tlb,
do {
next = pmd_addr_end(addr, end);
if (pmd_trans_huge(*pmd)) {
- if (next-addr != HPAGE_PMD_SIZE) {
+ if (next - addr != HPAGE_PMD_SIZE) {
VM_BUG_ON(!rwsem_is_locked(&tlb->mm->mmap_sem));
split_huge_page_pmd(vma->vm_mm, pmd);
} else if (zap_huge_pmd(tlb, vma, pmd))
- continue;
+ goto next;
/* fall through */
}
- if (pmd_none_or_clear_bad(pmd))
- continue;
+ /*
+ * Here there can be other concurrent MADV_DONTNEED or
+ * trans huge page faults running, and if the pmd is
+ * none or trans huge it can change under us. This is
+ * because MADV_DONTNEED holds the mmap_sem in read
+ * mode.
+ */
+ if (pmd_none_or_trans_huge_or_clear_bad(pmd))
+ goto next;
next = zap_pte_range(tlb, vma, pmd, addr, next, details);
+next:
cond_resched();
} while (pmd++, addr = next, addr != end);
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index e7fb9d25c54e..3dac2d168e47 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -511,7 +511,7 @@ static inline int check_pmd_range(struct vm_area_struct *vma, pud_t *pud,
do {
next = pmd_addr_end(addr, end);
split_huge_page_pmd(vma->vm_mm, pmd);
- if (pmd_none_or_clear_bad(pmd))
+ if (pmd_none_or_trans_huge_or_clear_bad(pmd))
continue;
if (check_pte_range(vma, pmd, addr, next, nodes,
flags, private))
@@ -606,27 +606,6 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end,
return first;
}
-/* Apply policy to a single VMA */
-static int policy_vma(struct vm_area_struct *vma, struct mempolicy *new)
-{
- int err = 0;
- struct mempolicy *old = vma->vm_policy;
-
- pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",
- vma->vm_start, vma->vm_end, vma->vm_pgoff,
- vma->vm_ops, vma->vm_file,
- vma->vm_ops ? vma->vm_ops->set_policy : NULL);
-
- if (vma->vm_ops && vma->vm_ops->set_policy)
- err = vma->vm_ops->set_policy(vma, new);
- if (!err) {
- mpol_get(new);
- vma->vm_policy = new;
- mpol_put(old);
- }
- return err;
-}
-
/* Step 2: apply policy to a range and do splits. */
static int mbind_range(struct mm_struct *mm, unsigned long start,
unsigned long end, struct mempolicy *new_pol)
@@ -666,9 +645,23 @@ static int mbind_range(struct mm_struct *mm, unsigned long start,
if (err)
goto out;
}
- err = policy_vma(vma, new_pol);
- if (err)
- goto out;
+
+ /*
+ * Apply policy to a single VMA. The reference counting of
+ * policy for vma_policy linkages has already been handled by
+ * vma_merge and split_vma as necessary. If this is a shared
+ * policy then ->set_policy will increment the reference count
+ * for an sp node.
+ */
+ pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",
+ vma->vm_start, vma->vm_end, vma->vm_pgoff,
+ vma->vm_ops, vma->vm_file,
+ vma->vm_ops ? vma->vm_ops->set_policy : NULL);
+ if (vma->vm_ops && vma->vm_ops->set_policy) {
+ err = vma->vm_ops->set_policy(vma, new_pol);
+ if (err)
+ goto out;
+ }
}
out:
diff --git a/mm/mincore.c b/mm/mincore.c
index a4e6b9d75c76..117ff5492795 100644
--- a/mm/mincore.c
+++ b/mm/mincore.c
@@ -161,7 +161,7 @@ static void mincore_pmd_range(struct vm_area_struct *vma, pud_t *pud,
}
/* fall through */
}
- if (pmd_none_or_clear_bad(pmd))
+ if (pmd_none_or_trans_huge_or_clear_bad(pmd))
mincore_unmapped_range(vma, addr, next, vec);
else
mincore_pte_range(vma, pmd, addr, next, vec);
diff --git a/mm/nobootmem.c b/mm/nobootmem.c
index 6e93dc7f2586..e39e3efe4a43 100644
--- a/mm/nobootmem.c
+++ b/mm/nobootmem.c
@@ -83,8 +83,7 @@ void __init free_bootmem_late(unsigned long addr, unsigned long size)
static void __init __free_pages_memory(unsigned long start, unsigned long end)
{
- int i;
- unsigned long start_aligned, end_aligned;
+ unsigned long i, start_aligned, end_aligned;
int order = ilog2(BITS_PER_LONG);
start_aligned = (start + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1);
diff --git a/mm/nommu.c b/mm/nommu.c
index 9edc897a3970..5ff9b35883ee 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -697,9 +697,11 @@ static void add_vma_to_mm(struct mm_struct *mm, struct vm_area_struct *vma)
if (vma->vm_file) {
mapping = vma->vm_file->f_mapping;
+ mutex_lock(&mapping->i_mmap_mutex);
flush_dcache_mmap_lock(mapping);
vma_prio_tree_insert(vma, &mapping->i_mmap);
flush_dcache_mmap_unlock(mapping);
+ mutex_unlock(&mapping->i_mmap_mutex);
}
/* add the VMA to the tree */
@@ -761,9 +763,11 @@ static void delete_vma_from_mm(struct vm_area_struct *vma)
if (vma->vm_file) {
mapping = vma->vm_file->f_mapping;
+ mutex_lock(&mapping->i_mmap_mutex);
flush_dcache_mmap_lock(mapping);
vma_prio_tree_remove(vma, &mapping->i_mmap);
flush_dcache_mmap_unlock(mapping);
+ mutex_unlock(&mapping->i_mmap_mutex);
}
/* remove from the MM's tree and list */
@@ -776,8 +780,6 @@ static void delete_vma_from_mm(struct vm_area_struct *vma)
if (vma->vm_next)
vma->vm_next->vm_prev = vma->vm_prev;
-
- vma->vm_mm = NULL;
}
/*
@@ -2061,6 +2063,7 @@ int nommu_shrink_inode_mappings(struct inode *inode, size_t size,
high = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
down_write(&nommu_region_sem);
+ mutex_lock(&inode->i_mapping->i_mmap_mutex);
/* search for VMAs that fall within the dead zone */
vma_prio_tree_foreach(vma, &iter, &inode->i_mapping->i_mmap,
@@ -2068,6 +2071,7 @@ int nommu_shrink_inode_mappings(struct inode *inode, size_t size,
/* found one - only interested if it's shared out of the page
* cache */
if (vma->vm_flags & VM_SHARED) {
+ mutex_unlock(&inode->i_mapping->i_mmap_mutex);
up_write(&nommu_region_sem);
return -ETXTBSY; /* not quite true, but near enough */
}
@@ -2095,6 +2099,7 @@ int nommu_shrink_inode_mappings(struct inode *inode, size_t size,
}
}
+ mutex_unlock(&inode->i_mapping->i_mmap_mutex);
up_write(&nommu_region_sem);
return 0;
}
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 8093fc766d16..7c72487ca459 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -162,7 +162,7 @@ static bool oom_unkillable_task(struct task_struct *p,
unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem,
const nodemask_t *nodemask, unsigned long totalpages)
{
- int points;
+ long points;
if (oom_unkillable_task(p, mem, nodemask))
return 0;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index afa80ed07253..e2f474da7ee2 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -5588,6 +5588,17 @@ __count_immobile_pages(struct zone *zone, struct page *page, int count)
bool is_pageblock_removable_nolock(struct page *page)
{
struct zone *zone = page_zone(page);
+ unsigned long pfn = page_to_pfn(page);
+
+ /*
+ * We have to be careful here because we are iterating over memory
+ * sections which are not zone aware so we might end up outside of
+ * the zone but still within the section.
+ */
+ if (!zone || zone->zone_start_pfn > pfn ||
+ zone->zone_start_pfn + zone->spanned_pages <= pfn)
+ return false;
+
return __count_immobile_pages(zone, page, 0);
}
diff --git a/mm/pagewalk.c b/mm/pagewalk.c
index c3450d533611..87eac0ea2bf1 100644
--- a/mm/pagewalk.c
+++ b/mm/pagewalk.c
@@ -59,7 +59,7 @@ again:
continue;
split_huge_page_pmd(walk->mm, pmd);
- if (pmd_none_or_clear_bad(pmd))
+ if (pmd_none_or_trans_huge_or_clear_bad(pmd))
goto again;
err = walk_pte_range(pmd, addr, next, walk);
if (err)
diff --git a/mm/percpu.c b/mm/percpu.c
index 93b5a7c96a7e..af0cc7a58f9f 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -1011,9 +1011,11 @@ phys_addr_t per_cpu_ptr_to_phys(void *addr)
if (!is_vmalloc_addr(addr))
return __pa(addr);
else
- return page_to_phys(vmalloc_to_page(addr));
+ return page_to_phys(vmalloc_to_page(addr)) +
+ offset_in_page(addr);
} else
- return page_to_phys(pcpu_addr_to_page(addr));
+ return page_to_phys(pcpu_addr_to_page(addr)) +
+ offset_in_page(addr);
}
/**
@@ -1628,6 +1630,16 @@ int __init pcpu_embed_first_chunk(size_t reserved_size, size_t dyn_size,
areas[group] = ptr;
base = min(ptr, base);
+ }
+
+ /*
+ * Copy data and free unused parts. This should happen after all
+ * allocations are complete; otherwise, we may end up with
+ * overlapping groups.
+ */
+ for (group = 0; group < ai->nr_groups; group++) {
+ struct pcpu_group_info *gi = &ai->groups[group];
+ void *ptr = areas[group];
for (i = 0; i < gi->nr_units; i++, ptr += ai->unit_size) {
if (gi->cpu_map[i] == NR_CPUS) {
diff --git a/mm/slub.c b/mm/slub.c
index 0d0901ebaea2..10ab2335e2ea 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -3439,13 +3439,14 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size,
if (kmem_cache_open(s, n,
size, align, flags, ctor)) {
list_add(&s->list, &slab_caches);
+ up_write(&slub_lock);
if (sysfs_slab_add(s)) {
+ down_write(&slub_lock);
list_del(&s->list);
kfree(n);
kfree(s);
goto err;
}
- up_write(&slub_lock);
return s;
}
kfree(n);
diff --git a/mm/sparse.c b/mm/sparse.c
index aa64b12831a2..4cd05e5f2f43 100644
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -353,29 +353,21 @@ static void __init sparse_early_usemaps_alloc_node(unsigned long**usemap_map,
usemap = sparse_early_usemaps_alloc_pgdat_section(NODE_DATA(nodeid),
usemap_count);
- if (usemap) {
- for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
- if (!present_section_nr(pnum))
- continue;
- usemap_map[pnum] = usemap;
- usemap += size;
+ if (!usemap) {
+ usemap = alloc_bootmem_node(NODE_DATA(nodeid), size * usemap_count);
+ if (!usemap) {
+ printk(KERN_WARNING "%s: allocation failed\n", __func__);
+ return;
}
- return;
}
- usemap = alloc_bootmem_node(NODE_DATA(nodeid), size * usemap_count);
- if (usemap) {
- for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
- if (!present_section_nr(pnum))
- continue;
- usemap_map[pnum] = usemap;
- usemap += size;
- check_usemap_section_nr(nodeid, usemap_map[pnum]);
- }
- return;
+ for (pnum = pnum_begin; pnum < pnum_end; pnum++) {
+ if (!present_section_nr(pnum))
+ continue;
+ usemap_map[pnum] = usemap;
+ usemap += size;
+ check_usemap_section_nr(nodeid, usemap_map[pnum]);
}
-
- printk(KERN_WARNING "%s: allocation failed\n", __func__);
}
#ifndef CONFIG_SPARSEMEM_VMEMMAP
diff --git a/mm/swap.c b/mm/swap.c
index 87627f181c3f..4a1fc6db89e8 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -667,7 +667,7 @@ void lru_add_page_tail(struct zone* zone,
VM_BUG_ON(!PageHead(page));
VM_BUG_ON(PageCompound(page_tail));
VM_BUG_ON(PageLRU(page_tail));
- VM_BUG_ON(!spin_is_locked(&zone->lru_lock));
+ VM_BUG_ON(NR_CPUS != 1 && !spin_is_locked(&zone->lru_lock));
SetPageLRU(page_tail);
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 46680461785b..10e9198778cf 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -28,7 +28,7 @@
*/
static const struct address_space_operations swap_aops = {
.writepage = swap_writepage,
- .set_page_dirty = __set_page_dirty_nobuffers,
+ .set_page_dirty = __set_page_dirty_no_writeback,
.migratepage = migrate_page,
};
diff --git a/mm/swapfile.c b/mm/swapfile.c
index ff8dc1a18cb4..c8f4338848df 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -932,9 +932,7 @@ static inline int unuse_pmd_range(struct vm_area_struct *vma, pud_t *pud,
pmd = pmd_offset(pud, addr);
do {
next = pmd_addr_end(addr, end);
- if (unlikely(pmd_trans_huge(*pmd)))
- continue;
- if (pmd_none_or_clear_bad(pmd))
+ if (pmd_none_or_trans_huge_or_clear_bad(pmd))
continue;
ret = unuse_pte_range(vma, pmd, addr, next, entry, page);
if (ret)
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 43b44dbaddaf..bdb70042c123 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -256,7 +256,7 @@ struct vmap_area {
struct rb_node rb_node; /* address sorted rbtree */
struct list_head list; /* address sorted list */
struct list_head purge_list; /* "lazy purge" list */
- void *private;
+ struct vm_struct *vm;
struct rcu_head rcu_head;
};
@@ -1174,9 +1174,10 @@ void __init vmalloc_init(void)
/* Import existing vmlist entries. */
for (tmp = vmlist; tmp; tmp = tmp->next) {
va = kzalloc(sizeof(struct vmap_area), GFP_NOWAIT);
- va->flags = tmp->flags | VM_VM_AREA;
+ va->flags = VM_VM_AREA;
va->va_start = (unsigned long)tmp->addr;
va->va_end = va->va_start + tmp->size;
+ va->vm = tmp;
__insert_vmap_area(va);
}
@@ -1274,7 +1275,7 @@ static void setup_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va,
vm->addr = (void *)va->va_start;
vm->size = va->va_end - va->va_start;
vm->caller = caller;
- va->private = vm;
+ va->vm = vm;
va->flags |= VM_VM_AREA;
}
@@ -1397,7 +1398,7 @@ static struct vm_struct *find_vm_area(const void *addr)
va = find_vmap_area((unsigned long)addr);
if (va && va->flags & VM_VM_AREA)
- return va->private;
+ return va->vm;
return NULL;
}
@@ -1416,7 +1417,7 @@ struct vm_struct *remove_vm_area(const void *addr)
va = find_vmap_area((unsigned long)addr);
if (va && va->flags & VM_VM_AREA) {
- struct vm_struct *vm = va->private;
+ struct vm_struct *vm = va->vm;
if (!(vm->flags & VM_UNLIST)) {
struct vm_struct *tmp, **p;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 6072d74a16f5..769935d17c01 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -665,7 +665,7 @@ static enum page_references page_check_references(struct page *page,
return PAGEREF_RECLAIM;
if (referenced_ptes) {
- if (PageAnon(page))
+ if (PageSwapBacked(page))
return PAGEREF_ACTIVATE;
/*
* All mapped pages start out with page table
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 5b4f51d440f4..d54845618c2a 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -154,7 +154,7 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb,
skb = __vlan_hwaccel_put_tag(skb, vlan_tci);
}
- skb_set_dev(skb, vlan_dev_info(dev)->real_dev);
+ skb->dev = vlan_dev_info(dev)->real_dev;
len = skb->len;
ret = dev_queue_xmit(skb);
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 1d4be60e1390..5889074e9718 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -364,33 +364,37 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct clip_priv *clip_priv = PRIV(dev);
+ struct dst_entry *dst = skb_dst(skb);
struct atmarp_entry *entry;
+ struct neighbour *n;
struct atm_vcc *vcc;
int old;
unsigned long flags;
pr_debug("(skb %p)\n", skb);
- if (!skb_dst(skb)) {
+ if (!dst) {
pr_err("skb_dst(skb) == NULL\n");
dev_kfree_skb(skb);
dev->stats.tx_dropped++;
return NETDEV_TX_OK;
}
- if (!skb_dst(skb)->neighbour) {
+ n = dst_get_neighbour(dst);
+ if (!n) {
#if 0
- skb_dst(skb)->neighbour = clip_find_neighbour(skb_dst(skb), 1);
- if (!skb_dst(skb)->neighbour) {
+ n = clip_find_neighbour(skb_dst(skb), 1);
+ if (!n) {
dev_kfree_skb(skb); /* lost that one */
dev->stats.tx_dropped++;
return 0;
}
+ dst_set_neighbour(dst, n);
#endif
pr_err("NO NEIGHBOUR !\n");
dev_kfree_skb(skb);
dev->stats.tx_dropped++;
return NETDEV_TX_OK;
}
- entry = NEIGH2ENTRY(skb_dst(skb)->neighbour);
+ entry = NEIGH2ENTRY(n);
if (!entry->vccs) {
if (time_after(jiffies, entry->expires)) {
/* should be resolved */
@@ -407,7 +411,7 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb,
}
pr_debug("neigh %p, vccs %p\n", entry, entry->vccs);
ATM_SKB(skb)->vcc = vcc = entry->vccs->vcc;
- pr_debug("using neighbour %p, vcc %p\n", skb_dst(skb)->neighbour, vcc);
+ pr_debug("using neighbour %p, vcc %p\n", n, vcc);
if (entry->vccs->encap) {
void *here;
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index e7c69f4619ec..b04a6ef4da94 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -2006,16 +2006,17 @@ static void __exit ax25_exit(void)
proc_net_remove(&init_net, "ax25_route");
proc_net_remove(&init_net, "ax25");
proc_net_remove(&init_net, "ax25_calls");
- ax25_rt_free();
- ax25_uid_free();
- ax25_dev_free();
- ax25_unregister_sysctl();
unregister_netdevice_notifier(&ax25_dev_notifier);
+ ax25_unregister_sysctl();
dev_remove_pack(&ax25_packet_type);
sock_unregister(PF_AX25);
proto_unregister(&ax25_proto);
+
+ ax25_rt_free();
+ ax25_uid_free();
+ ax25_dev_free();
}
module_exit(ax25_exit);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 3b3919864078..f38e633c7546 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -510,6 +510,11 @@ int hci_dev_open(__u16 dev)
hci_req_lock(hdev);
+ if (test_bit(HCI_UNREGISTER, &hdev->flags)) {
+ ret = -ENODEV;
+ goto done;
+ }
+
if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) {
ret = -ERFKILL;
goto done;
@@ -1563,6 +1568,8 @@ int hci_unregister_dev(struct hci_dev *hdev)
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
+ set_bit(HCI_UNREGISTER, &hdev->flags);
+
write_lock_bh(&hci_dev_list_lock);
list_del(&hdev->list);
write_unlock_bh(&hci_dev_list_lock);
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 995cbe0ac0b2..e78269d798c0 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -241,7 +241,6 @@ static void br_multicast_group_expired(unsigned long data)
hlist_del_rcu(&mp->hlist[mdb->ver]);
mdb->size--;
- del_timer(&mp->query_timer);
call_rcu_bh(&mp->rcu, br_multicast_free_group);
out:
@@ -271,7 +270,6 @@ static void br_multicast_del_pg(struct net_bridge *br,
rcu_assign_pointer(*pp, p->next);
hlist_del_init(&p->mglist);
del_timer(&p->timer);
- del_timer(&p->query_timer);
call_rcu_bh(&p->rcu, br_multicast_free_pg);
if (!mp->ports && !mp->mglist &&
@@ -446,8 +444,11 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,
ip6h->nexthdr = IPPROTO_HOPOPTS;
ip6h->hop_limit = 1;
ipv6_addr_set(&ip6h->daddr, htonl(0xff020000), 0, 0, htonl(1));
- ipv6_dev_get_saddr(dev_net(br->dev), br->dev, &ip6h->daddr, 0,
- &ip6h->saddr);
+ if (ipv6_dev_get_saddr(dev_net(br->dev), br->dev, &ip6h->daddr, 0,
+ &ip6h->saddr)) {
+ kfree_skb(skb);
+ return NULL;
+ }
ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
hopopt = (u8 *)(ip6h + 1);
@@ -504,74 +505,6 @@ static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br,
return NULL;
}
-static void br_multicast_send_group_query(struct net_bridge_mdb_entry *mp)
-{
- struct net_bridge *br = mp->br;
- struct sk_buff *skb;
-
- skb = br_multicast_alloc_query(br, &mp->addr);
- if (!skb)
- goto timer;
-
- netif_rx(skb);
-
-timer:
- if (++mp->queries_sent < br->multicast_last_member_count)
- mod_timer(&mp->query_timer,
- jiffies + br->multicast_last_member_interval);
-}
-
-static void br_multicast_group_query_expired(unsigned long data)
-{
- struct net_bridge_mdb_entry *mp = (void *)data;
- struct net_bridge *br = mp->br;
-
- spin_lock(&br->multicast_lock);
- if (!netif_running(br->dev) || !mp->mglist ||
- mp->queries_sent >= br->multicast_last_member_count)
- goto out;
-
- br_multicast_send_group_query(mp);
-
-out:
- spin_unlock(&br->multicast_lock);
-}
-
-static void br_multicast_send_port_group_query(struct net_bridge_port_group *pg)
-{
- struct net_bridge_port *port = pg->port;
- struct net_bridge *br = port->br;
- struct sk_buff *skb;
-
- skb = br_multicast_alloc_query(br, &pg->addr);
- if (!skb)
- goto timer;
-
- br_deliver(port, skb);
-
-timer:
- if (++pg->queries_sent < br->multicast_last_member_count)
- mod_timer(&pg->query_timer,
- jiffies + br->multicast_last_member_interval);
-}
-
-static void br_multicast_port_group_query_expired(unsigned long data)
-{
- struct net_bridge_port_group *pg = (void *)data;
- struct net_bridge_port *port = pg->port;
- struct net_bridge *br = port->br;
-
- spin_lock(&br->multicast_lock);
- if (!netif_running(br->dev) || hlist_unhashed(&pg->mglist) ||
- pg->queries_sent >= br->multicast_last_member_count)
- goto out;
-
- br_multicast_send_port_group_query(pg);
-
-out:
- spin_unlock(&br->multicast_lock);
-}
-
static struct net_bridge_mdb_entry *br_multicast_get_group(
struct net_bridge *br, struct net_bridge_port *port,
struct br_ip *group, int hash)
@@ -687,8 +620,6 @@ rehash:
mp->addr = *group;
setup_timer(&mp->timer, br_multicast_group_expired,
(unsigned long)mp);
- setup_timer(&mp->query_timer, br_multicast_group_query_expired,
- (unsigned long)mp);
hlist_add_head_rcu(&mp->hlist[mdb->ver], &mdb->mhash[hash]);
mdb->size++;
@@ -743,8 +674,6 @@ static int br_multicast_add_group(struct net_bridge *br,
hlist_add_head(&p->mglist, &port->mglist);
setup_timer(&p->timer, br_multicast_port_group_expired,
(unsigned long)p);
- setup_timer(&p->query_timer, br_multicast_port_group_query_expired,
- (unsigned long)p);
rcu_assign_pointer(*pp, p);
@@ -1288,9 +1217,6 @@ static void br_multicast_leave_group(struct net_bridge *br,
time_after(mp->timer.expires, time) :
try_to_del_timer_sync(&mp->timer) >= 0)) {
mod_timer(&mp->timer, time);
-
- mp->queries_sent = 0;
- mod_timer(&mp->query_timer, now);
}
goto out;
@@ -1307,9 +1233,6 @@ static void br_multicast_leave_group(struct net_bridge *br,
time_after(p->timer.expires, time) :
try_to_del_timer_sync(&p->timer) >= 0)) {
mod_timer(&p->timer, time);
-
- p->queries_sent = 0;
- mod_timer(&p->query_timer, now);
}
break;
@@ -1675,7 +1598,6 @@ void br_multicast_stop(struct net_bridge *br)
hlist_for_each_entry_safe(mp, p, n, &mdb->mhash[i],
hlist[ver]) {
del_timer(&mp->timer);
- del_timer(&mp->query_timer);
call_rcu_bh(&mp->rcu, br_multicast_free_group);
}
}
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index 56149ec36d7f..3dc7f5446a9d 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -343,24 +343,26 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb)
static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
{
struct nf_bridge_info *nf_bridge = skb->nf_bridge;
+ struct neighbour *neigh;
struct dst_entry *dst;
skb->dev = bridge_parent(skb->dev);
if (!skb->dev)
goto free_skb;
dst = skb_dst(skb);
+ neigh = dst_get_neighbour(dst);
if (dst->hh) {
neigh_hh_bridge(dst->hh, skb);
skb->dev = nf_bridge->physindev;
return br_handle_frame_finish(skb);
- } else if (dst->neighbour) {
+ } else if (neigh) {
/* the neighbour function below overwrites the complete
* MAC header, so we save the Ethernet source address and
* protocol number. */
skb_copy_from_linear_data_offset(skb, -(ETH_HLEN-ETH_ALEN), skb->nf_bridge->data, ETH_HLEN-ETH_ALEN);
/* tell br_dev_xmit to continue with forwarding */
nf_bridge->mask |= BRNF_BRIDGED_DNAT;
- return dst->neighbour->output(skb);
+ return neigh->output(skb);
}
free_skb:
kfree_skb(skb);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 857a021deea9..1ca1b1c7560e 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -77,9 +77,7 @@ struct net_bridge_port_group {
struct hlist_node mglist;
struct rcu_head rcu;
struct timer_list timer;
- struct timer_list query_timer;
struct br_ip addr;
- u32 queries_sent;
};
struct net_bridge_mdb_entry
@@ -89,10 +87,8 @@ struct net_bridge_mdb_entry
struct net_bridge_port_group __rcu *ports;
struct rcu_head rcu;
struct timer_list timer;
- struct timer_list query_timer;
struct br_ip addr;
bool mglist;
- u32 queries_sent;
};
struct net_bridge_mdb_htable
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c
index dbdaa95b8005..5ba4366a220d 100644
--- a/net/caif/caif_dev.c
+++ b/net/caif/caif_dev.c
@@ -53,7 +53,6 @@ struct cfcnfg *get_cfcnfg(struct net *net)
struct caif_net *caifn;
BUG_ON(!net);
caifn = net_generic(net, caif_net_id);
- BUG_ON(!caifn);
return caifn->cfg;
}
EXPORT_SYMBOL(get_cfcnfg);
@@ -63,7 +62,6 @@ static struct caif_device_entry_list *caif_device_list(struct net *net)
struct caif_net *caifn;
BUG_ON(!net);
caifn = net_generic(net, caif_net_id);
- BUG_ON(!caifn);
return &caifn->caifdevs;
}
@@ -92,7 +90,6 @@ static struct caif_device_entry *caif_device_alloc(struct net_device *dev)
struct caif_device_entry *caifd;
caifdevs = caif_device_list(dev_net(dev));
- BUG_ON(!caifdevs);
caifd = kzalloc(sizeof(*caifd), GFP_ATOMIC);
if (!caifd)
@@ -108,7 +105,7 @@ static struct caif_device_entry *caif_get(struct net_device *dev)
struct caif_device_entry_list *caifdevs =
caif_device_list(dev_net(dev));
struct caif_device_entry *caifd;
- BUG_ON(!caifdevs);
+
list_for_each_entry_rcu(caifd, &caifdevs->list, list) {
if (caifd->netdev == dev)
return caifd;
@@ -349,7 +346,7 @@ static struct notifier_block caif_device_notifier = {
static int caif_init_net(struct net *net)
{
struct caif_net *caifn = net_generic(net, caif_net_id);
- BUG_ON(!caifn);
+
INIT_LIST_HEAD(&caifn->caifdevs.list);
mutex_init(&caifn->caifdevs.lock);
@@ -414,7 +411,7 @@ static int __init caif_device_init(void)
{
int result;
- result = register_pernet_device(&caif_net_ops);
+ result = register_pernet_subsys(&caif_net_ops);
if (result)
return result;
@@ -427,7 +424,7 @@ static int __init caif_device_init(void)
static void __exit caif_device_exit(void)
{
- unregister_pernet_device(&caif_net_ops);
+ unregister_pernet_subsys(&caif_net_ops);
unregister_netdevice_notifier(&caif_device_notifier);
dev_remove_pack(&caif_packet_type);
}
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c
index 52fe33bee029..bca32d7c15c9 100644
--- a/net/caif/cfcnfg.c
+++ b/net/caif/cfcnfg.c
@@ -313,7 +313,6 @@ int caif_connect_client(struct net *net, struct caif_connect_request *conn_req,
int err;
struct cfctrl_link_param param;
struct cfcnfg *cfg = get_cfcnfg(net);
- caif_assert(cfg != NULL);
rcu_read_lock();
err = caif_connect_req_to_link_param(cfg, conn_req, &param);
diff --git a/net/core/dev.c b/net/core/dev.c
index f14f6015a7ab..a71eafc392e7 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1406,14 +1406,34 @@ EXPORT_SYMBOL(register_netdevice_notifier);
* register_netdevice_notifier(). The notifier is unlinked into the
* kernel structures and may then be reused. A negative errno code
* is returned on a failure.
+ *
+ * After unregistering unregister and down device events are synthesized
+ * for all devices on the device list to the removed notifier to remove
+ * the need for special case cleanup code.
*/
int unregister_netdevice_notifier(struct notifier_block *nb)
{
+ struct net_device *dev;
+ struct net *net;
int err;
rtnl_lock();
err = raw_notifier_chain_unregister(&netdev_chain, nb);
+ if (err)
+ goto unlock;
+
+ for_each_net(net) {
+ for_each_netdev(net, dev) {
+ if (dev->flags & IFF_UP) {
+ nb->notifier_call(nb, NETDEV_GOING_DOWN, dev);
+ nb->notifier_call(nb, NETDEV_DOWN, dev);
+ }
+ nb->notifier_call(nb, NETDEV_UNREGISTER, dev);
+ nb->notifier_call(nb, NETDEV_UNREGISTER_BATCH, dev);
+ }
+ }
+unlock:
rtnl_unlock();
return err;
}
@@ -1513,10 +1533,14 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
kfree_skb(skb);
return NET_RX_DROP;
}
- skb_set_dev(skb, dev);
+ skb->dev = dev;
+ skb_dst_drop(skb);
skb->tstamp.tv64 = 0;
skb->pkt_type = PACKET_HOST;
skb->protocol = eth_type_trans(skb, dev);
+ skb->mark = 0;
+ secpath_reset(skb);
+ nf_reset(skb);
return netif_rx(skb);
}
EXPORT_SYMBOL_GPL(dev_forward_skb);
@@ -1771,36 +1795,6 @@ void netif_device_attach(struct net_device *dev)
}
EXPORT_SYMBOL(netif_device_attach);
-/**
- * skb_dev_set -- assign a new device to a buffer
- * @skb: buffer for the new device
- * @dev: network device
- *
- * If an skb is owned by a device already, we have to reset
- * all data private to the namespace a device belongs to
- * before assigning it a new device.
- */
-#ifdef CONFIG_NET_NS
-void skb_set_dev(struct sk_buff *skb, struct net_device *dev)
-{
- skb_dst_drop(skb);
- if (skb->dev && !net_eq(dev_net(skb->dev), dev_net(dev))) {
- secpath_reset(skb);
- nf_reset(skb);
- skb_init_secmark(skb);
- skb->mark = 0;
- skb->priority = 0;
- skb->nf_trace = 0;
- skb->ipvs_property = 0;
-#ifdef CONFIG_NET_SCHED
- skb->tc_index = 0;
-#endif
- }
- skb->dev = dev;
-}
-EXPORT_SYMBOL(skb_set_dev);
-#endif /* CONFIG_NET_NS */
-
/*
* Invalidate hardware checksum when packet is to be mangled, and
* complete checksum manually on outgoing path.
@@ -3434,14 +3428,20 @@ static inline gro_result_t
__napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
{
struct sk_buff *p;
+ unsigned int maclen = skb->dev->hard_header_len;
for (p = napi->gro_list; p; p = p->next) {
unsigned long diffs;
diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev;
diffs |= p->vlan_tci ^ skb->vlan_tci;
- diffs |= compare_ether_header(skb_mac_header(p),
- skb_gro_mac_header(skb));
+ if (maclen == ETH_HLEN)
+ diffs |= compare_ether_header(skb_mac_header(p),
+ skb_gro_mac_header(skb));
+ else if (!diffs)
+ diffs = memcmp(skb_mac_header(p),
+ skb_gro_mac_header(skb),
+ maclen);
NAPI_GRO_CB(p)->same_flow = !diffs;
NAPI_GRO_CB(p)->flush = 0;
}
@@ -3498,7 +3498,8 @@ EXPORT_SYMBOL(napi_gro_receive);
static void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb)
{
__skb_pull(skb, skb_headlen(skb));
- skb_reserve(skb, NET_IP_ALIGN - skb_headroom(skb));
+ /* restore the reserve we had after netdev_alloc_skb_ip_align() */
+ skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN - skb_headroom(skb));
skb->vlan_tci = 0;
skb->dev = napi->dev;
skb->skb_iif = 0;
diff --git a/net/core/dst.c b/net/core/dst.c
index 6135f3671692..8246d47a2184 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -171,7 +171,7 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev,
dst_init_metrics(dst, dst_default_metrics, true);
dst->expires = 0UL;
dst->path = dst;
- dst->neighbour = NULL;
+ RCU_INIT_POINTER(dst->_neighbour, NULL);
dst->hh = NULL;
#ifdef CONFIG_XFRM
dst->xfrm = NULL;
@@ -231,7 +231,7 @@ struct dst_entry *dst_destroy(struct dst_entry * dst)
smp_rmb();
again:
- neigh = dst->neighbour;
+ neigh = rcu_dereference_protected(dst->_neighbour, 1);
hh = dst->hh;
child = dst->child;
@@ -240,7 +240,7 @@ again:
hh_cache_put(hh);
if (neigh) {
- dst->neighbour = NULL;
+ RCU_INIT_POINTER(dst->_neighbour, NULL);
neigh_release(neigh);
}
@@ -367,14 +367,19 @@ static void dst_ifdown(struct dst_entry *dst, struct net_device *dev,
if (!unregister) {
dst->input = dst->output = dst_discard;
} else {
+ struct neighbour *neigh;
+
dst->dev = dev_net(dst->dev)->loopback_dev;
dev_hold(dst->dev);
dev_put(dev);
- if (dst->neighbour && dst->neighbour->dev == dev) {
- dst->neighbour->dev = dst->dev;
+ rcu_read_lock();
+ neigh = dst_get_neighbour(dst);
+ if (neigh && neigh->dev == dev) {
+ neigh->dev = dst->dev;
dev_hold(dst->dev);
dev_put(dev);
}
+ rcu_read_unlock();
}
}
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 16db88707804..96bb0a33f861 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -823,6 +823,8 @@ next_elt:
write_unlock_bh(&tbl->lock);
cond_resched();
write_lock_bh(&tbl->lock);
+ nht = rcu_dereference_protected(tbl->nht,
+ lockdep_is_held(&tbl->lock));
}
/* Cycle through all hash buckets every base_reachable_time/2 ticks.
* ARP entry timeouts range from 1/2 base_reachable_time to 3/2
@@ -1173,12 +1175,17 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
while (neigh->nud_state & NUD_VALID &&
(skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
- struct neighbour *n1 = neigh;
+ struct dst_entry *dst = skb_dst(skb);
+ struct neighbour *n2, *n1 = neigh;
write_unlock_bh(&neigh->lock);
+
+ rcu_read_lock();
/* On shaper/eql skb->dst->neighbour != neigh :( */
- if (skb_dst(skb) && skb_dst(skb)->neighbour)
- n1 = skb_dst(skb)->neighbour;
+ if (dst && (n2 = dst_get_neighbour(dst)) != NULL)
+ n1 = n2;
n1->output(skb);
+ rcu_read_unlock();
+
write_lock_bh(&neigh->lock);
}
skb_queue_purge(&neigh->arp_queue);
@@ -1300,10 +1307,10 @@ EXPORT_SYMBOL(neigh_compat_output);
int neigh_resolve_output(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
- struct neighbour *neigh;
+ struct neighbour *neigh = dst_get_neighbour(dst);
int rc = 0;
- if (!dst || !(neigh = dst->neighbour))
+ if (!dst)
goto discard;
__skb_pull(skb, skb_network_offset(skb));
@@ -1333,7 +1340,7 @@ out:
return rc;
discard:
NEIGH_PRINTK1("neigh_resolve_output: dst=%p neigh=%p\n",
- dst, dst ? dst->neighbour : NULL);
+ dst, neigh);
out_kfree_skb:
rc = -EINVAL;
kfree_skb(skb);
@@ -1347,7 +1354,7 @@ int neigh_connected_output(struct sk_buff *skb)
{
int err;
struct dst_entry *dst = skb_dst(skb);
- struct neighbour *neigh = dst->neighbour;
+ struct neighbour *neigh = dst_get_neighbour(dst);
struct net_device *dev = neigh->dev;
unsigned int seq;
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index ea489db1bc23..2772ed11bec9 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -29,6 +29,20 @@ EXPORT_SYMBOL(init_net);
#define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */
+static unsigned int max_gen_ptrs = INITIAL_NET_GEN_PTRS;
+
+static struct net_generic *net_alloc_generic(void)
+{
+ struct net_generic *ng;
+ size_t generic_size = offsetof(struct net_generic, ptr[max_gen_ptrs]);
+
+ ng = kzalloc(generic_size, GFP_KERNEL);
+ if (ng)
+ ng->len = max_gen_ptrs;
+
+ return ng;
+}
+
static int net_assign_generic(struct net *net, int id, void *data)
{
struct net_generic *ng, *old_ng;
@@ -42,8 +56,7 @@ static int net_assign_generic(struct net *net, int id, void *data)
if (old_ng->len >= id)
goto assign;
- ng = kzalloc(sizeof(struct net_generic) +
- id * sizeof(void *), GFP_KERNEL);
+ ng = net_alloc_generic();
if (ng == NULL)
return -ENOMEM;
@@ -58,7 +71,6 @@ static int net_assign_generic(struct net *net, int id, void *data)
* the old copy for kfree after a grace period.
*/
- ng->len = id;
memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*));
rcu_assign_pointer(net->gen, ng);
@@ -70,21 +82,29 @@ assign:
static int ops_init(const struct pernet_operations *ops, struct net *net)
{
- int err;
+ int err = -ENOMEM;
+ void *data = NULL;
+
if (ops->id && ops->size) {
- void *data = kzalloc(ops->size, GFP_KERNEL);
+ data = kzalloc(ops->size, GFP_KERNEL);
if (!data)
- return -ENOMEM;
+ goto out;
err = net_assign_generic(net, *ops->id, data);
- if (err) {
- kfree(data);
- return err;
- }
+ if (err)
+ goto cleanup;
}
+ err = 0;
if (ops->init)
- return ops->init(net);
- return 0;
+ err = ops->init(net);
+ if (!err)
+ return 0;
+
+cleanup:
+ kfree(data);
+
+out:
+ return err;
}
static void ops_free(const struct pernet_operations *ops, struct net *net)
@@ -159,18 +179,6 @@ out_undo:
goto out;
}
-static struct net_generic *net_alloc_generic(void)
-{
- struct net_generic *ng;
- size_t generic_size = sizeof(struct net_generic) +
- INITIAL_NET_GEN_PTRS * sizeof(void *);
-
- ng = kzalloc(generic_size, GFP_KERNEL);
- if (ng)
- ng->len = INITIAL_NET_GEN_PTRS;
-
- return ng;
-}
#ifdef CONFIG_NET_NS
static struct kmem_cache *net_cachep;
@@ -446,12 +454,7 @@ static void __unregister_pernet_operations(struct pernet_operations *ops)
static int __register_pernet_operations(struct list_head *list,
struct pernet_operations *ops)
{
- int err = 0;
- err = ops_init(ops, &init_net);
- if (err)
- ops_free(ops, &init_net);
- return err;
-
+ return ops_init(ops, &init_net);
}
static void __unregister_pernet_operations(struct pernet_operations *ops)
@@ -481,6 +484,7 @@ again:
}
return error;
}
+ max_gen_ptrs = max_t(unsigned int, max_gen_ptrs, *ops->id);
}
error = __register_pernet_operations(list, ops);
if (error) {
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 18d9cbda3a39..05db410fd135 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -193,7 +193,7 @@ void netpoll_poll_dev(struct net_device *dev)
poll_napi(dev);
- if (dev->priv_flags & IFF_SLAVE) {
+ if (dev->flags & IFF_SLAVE) {
if (dev->npinfo) {
struct net_device *bond_dev = dev->master;
struct sk_buff *skb;
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index e35a6fbb8110..c0e0f7679e75 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -1932,7 +1932,7 @@ static int pktgen_device_event(struct notifier_block *unused,
{
struct net_device *dev = ptr;
- if (!net_eq(dev_net(dev), &init_net))
+ if (!net_eq(dev_net(dev), &init_net) || pktgen_exiting)
return NOTIFY_DONE;
/* It is OK that we do not hold the group lock right now,
@@ -3755,12 +3755,18 @@ static void __exit pg_cleanup(void)
{
struct pktgen_thread *t;
struct list_head *q, *n;
+ LIST_HEAD(list);
/* Stop all interfaces & threads */
pktgen_exiting = true;
- list_for_each_safe(q, n, &pktgen_threads) {
+ mutex_lock(&pktgen_thread_lock);
+ list_splice_init(&pktgen_threads, &list);
+ mutex_unlock(&pktgen_thread_lock);
+
+ list_for_each_safe(q, n, &list) {
t = list_entry(q, struct pktgen_thread, th_list);
+ list_del(&t->th_list);
kthread_stop(t->tsk);
kfree(t);
}
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 46cbd28f40f9..4821df84eba3 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2985,6 +2985,8 @@ static void sock_rmem_free(struct sk_buff *skb)
*/
int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
{
+ int len = skb->len;
+
if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
(unsigned)sk->sk_rcvbuf)
return -ENOMEM;
@@ -2999,7 +3001,7 @@ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
skb_queue_tail(&sk->sk_error_queue, skb);
if (!sock_flag(sk, SOCK_DEAD))
- sk->sk_data_ready(sk, skb->len);
+ sk->sk_data_ready(sk, len);
return 0;
}
EXPORT_SYMBOL(sock_queue_err_skb);
diff --git a/net/core/sock.c b/net/core/sock.c
index aebb419519b3..b4bb59a9245b 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1501,6 +1501,11 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
gfp_t gfp_mask;
long timeo;
int err;
+ int npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
+
+ err = -EMSGSIZE;
+ if (npages > MAX_SKB_FRAGS)
+ goto failure;
gfp_mask = sk->sk_allocation;
if (gfp_mask & __GFP_WAIT)
@@ -1519,14 +1524,12 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
if (atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) {
skb = alloc_skb(header_len, gfp_mask);
if (skb) {
- int npages;
int i;
/* No pages, we're done... */
if (!data_len)
break;
- npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
skb->truesize += data_len;
skb_shinfo(skb)->nr_frags = npages;
for (i = 0; i < npages; i++) {
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index 602dade7e9a3..9810610d26c6 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -208,7 +208,7 @@ static int dn_neigh_output_packet(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
struct dn_route *rt = (struct dn_route *)dst;
- struct neighbour *neigh = dst->neighbour;
+ struct neighbour *neigh = dst_get_neighbour(dst);
struct net_device *dev = neigh->dev;
char mac_addr[ETH_ALEN];
@@ -227,7 +227,7 @@ static int dn_neigh_output_packet(struct sk_buff *skb)
static int dn_long_output(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
- struct neighbour *neigh = dst->neighbour;
+ struct neighbour *neigh = dst_get_neighbour(dst);
struct net_device *dev = neigh->dev;
int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3;
unsigned char *data;
@@ -274,7 +274,7 @@ static int dn_long_output(struct sk_buff *skb)
static int dn_short_output(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
- struct neighbour *neigh = dst->neighbour;
+ struct neighbour *neigh = dst_get_neighbour(dst);
struct net_device *dev = neigh->dev;
int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
struct dn_short_packet *sp;
@@ -318,7 +318,7 @@ static int dn_short_output(struct sk_buff *skb)
static int dn_phase3_output(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
- struct neighbour *neigh = dst->neighbour;
+ struct neighbour *neigh = dst_get_neighbour(dst);
struct net_device *dev = neigh->dev;
int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
struct dn_short_packet *sp;
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 74544bc6fdec..b91b60363c39 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -241,9 +241,11 @@ static int dn_dst_gc(struct dst_ops *ops)
*/
static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu)
{
+ struct neighbour *n = dst_get_neighbour(dst);
u32 min_mtu = 230;
- struct dn_dev *dn = dst->neighbour ?
- rcu_dereference_raw(dst->neighbour->dev->dn_ptr) : NULL;
+ struct dn_dev *dn;
+
+ dn = n ? rcu_dereference_raw(n->dev->dn_ptr) : NULL;
if (dn && dn->use_long == 0)
min_mtu -= 6;
@@ -715,7 +717,7 @@ static int dn_output(struct sk_buff *skb)
int err = -EINVAL;
- if ((neigh = dst->neighbour) == NULL)
+ if ((neigh = dst_get_neighbour(dst)) == NULL)
goto error;
skb->dev = dev;
@@ -750,7 +752,7 @@ static int dn_forward(struct sk_buff *skb)
struct dst_entry *dst = skb_dst(skb);
struct dn_dev *dn_db = rcu_dereference(dst->dev->dn_ptr);
struct dn_route *rt;
- struct neighbour *neigh = dst->neighbour;
+ struct neighbour *neigh = dst_get_neighbour(dst);
int header_len;
#ifdef CONFIG_NETFILTER
struct net_device *dev = skb->dev;
@@ -833,11 +835,11 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
}
rt->rt_type = res->type;
- if (dev != NULL && rt->dst.neighbour == NULL) {
+ if (dev != NULL && dst_get_neighbour(&rt->dst) == NULL) {
n = __neigh_lookup_errno(&dn_neigh_table, &rt->rt_gateway, dev);
if (IS_ERR(n))
return PTR_ERR(n);
- rt->dst.neighbour = n;
+ dst_set_neighbour(&rt->dst, n);
}
if (dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu)
@@ -1144,7 +1146,7 @@ make_route:
rt->rt_dst_map = fld.daddr;
rt->rt_src_map = fld.saddr;
- rt->dst.neighbour = neigh;
+ dst_set_neighbour(&rt->dst, neigh);
neigh = NULL;
rt->dst.lastuse = jiffies;
@@ -1416,7 +1418,7 @@ make_route:
rt->fld.flowidn_iif = in_dev->ifindex;
rt->fld.flowidn_mark = fld.flowidn_mark;
- rt->dst.neighbour = neigh;
+ dst_set_neighbour(&rt->dst, neigh);
rt->dst.lastuse = jiffies;
rt->dst.output = dn_rt_bug;
switch(res.type) {
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index c1f4154552fc..36d14406261e 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -136,8 +136,6 @@ static void ah_output_done(struct crypto_async_request *base, int err)
memcpy(top_iph+1, iph+1, top_iph->ihl*4 - sizeof(struct iphdr));
}
- err = ah->nexthdr;
-
kfree(AH_SKB_CB(skb)->tmp);
xfrm_output_resume(skb, err);
}
@@ -264,12 +262,12 @@ static void ah_input_done(struct crypto_async_request *base, int err)
if (err)
goto out;
+ err = ah->nexthdr;
+
skb->network_header += ah_hlen;
memcpy(skb_network_header(skb), work_iph, ihl);
__skb_pull(skb, ah_hlen + ihl);
skb_set_transport_header(skb, -ihl);
-
- err = ah->nexthdr;
out:
kfree(AH_SKB_CB(skb)->tmp);
xfrm_input_resume(skb, err);
@@ -371,8 +369,6 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
if (err == -EINPROGRESS)
goto out;
- if (err == -EBUSY)
- err = NET_XMIT_DROP;
goto out_free;
}
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 1b74d3b64371..d8f852dbf660 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -518,26 +518,32 @@ EXPORT_SYMBOL(arp_find);
/* END OF OBSOLETE FUNCTIONS */
+struct neighbour *__arp_bind_neighbour(struct dst_entry *dst, __be32 nexthop)
+{
+ struct net_device *dev = dst->dev;
+
+ if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
+ nexthop = 0;
+ return __neigh_lookup_errno(
+#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
+ dev->type == ARPHRD_ATM ?
+ clip_tbl_hook :
+#endif
+ &arp_tbl, &nexthop, dev);
+}
+
int arp_bind_neighbour(struct dst_entry *dst)
{
struct net_device *dev = dst->dev;
- struct neighbour *n = dst->neighbour;
+ struct neighbour *n = dst_get_neighbour(dst);
if (dev == NULL)
return -EINVAL;
if (n == NULL) {
- __be32 nexthop = ((struct rtable *)dst)->rt_gateway;
- if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))
- nexthop = 0;
- n = __neigh_lookup_errno(
-#if defined(CONFIG_ATM_CLIP) || defined(CONFIG_ATM_CLIP_MODULE)
- dev->type == ARPHRD_ATM ?
- clip_tbl_hook :
-#endif
- &arp_tbl, &nexthop, dev);
+ n = __arp_bind_neighbour(dst, ((struct rtable *)dst)->rt_gateway);
if (IS_ERR(n))
return PTR_ERR(n);
- dst->neighbour = n;
+ dst_set_neighbour(dst, n);
}
return 0;
}
@@ -900,7 +906,8 @@ static int arp_process(struct sk_buff *skb)
if (addr_type == RTN_UNICAST &&
(arp_fwd_proxy(in_dev, dev, rt) ||
arp_fwd_pvlan(in_dev, dev, rt, sip, tip) ||
- pneigh_lookup(&arp_tbl, net, &tip, dev, 0))) {
+ (rt->dst.dev != dev &&
+ pneigh_lookup(&arp_tbl, net, &tip, dev, 0)))) {
n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
if (n)
neigh_release(n);
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 66439a7c6d31..c48323ad268b 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1496,7 +1496,9 @@ static int devinet_conf_proc(ctl_table *ctl, int write,
void __user *buffer,
size_t *lenp, loff_t *ppos)
{
+ int old_value = *(int *)ctl->data;
int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+ int new_value = *(int *)ctl->data;
if (write) {
struct ipv4_devconf *cnf = ctl->extra1;
@@ -1507,6 +1509,9 @@ static int devinet_conf_proc(ctl_table *ctl, int write,
if (cnf == net->ipv4.devconf_dflt)
devinet_copy_dflt_conf(net, i);
+ if (i == IPV4_DEVCONF_ACCEPT_LOCAL - 1)
+ if ((new_value == 0) && (old_value != 0))
+ rt_cache_flush(net, 0);
}
return ret;
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index a5b413416da3..530787bc1990 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -457,28 +457,22 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu)
struct esp_data *esp = x->data;
u32 blksize = ALIGN(crypto_aead_blocksize(esp->aead), 4);
u32 align = max_t(u32, blksize, esp->padlen);
- u32 rem;
-
- mtu -= x->props.header_len + crypto_aead_authsize(esp->aead);
- rem = mtu & (align - 1);
- mtu &= ~(align - 1);
+ unsigned int net_adj;
switch (x->props.mode) {
- case XFRM_MODE_TUNNEL:
- break;
- default:
case XFRM_MODE_TRANSPORT:
- /* The worst case */
- mtu -= blksize - 4;
- mtu += min_t(u32, blksize - 4, rem);
- break;
case XFRM_MODE_BEET:
- /* The worst case. */
- mtu += min_t(u32, IPV4_BEET_PHMAXLEN, rem);
+ net_adj = sizeof(struct iphdr);
break;
+ case XFRM_MODE_TUNNEL:
+ net_adj = 0;
+ break;
+ default:
+ BUG();
}
- return mtu - 2;
+ return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) -
+ net_adj) & ~(align - 1)) + (net_adj - 2);
}
static void esp4_err(struct sk_buff *skb, u32 info)
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 33e2c35b74b7..7e454ba8e850 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -142,6 +142,18 @@ const struct fib_prop fib_props[RTN_MAX + 1] = {
};
/* Release a nexthop info record */
+static void free_fib_info_rcu(struct rcu_head *head)
+{
+ struct fib_info *fi = container_of(head, struct fib_info, rcu);
+
+ change_nexthops(fi) {
+ if (nexthop_nh->nh_dev)
+ dev_put(nexthop_nh->nh_dev);
+ } endfor_nexthops(fi);
+
+ release_net(fi->fib_net);
+ kfree(fi);
+}
void free_fib_info(struct fib_info *fi)
{
@@ -149,14 +161,8 @@ void free_fib_info(struct fib_info *fi)
pr_warning("Freeing alive fib_info %p\n", fi);
return;
}
- change_nexthops(fi) {
- if (nexthop_nh->nh_dev)
- dev_put(nexthop_nh->nh_dev);
- nexthop_nh->nh_dev = NULL;
- } endfor_nexthops(fi);
fib_info_cnt--;
- release_net(fi->fib_net);
- kfree_rcu(fi, rcu);
+ call_rcu(&fi->rcu, free_fib_info_rcu);
}
void fib_release_info(struct fib_info *fi)
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 58c25ea5a5c1..0d884eb2b14f 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1371,6 +1371,8 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)
continue;
+ if (fi->fib_dead)
+ continue;
if (fa->fa_info->fib_scope < flp->flowi4_scope)
continue;
fib_alias_accessed(fa);
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index d577199eabd5..e0d42dbb33fe 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -875,6 +875,8 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
* to be intended in a v3 query.
*/
max_delay = IGMPV3_MRC(ih3->code)*(HZ/IGMP_TIMER_SCALE);
+ if (!max_delay)
+ max_delay = 1; /* can't mod w/ 0 */
} else { /* v3 */
if (!pskb_may_pull(skb, sizeof(struct igmpv3_query)))
return;
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
index 3b34d1c86270..29a07b6c7168 100644
--- a/net/ipv4/ip_forward.c
+++ b/net/ipv4/ip_forward.c
@@ -84,7 +84,7 @@ int ip_forward(struct sk_buff *skb)
rt = skb_rtable(skb);
- if (opt->is_strictroute && ip_hdr(skb)->daddr != rt->rt_gateway)
+ if (opt->is_strictroute && opt->nexthop != rt->rt_gateway)
goto sr_failed;
if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) &&
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 8871067560db..d7bb94c48345 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -731,9 +731,9 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
}
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
else if (skb->protocol == htons(ETH_P_IPV6)) {
+ struct neighbour *neigh = dst_get_neighbour(skb_dst(skb));
const struct in6_addr *addr6;
int addr_type;
- struct neighbour *neigh = skb_dst(skb)->neighbour;
if (neigh == NULL)
goto tx_error;
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index ec93335901dd..42dd1a90edea 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -568,11 +568,12 @@ void ip_forward_options(struct sk_buff *skb)
) {
if (srrptr + 3 > srrspace)
break;
- if (memcmp(&ip_hdr(skb)->daddr, &optptr[srrptr-1], 4) == 0)
+ if (memcmp(&opt->nexthop, &optptr[srrptr-1], 4) == 0)
break;
}
if (srrptr + 3 <= srrspace) {
opt->is_changed = 1;
+ ip_hdr(skb)->daddr = opt->nexthop;
ip_rt_get_source(&optptr[srrptr-1], skb, rt);
optptr[2] = srrptr+4;
} else if (net_ratelimit())
@@ -640,6 +641,7 @@ int ip_options_rcv_srr(struct sk_buff *skb)
}
if (srrptr <= srrspace) {
opt->srr_is_hit = 1;
+ opt->nexthop = nexthop;
opt->is_changed = 1;
}
return 0;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 0c99db4c80b1..51a3eec2c706 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -182,6 +182,8 @@ static inline int ip_finish_output2(struct sk_buff *skb)
struct rtable *rt = (struct rtable *)dst;
struct net_device *dev = dst->dev;
unsigned int hh_len = LL_RESERVED_SPACE(dev);
+ struct neighbour *neigh;
+ int res;
if (rt->rt_type == RTN_MULTICAST) {
IP_UPD_PO_STATS(dev_net(dev), IPSTATS_MIB_OUTMCAST, skb->len);
@@ -203,10 +205,22 @@ static inline int ip_finish_output2(struct sk_buff *skb)
skb = skb2;
}
- if (dst->hh)
- return neigh_hh_output(dst->hh, skb);
- else if (dst->neighbour)
- return dst->neighbour->output(skb);
+ rcu_read_lock();
+ if (dst->hh) {
+ int res = neigh_hh_output(dst->hh, skb);
+
+ rcu_read_unlock();
+ return res;
+ } else {
+ neigh = dst_get_neighbour(dst);
+ if (neigh) {
+ res = neigh->output(skb);
+
+ rcu_read_unlock();
+ return res;
+ }
+ rcu_read_unlock();
+ }
if (net_ratelimit())
printk(KERN_DEBUG "ip_finish_output2: No header cache and no neighbour!\n");
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index ab7e5542c1cf..7fbcabafa29b 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -252,6 +252,10 @@ static int __init ic_open_devs(void)
}
}
+ /* no point in waiting if we could not bring up at least one device */
+ if (!ic_first_dev)
+ goto have_carrier;
+
/* wait for a carrier on at least one device */
start = jiffies;
while (jiffies - start < msecs_to_jiffies(CONF_CARRIER_TIMEOUT)) {
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 378b20b7ca6e..6f06f7f39ea2 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -285,6 +285,8 @@ static struct ip_tunnel * ipip_tunnel_locate(struct net *net,
if (register_netdevice(dev) < 0)
goto failed_free;
+ strcpy(nt->parms.name, dev->name);
+
dev_hold(dev);
ipip_tunnel_link(ipn, nt);
return nt;
@@ -759,7 +761,6 @@ static int ipip_tunnel_init(struct net_device *dev)
struct ip_tunnel *tunnel = netdev_priv(dev);
tunnel->dev = dev;
- strcpy(tunnel->parms.name, dev->name);
memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
@@ -825,6 +826,7 @@ static void ipip_destroy_tunnels(struct ipip_net *ipn, struct list_head *head)
static int __net_init ipip_init_net(struct net *net)
{
struct ipip_net *ipn = net_generic(net, ipip_net_id);
+ struct ip_tunnel *t;
int err;
ipn->tunnels[0] = ipn->tunnels_wc;
@@ -848,6 +850,9 @@ static int __net_init ipip_init_net(struct net *net)
if ((err = register_netdev(ipn->fb_tunnel_dev)))
goto err_reg_dev;
+ t = netdev_priv(ipn->fb_tunnel_dev);
+
+ strcpy(t->parms.name, ipn->fb_tunnel_dev->name);
return 0;
err_reg_dev:
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 75ef66f31832..6b95f74a91d3 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -91,6 +91,7 @@
#include <linux/rcupdate.h>
#include <linux/times.h>
#include <linux/slab.h>
+#include <linux/prefetch.h>
#include <net/dst.h>
#include <net/net_namespace.h>
#include <net/protocol.h>
@@ -132,6 +133,9 @@ static int ip_rt_min_pmtu __read_mostly = 512 + 20 + 20;
static int ip_rt_min_advmss __read_mostly = 256;
static int rt_chain_length_max __read_mostly = 20;
+static struct delayed_work expires_work;
+static unsigned long expires_ljiffies;
+
/*
* Interface to generic destination cache.
*/
@@ -412,7 +416,13 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
"HHUptod\tSpecDst");
else {
struct rtable *r = v;
- int len;
+ struct neighbour *n;
+ int len, HHUptod;
+
+ rcu_read_lock();
+ n = dst_get_neighbour(&r->dst);
+ HHUptod = (n && (n->nud_state & NUD_CONNECTED)) ? 1 : 0;
+ rcu_read_unlock();
seq_printf(seq, "%s\t%08X\t%08X\t%8X\t%d\t%u\t%d\t"
"%08X\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n",
@@ -427,8 +437,7 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
dst_metric(&r->dst, RTAX_RTTVAR)),
r->rt_key_tos,
r->dst.hh ? atomic_read(&r->dst.hh->hh_refcnt) : -1,
- r->dst.hh ? (r->dst.hh->hh_output ==
- dev_queue_xmit) : 0,
+ HHUptod,
r->rt_spec_dst, &len);
seq_printf(seq, "%*s\n", 127 - len, "");
@@ -821,6 +830,97 @@ static int has_noalias(const struct rtable *head, const struct rtable *rth)
return ONE;
}
+static void rt_check_expire(void)
+{
+ static unsigned int rover;
+ unsigned int i = rover, goal;
+ struct rtable *rth;
+ struct rtable __rcu **rthp;
+ unsigned long samples = 0;
+ unsigned long sum = 0, sum2 = 0;
+ unsigned long delta;
+ u64 mult;
+
+ delta = jiffies - expires_ljiffies;
+ expires_ljiffies = jiffies;
+ mult = ((u64)delta) << rt_hash_log;
+ if (ip_rt_gc_timeout > 1)
+ do_div(mult, ip_rt_gc_timeout);
+ goal = (unsigned int)mult;
+ if (goal > rt_hash_mask)
+ goal = rt_hash_mask + 1;
+ for (; goal > 0; goal--) {
+ unsigned long tmo = ip_rt_gc_timeout;
+ unsigned long length;
+
+ i = (i + 1) & rt_hash_mask;
+ rthp = &rt_hash_table[i].chain;
+
+ if (need_resched())
+ cond_resched();
+
+ samples++;
+
+ if (rcu_dereference_raw(*rthp) == NULL)
+ continue;
+ length = 0;
+ spin_lock_bh(rt_hash_lock_addr(i));
+ while ((rth = rcu_dereference_protected(*rthp,
+ lockdep_is_held(rt_hash_lock_addr(i)))) != NULL) {
+ prefetch(rth->dst.rt_next);
+ if (rt_is_expired(rth)) {
+ *rthp = rth->dst.rt_next;
+ rt_free(rth);
+ continue;
+ }
+ if (rth->dst.expires) {
+ /* Entry is expired even if it is in use */
+ if (time_before_eq(jiffies, rth->dst.expires)) {
+nofree:
+ tmo >>= 1;
+ rthp = &rth->dst.rt_next;
+ /*
+ * We only count entries on
+ * a chain with equal hash inputs once
+ * so that entries for different QOS
+ * levels, and other non-hash input
+ * attributes don't unfairly skew
+ * the length computation
+ */
+ length += has_noalias(rt_hash_table[i].chain, rth);
+ continue;
+ }
+ } else if (!rt_may_expire(rth, tmo, ip_rt_gc_timeout))
+ goto nofree;
+
+ /* Cleanup aged off entries. */
+ *rthp = rth->dst.rt_next;
+ rt_free(rth);
+ }
+ spin_unlock_bh(rt_hash_lock_addr(i));
+ sum += length;
+ sum2 += length*length;
+ }
+ if (samples) {
+ unsigned long avg = sum / samples;
+ unsigned long sd = int_sqrt(sum2 / samples - avg*avg);
+ rt_chain_length_max = max_t(unsigned long,
+ ip_rt_gc_elasticity,
+ (avg + 4*sd) >> FRACT_BITS);
+ }
+ rover = i;
+}
+
+/*
+ * rt_worker_func() is run in process context.
+ * we call rt_check_expire() to scan part of the hash table
+ */
+static void rt_worker_func(struct work_struct *work)
+{
+ rt_check_expire();
+ schedule_delayed_work(&expires_work, ip_rt_gc_interval);
+}
+
/*
* Perturbation of rt_genid by a small quantity [1..256]
* Using 8 bits of shuffling ensure we can call rt_cache_invalidate()
@@ -1269,11 +1369,41 @@ static void rt_del(unsigned hash, struct rtable *rt)
spin_unlock_bh(rt_hash_lock_addr(hash));
}
+static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)
+{
+ struct rtable *rt = (struct rtable *) dst;
+ __be32 orig_gw = rt->rt_gateway;
+ struct neighbour *n, *old_n;
+
+ dst_confirm(&rt->dst);
+
+ rt->rt_gateway = peer->redirect_learned.a4;
+ n = __arp_bind_neighbour(&rt->dst, rt->rt_gateway);
+ if (IS_ERR(n))
+ return PTR_ERR(n);
+ old_n = xchg(&rt->dst._neighbour, n);
+ if (old_n)
+ neigh_release(old_n);
+ if (!n || !(n->nud_state & NUD_VALID)) {
+ if (n)
+ neigh_event_send(n, NULL);
+ rt->rt_gateway = orig_gw;
+ return -EAGAIN;
+ } else {
+ rt->rt_flags |= RTCF_REDIRECTED;
+ call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
+ }
+ return 0;
+}
+
/* called in rcu_read_lock() section */
void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
__be32 saddr, struct net_device *dev)
{
+ int s, i;
struct in_device *in_dev = __in_dev_get_rcu(dev);
+ __be32 skeys[2] = { saddr, 0 };
+ int ikeys[2] = { dev->ifindex, 0 };
struct inet_peer *peer;
struct net *net;
@@ -1296,13 +1426,43 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
goto reject_redirect;
}
- peer = inet_getpeer_v4(daddr, 1);
- if (peer) {
- peer->redirect_learned.a4 = new_gw;
+ for (s = 0; s < 2; s++) {
+ for (i = 0; i < 2; i++) {
+ unsigned int hash;
+ struct rtable __rcu **rthp;
+ struct rtable *rt;
- inet_putpeer(peer);
+ hash = rt_hash(daddr, skeys[s], ikeys[i], rt_genid(net));
- atomic_inc(&__rt_peer_genid);
+ rthp = &rt_hash_table[hash].chain;
+
+ while ((rt = rcu_dereference(*rthp)) != NULL) {
+ rthp = &rt->dst.rt_next;
+
+ if (rt->rt_key_dst != daddr ||
+ rt->rt_key_src != skeys[s] ||
+ rt->rt_oif != ikeys[i] ||
+ rt_is_input_route(rt) ||
+ rt_is_expired(rt) ||
+ !net_eq(dev_net(rt->dst.dev), net) ||
+ rt->dst.error ||
+ rt->dst.dev != dev ||
+ rt->rt_gateway != old_gw)
+ continue;
+
+ if (!rt->peer)
+ rt_bind_peer(rt, rt->rt_dst, 1);
+
+ peer = rt->peer;
+ if (peer) {
+ if (peer->redirect_learned.a4 != new_gw) {
+ peer->redirect_learned.a4 = new_gw;
+ atomic_inc(&__rt_peer_genid);
+ }
+ check_peer_redir(&rt->dst, peer);
+ }
+ }
+ }
}
return;
@@ -1589,31 +1749,6 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
}
}
-static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)
-{
- struct rtable *rt = (struct rtable *) dst;
- __be32 orig_gw = rt->rt_gateway;
-
- dst_confirm(&rt->dst);
-
- neigh_release(rt->dst.neighbour);
- rt->dst.neighbour = NULL;
-
- rt->rt_gateway = peer->redirect_learned.a4;
- if (arp_bind_neighbour(&rt->dst) ||
- !(rt->dst.neighbour->nud_state & NUD_VALID)) {
- if (rt->dst.neighbour)
- neigh_event_send(rt->dst.neighbour, NULL);
- rt->rt_gateway = orig_gw;
- return -EAGAIN;
- } else {
- rt->rt_flags |= RTCF_REDIRECTED;
- call_netevent_notifiers(NETEVENT_NEIGH_UPDATE,
- rt->dst.neighbour);
- }
- return 0;
-}
-
static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
{
struct rtable *rt = (struct rtable *) dst;
@@ -3088,6 +3223,13 @@ static ctl_table ipv4_route_table[] = {
.proc_handler = proc_dointvec_jiffies,
},
{
+ .procname = "gc_interval",
+ .data = &ip_rt_gc_interval,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec_jiffies,
+ },
+ {
.procname = "redirect_load",
.data = &ip_rt_redirect_load,
.maxlen = sizeof(int),
@@ -3297,6 +3439,11 @@ int __init ip_rt_init(void)
devinet_init();
ip_fib_init();
+ INIT_DELAYED_WORK_DEFERRABLE(&expires_work, rt_worker_func);
+ expires_ljiffies = jiffies;
+ schedule_delayed_work(&expires_work,
+ net_random() % ip_rt_gc_interval + ip_rt_gc_interval);
+
if (ip_rt_proc_init())
printk(KERN_ERR "Unable to create route proc files\n");
#ifdef CONFIG_XFRM
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index 438262977b0f..895f2157e136 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -277,6 +277,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
struct rtable *rt;
__u8 rcv_wscale;
bool ecn_ok = false;
+ struct flowi4 fl4;
if (!sysctl_tcp_syncookies || !th->ack || th->rst)
goto out;
@@ -344,20 +345,16 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
* hasn't changed since we received the original syn, but I see
* no easy way to do this.
*/
- {
- struct flowi4 fl4;
-
- flowi4_init_output(&fl4, 0, sk->sk_mark, RT_CONN_FLAGS(sk),
- RT_SCOPE_UNIVERSE, IPPROTO_TCP,
- inet_sk_flowi_flags(sk),
- (opt && opt->srr) ? opt->faddr : ireq->rmt_addr,
- ireq->loc_addr, th->source, th->dest);
- security_req_classify_flow(req, flowi4_to_flowi(&fl4));
- rt = ip_route_output_key(sock_net(sk), &fl4);
- if (IS_ERR(rt)) {
- reqsk_free(req);
- goto out;
- }
+ flowi4_init_output(&fl4, 0, sk->sk_mark, RT_CONN_FLAGS(sk),
+ RT_SCOPE_UNIVERSE, IPPROTO_TCP,
+ inet_sk_flowi_flags(sk),
+ (opt && opt->srr) ? opt->faddr : ireq->rmt_addr,
+ ireq->loc_addr, th->source, th->dest);
+ security_req_classify_flow(req, flowi4_to_flowi(&fl4));
+ rt = ip_route_output_key(sock_net(sk), &fl4);
+ if (IS_ERR(rt)) {
+ reqsk_free(req);
+ goto out;
}
/* Try to redo what tcp_v4_send_synack did. */
@@ -371,5 +368,10 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
ireq->rcv_wscale = rcv_wscale;
ret = get_cookie_sock(sk, skb, req, &rt->dst);
+ /* ip_queue_xmit() depends on our flow being setup
+ * Normal sockets get it right from inet_csk_route_child_sock()
+ */
+ if (ret)
+ inet_sk(ret)->cork.fl.u.ip4 = fl4;
out: return ret;
}
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 09ced58e6a51..58a944f4f791 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -854,8 +854,7 @@ new_segment:
wait_for_sndbuf:
set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
wait_for_memory:
- if (copied)
- tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);
+ tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);
if ((err = sk_stream_wait_memory(sk, &timeo)) != 0)
goto do_error;
@@ -864,7 +863,7 @@ wait_for_memory:
}
out:
- if (copied)
+ if (copied && !(flags & MSG_SENDPAGE_NOTLAST))
tcp_push(sk, flags, mss_now, tp->nonagle);
return copied;
@@ -3236,7 +3235,7 @@ void __init tcp_init(void)
{
struct sk_buff *skb = NULL;
unsigned long limit;
- int i, max_share, cnt;
+ int i, max_rshare, max_wshare, cnt;
unsigned long jiffy = jiffies;
BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb));
@@ -3300,15 +3299,16 @@ void __init tcp_init(void)
/* Set per-socket limits to no more than 1/128 the pressure threshold */
limit = ((unsigned long)sysctl_tcp_mem[1]) << (PAGE_SHIFT - 7);
- max_share = min(4UL*1024*1024, limit);
+ max_wshare = min(4UL*1024*1024, limit);
+ max_rshare = min(6UL*1024*1024, limit);
sysctl_tcp_wmem[0] = SK_MEM_QUANTUM;
sysctl_tcp_wmem[1] = 16*1024;
- sysctl_tcp_wmem[2] = max(64*1024, max_share);
+ sysctl_tcp_wmem[2] = max(64*1024, max_wshare);
sysctl_tcp_rmem[0] = SK_MEM_QUANTUM;
sysctl_tcp_rmem[1] = 87380;
- sysctl_tcp_rmem[2] = max(87380, max_share);
+ sysctl_tcp_rmem[2] = max(87380, max_rshare);
printk(KERN_INFO "TCP: Hash tables configured "
"(established %u bind %u)\n",
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index c68040fe9cd9..7410a8c28e14 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -83,7 +83,7 @@ int sysctl_tcp_ecn __read_mostly = 2;
EXPORT_SYMBOL(sysctl_tcp_ecn);
int sysctl_tcp_dsack __read_mostly = 1;
int sysctl_tcp_app_win __read_mostly = 31;
-int sysctl_tcp_adv_win_scale __read_mostly = 2;
+int sysctl_tcp_adv_win_scale __read_mostly = 1;
EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
int sysctl_tcp_stdurg __read_mostly;
@@ -328,6 +328,7 @@ static void tcp_grow_window(struct sock *sk, struct sk_buff *skb)
incr = __tcp_grow_window(sk, skb);
if (incr) {
+ incr = max_t(int, incr, 2 * skb->len);
tp->rcv_ssthresh = min(tp->rcv_ssthresh + incr,
tp->window_clamp);
inet_csk(sk)->icsk_ack.quick |= 1;
@@ -460,8 +461,11 @@ static void tcp_rcv_rtt_update(struct tcp_sock *tp, u32 sample, int win_dep)
if (!win_dep) {
m -= (new_sample >> 3);
new_sample += m;
- } else if (m < new_sample)
- new_sample = m << 3;
+ } else {
+ m <<= 3;
+ if (m < new_sample)
+ new_sample = m;
+ }
} else {
/* No previous measure. */
new_sample = m << 3;
@@ -1289,25 +1293,26 @@ static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb,
return in_sack;
}
-static u8 tcp_sacktag_one(struct sk_buff *skb, struct sock *sk,
- struct tcp_sacktag_state *state,
+/* Mark the given newly-SACKed range as such, adjusting counters and hints. */
+static u8 tcp_sacktag_one(struct sock *sk,
+ struct tcp_sacktag_state *state, u8 sacked,
+ u32 start_seq, u32 end_seq,
int dup_sack, int pcount)
{
struct tcp_sock *tp = tcp_sk(sk);
- u8 sacked = TCP_SKB_CB(skb)->sacked;
int fack_count = state->fack_count;
/* Account D-SACK for retransmitted packet. */
if (dup_sack && (sacked & TCPCB_RETRANS)) {
if (tp->undo_marker && tp->undo_retrans &&
- after(TCP_SKB_CB(skb)->end_seq, tp->undo_marker))
+ after(end_seq, tp->undo_marker))
tp->undo_retrans--;
if (sacked & TCPCB_SACKED_ACKED)
state->reord = min(fack_count, state->reord);
}
/* Nothing to do; acked frame is about to be dropped (was ACKed). */
- if (!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una))
+ if (!after(end_seq, tp->snd_una))
return sacked;
if (!(sacked & TCPCB_SACKED_ACKED)) {
@@ -1326,13 +1331,13 @@ static u8 tcp_sacktag_one(struct sk_buff *skb, struct sock *sk,
/* New sack for not retransmitted frame,
* which was in hole. It is reordering.
*/
- if (before(TCP_SKB_CB(skb)->seq,
+ if (before(start_seq,
tcp_highest_sack_seq(tp)))
state->reord = min(fack_count,
state->reord);
/* SACK enhanced F-RTO (RFC4138; Appendix B) */
- if (!after(TCP_SKB_CB(skb)->end_seq, tp->frto_highmark))
+ if (!after(end_seq, tp->frto_highmark))
state->flag |= FLAG_ONLY_ORIG_SACKED;
}
@@ -1350,8 +1355,7 @@ static u8 tcp_sacktag_one(struct sk_buff *skb, struct sock *sk,
/* Lost marker hint past SACKed? Tweak RFC3517 cnt */
if (!tcp_is_fack(tp) && (tp->lost_skb_hint != NULL) &&
- before(TCP_SKB_CB(skb)->seq,
- TCP_SKB_CB(tp->lost_skb_hint)->seq))
+ before(start_seq, TCP_SKB_CB(tp->lost_skb_hint)->seq))
tp->lost_cnt_hint += pcount;
if (fack_count > tp->fackets_out)
@@ -1370,6 +1374,9 @@ static u8 tcp_sacktag_one(struct sk_buff *skb, struct sock *sk,
return sacked;
}
+/* Shift newly-SACKed bytes from this skb to the immediately previous
+ * already-SACKed sk_buff. Mark the newly-SACKed bytes as such.
+ */
static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb,
struct tcp_sacktag_state *state,
unsigned int pcount, int shifted, int mss,
@@ -1377,9 +1384,20 @@ static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb,
{
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *prev = tcp_write_queue_prev(sk, skb);
+ u32 start_seq = TCP_SKB_CB(skb)->seq; /* start of newly-SACKed */
+ u32 end_seq = start_seq + shifted; /* end of newly-SACKed */
BUG_ON(!pcount);
+ /* Adjust counters and hints for the newly sacked sequence
+ * range but discard the return value since prev is already
+ * marked. We must tag the range first because the seq
+ * advancement below implicitly advances
+ * tcp_highest_sack_seq() when skb is highest_sack.
+ */
+ tcp_sacktag_one(sk, state, TCP_SKB_CB(skb)->sacked,
+ start_seq, end_seq, dup_sack, pcount);
+
if (skb == tp->lost_skb_hint)
tp->lost_cnt_hint += pcount;
@@ -1406,9 +1424,6 @@ static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb,
skb_shinfo(skb)->gso_type = 0;
}
- /* We discard results */
- tcp_sacktag_one(skb, sk, state, dup_sack, pcount);
-
/* Difference in this won't matter, both ACKed by the same cumul. ACK */
TCP_SKB_CB(prev)->sacked |= (TCP_SKB_CB(skb)->sacked & TCPCB_EVER_RETRANS);
@@ -1556,6 +1571,10 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb,
}
}
+ /* tcp_sacktag_one() won't SACK-tag ranges below snd_una */
+ if (!after(TCP_SKB_CB(skb)->seq + len, tp->snd_una))
+ goto fallback;
+
if (!skb_shift(prev, skb, len))
goto fallback;
if (!tcp_shifted_skb(sk, skb, state, pcount, len, mss, dup_sack))
@@ -1646,10 +1665,14 @@ static struct sk_buff *tcp_sacktag_walk(struct sk_buff *skb, struct sock *sk,
break;
if (in_sack) {
- TCP_SKB_CB(skb)->sacked = tcp_sacktag_one(skb, sk,
- state,
- dup_sack,
- tcp_skb_pcount(skb));
+ TCP_SKB_CB(skb)->sacked =
+ tcp_sacktag_one(sk,
+ state,
+ TCP_SKB_CB(skb)->sacked,
+ TCP_SKB_CB(skb)->seq,
+ TCP_SKB_CB(skb)->end_seq,
+ dup_sack,
+ tcp_skb_pcount(skb));
if (!before(TCP_SKB_CB(skb)->seq,
tcp_highest_sack_seq(tp)))
@@ -2534,6 +2557,7 @@ static void tcp_mark_head_lost(struct sock *sk, int packets, int mark_head)
if (cnt > packets) {
if ((tcp_is_sack(tp) && !tcp_is_fack(tp)) ||
+ (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED) ||
(oldcnt >= packets))
break;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 69790aa31981..53a5af66c0bb 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -630,7 +630,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
arg.iov[0].iov_len = sizeof(rep.th);
#ifdef CONFIG_TCP_MD5SIG
- key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr) : NULL;
+ key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->saddr) : NULL;
if (key) {
rep.opt[0] = htonl((TCPOPT_NOP << 24) |
(TCPOPT_NOP << 16) |
@@ -650,6 +650,11 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
arg.iov[0].iov_len, IPPROTO_TCP, 0);
arg.csumoffset = offsetof(struct tcphdr, check) / 2;
arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0;
+ /* When socket is gone, all binding information is lost.
+ * routing might fail in this case. using iif for oif to
+ * make sure we can deliver it
+ */
+ arg.bound_dev_if = sk ? sk->sk_bound_dev_if : inet_iif(skb);
net = dev_net(skb_dst(skb)->dev);
ip_send_reply(net->ipv4.tcp_sock, skb, ip_hdr(skb)->saddr,
@@ -1449,9 +1454,13 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen;
newinet->inet_id = newtp->write_seq ^ jiffies;
- if (!dst && (dst = inet_csk_route_child_sock(sk, newsk, req)) == NULL)
- goto put_and_exit;
-
+ if (!dst) {
+ dst = inet_csk_route_child_sock(sk, newsk, req);
+ if (!dst)
+ goto put_and_exit;
+ } else {
+ /* syncookie case : see end of cookie_v4_check() */
+ }
sk_setup_caps(newsk, dst);
tcp_mtup_init(newsk);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 882e0b0964d0..faf257b94154 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1134,11 +1134,9 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
sk_mem_uncharge(sk, len);
sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
- /* Any change of skb->len requires recalculation of tso
- * factor and mss.
- */
+ /* Any change of skb->len requires recalculation of tso factor. */
if (tcp_skb_pcount(skb) > 1)
- tcp_set_skb_tso_segs(sk, skb, tcp_current_mss(sk));
+ tcp_set_skb_tso_segs(sk, skb, tcp_skb_mss(skb));
return 0;
}
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index 63418185f524..e3db3f915114 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -110,10 +110,7 @@ static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb)
skb_push(skb, sizeof(*iph));
skb_reset_network_header(skb);
-
- memmove(skb->data - skb->mac_len, skb_mac_header(skb),
- skb->mac_len);
- skb_set_mac_header(skb, -skb->mac_len);
+ skb_mac_header_rebuild(skb);
xfrm4_beet_make_header(skb);
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index 534972e114ac..ed4bf11ef9f4 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -66,7 +66,6 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
{
- const unsigned char *old_mac;
int err = -EINVAL;
if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP)
@@ -84,10 +83,9 @@ static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
if (!(x->props.flags & XFRM_STATE_NOECN))
ipip_ecn_decapsulate(skb);
- old_mac = skb_mac_header(skb);
- skb_set_mac_header(skb, -skb->mac_len);
- memmove(skb_mac_header(skb), old_mac, skb->mac_len);
skb_reset_network_header(skb);
+ skb_mac_header_rebuild(skb);
+
err = 0;
out:
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index cf2cf62f33fc..8a4bf719c253 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -433,6 +433,10 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
/* Join all-node multicast group */
ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes);
+ /* Join all-router multicast group if forwarding is set */
+ if (ndev->cnf.forwarding && dev && (dev->flags & IFF_MULTICAST))
+ ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters);
+
return ndev;
}
@@ -656,7 +660,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
* layer address of our nexhop router
*/
- if (rt->rt6i_nexthop == NULL)
+ if (dst_get_neighbour_raw(&rt->dst) == NULL)
ifa->flags &= ~IFA_F_OPTIMISTIC;
ifa->idev = idev;
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index 2195ae651923..4c0f894d0843 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -324,8 +324,6 @@ static void ah6_output_done(struct crypto_async_request *base, int err)
#endif
}
- err = ah->nexthdr;
-
kfree(AH_SKB_CB(skb)->tmp);
xfrm_output_resume(skb, err);
}
@@ -466,12 +464,12 @@ static void ah6_input_done(struct crypto_async_request *base, int err)
if (err)
goto out;
+ err = ah->nexthdr;
+
skb->network_header += ah_hlen;
memcpy(skb_network_header(skb), work_iph, hdr_len);
__skb_pull(skb, ah_hlen + hdr_len);
skb_set_transport_header(skb, -hdr_len);
-
- err = ah->nexthdr;
out:
kfree(AH_SKB_CB(skb)->tmp);
xfrm_input_resume(skb, err);
@@ -583,8 +581,6 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
if (err == -EINPROGRESS)
goto out;
- if (err == -EBUSY)
- err = NET_XMIT_DROP;
goto out_free;
}
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 1ac7938dd9ec..65dd5433f08b 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -411,19 +411,15 @@ static u32 esp6_get_mtu(struct xfrm_state *x, int mtu)
struct esp_data *esp = x->data;
u32 blksize = ALIGN(crypto_aead_blocksize(esp->aead), 4);
u32 align = max_t(u32, blksize, esp->padlen);
- u32 rem;
+ unsigned int net_adj;
- mtu -= x->props.header_len + crypto_aead_authsize(esp->aead);
- rem = mtu & (align - 1);
- mtu &= ~(align - 1);
-
- if (x->props.mode != XFRM_MODE_TUNNEL) {
- u32 padsize = ((blksize - 1) & 7) + 1;
- mtu -= blksize - padsize;
- mtu += min_t(u32, blksize - padsize, rem);
- }
+ if (x->props.mode != XFRM_MODE_TUNNEL)
+ net_adj = sizeof(struct ipv6hdr);
+ else
+ net_adj = 0;
- return mtu - 2;
+ return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) -
+ net_adj) & ~(align - 1)) + (net_adj - 2);
}
static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 4076a0b14b20..0f9b37a1c1d4 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -1455,7 +1455,7 @@ static int fib6_age(struct rt6_info *rt, void *arg)
RT6_TRACE("aging clone %p\n", rt);
return -1;
} else if ((rt->rt6i_flags & RTF_GATEWAY) &&
- (!(rt->rt6i_nexthop->flags & NTF_ROUTER))) {
+ (!(dst_get_neighbour_raw(&rt->dst)->flags & NTF_ROUTER))) {
RT6_TRACE("purging route %p via non-router but gateway\n",
rt);
return -1;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index e17596b8407a..ae9f6d436171 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -100,6 +100,8 @@ static int ip6_finish_output2(struct sk_buff *skb)
{
struct dst_entry *dst = skb_dst(skb);
struct net_device *dev = dst->dev;
+ struct neighbour *neigh;
+ int res;
skb->protocol = htons(ETH_P_IPV6);
skb->dev = dev;
@@ -134,10 +136,22 @@ static int ip6_finish_output2(struct sk_buff *skb)
skb->len);
}
- if (dst->hh)
- return neigh_hh_output(dst->hh, skb);
- else if (dst->neighbour)
- return dst->neighbour->output(skb);
+ rcu_read_lock();
+ if (dst->hh) {
+ res = neigh_hh_output(dst->hh, skb);
+
+ rcu_read_unlock();
+ return res;
+ } else {
+ neigh = dst_get_neighbour(dst);
+ if (neigh) {
+ res = neigh->output(skb);
+
+ rcu_read_unlock();
+ return res;
+ }
+ rcu_read_unlock();
+ }
IP6_INC_STATS_BH(dev_net(dst->dev),
ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
@@ -385,6 +399,7 @@ int ip6_forward(struct sk_buff *skb)
struct ipv6hdr *hdr = ipv6_hdr(skb);
struct inet6_skb_parm *opt = IP6CB(skb);
struct net *net = dev_net(dst->dev);
+ struct neighbour *n;
u32 mtu;
if (net->ipv6.devconf_all->forwarding == 0)
@@ -459,11 +474,10 @@ int ip6_forward(struct sk_buff *skb)
send redirects to source routed frames.
We don't send redirects to frames decapsulated from IPsec.
*/
- if (skb->dev == dst->dev && dst->neighbour && opt->srcrt == 0 &&
- !skb_sec_path(skb)) {
+ n = dst_get_neighbour(dst);
+ if (skb->dev == dst->dev && n && opt->srcrt == 0 && !skb_sec_path(skb)) {
struct in6_addr *target = NULL;
struct rt6_info *rt;
- struct neighbour *n = dst->neighbour;
/*
* incoming and outgoing devices are the same
@@ -949,8 +963,11 @@ out:
static int ip6_dst_lookup_tail(struct sock *sk,
struct dst_entry **dst, struct flowi6 *fl6)
{
- int err;
struct net *net = sock_net(sk);
+#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
+ struct neighbour *n;
+#endif
+ int err;
if (*dst == NULL)
*dst = ip6_route_output(net, sk, fl6);
@@ -976,11 +993,14 @@ static int ip6_dst_lookup_tail(struct sock *sk,
* dst entry and replace it instead with the
* dst entry of the nexthop router
*/
- if ((*dst)->neighbour && !((*dst)->neighbour->nud_state & NUD_VALID)) {
+ rcu_read_lock();
+ n = dst_get_neighbour(*dst);
+ if (n && !(n->nud_state & NUD_VALID)) {
struct inet6_ifaddr *ifp;
struct flowi6 fl_gw6;
int redirect;
+ rcu_read_unlock();
ifp = ipv6_get_ifaddr(net, &fl6->saddr,
(*dst)->dev, 1);
@@ -1000,6 +1020,8 @@ static int ip6_dst_lookup_tail(struct sock *sk,
if ((err = (*dst)->error))
goto out_err_release;
}
+ } else {
+ rcu_read_unlock();
}
#endif
@@ -1172,6 +1194,29 @@ static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src,
return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL;
}
+static void ip6_append_data_mtu(int *mtu,
+ int *maxfraglen,
+ unsigned int fragheaderlen,
+ struct sk_buff *skb,
+ struct rt6_info *rt)
+{
+ if (!(rt->dst.flags & DST_XFRM_TUNNEL)) {
+ if (skb == NULL) {
+ /* first fragment, reserve header_len */
+ *mtu = *mtu - rt->dst.header_len;
+
+ } else {
+ /*
+ * this fragment is not first, the headers
+ * space is regarded as data space.
+ */
+ *mtu = dst_mtu(rt->dst.path);
+ }
+ *maxfraglen = ((*mtu - fragheaderlen) & ~7)
+ + fragheaderlen - sizeof(struct frag_hdr);
+ }
+}
+
int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
int offset, int len, int odd, struct sk_buff *skb),
void *from, int length, int transhdrlen,
@@ -1181,7 +1226,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
struct inet_sock *inet = inet_sk(sk);
struct ipv6_pinfo *np = inet6_sk(sk);
struct inet_cork *cork;
- struct sk_buff *skb;
+ struct sk_buff *skb, *skb_prev = NULL;
unsigned int maxfraglen, fragheaderlen;
int exthdrlen;
int hh_len;
@@ -1238,8 +1283,12 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
inet->cork.fl.u.ip6 = *fl6;
np->cork.hop_limit = hlimit;
np->cork.tclass = tclass;
- mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ?
- rt->dst.dev->mtu : dst_mtu(rt->dst.path);
+ if (rt->dst.flags & DST_XFRM_TUNNEL)
+ mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ?
+ rt->dst.dev->mtu : dst_mtu(&rt->dst);
+ else
+ mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ?
+ rt->dst.dev->mtu : dst_mtu(rt->dst.path);
if (np->frag_size < mtu) {
if (np->frag_size)
mtu = np->frag_size;
@@ -1334,38 +1383,43 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to,
unsigned int fraglen;
unsigned int fraggap;
unsigned int alloclen;
- struct sk_buff *skb_prev;
alloc_new_skb:
- skb_prev = skb;
-
/* There's no room in the current skb */
- if (skb_prev)
- fraggap = skb_prev->len - maxfraglen;
+ if (skb)
+ fraggap = skb->len - maxfraglen;
else
fraggap = 0;
+ /* update mtu and maxfraglen if necessary */
+ if (skb == NULL || skb_prev == NULL)
+ ip6_append_data_mtu(&mtu, &maxfraglen,
+ fragheaderlen, skb, rt);
+
+ skb_prev = skb;
/*
* If remaining data exceeds the mtu,
* we know we need more fragment(s).
*/
datalen = length + fraggap;
- if (datalen > (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen)
- datalen = maxfraglen - fragheaderlen;
- fraglen = datalen + fragheaderlen;
+ if (datalen > (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen)
+ datalen = maxfraglen - fragheaderlen - rt->dst.trailer_len;
if ((flags & MSG_MORE) &&
!(rt->dst.dev->features&NETIF_F_SG))
alloclen = mtu;
else
alloclen = datalen + fragheaderlen;
- /*
- * The last fragment gets additional space at tail.
- * Note: we overallocate on fragments with MSG_MODE
- * because we have no idea if we're the last one.
- */
- if (datalen == length + fraggap)
- alloclen += rt->dst.trailer_len;
+ if (datalen != length + fraggap) {
+ /*
+ * this is not the last fragment, the trailer
+ * space is regarded as data space.
+ */
+ datalen += rt->dst.trailer_len;
+ }
+
+ alloclen += rt->dst.trailer_len;
+ fraglen = datalen + fragheaderlen;
/*
* We just reserve space for fragment header.
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 82a809901f8e..86e3cc10fc2e 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -696,8 +696,10 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb,
int err;
err = ip6mr_fib_lookup(net, &fl6, &mrt);
- if (err < 0)
+ if (err < 0) {
+ kfree_skb(skb);
return err;
+ }
read_lock(&mrt_lock);
dev->stats.tx_bytes += skb->len;
@@ -2051,8 +2053,10 @@ int ip6_mr_input(struct sk_buff *skb)
int err;
err = ip6mr_fib_lookup(net, &fl6, &mrt);
- if (err < 0)
+ if (err < 0) {
+ kfree_skb(skb);
return err;
+ }
read_lock(&mrt_lock);
cache = ip6mr_cache_find(mrt,
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index ee7839f4d6e3..f2d74ea19a76 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -257,7 +257,6 @@ static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net,
if (rt) {
dev = rt->rt6i_dev;
- dev_hold(dev);
dst_release(&rt->dst);
}
} else
@@ -2055,7 +2054,7 @@ static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca,
if (!delta)
pmc->mca_sfcount[sfmode]--;
for (j=0; j<i; j++)
- (void) ip6_mc_del1_src(pmc, sfmode, &psfsrc[i]);
+ ip6_mc_del1_src(pmc, sfmode, &psfsrc[j]);
} else if (isexclude != (pmc->mca_sfcount[MCAST_EXCLUDE] != 0)) {
struct ip6_sf_list *psf;
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 7596f071d308..10a8d411707e 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1244,7 +1244,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
rt = rt6_get_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev);
if (rt)
- neigh = rt->rt6i_nexthop;
+ neigh = dst_get_neighbour(&rt->dst);
if (rt && lifetime == 0) {
neigh_clone(neigh);
@@ -1265,7 +1265,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
return;
}
- neigh = rt->rt6i_nexthop;
+ neigh = dst_get_neighbour(&rt->dst);
if (neigh == NULL) {
ND_PRINTK0(KERN_ERR
"ICMPv6 RA: %s() got default router without neighbour.\n",
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 0ef1f086feb8..8e600f827fe7 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -356,7 +356,7 @@ out:
#ifdef CONFIG_IPV6_ROUTER_PREF
static void rt6_probe(struct rt6_info *rt)
{
- struct neighbour *neigh = rt ? rt->rt6i_nexthop : NULL;
+ struct neighbour *neigh;
/*
* Okay, this does not seem to be appropriate
* for now, however, we need to check if it
@@ -365,8 +365,10 @@ static void rt6_probe(struct rt6_info *rt)
* Router Reachability Probe MUST be rate-limited
* to no more than one per minute.
*/
+ rcu_read_lock();
+ neigh = rt ? dst_get_neighbour(&rt->dst) : NULL;
if (!neigh || (neigh->nud_state & NUD_VALID))
- return;
+ goto out;
read_lock_bh(&neigh->lock);
if (!(neigh->nud_state & NUD_VALID) &&
time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) {
@@ -379,8 +381,11 @@ static void rt6_probe(struct rt6_info *rt)
target = (struct in6_addr *)&neigh->primary_key;
addrconf_addr_solict_mult(target, &mcaddr);
ndisc_send_ns(rt->rt6i_dev, NULL, target, &mcaddr, NULL);
- } else
+ } else {
read_unlock_bh(&neigh->lock);
+ }
+out:
+ rcu_read_unlock();
}
#else
static inline void rt6_probe(struct rt6_info *rt)
@@ -404,8 +409,11 @@ static inline int rt6_check_dev(struct rt6_info *rt, int oif)
static inline int rt6_check_neigh(struct rt6_info *rt)
{
- struct neighbour *neigh = rt->rt6i_nexthop;
+ struct neighbour *neigh;
int m;
+
+ rcu_read_lock();
+ neigh = dst_get_neighbour(&rt->dst);
if (rt->rt6i_flags & RTF_NONEXTHOP ||
!(rt->rt6i_flags & RTF_GATEWAY))
m = 1;
@@ -422,6 +430,7 @@ static inline int rt6_check_neigh(struct rt6_info *rt)
read_unlock_bh(&neigh->lock);
} else
m = 0;
+ rcu_read_unlock();
return m;
}
@@ -745,8 +754,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_add
dst_free(&rt->dst);
return NULL;
}
- rt->rt6i_nexthop = neigh;
-
+ dst_set_neighbour(&rt->dst, neigh);
}
return rt;
@@ -760,7 +768,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, const struct in6_a
rt->rt6i_dst.plen = 128;
rt->rt6i_flags |= RTF_CACHE;
rt->dst.flags |= DST_HOST;
- rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop);
+ dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour_raw(&ort->dst)));
}
return rt;
}
@@ -794,7 +802,7 @@ restart:
dst_hold(&rt->dst);
read_unlock_bh(&table->tb6_lock);
- if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
+ if (!dst_get_neighbour_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP))
nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr);
else if (!(rt->dst.flags & DST_HOST))
nrt = rt6_alloc_clone(rt, &fl6->daddr);
@@ -1058,7 +1066,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
}
rt->rt6i_idev = idev;
- rt->rt6i_nexthop = neigh;
+ dst_set_neighbour(&rt->dst, neigh);
atomic_set(&rt->dst.__refcnt, 1);
dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255);
rt->dst.output = ip6_output;
@@ -1338,12 +1346,12 @@ int ip6_route_add(struct fib6_config *cfg)
rt->rt6i_prefsrc.plen = 0;
if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) {
- rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev);
- if (IS_ERR(rt->rt6i_nexthop)) {
- err = PTR_ERR(rt->rt6i_nexthop);
- rt->rt6i_nexthop = NULL;
+ struct neighbour *neigh = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev);
+ if (IS_ERR(neigh)) {
+ err = PTR_ERR(neigh);
goto out;
}
+ dst_set_neighbour(&rt->dst, neigh);
}
rt->rt6i_flags = cfg->fc_flags;
@@ -1574,7 +1582,7 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src,
dst_confirm(&rt->dst);
/* Duplicate redirect: silently ignore. */
- if (neigh == rt->dst.neighbour)
+ if (neigh == dst_get_neighbour_raw(&rt->dst))
goto out;
nrt = ip6_rt_copy(rt);
@@ -1590,7 +1598,7 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src,
nrt->dst.flags |= DST_HOST;
ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key);
- nrt->rt6i_nexthop = neigh_clone(neigh);
+ dst_set_neighbour(&nrt->dst, neigh_clone(neigh));
if (ip6_ins_rt(nrt))
goto out;
@@ -1670,7 +1678,7 @@ again:
1. It is connected route. Action: COW
2. It is gatewayed route or NONEXTHOP route. Action: clone it.
*/
- if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP))
+ if (!dst_get_neighbour_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP))
nrt = rt6_alloc_cow(rt, daddr, saddr);
else
nrt = rt6_alloc_clone(rt, daddr);
@@ -2035,7 +2043,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
return ERR_CAST(neigh);
}
- rt->rt6i_nexthop = neigh;
+ dst_set_neighbour(&rt->dst, neigh);
ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
rt->rt6i_dst.plen = 128;
@@ -2312,6 +2320,7 @@ static int rt6_fill_node(struct net *net,
struct nlmsghdr *nlh;
long expires;
u32 table;
+ struct neighbour *n;
if (prefix) { /* user wants prefix routes only */
if (!(rt->rt6i_flags & RTF_PREFIX_RT)) {
@@ -2400,8 +2409,15 @@ static int rt6_fill_node(struct net *net,
if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)
goto nla_put_failure;
- if (rt->dst.neighbour)
- NLA_PUT(skb, RTA_GATEWAY, 16, &rt->dst.neighbour->primary_key);
+ rcu_read_lock();
+ n = dst_get_neighbour(&rt->dst);
+ if (n) {
+ if (nla_put(skb, RTA_GATEWAY, 16, &n->primary_key) < 0) {
+ rcu_read_unlock();
+ goto nla_put_failure;
+ }
+ }
+ rcu_read_unlock();
if (rt->dst.dev)
NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex);
@@ -2585,6 +2601,7 @@ struct rt6_proc_arg
static int rt6_info_route(struct rt6_info *rt, void *p_arg)
{
struct seq_file *m = p_arg;
+ struct neighbour *n;
seq_printf(m, "%pi6 %02x ", &rt->rt6i_dst.addr, rt->rt6i_dst.plen);
@@ -2593,12 +2610,14 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg)
#else
seq_puts(m, "00000000000000000000000000000000 00 ");
#endif
-
- if (rt->rt6i_nexthop) {
- seq_printf(m, "%pi6", rt->rt6i_nexthop->primary_key);
+ rcu_read_lock();
+ n = dst_get_neighbour(&rt->dst);
+ if (n) {
+ seq_printf(m, "%pi6", n->primary_key);
} else {
seq_puts(m, "00000000000000000000000000000000");
}
+ rcu_read_unlock();
seq_printf(m, " %08x %08x %08x %08x %8s\n",
rt->rt6i_metric, atomic_read(&rt->dst.__refcnt),
rt->dst.__use, rt->rt6i_flags,
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 1cca5761aea9..f56acd096598 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -263,6 +263,8 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net,
if (register_netdevice(dev) < 0)
goto failed_free;
+ strcpy(nt->parms.name, dev->name);
+
dev_hold(dev);
ipip6_tunnel_link(sitn, nt);
@@ -677,7 +679,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
struct neighbour *neigh = NULL;
if (skb_dst(skb))
- neigh = skb_dst(skb)->neighbour;
+ neigh = dst_get_neighbour(skb_dst(skb));
if (neigh == NULL) {
if (net_ratelimit())
@@ -702,7 +704,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
struct neighbour *neigh = NULL;
if (skb_dst(skb))
- neigh = skb_dst(skb)->neighbour;
+ neigh = dst_get_neighbour(skb_dst(skb));
if (neigh == NULL) {
if (net_ratelimit())
@@ -1141,7 +1143,6 @@ static int ipip6_tunnel_init(struct net_device *dev)
struct ip_tunnel *tunnel = netdev_priv(dev);
tunnel->dev = dev;
- strcpy(tunnel->parms.name, dev->name);
memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
@@ -1204,6 +1205,7 @@ static void __net_exit sit_destroy_tunnels(struct sit_net *sitn, struct list_hea
static int __net_init sit_init_net(struct net *net)
{
struct sit_net *sitn = net_generic(net, sit_net_id);
+ struct ip_tunnel *t;
int err;
sitn->tunnels[0] = sitn->tunnels_wc;
@@ -1228,6 +1230,9 @@ static int __net_init sit_init_net(struct net *net)
if ((err = register_netdev(sitn->fb_tunnel_dev)))
goto err_reg_dev;
+ t = netdev_priv(sitn->fb_tunnel_dev);
+
+ strcpy(t->parms.name, sitn->fb_tunnel_dev->name);
return 0;
err_reg_dev:
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 296510a82c35..848f9634bbdf 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1096,7 +1096,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
#ifdef CONFIG_TCP_MD5SIG
if (sk)
- key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr);
+ key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr);
#endif
if (th->ack)
@@ -1514,6 +1514,10 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
tcp_mtup_init(newsk);
tcp_sync_mss(newsk, dst_mtu(dst));
newtp->advmss = dst_metric_advmss(dst);
+ if (tcp_sk(sk)->rx_opt.user_mss &&
+ tcp_sk(sk)->rx_opt.user_mss < newtp->advmss)
+ newtp->advmss = tcp_sk(sk)->rx_opt.user_mss;
+
tcp_initialize_rcv_mss(newsk);
newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index 3437d7d4eed6..f37cba9e6891 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -80,7 +80,6 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb)
{
struct ipv6hdr *ip6h;
- const unsigned char *old_mac;
int size = sizeof(struct ipv6hdr);
int err;
@@ -90,10 +89,7 @@ static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb)
__skb_push(skb, size);
skb_reset_network_header(skb);
-
- old_mac = skb_mac_header(skb);
- skb_set_mac_header(skb, -skb->mac_len);
- memmove(skb_mac_header(skb), old_mac, skb->mac_len);
+ skb_mac_header_rebuild(skb);
xfrm6_beet_make_header(skb);
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 4d6edff0498f..23ecd68a5e62 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -63,7 +63,6 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
{
int err = -EINVAL;
- const unsigned char *old_mac;
if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6)
goto out;
@@ -80,10 +79,9 @@ static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
if (!(x->props.flags & XFRM_STATE_NOECN))
ipip6_ecn_decapsulate(skb);
- old_mac = skb_mac_header(skb);
- skb_set_mac_header(skb, -skb->mac_len);
- memmove(skb_mac_header(skb), old_mac, skb->mac_len);
skb_reset_network_header(skb);
+ skb_mac_header_rebuild(skb);
+
err = 0;
out:
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c
index d2726a74597d..3c55f633928e 100644
--- a/net/l2tp/l2tp_eth.c
+++ b/net/l2tp/l2tp_eth.c
@@ -167,6 +167,7 @@ static void l2tp_eth_delete(struct l2tp_session *session)
if (dev) {
unregister_netdev(dev);
spriv->dev = NULL;
+ module_put(THIS_MODULE);
}
}
}
@@ -254,6 +255,7 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p
if (rc < 0)
goto out_del_dev;
+ __module_get(THIS_MODULE);
/* Must be done after register_netdev() */
strlcpy(session->ifname, dev->name, IFNAMSIZ);
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index b6466e71f5e1..78bc442b2b6f 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -251,9 +251,16 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
struct inet_sock *inet = inet_sk(sk);
struct sockaddr_l2tpip *addr = (struct sockaddr_l2tpip *) uaddr;
- int ret = -EINVAL;
+ int ret;
int chk_addr_ret;
+ if (!sock_flag(sk, SOCK_ZAPPED))
+ return -EINVAL;
+ if (addr_len < sizeof(struct sockaddr_l2tpip))
+ return -EINVAL;
+ if (addr->l2tp_family != AF_INET)
+ return -EINVAL;
+
ret = -EADDRINUSE;
read_lock_bh(&l2tp_ip_lock);
if (__l2tp_ip_bind_lookup(&init_net, addr->l2tp_addr.s_addr, sk->sk_bound_dev_if, addr->l2tp_conn_id))
@@ -283,6 +290,8 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
sk_del_node_init(sk);
write_unlock_bh(&l2tp_ip_lock);
ret = 0;
+ sock_reset_flag(sk, SOCK_ZAPPED);
+
out:
release_sock(sk);
@@ -303,13 +312,14 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
__be32 saddr;
int oif, rc;
- rc = -EINVAL;
+ if (sock_flag(sk, SOCK_ZAPPED)) /* Must bind first - autobinding does not work */
+ return -EINVAL;
+
if (addr_len < sizeof(*lsa))
- goto out;
+ return -EINVAL;
- rc = -EAFNOSUPPORT;
if (lsa->l2tp_family != AF_INET)
- goto out;
+ return -EAFNOSUPPORT;
lock_sock(sk);
@@ -363,6 +373,14 @@ out:
return rc;
}
+static int l2tp_ip_disconnect(struct sock *sk, int flags)
+{
+ if (sock_flag(sk, SOCK_ZAPPED))
+ return 0;
+
+ return udp_disconnect(sk, flags);
+}
+
static int l2tp_ip_getname(struct socket *sock, struct sockaddr *uaddr,
int *uaddr_len, int peer)
{
@@ -393,11 +411,6 @@ static int l2tp_ip_backlog_recv(struct sock *sk, struct sk_buff *skb)
{
int rc;
- if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
- goto drop;
-
- nf_reset(skb);
-
/* Charge it to the socket, dropping if the queue is full. */
rc = sock_queue_rcv_skb(sk, skb);
if (rc < 0)
@@ -446,8 +459,9 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
daddr = lip->l2tp_addr.s_addr;
} else {
+ rc = -EDESTADDRREQ;
if (sk->sk_state != TCP_ESTABLISHED)
- return -EDESTADDRREQ;
+ goto out;
daddr = inet->inet_daddr;
connected = 1;
@@ -595,7 +609,7 @@ static struct proto l2tp_ip_prot = {
.close = l2tp_ip_close,
.bind = l2tp_ip_bind,
.connect = l2tp_ip_connect,
- .disconnect = udp_disconnect,
+ .disconnect = l2tp_ip_disconnect,
.ioctl = udp_ioctl,
.destroy = l2tp_ip_destroy_sock,
.setsockopt = ip_setsockopt,
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index 39a21d0c61c4..13f9868e6949 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -908,7 +908,7 @@ static int pppol2tp_getname(struct socket *sock, struct sockaddr *uaddr,
goto end_put_sess;
}
- inet = inet_sk(sk);
+ inet = inet_sk(tunnel->sock);
if (tunnel->version == 2) {
struct sockaddr_pppol2tp sp;
len = sizeof(sp);
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index dfd3a648a551..a18e6c3d36e3 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -833,15 +833,15 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
copied += used;
len -= used;
+ /* For non stream protcols we get one packet per recvmsg call */
+ if (sk->sk_type != SOCK_STREAM)
+ goto copy_uaddr;
+
if (!(flags & MSG_PEEK)) {
sk_eat_skb(sk, skb, 0);
*seq = 0;
}
- /* For non stream protcols we get one packet per recvmsg call */
- if (sk->sk_type != SOCK_STREAM)
- goto copy_uaddr;
-
/* Partial read */
if (used + offset < skb->len)
continue;
@@ -857,6 +857,12 @@ copy_uaddr:
}
if (llc_sk(sk)->cmsg_flags)
llc_cmsg_rcv(msg, skb);
+
+ if (!(flags & MSG_PEEK)) {
+ sk_eat_skb(sk, skb, 0);
+ *seq = 0;
+ }
+
goto out;
}
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 9c0d76cdca92..1a41b1423d24 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -48,6 +48,8 @@ static void ieee80211_free_tid_rx(struct rcu_head *h)
container_of(h, struct tid_ampdu_rx, rcu_head);
int i;
+ del_timer_sync(&tid_rx->reorder_timer);
+
for (i = 0; i < tid_rx->buf_size; i++)
dev_kfree_skb(tid_rx->reorder_buf[i]);
kfree(tid_rx->reorder_buf);
@@ -87,7 +89,6 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
tid, 0, reason);
del_timer_sync(&tid_rx->session_timer);
- del_timer_sync(&tid_rx->reorder_timer);
call_rcu(&tid_rx->rcu_head, ieee80211_free_tid_rx);
}
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index db7db43ccf42..b7f4f5c1f693 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -304,6 +304,38 @@ ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid)
__release(agg_queue);
}
+/*
+ * splice packets from the STA's pending to the local pending,
+ * requires a call to ieee80211_agg_splice_finish later
+ */
+static void __acquires(agg_queue)
+ieee80211_agg_splice_packets(struct ieee80211_local *local,
+ struct tid_ampdu_tx *tid_tx, u16 tid)
+{
+ int queue = ieee80211_ac_from_tid(tid);
+ unsigned long flags;
+
+ ieee80211_stop_queue_agg(local, tid);
+
+ if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates"
+ " from the pending queue\n", tid))
+ return;
+
+ if (!skb_queue_empty(&tid_tx->pending)) {
+ spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+ /* copy over remaining packets */
+ skb_queue_splice_tail_init(&tid_tx->pending,
+ &local->pending[queue]);
+ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+ }
+}
+
+static void __releases(agg_queue)
+ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid)
+{
+ ieee80211_wake_queue_agg(local, tid);
+}
+
void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
{
struct tid_ampdu_tx *tid_tx;
@@ -315,19 +347,17 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
/*
- * While we're asking the driver about the aggregation,
- * stop the AC queue so that we don't have to worry
- * about frames that came in while we were doing that,
- * which would require us to put them to the AC pending
- * afterwards which just makes the code more complex.
+ * Start queuing up packets for this aggregation session.
+ * We're going to release them once the driver is OK with
+ * that.
*/
- ieee80211_stop_queue_agg(local, tid);
-
clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state);
/*
- * make sure no packets are being processed to get
- * valid starting sequence number
+ * Make sure no packets are being processed. This ensures that
+ * we have a valid starting sequence number and that in-flight
+ * packets have been flushed out and no packets for this TID
+ * will go into the driver during the ampdu_action call.
*/
synchronize_net();
@@ -341,17 +371,15 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
" tid %d\n", tid);
#endif
spin_lock_bh(&sta->lock);
+ ieee80211_agg_splice_packets(local, tid_tx, tid);
ieee80211_assign_tid_tx(sta, tid, NULL);
+ ieee80211_agg_splice_finish(local, tid);
spin_unlock_bh(&sta->lock);
- ieee80211_wake_queue_agg(local, tid);
kfree_rcu(tid_tx, rcu_head);
return;
}
- /* we can take packets again now */
- ieee80211_wake_queue_agg(local, tid);
-
/* activate the timer for the recipient's addBA response */
mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL);
#ifdef CONFIG_MAC80211_HT_DEBUG
@@ -471,38 +499,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
}
EXPORT_SYMBOL(ieee80211_start_tx_ba_session);
-/*
- * splice packets from the STA's pending to the local pending,
- * requires a call to ieee80211_agg_splice_finish later
- */
-static void __acquires(agg_queue)
-ieee80211_agg_splice_packets(struct ieee80211_local *local,
- struct tid_ampdu_tx *tid_tx, u16 tid)
-{
- int queue = ieee80211_ac_from_tid(tid);
- unsigned long flags;
-
- ieee80211_stop_queue_agg(local, tid);
-
- if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates"
- " from the pending queue\n", tid))
- return;
-
- if (!skb_queue_empty(&tid_tx->pending)) {
- spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
- /* copy over remaining packets */
- skb_queue_splice_tail_init(&tid_tx->pending,
- &local->pending[queue]);
- spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
- }
-}
-
-static void __releases(agg_queue)
-ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid)
-{
- ieee80211_wake_queue_agg(local, tid);
-}
-
static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
struct sta_info *sta, u16 tid)
{
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 895eec19f2e2..65f3764c5aa2 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -498,6 +498,18 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
ieee80211_configure_filter(local);
break;
default:
+ mutex_lock(&local->mtx);
+ if (local->hw_roc_dev == sdata->dev &&
+ local->hw_roc_channel) {
+ /* ignore return value since this is racy */
+ drv_cancel_remain_on_channel(local);
+ ieee80211_queue_work(&local->hw, &local->hw_roc_done);
+ }
+ mutex_unlock(&local->mtx);
+
+ flush_work(&local->hw_roc_start);
+ flush_work(&local->hw_roc_done);
+
flush_work(&sdata->work);
/*
* When we get here, the interface is marked down.
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 866f269183cf..1e36fb3318cb 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -910,6 +910,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
result);
+ ieee80211_led_init(local);
+
rtnl_lock();
result = ieee80211_init_rate_ctrl_alg(local,
@@ -931,8 +933,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
rtnl_unlock();
- ieee80211_led_init(local);
-
local->network_latency_notifier.notifier_call =
ieee80211_max_network_latency;
result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY,
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index 13427b194ced..c55eb9d8ea55 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -251,6 +251,22 @@ static void ieee80211_hw_roc_done(struct work_struct *work)
return;
}
+ /* was never transmitted */
+ if (local->hw_roc_skb) {
+ u64 cookie;
+
+ cookie = local->hw_roc_cookie ^ 2;
+
+ cfg80211_mgmt_tx_status(local->hw_roc_dev, cookie,
+ local->hw_roc_skb->data,
+ local->hw_roc_skb->len, false,
+ GFP_KERNEL);
+
+ kfree_skb(local->hw_roc_skb);
+ local->hw_roc_skb = NULL;
+ local->hw_roc_skb_for_status = NULL;
+ }
+
if (!local->hw_roc_for_tx)
cfg80211_remain_on_channel_expired(local->hw_roc_dev,
local->hw_roc_cookie,
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index 3d5a2cb835c4..816590b0d7f2 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -314,7 +314,7 @@ void rate_control_get_rate(struct ieee80211_sub_if_data *sdata,
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
info->control.rates[i].idx = -1;
info->control.rates[i].flags = 0;
- info->control.rates[i].count = 1;
+ info->control.rates[i].count = 0;
}
if (sdata->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 378bd67334ba..41000650f4a0 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -610,7 +610,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw,
index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
tid_agg_rx->buf_size;
if (!tid_agg_rx->reorder_buf[index] &&
- tid_agg_rx->stored_mpdu_num > 1) {
+ tid_agg_rx->stored_mpdu_num) {
/*
* No buffers ready to be released, but check whether any
* frames in the reorder buffer have timed out.
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 3104c844b544..da878c14182c 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1222,7 +1222,8 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
tx->sta = rcu_dereference(sdata->u.vlan.sta);
if (!tx->sta && sdata->dev->ieee80211_ptr->use_4addr)
return TX_DROP;
- } else if (info->flags & IEEE80211_TX_CTL_INJECTED) {
+ } else if (info->flags & IEEE80211_TX_CTL_INJECTED ||
+ tx->sdata->control_port_protocol == tx->skb->protocol) {
tx->sta = sta_info_get_bss(sdata, hdr->addr1);
}
if (!tx->sta)
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 2124db8e72be..11d9d49f22dc 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1254,6 +1254,12 @@ int ieee80211_reconfig(struct ieee80211_local *local)
}
}
+ /* add back keys */
+ list_for_each_entry(sdata, &local->interfaces, list)
+ if (ieee80211_sdata_running(sdata))
+ ieee80211_enable_keys(sdata);
+
+ wake_up:
/*
* Clear the WLAN_STA_BLOCK_BA flag so new aggregation
* sessions can be established after a resume.
@@ -1275,12 +1281,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
mutex_unlock(&local->sta_mtx);
}
- /* add back keys */
- list_for_each_entry(sdata, &local->interfaces, list)
- if (ieee80211_sdata_running(sdata))
- ieee80211_enable_keys(sdata);
-
- wake_up:
ieee80211_wake_queues_by_reason(hw,
IEEE80211_QUEUE_STOP_REASON_SUSPEND);
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 8f6a302d2ac3..aa1c40ab6a7c 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -109,7 +109,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
if (status->flag & RX_FLAG_MMIC_ERROR)
goto mic_fail;
- if (!(status->flag & RX_FLAG_IV_STRIPPED))
+ if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key)
goto update_iv;
return RX_CONTINUE;
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 24c28d238dcb..0787bed04180 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -233,6 +233,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
__be16 dport = 0; /* destination port to forward */
unsigned int flags;
struct ip_vs_conn_param param;
+ const union nf_inet_addr fwmark = { .ip = htonl(svc->fwmark) };
union nf_inet_addr snet; /* source network of the client,
after masking */
@@ -268,7 +269,6 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
{
int protocol = iph.protocol;
const union nf_inet_addr *vaddr = &iph.daddr;
- const union nf_inet_addr fwmark = { .ip = htonl(svc->fwmark) };
__be16 vport = 0;
if (dst_port == svc->port) {
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 6ef64adf7362..24bc620b539a 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -830,12 +830,19 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb,
return 0;
}
-int netlink_sendskb(struct sock *sk, struct sk_buff *skb)
+static int __netlink_sendskb(struct sock *sk, struct sk_buff *skb)
{
int len = skb->len;
skb_queue_tail(&sk->sk_receive_queue, skb);
sk->sk_data_ready(sk, len);
+ return len;
+}
+
+int netlink_sendskb(struct sock *sk, struct sk_buff *skb)
+{
+ int len = __netlink_sendskb(sk, skb);
+
sock_put(sk);
return len;
}
@@ -960,8 +967,7 @@ static inline int netlink_broadcast_deliver(struct sock *sk,
if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf &&
!test_bit(0, &nlk->state)) {
skb_set_owner_r(skb, sk);
- skb_queue_tail(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk, skb->len);
+ __netlink_sendskb(sk, skb);
return atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf;
}
return -1;
@@ -1682,10 +1688,8 @@ static int netlink_dump(struct sock *sk)
if (sk_filter(sk, skb))
kfree_skb(skb);
- else {
- skb_queue_tail(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk, skb->len);
- }
+ else
+ __netlink_sendskb(sk, skb);
return 0;
}
@@ -1697,10 +1701,8 @@ static int netlink_dump(struct sock *sk)
if (sk_filter(sk, skb))
kfree_skb(skb);
- else {
- skb_queue_tail(&sk->sk_receive_queue, skb);
- sk->sk_data_ready(sk, skb->len);
- }
+ else
+ __netlink_sendskb(sk, skb);
if (cb->done)
cb->done(cb);
diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index f17fd841f948..d29a7fb3f61d 100644
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -1045,6 +1045,9 @@ static int pep_sendmsg(struct kiocb *iocb, struct sock *sk,
int flags = msg->msg_flags;
int err, done;
+ if (len > USHRT_MAX)
+ return -EMSGSIZE;
+
if ((msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL|
MSG_CMSG_COMPAT)) ||
!(msg->msg_flags & MSG_EOR))
diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c
index bb6ad81b671d..424ff622ab5f 100644
--- a/net/rds/af_rds.c
+++ b/net/rds/af_rds.c
@@ -68,7 +68,6 @@ static int rds_release(struct socket *sock)
{
struct sock *sk = sock->sk;
struct rds_sock *rs;
- unsigned long flags;
if (!sk)
goto out;
@@ -94,10 +93,10 @@ static int rds_release(struct socket *sock)
rds_rdma_drop_keys(rs);
rds_notify_queue_get(rs, NULL);
- spin_lock_irqsave(&rds_sock_lock, flags);
+ spin_lock_bh(&rds_sock_lock);
list_del_init(&rs->rs_item);
rds_sock_count--;
- spin_unlock_irqrestore(&rds_sock_lock, flags);
+ spin_unlock_bh(&rds_sock_lock);
rds_trans_put(rs->rs_transport);
@@ -409,7 +408,6 @@ static const struct proto_ops rds_proto_ops = {
static int __rds_create(struct socket *sock, struct sock *sk, int protocol)
{
- unsigned long flags;
struct rds_sock *rs;
sock_init_data(sock, sk);
@@ -426,10 +424,10 @@ static int __rds_create(struct socket *sock, struct sock *sk, int protocol)
spin_lock_init(&rs->rs_rdma_lock);
rs->rs_rdma_keys = RB_ROOT;
- spin_lock_irqsave(&rds_sock_lock, flags);
+ spin_lock_bh(&rds_sock_lock);
list_add_tail(&rs->rs_item, &rds_sock_list);
rds_sock_count++;
- spin_unlock_irqrestore(&rds_sock_lock, flags);
+ spin_unlock_bh(&rds_sock_lock);
return 0;
}
@@ -471,12 +469,11 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len,
{
struct rds_sock *rs;
struct rds_incoming *inc;
- unsigned long flags;
unsigned int total = 0;
len /= sizeof(struct rds_info_message);
- spin_lock_irqsave(&rds_sock_lock, flags);
+ spin_lock_bh(&rds_sock_lock);
list_for_each_entry(rs, &rds_sock_list, rs_item) {
read_lock(&rs->rs_recv_lock);
@@ -492,7 +489,7 @@ static void rds_sock_inc_info(struct socket *sock, unsigned int len,
read_unlock(&rs->rs_recv_lock);
}
- spin_unlock_irqrestore(&rds_sock_lock, flags);
+ spin_unlock_bh(&rds_sock_lock);
lens->nr = total;
lens->each = sizeof(struct rds_info_message);
@@ -504,11 +501,10 @@ static void rds_sock_info(struct socket *sock, unsigned int len,
{
struct rds_info_socket sinfo;
struct rds_sock *rs;
- unsigned long flags;
len /= sizeof(struct rds_info_socket);
- spin_lock_irqsave(&rds_sock_lock, flags);
+ spin_lock_bh(&rds_sock_lock);
if (len < rds_sock_count)
goto out;
@@ -529,7 +525,7 @@ out:
lens->nr = rds_sock_count;
lens->each = sizeof(struct rds_info_socket);
- spin_unlock_irqrestore(&rds_sock_lock, flags);
+ spin_unlock_bh(&rds_sock_lock);
}
static void rds_exit(void)
diff --git a/net/rds/send.c b/net/rds/send.c
index d58ae5f9339e..c803341f2844 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -932,7 +932,6 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
/* Mirror Linux UDP mirror of BSD error message compatibility */
/* XXX: Perhaps MSG_MORE someday */
if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_CMSG_COMPAT)) {
- printk(KERN_INFO "msg_flags 0x%08X\n", msg->msg_flags);
ret = -EOPNOTSUPP;
goto out;
}
diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c
index 178ff4f73c85..2679507ad333 100644
--- a/net/rose/rose_dev.c
+++ b/net/rose/rose_dev.c
@@ -96,11 +96,11 @@ static int rose_set_mac_address(struct net_device *dev, void *addr)
struct sockaddr *sa = addr;
int err;
- if (!memcpy(dev->dev_addr, sa->sa_data, dev->addr_len))
+ if (!memcmp(dev->dev_addr, sa->sa_data, dev->addr_len))
return 0;
if (dev->flags & IFF_UP) {
- err = rose_add_loopback_node((rose_address *)dev->dev_addr);
+ err = rose_add_loopback_node((rose_address *)sa->sa_data);
if (err)
return err;
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c
index 06afbaeb4c88..178ee83175a4 100644
--- a/net/sched/sch_choke.c
+++ b/net/sched/sch_choke.c
@@ -225,8 +225,7 @@ struct choke_skb_cb {
static inline struct choke_skb_cb *choke_skb_cb(const struct sk_buff *skb)
{
- BUILD_BUG_ON(sizeof(skb->cb) <
- sizeof(struct qdisc_skb_cb) + sizeof(struct choke_skb_cb));
+ qdisc_cb_private_validate(skb, sizeof(struct choke_skb_cb));
return (struct choke_skb_cb *)qdisc_skb_cb(skb)->data;
}
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index b9493a09a870..e1afe0c205fa 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -385,7 +385,7 @@ static inline int gred_change_vq(struct Qdisc *sch, int dp,
struct gred_sched_data *q;
if (table->tab[dp] == NULL) {
- table->tab[dp] = kzalloc(sizeof(*q), GFP_KERNEL);
+ table->tab[dp] = kzalloc(sizeof(*q), GFP_ATOMIC);
if (table->tab[dp] == NULL)
return -ENOMEM;
}
@@ -544,11 +544,8 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
opt.packets = q->packetsin;
opt.bytesin = q->bytesin;
- if (gred_wred_mode(table)) {
- q->parms.qidlestart =
- table->tab[table->def]->parms.qidlestart;
- q->parms.qavg = table->tab[table->def]->parms.qavg;
- }
+ if (gred_wred_mode(table))
+ gred_load_wred_set(table, q);
opt.qave = red_calc_qavg(&q->parms, q->parms.qavg);
diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c
index ea17cbed29ef..59b26b8ff4b0 100644
--- a/net/sched/sch_mqprio.c
+++ b/net/sched/sch_mqprio.c
@@ -106,7 +106,7 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt)
if (!netif_is_multiqueue(dev))
return -EOPNOTSUPP;
- if (nla_len(opt) < sizeof(*qopt))
+ if (!opt || nla_len(opt) < sizeof(*qopt))
return -EINVAL;
qopt = nla_data(opt);
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index eb3b9a86c6ed..f0913ffc18d6 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -118,8 +118,7 @@ struct netem_skb_cb {
static inline struct netem_skb_cb *netem_skb_cb(struct sk_buff *skb)
{
- BUILD_BUG_ON(sizeof(skb->cb) <
- sizeof(struct qdisc_skb_cb) + sizeof(struct netem_skb_cb));
+ qdisc_cb_private_validate(skb, sizeof(struct netem_skb_cb));
return (struct netem_skb_cb *)qdisc_skb_cb(skb)->data;
}
@@ -352,10 +351,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
if (q->corrupt && q->corrupt >= get_crandom(&q->corrupt_cor)) {
if (!(skb = skb_unshare(skb, GFP_ATOMIC)) ||
(skb->ip_summed == CHECKSUM_PARTIAL &&
- skb_checksum_help(skb))) {
- sch->qstats.drops++;
- return NET_XMIT_DROP;
- }
+ skb_checksum_help(skb)))
+ return qdisc_drop(skb, sch);
skb->data[net_random() % skb_headlen(skb)] ^= 1<<(net_random() % 8);
}
@@ -383,8 +380,8 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
q->counter = 0;
__skb_queue_head(&q->qdisc->q, skb);
- q->qdisc->qstats.backlog += qdisc_pkt_len(skb);
- q->qdisc->qstats.requeues++;
+ sch->qstats.backlog += qdisc_pkt_len(skb);
+ sch->qstats.requeues++;
ret = NET_XMIT_SUCCESS;
}
diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
index 0a833d0c1f61..47ee29fad350 100644
--- a/net/sched/sch_sfb.c
+++ b/net/sched/sch_sfb.c
@@ -93,8 +93,7 @@ struct sfb_skb_cb {
static inline struct sfb_skb_cb *sfb_skb_cb(const struct sk_buff *skb)
{
- BUILD_BUG_ON(sizeof(skb->cb) <
- sizeof(struct qdisc_skb_cb) + sizeof(struct sfb_skb_cb));
+ qdisc_cb_private_validate(skb, sizeof(struct sfb_skb_cb));
return (struct sfb_skb_cb *)qdisc_skb_cb(skb)->data;
}
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c
index 45cd30098e34..4f4c52c0eeb3 100644
--- a/net/sched/sch_teql.c
+++ b/net/sched/sch_teql.c
@@ -225,11 +225,11 @@ static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt)
static int
-__teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *dev)
+__teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res,
+ struct net_device *dev, struct netdev_queue *txq,
+ struct neighbour *mn)
{
- struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, 0);
- struct teql_sched_data *q = qdisc_priv(dev_queue->qdisc);
- struct neighbour *mn = skb_dst(skb)->neighbour;
+ struct teql_sched_data *q = qdisc_priv(txq->qdisc);
struct neighbour *n = q->ncache;
if (mn->tbl == NULL)
@@ -262,17 +262,26 @@ __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *
}
static inline int teql_resolve(struct sk_buff *skb,
- struct sk_buff *skb_res, struct net_device *dev)
+ struct sk_buff *skb_res,
+ struct net_device *dev,
+ struct netdev_queue *txq)
{
- struct netdev_queue *txq = netdev_get_tx_queue(dev, 0);
+ struct dst_entry *dst = skb_dst(skb);
+ struct neighbour *mn;
+ int res;
+
if (txq->qdisc == &noop_qdisc)
return -ENODEV;
- if (dev->header_ops == NULL ||
- skb_dst(skb) == NULL ||
- skb_dst(skb)->neighbour == NULL)
+ if (!dev->header_ops || !dst)
return 0;
- return __teql_resolve(skb, skb_res, dev);
+
+ rcu_read_lock();
+ mn = dst_get_neighbour(dst);
+ res = mn ? __teql_resolve(skb, skb_res, dev, txq, mn) : 0;
+ rcu_read_unlock();
+
+ return res;
}
static netdev_tx_t teql_master_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -307,7 +316,7 @@ restart:
continue;
}
- switch (teql_resolve(skb, skb_res, slave)) {
+ switch (teql_resolve(skb, skb_res, slave, slave_txq)) {
case 0:
if (__netif_tx_trylock(slave_txq)) {
unsigned int length = qdisc_pkt_len(skb);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 4a62888f2e43..17a6e658a4ca 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -173,7 +173,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0;
asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay;
asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
- (unsigned long)sp->autoclose * HZ;
+ min_t(unsigned long, sp->autoclose, sctp_max_autoclose) * HZ;
/* Initializes the timers */
for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i)
diff --git a/net/sctp/output.c b/net/sctp/output.c
index 08b3cead6503..8fc4dcd294ab 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -377,9 +377,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
*/
skb_set_owner_w(nskb, sk);
- /* The 'obsolete' field of dst is set to 2 when a dst is freed. */
- if (!dst || (dst->obsolete > 1)) {
- dst_release(dst);
+ if (!sctp_transport_dst_check(tp)) {
sctp_transport_route(tp, NULL, sctp_sk(sk));
if (asoc && (asoc->param_flags & SPP_PMTUD_ENABLE)) {
sctp_assoc_sync_pmtu(asoc);
@@ -697,13 +695,7 @@ static void sctp_packet_append_data(struct sctp_packet *packet,
/* Keep track of how many bytes are in flight to the receiver. */
asoc->outqueue.outstanding_bytes += datasize;
- /* Update our view of the receiver's rwnd. Include sk_buff overhead
- * while updating peer.rwnd so that it reduces the chances of a
- * receiver running out of receive buffer space even when receive
- * window is still open. This can happen when a sender is sending
- * sending small messages.
- */
- datasize += sizeof(struct sk_buff);
+ /* Update our view of the receiver's rwnd. */
if (datasize < rwnd)
rwnd -= datasize;
else
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index d03682109b7a..1f2938fbf9b7 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -411,8 +411,7 @@ void sctp_retransmit_mark(struct sctp_outq *q,
chunk->transport->flight_size -=
sctp_data_size(chunk);
q->outstanding_bytes -= sctp_data_size(chunk);
- q->asoc->peer.rwnd += (sctp_data_size(chunk) +
- sizeof(struct sk_buff));
+ q->asoc->peer.rwnd += sctp_data_size(chunk);
}
continue;
}
@@ -432,8 +431,7 @@ void sctp_retransmit_mark(struct sctp_outq *q,
* (Section 7.2.4)), add the data size of those
* chunks to the rwnd.
*/
- q->asoc->peer.rwnd += (sctp_data_size(chunk) +
- sizeof(struct sk_buff));
+ q->asoc->peer.rwnd += sctp_data_size(chunk);
q->outstanding_bytes -= sctp_data_size(chunk);
if (chunk->transport)
transport->flight_size -= sctp_data_size(chunk);
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 207175b2f40a..946afd6045c3 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -1144,6 +1144,9 @@ SCTP_STATIC __init int sctp_init(void)
sctp_max_instreams = SCTP_DEFAULT_INSTREAMS;
sctp_max_outstreams = SCTP_DEFAULT_OUTSTREAMS;
+ /* Initialize maximum autoclose timeout. */
+ sctp_max_autoclose = INT_MAX / HZ;
+
/* Initialize handle used for association ids. */
idr_init(&sctp_assocs_id);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index d3ccf7973c59..4434853a9fe7 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2129,8 +2129,6 @@ static int sctp_setsockopt_autoclose(struct sock *sk, char __user *optval,
return -EINVAL;
if (copy_from_user(&sp->autoclose, optval, optlen))
return -EFAULT;
- /* make sure it won't exceed MAX_SCHEDULE_TIMEOUT */
- sp->autoclose = min_t(long, sp->autoclose, MAX_SCHEDULE_TIMEOUT / HZ);
return 0;
}
@@ -4011,9 +4009,10 @@ static int sctp_getsockopt_disable_fragments(struct sock *sk, int len,
static int sctp_getsockopt_events(struct sock *sk, int len, char __user *optval,
int __user *optlen)
{
- if (len < sizeof(struct sctp_event_subscribe))
+ if (len <= 0)
return -EINVAL;
- len = sizeof(struct sctp_event_subscribe);
+ if (len > sizeof(struct sctp_event_subscribe))
+ len = sizeof(struct sctp_event_subscribe);
if (put_user(len, optlen))
return -EFAULT;
if (copy_to_user(optval, &sctp_sk(sk)->subscribe, len))
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 50cb57f0919e..6752f489febf 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -53,6 +53,10 @@ static int sack_timer_min = 1;
static int sack_timer_max = 500;
static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */
static int rwnd_scale_max = 16;
+static unsigned long max_autoclose_min = 0;
+static unsigned long max_autoclose_max =
+ (MAX_SCHEDULE_TIMEOUT / HZ > UINT_MAX)
+ ? UINT_MAX : MAX_SCHEDULE_TIMEOUT / HZ;
extern long sysctl_sctp_mem[3];
extern int sysctl_sctp_rmem[3];
@@ -251,6 +255,15 @@ static ctl_table sctp_table[] = {
.extra1 = &one,
.extra2 = &rwnd_scale_max,
},
+ {
+ .procname = "max_autoclose",
+ .data = &sctp_max_autoclose,
+ .maxlen = sizeof(unsigned long),
+ .mode = 0644,
+ .proc_handler = &proc_doulongvec_minmax,
+ .extra1 = &max_autoclose_min,
+ .extra2 = &max_autoclose_max,
+ },
{ /* sentinel */ }
};
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 394c57ca2f54..8da4481ed30a 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -226,23 +226,6 @@ void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk)
transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT;
}
-/* this is a complete rip-off from __sk_dst_check
- * the cookie is always 0 since this is how it's used in the
- * pmtu code
- */
-static struct dst_entry *sctp_transport_dst_check(struct sctp_transport *t)
-{
- struct dst_entry *dst = t->dst;
-
- if (dst && dst->obsolete && dst->ops->check(dst, 0) == NULL) {
- dst_release(t->dst);
- t->dst = NULL;
- return NULL;
- }
-
- return dst;
-}
-
void sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu)
{
struct dst_entry *dst;
diff --git a/net/socket.c b/net/socket.c
index 1ad42d3604e4..cf41afcc89bb 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -791,9 +791,9 @@ static ssize_t sock_sendpage(struct file *file, struct page *page,
sock = file->private_data;
- flags = !(file->f_flags & O_NONBLOCK) ? 0 : MSG_DONTWAIT;
- if (more)
- flags |= MSG_MORE;
+ flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;
+ /* more is a combination of MSG_MORE and MSG_SENDPAGE_NOTLAST */
+ flags |= more;
return kernel_sendpage(sock, page, offset, size, flags);
}
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 72ad836e4fe0..4530a912b8b0 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -828,6 +828,8 @@ static ssize_t cache_do_downcall(char *kaddr, const char __user *buf,
{
ssize_t ret;
+ if (count == 0)
+ return -EINVAL;
if (copy_from_user(kaddr, buf, count))
return -EFAULT;
kaddr[count] = '\0';
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 4814e246a874..b6bb22571c57 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -480,14 +480,18 @@ EXPORT_SYMBOL_GPL(rpc_wake_up_next);
*/
void rpc_wake_up(struct rpc_wait_queue *queue)
{
- struct rpc_task *task, *next;
struct list_head *head;
spin_lock_bh(&queue->lock);
head = &queue->tasks[queue->maxpriority];
for (;;) {
- list_for_each_entry_safe(task, next, head, u.tk_wait.list)
+ while (!list_empty(head)) {
+ struct rpc_task *task;
+ task = list_first_entry(head,
+ struct rpc_task,
+ u.tk_wait.list);
rpc_wake_up_task_queue_locked(queue, task);
+ }
if (head == &queue->tasks[0])
break;
head--;
@@ -505,13 +509,16 @@ EXPORT_SYMBOL_GPL(rpc_wake_up);
*/
void rpc_wake_up_status(struct rpc_wait_queue *queue, int status)
{
- struct rpc_task *task, *next;
struct list_head *head;
spin_lock_bh(&queue->lock);
head = &queue->tasks[queue->maxpriority];
for (;;) {
- list_for_each_entry_safe(task, next, head, u.tk_wait.list) {
+ while (!list_empty(head)) {
+ struct rpc_task *task;
+ task = list_first_entry(head,
+ struct rpc_task,
+ u.tk_wait.list);
task->tk_status = status;
rpc_wake_up_task_queue_locked(queue, task);
}
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 2b90292e9505..ce5f111fe325 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -167,6 +167,7 @@ svc_pool_map_alloc_arrays(struct svc_pool_map *m, unsigned int maxpools)
fail_free:
kfree(m->to_pool);
+ m->to_pool = NULL;
fail:
return -ENOMEM;
}
@@ -287,7 +288,9 @@ svc_pool_map_put(void)
if (!--m->count) {
m->mode = SVC_POOL_DEFAULT;
kfree(m->to_pool);
+ m->to_pool = NULL;
kfree(m->pool_to);
+ m->pool_to = NULL;
m->npools = 0;
}
@@ -472,17 +475,20 @@ svc_destroy(struct svc_serv *serv)
printk("svc_destroy: no threads for serv=%p!\n", serv);
del_timer_sync(&serv->sv_temptimer);
-
- svc_close_all(&serv->sv_tempsocks);
+ /*
+ * The set of xprts (contained in the sv_tempsocks and
+ * sv_permsocks lists) is now constant, since it is modified
+ * only by accepting new sockets (done by service threads in
+ * svc_recv) or aging old ones (done by sv_temptimer), or
+ * configuration changes (excluded by whatever locking the
+ * caller is using--nfsd_mutex in the case of nfsd). So it's
+ * safe to traverse those lists and shut everything down:
+ */
+ svc_close_all(serv);
if (serv->sv_shutdown)
serv->sv_shutdown(serv);
- svc_close_all(&serv->sv_permsocks);
-
- BUG_ON(!list_empty(&serv->sv_permsocks));
- BUG_ON(!list_empty(&serv->sv_tempsocks));
-
cache_clean_deferred(serv);
if (svc_serv_is_pooled(serv))
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index bd31208bbb61..9d7ed0b48b51 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -901,14 +901,7 @@ void svc_delete_xprt(struct svc_xprt *xprt)
spin_lock_bh(&serv->sv_lock);
if (!test_and_set_bit(XPT_DETACHED, &xprt->xpt_flags))
list_del_init(&xprt->xpt_list);
- /*
- * The only time we're called while xpt_ready is still on a list
- * is while the list itself is about to be destroyed (in
- * svc_destroy). BUT svc_xprt_enqueue could still be attempting
- * to add new entries to the sp_sockets list, so we can't leave
- * a freed xprt on it.
- */
- list_del_init(&xprt->xpt_ready);
+ BUG_ON(!list_empty(&xprt->xpt_ready));
if (test_bit(XPT_TEMP, &xprt->xpt_flags))
serv->sv_tmpcnt--;
spin_unlock_bh(&serv->sv_lock);
@@ -936,22 +929,48 @@ void svc_close_xprt(struct svc_xprt *xprt)
}
EXPORT_SYMBOL_GPL(svc_close_xprt);
-void svc_close_all(struct list_head *xprt_list)
+static void svc_close_list(struct list_head *xprt_list)
+{
+ struct svc_xprt *xprt;
+
+ list_for_each_entry(xprt, xprt_list, xpt_list) {
+ set_bit(XPT_CLOSE, &xprt->xpt_flags);
+ set_bit(XPT_BUSY, &xprt->xpt_flags);
+ }
+}
+
+void svc_close_all(struct svc_serv *serv)
{
+ struct svc_pool *pool;
struct svc_xprt *xprt;
struct svc_xprt *tmp;
+ int i;
+
+ svc_close_list(&serv->sv_tempsocks);
+ svc_close_list(&serv->sv_permsocks);
+ for (i = 0; i < serv->sv_nrpools; i++) {
+ pool = &serv->sv_pools[i];
+
+ spin_lock_bh(&pool->sp_lock);
+ while (!list_empty(&pool->sp_sockets)) {
+ xprt = list_first_entry(&pool->sp_sockets, struct svc_xprt, xpt_ready);
+ list_del_init(&xprt->xpt_ready);
+ }
+ spin_unlock_bh(&pool->sp_lock);
+ }
/*
- * The server is shutting down, and no more threads are running.
- * svc_xprt_enqueue() might still be running, but at worst it
- * will re-add the xprt to sp_sockets, which will soon get
- * freed. So we don't bother with any more locking, and don't
- * leave the close to the (nonexistent) server threads:
+ * At this point the sp_sockets lists will stay empty, since
+ * svc_enqueue will not add new entries without taking the
+ * sp_lock and checking XPT_BUSY.
*/
- list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) {
- set_bit(XPT_CLOSE, &xprt->xpt_flags);
+ list_for_each_entry_safe(xprt, tmp, &serv->sv_tempsocks, xpt_list)
svc_delete_xprt(xprt);
- }
+ list_for_each_entry_safe(xprt, tmp, &serv->sv_permsocks, xpt_list)
+ svc_delete_xprt(xprt);
+
+ BUG_ON(!list_empty(&serv->sv_permsocks));
+ BUG_ON(!list_empty(&serv->sv_tempsocks));
}
/*
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 924e4f4d6aa6..4e84e222a490 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1202,6 +1202,11 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
goto bad_res;
}
+ if (!netif_running(netdev)) {
+ result = -ENETDOWN;
+ goto bad_res;
+ }
+
nla_for_each_nested(nl_txq_params,
info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
rem_txq_params) {
@@ -5506,7 +5511,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_get_key,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -5538,7 +5543,7 @@ static struct genl_ops nl80211_ops[] = {
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
.doit = nl80211_addset_beacon,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -5546,7 +5551,7 @@ static struct genl_ops nl80211_ops[] = {
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
.doit = nl80211_addset_beacon,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -5570,7 +5575,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_set_station,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -5586,7 +5591,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_del_station,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -5619,7 +5624,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_del_mpath,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -5627,7 +5632,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_set_bss,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -5653,7 +5658,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_get_mesh_config,
.policy = nl80211_policy,
/* can be retrieved by unprivileged users */
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -5785,7 +5790,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_setdel_pmksa,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -5793,7 +5798,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_setdel_pmksa,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -5801,7 +5806,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_flush_pmksa,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -5889,7 +5894,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_set_wds_peer,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV |
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
{
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 72f7feee254a..9bcb6bc2ce0c 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -379,7 +379,15 @@ static void reg_regdb_query(const char *alpha2)
schedule_work(&reg_regdb_work);
}
+
+/* Feel free to add any other sanity checks here */
+static void reg_regdb_size_check(void)
+{
+ /* We should ideally BUILD_BUG_ON() but then random builds would fail */
+ WARN_ONCE(!reg_regdb_size, "db.txt is empty, you should update it...");
+}
#else
+static inline void reg_regdb_size_check(void) {}
static inline void reg_regdb_query(const char *alpha2) {}
#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
@@ -2228,6 +2236,8 @@ int __init regulatory_init(void)
spin_lock_init(&reg_requests_lock);
spin_lock_init(&reg_pending_beacons_lock);
+ reg_regdb_size_check();
+
cfg80211_regdomain = cfg80211_world_regdom;
user_alpha2[0] = '9';
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 4d7b83fbc32f..30f68dc76ac0 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -937,6 +937,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
enum nl80211_iftype iftype)
{
struct wireless_dev *wdev_iter;
+ u32 used_iftypes = BIT(iftype);
int num[NUM_NL80211_IFTYPES];
int total = 1;
int i, j;
@@ -970,12 +971,14 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
num[wdev_iter->iftype]++;
total++;
+ used_iftypes |= BIT(wdev_iter->iftype);
}
mutex_unlock(&rdev->devlist_mtx);
for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) {
const struct ieee80211_iface_combination *c;
struct ieee80211_iface_limit *limits;
+ u32 all_iftypes = 0;
c = &rdev->wiphy.iface_combinations[i];
@@ -990,14 +993,28 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
if (rdev->wiphy.software_iftypes & BIT(iftype))
continue;
for (j = 0; j < c->n_limits; j++) {
- if (!(limits[j].types & iftype))
+ all_iftypes |= limits[j].types;
+ if (!(limits[j].types & BIT(iftype)))
continue;
if (limits[j].max < num[iftype])
goto cont;
limits[j].max -= num[iftype];
}
}
- /* yay, it fits */
+
+ /*
+ * Finally check that all iftypes that we're currently
+ * using are actually part of this combination. If they
+ * aren't then we can't use this combination and have
+ * to continue to the next.
+ */
+ if ((all_iftypes & used_iftypes) != used_iftypes)
+ goto cont;
+
+ /*
+ * This combination covered all interface types and
+ * supported the requested numbers, so we're good.
+ */
kfree(limits);
return 0;
cont:
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 5ce74a385525..0c0e40e9cfc1 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1497,7 +1497,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
goto free_dst;
/* Copy neighbour for reachability confirmation */
- dst0->neighbour = neigh_clone(dst->neighbour);
+ dst_set_neighbour(dst0, neigh_clone(dst_get_neighbour(dst)));
xfrm_init_path((struct xfrm_dst *)dst0, dst, nfheader_len);
xfrm_init_pmtu(dst_prev);
@@ -1917,6 +1917,9 @@ no_transform:
}
ok:
xfrm_pols_put(pols, drop_pols);
+ if (dst && dst->xfrm &&
+ dst->xfrm->props.mode == XFRM_MODE_TUNNEL)
+ dst->flags |= DST_XFRM_TUNNEL;
return dst;
nopol:
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c
index b11ea692bd7d..3235023eaf4e 100644
--- a/net/xfrm/xfrm_replay.c
+++ b/net/xfrm/xfrm_replay.c
@@ -166,7 +166,7 @@ static void xfrm_replay_advance(struct xfrm_state *x, __be32 net_seq)
}
if (xfrm_aevent_is_on(xs_net(x)))
- xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
+ x->repl->notify(x, XFRM_REPLAY_UPDATE);
}
static int xfrm_replay_overflow_bmp(struct xfrm_state *x, struct sk_buff *skb)
@@ -293,7 +293,7 @@ static void xfrm_replay_advance_bmp(struct xfrm_state *x, __be32 net_seq)
}
if (xfrm_aevent_is_on(xs_net(x)))
- xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
+ x->repl->notify(x, XFRM_REPLAY_UPDATE);
}
static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event)
@@ -502,7 +502,7 @@ static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)
}
if (xfrm_aevent_is_on(xs_net(x)))
- xfrm_replay_notify(x, XFRM_REPLAY_UPDATE);
+ x->repl->notify(x, XFRM_REPLAY_UPDATE);
}
static struct xfrm_replay xfrm_replay_legacy = {
diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
index a4fe923c0131..25f1e71c9bb5 100644
--- a/scripts/kconfig/streamline_config.pl
+++ b/scripts/kconfig/streamline_config.pl
@@ -242,33 +242,61 @@ if ($kconfig) {
read_kconfig($kconfig);
}
+sub convert_vars {
+ my ($line, %vars) = @_;
+
+ my $process = "";
+
+ while ($line =~ s/^(.*?)(\$\((.*?)\))//) {
+ my $start = $1;
+ my $variable = $2;
+ my $var = $3;
+
+ if (defined($vars{$var})) {
+ $process .= $start . $vars{$var};
+ } else {
+ $process .= $start . $variable;
+ }
+ }
+
+ $process .= $line;
+
+ return $process;
+}
+
# Read all Makefiles to map the configs to the objects
foreach my $makefile (@makefiles) {
- my $cont = 0;
+ my $line = "";
+ my %make_vars;
open(MIN,$makefile) || die "Can't open $makefile";
while (<MIN>) {
+ # if this line ends with a backslash, continue
+ chomp;
+ if (/^(.*)\\$/) {
+ $line .= $1;
+ next;
+ }
+
+ $line .= $_;
+ $_ = $line;
+ $line = "";
+
my $objs;
- # is this a line after a line with a backslash?
- if ($cont && /(\S.*)$/) {
- $objs = $1;
- }
- $cont = 0;
+ $_ = convert_vars($_, %make_vars);
# collect objects after obj-$(CONFIG_FOO_BAR)
if (/obj-\$\((CONFIG_[^\)]*)\)\s*[+:]?=\s*(.*)/) {
$var = $1;
$objs = $2;
+
+ # check if variables are set
+ } elsif (/^\s*(\S+)\s*[:]?=\s*(.*\S)/) {
+ $make_vars{$1} = $2;
}
if (defined($objs)) {
- # test if the line ends with a backslash
- if ($objs =~ m,(.*)\\$,) {
- $objs = $1;
- $cont = 1;
- }
-
foreach my $obj (split /\s+/,$objs) {
$obj =~ s/-/_/g;
if ($obj =~ /(.*)\.o$/) {
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index e26e2fb462d4..f210eae9bd7e 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -905,6 +905,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections)
return;
+ /* We're looking for an object */
+ if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
+ return;
+
/* Handle all-NULL symbols allocated into .bss */
if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) {
zeros = calloc(1, sym->st_size);
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 413c53693e62..e3cd34525894 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -132,8 +132,10 @@ static struct module *new_module(char *modname)
/* strip trailing .o */
s = strrchr(p, '.');
if (s != NULL)
- if (strcmp(s, ".o") == 0)
+ if (strcmp(s, ".o") == 0) {
*s = '\0';
+ mod->is_dot_o = 1;
+ }
/* add to list */
mod->name = p;
@@ -254,6 +256,28 @@ static enum export export_no(const char *s)
return export_unknown;
}
+static const char *sec_name(struct elf_info *elf, int secindex);
+
+#define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0)
+
+static enum export export_from_secname(struct elf_info *elf, unsigned int sec)
+{
+ const char *secname = sec_name(elf, sec);
+
+ if (strstarts(secname, "___ksymtab+"))
+ return export_plain;
+ else if (strstarts(secname, "___ksymtab_unused+"))
+ return export_unused;
+ else if (strstarts(secname, "___ksymtab_gpl+"))
+ return export_gpl;
+ else if (strstarts(secname, "___ksymtab_unused_gpl+"))
+ return export_unused_gpl;
+ else if (strstarts(secname, "___ksymtab_gpl_future+"))
+ return export_gpl_future;
+ else
+ return export_unknown;
+}
+
static enum export export_from_sec(struct elf_info *elf, unsigned int sec)
{
if (sec == elf->export_sec)
@@ -563,7 +587,13 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
Elf_Sym *sym, const char *symname)
{
unsigned int crc;
- enum export export = export_from_sec(info, get_secindex(info, sym));
+ enum export export;
+
+ if ((!is_vmlinux(mod->name) || mod->is_dot_o) &&
+ strncmp(symname, "__ksymtab", 9) == 0)
+ export = export_from_secname(info, get_secindex(info, sym));
+ else
+ export = export_from_sec(info, get_secindex(info, sym));
switch (sym->st_shndx) {
case SHN_COMMON:
@@ -822,7 +852,7 @@ static void check_section(const char *modname, struct elf_info *elf,
#define ALL_INIT_DATA_SECTIONS \
".init.setup$", ".init.rodata$", \
- ".devinit.rodata$", ".cpuinit.rodata$", ".meminit.rodata$" \
+ ".devinit.rodata$", ".cpuinit.rodata$", ".meminit.rodata$", \
".init.data$", ".devinit.data$", ".cpuinit.data$", ".meminit.data$"
#define ALL_EXIT_DATA_SECTIONS \
".exit.data$", ".devexit.data$", ".cpuexit.data$", ".memexit.data$"
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index 2031119080dc..51207e4d5f8b 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -113,6 +113,7 @@ struct module {
int has_cleanup;
struct buffer dev_table_buf;
char srcversion[25];
+ int is_dot_o;
};
struct elf_info {
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index f6cbc3ddb68b..3c6c0b14c807 100644
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -238,14 +238,14 @@ EOF
fi
# Build header package
-(cd $srctree; find . -name Makefile -o -name Kconfig\* -o -name \*.pl > /tmp/files$$)
-(cd $srctree; find arch/$SRCARCH/include include scripts -type f >> /tmp/files$$)
-(cd $objtree; find .config Module.symvers include scripts -type f >> /tmp/objfiles$$)
+(cd $srctree; find . -name Makefile -o -name Kconfig\* -o -name \*.pl > "$objtree/debian/hdrsrcfiles")
+(cd $srctree; find arch/$SRCARCH/include include scripts -type f >> "$objtree/debian/hdrsrcfiles")
+(cd $objtree; find .config Module.symvers include scripts -type f >> "$objtree/debian/hdrobjfiles")
destdir=$kernel_headers_dir/usr/src/linux-headers-$version
mkdir -p "$destdir"
-(cd $srctree; tar -c -f - -T /tmp/files$$) | (cd $destdir; tar -xf -)
-(cd $objtree; tar -c -f - -T /tmp/objfiles$$) | (cd $destdir; tar -xf -)
-rm -f /tmp/files$$ /tmp/objfiles$$
+(cd $srctree; tar -c -f - -T "$objtree/debian/hdrsrcfiles") | (cd $destdir; tar -xf -)
+(cd $objtree; tar -c -f - -T "$objtree/debian/hdrobjfiles") | (cd $destdir; tar -xf -)
+rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles"
arch=$(dpkg --print-architecture)
cat <<EOF >> debian/control
diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h
index f40a6af6bf40..54e35c1e5948 100644
--- a/scripts/recordmcount.h
+++ b/scripts/recordmcount.h
@@ -462,7 +462,7 @@ __has_rel_mcount(Elf_Shdr const *const relhdr, /* is SHT_REL or SHT_RELA */
succeed_file();
}
if (w(txthdr->sh_type) != SHT_PROGBITS ||
- !(w(txthdr->sh_flags) & SHF_EXECINSTR))
+ !(_w(txthdr->sh_flags) & SHF_EXECINSTR))
return NULL;
return txtname;
}
diff --git a/security/commoncap.c b/security/commoncap.c
index 1322b6aa648d..ccfe568b396f 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -28,6 +28,7 @@
#include <linux/prctl.h>
#include <linux/securebits.h>
#include <linux/user_namespace.h>
+#include <linux/personality.h>
#ifdef CONFIG_ANDROID_PARANOID_NETWORK
#include <linux/android_aid.h>
@@ -519,6 +520,11 @@ int cap_bprm_set_creds(struct linux_binprm *bprm)
}
skip:
+ /* if we have fs caps, clear dangerous personality flags */
+ if (!cap_issubset(new->cap_permitted, old->cap_permitted))
+ bprm->per_clear |= PER_CLEAR_ON_SETID;
+
+
/* Don't let someone trace a set[ug]id/setpcap binary with the revised
* credentials unless they have the appropriate permit
*/
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index da36d2c085a4..5335605571fe 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -177,8 +177,8 @@ void ima_store_measurement(struct ima_iint_cache *iint, struct file *file,
strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX);
result = ima_store_template(entry, violation, inode);
- if (!result)
+ if (!result || result == -EEXIST)
iint->flags |= IMA_MEASURED;
- else
+ if (result < 0)
kfree(entry);
}
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c
index 8e28f04a5e2e..55a6271bce7a 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -23,6 +23,8 @@
#include <linux/slab.h>
#include "ima.h"
+#define AUDIT_CAUSE_LEN_MAX 32
+
LIST_HEAD(ima_measurements); /* list of all measurements */
/* key: inode (before secure-hashing a file) */
@@ -94,7 +96,8 @@ static int ima_pcr_extend(const u8 *hash)
result = tpm_pcr_extend(TPM_ANY_NUM, CONFIG_IMA_MEASURE_PCR_IDX, hash);
if (result != 0)
- pr_err("IMA: Error Communicating to TPM chip\n");
+ pr_err("IMA: Error Communicating to TPM chip, result: %d\n",
+ result);
return result;
}
@@ -106,14 +109,16 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
{
u8 digest[IMA_DIGEST_SIZE];
const char *audit_cause = "hash_added";
+ char tpm_audit_cause[AUDIT_CAUSE_LEN_MAX];
int audit_info = 1;
- int result = 0;
+ int result = 0, tpmresult = 0;
mutex_lock(&ima_extend_list_mutex);
if (!violation) {
memcpy(digest, entry->digest, sizeof digest);
if (ima_lookup_digest_entry(digest)) {
audit_cause = "hash_exists";
+ result = -EEXIST;
goto out;
}
}
@@ -128,9 +133,11 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
if (violation) /* invalidate pcr */
memset(digest, 0xff, sizeof digest);
- result = ima_pcr_extend(digest);
- if (result != 0) {
- audit_cause = "TPM error";
+ tpmresult = ima_pcr_extend(digest);
+ if (tpmresult != 0) {
+ snprintf(tpm_audit_cause, AUDIT_CAUSE_LEN_MAX, "TPM_error(%d)",
+ tpmresult);
+ audit_cause = tpm_audit_cause;
audit_info = 0;
}
out:
diff --git a/security/selinux/netport.c b/security/selinux/netport.c
index cfe2d72d3fb7..e2b74ebdc383 100644
--- a/security/selinux/netport.c
+++ b/security/selinux/netport.c
@@ -139,7 +139,9 @@ static void sel_netport_insert(struct sel_netport *port)
if (sel_netport_hash[idx].size == SEL_NETPORT_HASH_BKT_LIMIT) {
struct sel_netport *tail;
tail = list_entry(
- rcu_dereference(sel_netport_hash[idx].list.prev),
+ rcu_dereference_protected(
+ sel_netport_hash[idx].list.prev,
+ lockdep_is_held(&sel_netport_lock)),
struct sel_netport, list);
list_del_rcu(&tail->list);
call_rcu(&tail->rcu, sel_netport_free);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 35459340019e..27a96732b872 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -1241,6 +1241,7 @@ static int sel_make_bools(void)
kfree(bool_pending_names[i]);
kfree(bool_pending_names);
kfree(bool_pending_values);
+ bool_num = 0;
bool_pending_names = NULL;
bool_pending_values = NULL;
diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c
index 9fc2e15841c9..892494ac58e2 100644
--- a/security/tomoyo/mount.c
+++ b/security/tomoyo/mount.c
@@ -205,30 +205,32 @@ int tomoyo_mount_permission(char *dev_name, struct path *path, char *type,
if (flags & MS_REMOUNT) {
type = TOMOYO_MOUNT_REMOUNT_KEYWORD;
flags &= ~MS_REMOUNT;
- }
- if (flags & MS_MOVE) {
- type = TOMOYO_MOUNT_MOVE_KEYWORD;
- flags &= ~MS_MOVE;
- }
- if (flags & MS_BIND) {
+ } else if (flags & MS_BIND) {
type = TOMOYO_MOUNT_BIND_KEYWORD;
flags &= ~MS_BIND;
- }
- if (flags & MS_UNBINDABLE) {
- type = TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD;
- flags &= ~MS_UNBINDABLE;
- }
- if (flags & MS_PRIVATE) {
+ } else if (flags & MS_SHARED) {
+ if (flags & (MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
+ return -EINVAL;
+ type = TOMOYO_MOUNT_MAKE_SHARED_KEYWORD;
+ flags &= ~MS_SHARED;
+ } else if (flags & MS_PRIVATE) {
+ if (flags & (MS_SHARED | MS_SLAVE | MS_UNBINDABLE))
+ return -EINVAL;
type = TOMOYO_MOUNT_MAKE_PRIVATE_KEYWORD;
flags &= ~MS_PRIVATE;
- }
- if (flags & MS_SLAVE) {
+ } else if (flags & MS_SLAVE) {
+ if (flags & (MS_SHARED | MS_PRIVATE | MS_UNBINDABLE))
+ return -EINVAL;
type = TOMOYO_MOUNT_MAKE_SLAVE_KEYWORD;
flags &= ~MS_SLAVE;
- }
- if (flags & MS_SHARED) {
- type = TOMOYO_MOUNT_MAKE_SHARED_KEYWORD;
- flags &= ~MS_SHARED;
+ } else if (flags & MS_UNBINDABLE) {
+ if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE))
+ return -EINVAL;
+ type = TOMOYO_MOUNT_MAKE_UNBINDABLE_KEYWORD;
+ flags &= ~MS_UNBINDABLE;
+ } else if (flags & MS_MOVE) {
+ type = TOMOYO_MOUNT_MOVE_KEYWORD;
+ flags &= ~MS_MOVE;
}
if (!type)
type = "<NULL>";
diff --git a/sound/pci/echoaudio/echoaudio_dsp.c b/sound/pci/echoaudio/echoaudio_dsp.c
index 64417a733220..d8c670c9d62c 100644
--- a/sound/pci/echoaudio/echoaudio_dsp.c
+++ b/sound/pci/echoaudio/echoaudio_dsp.c
@@ -475,7 +475,7 @@ static int load_firmware(struct echoaudio *chip)
const struct firmware *fw;
int box_type, err;
- if (snd_BUG_ON(!chip->dsp_code_to_load || !chip->comm_page))
+ if (snd_BUG_ON(!chip->comm_page))
return -EPERM;
/* See if the ASIC is present and working - only if the DSP is already loaded */
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 21958518467f..39e1a6a3ede8 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1328,7 +1328,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
for (i = 0; i < c->cvt_setups.used; i++) {
p = snd_array_elem(&c->cvt_setups, i);
if (!p->active && p->stream_tag == stream_tag &&
- get_wcaps_type(get_wcaps(codec, p->nid)) == type)
+ get_wcaps_type(get_wcaps(c, p->nid)) == type)
p->dirty = 1;
}
}
@@ -1651,7 +1651,11 @@ static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
parm |= index << AC_AMP_SET_INDEX_SHIFT;
- parm |= val;
+ if ((val & HDA_AMP_MUTE) && !(info->amp_caps & AC_AMPCAP_MUTE) &&
+ (info->amp_caps & AC_AMPCAP_MIN_MUTE))
+ ; /* set the zero value as a fake mute */
+ else
+ parm |= val;
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
info->vol[ch] = val;
}
@@ -1918,7 +1922,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
val1 += ofs;
val1 = ((int)val1) * ((int)val2);
- if (min_mute)
+ if (min_mute || (caps & AC_AMPCAP_MIN_MUTE))
val2 |= TLV_DB_SCALE_MUTE;
if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
return -EFAULT;
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 59c97306c1de..eff1fc54e56c 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -302,6 +302,9 @@ enum {
#define AC_AMPCAP_MUTE (1<<31) /* mute capable */
#define AC_AMPCAP_MUTE_SHIFT 31
+/* driver-specific amp-caps: using bits 24-30 */
+#define AC_AMPCAP_MIN_MUTE (1 << 30) /* min-volume = mute */
+
/* Connection list */
#define AC_CLIST_LENGTH (0x7f<<0)
#define AC_CLIST_LONG (1<<7)
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 981b6fd1ae7c..c5c97880f505 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -702,11 +702,13 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
{
struct azx *chip = bus->private_data;
unsigned long timeout;
+ unsigned long loopcounter;
int do_poll = 0;
again:
timeout = jiffies + msecs_to_jiffies(1000);
- for (;;) {
+
+ for (loopcounter = 0;; loopcounter++) {
if (chip->polling_mode || do_poll) {
spin_lock_irq(&chip->reg_lock);
azx_update_rirb(chip);
@@ -722,7 +724,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
}
if (time_after(jiffies, timeout))
break;
- if (bus->needs_damn_long_delay)
+ if (bus->needs_damn_long_delay || loopcounter > 3000)
msleep(2); /* temporary workaround */
else {
udelay(10);
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 08ec073444e2..e289a13c4889 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -474,7 +474,12 @@ static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid)
}
/* get the widget type from widget capability bits */
-#define get_wcaps_type(wcaps) (((wcaps) & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT)
+static inline int get_wcaps_type(unsigned int wcaps)
+{
+ if (!wcaps)
+ return -1; /* invalid type */
+ return (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+}
static inline unsigned int get_wcaps_channels(u32 wcaps)
{
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index bfe74c2fb079..6fe944a386c2 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -54,6 +54,8 @@ static const char *get_wid_type_name(unsigned int wid_value)
[AC_WID_BEEP] = "Beep Generator Widget",
[AC_WID_VENDOR] = "Vendor Defined Widget",
};
+ if (wid_value == -1)
+ return "UNKNOWN Widget";
wid_value &= 0xf;
if (names[wid_value])
return names[wid_value];
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 3c2381ca3723..4cf3266c9424 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -1917,6 +1917,10 @@ static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid,
snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | event);
+}
+
+static void cxt5051_init_mic_jack(struct hda_codec *codec, hda_nid_t nid)
+{
snd_hda_input_jack_add(codec, nid, SND_JACK_MICROPHONE, NULL);
snd_hda_input_jack_report(codec, nid);
}
@@ -1934,7 +1938,6 @@ static int cxt5051_init(struct hda_codec *codec)
struct conexant_spec *spec = codec->spec;
conexant_init(codec);
- conexant_init_jacks(codec);
if (spec->auto_mic & AUTO_MIC_PORTB)
cxt5051_init_mic_port(codec, 0x17, CXT5051_PORTB_EVENT);
@@ -2067,6 +2070,12 @@ static int patch_cxt5051(struct hda_codec *codec)
if (spec->beep_amp)
snd_hda_attach_beep_device(codec, spec->beep_amp);
+ conexant_init_jacks(codec);
+ if (spec->auto_mic & AUTO_MIC_PORTB)
+ cxt5051_init_mic_jack(codec, 0x17);
+ if (spec->auto_mic & AUTO_MIC_PORTC)
+ cxt5051_init_mic_jack(codec, 0x18);
+
return 0;
}
@@ -3994,9 +4003,14 @@ static void cx_auto_init_output(struct hda_codec *codec)
int i;
mute_outputs(codec, spec->multiout.num_dacs, spec->multiout.dac_nids);
- for (i = 0; i < cfg->hp_outs; i++)
+ for (i = 0; i < cfg->hp_outs; i++) {
+ unsigned int val = PIN_OUT;
+ if (snd_hda_query_pin_caps(codec, cfg->hp_pins[i]) &
+ AC_PINCAP_HP_DRV)
+ val |= AC_PINCTL_HP_EN;
snd_hda_codec_write(codec, cfg->hp_pins[i], 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP);
+ AC_VERB_SET_PIN_WIDGET_CONTROL, val);
+ }
mute_outputs(codec, cfg->hp_outs, cfg->hp_pins);
mute_outputs(codec, cfg->line_outs, cfg->line_out_pins);
mute_outputs(codec, cfg->speaker_outs, cfg->speaker_pins);
@@ -4118,7 +4132,8 @@ static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
err = snd_hda_ctl_add(codec, nid, kctl);
if (err < 0)
return err;
- if (!(query_amp_caps(codec, nid, hda_dir) & AC_AMPCAP_MUTE))
+ if (!(query_amp_caps(codec, nid, hda_dir) &
+ (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)))
break;
}
return 0;
@@ -4363,6 +4378,22 @@ static const struct hda_codec_ops cx_auto_patch_ops = {
.reboot_notify = snd_hda_shutup_pins,
};
+/* add "fake" mute amp-caps to DACs on cx5051 so that mixer mute switches
+ * can be created (bko#42825)
+ */
+static void add_cx5051_fake_mutes(struct hda_codec *codec)
+{
+ static hda_nid_t out_nids[] = {
+ 0x10, 0x11, 0
+ };
+ hda_nid_t *p;
+
+ for (p = out_nids; *p; p++)
+ snd_hda_override_amp_caps(codec, *p, HDA_OUTPUT,
+ AC_AMPCAP_MIN_MUTE |
+ query_amp_caps(codec, *p, HDA_OUTPUT));
+}
+
static int patch_conexant_auto(struct hda_codec *codec)
{
struct conexant_spec *spec;
@@ -4381,6 +4412,9 @@ static int patch_conexant_auto(struct hda_codec *codec)
case 0x14f15045:
spec->single_adc_amp = 1;
break;
+ case 0x14f15051:
+ add_cx5051_fake_mutes(codec);
+ break;
}
err = cx_auto_search_adcs(codec);
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index eb0a141966a0..51412e1296f7 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -16419,6 +16419,7 @@ static const struct alc_config_preset alc861_presets[] = {
/* Pin config fixes */
enum {
PINFIX_FSC_AMILO_PI1505,
+ PINFIX_ASUS_A6RP,
};
static const struct alc_fixup alc861_fixups[] = {
@@ -16430,9 +16431,19 @@ static const struct alc_fixup alc861_fixups[] = {
{ }
}
},
+ [PINFIX_ASUS_A6RP] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ /* node 0x0f VREF seems controlling the master output */
+ { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
+ { }
+ },
+ },
};
static const struct snd_pci_quirk alc861_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", PINFIX_ASUS_A6RP),
+ SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", PINFIX_ASUS_A6RP),
SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
{}
};
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 5d2e97abb2eb..86706821a236 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -1602,7 +1602,7 @@ static const struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02bd,
"Dell Studio 1557", STAC_DELL_M6_DMIC),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02fe,
- "Dell Studio XPS 1645", STAC_DELL_M6_BOTH),
+ "Dell Studio XPS 1645", STAC_DELL_M6_DMIC),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0413,
"Dell Studio 1558", STAC_DELL_M6_DMIC),
{} /* terminator */
@@ -4162,13 +4162,15 @@ static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid,
return 1;
}
-static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
+static int is_nid_out_jack_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
{
int i;
for (i = 0; i < cfg->hp_outs; i++)
if (cfg->hp_pins[i] == nid)
return 1; /* nid is a HP-Out */
-
+ for (i = 0; i < cfg->line_outs; i++)
+ if (cfg->line_out_pins[i] == nid)
+ return 1; /* nid is a line-Out */
return 0; /* nid is not a HP-Out */
};
@@ -4354,7 +4356,7 @@ static int stac92xx_init(struct hda_codec *codec)
continue;
}
- if (is_nid_hp_pin(cfg, nid))
+ if (is_nid_out_jack_pin(cfg, nid))
continue; /* already has an unsol event */
pinctl = snd_hda_codec_read(codec, nid, 0,
@@ -4587,7 +4589,7 @@ static void stac92xx_hp_detect(struct hda_codec *codec)
unsigned int val = AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN;
if (no_hp_sensing(spec, i))
continue;
- if (presence)
+ if (1 /*presence*/)
stac92xx_set_pinctl(codec, cfg->hp_pins[i], val);
#if 0 /* FIXME */
/* Resetting the pinctl like below may lead to (a sort of) regressions
diff --git a/sound/pci/ice1712/amp.c b/sound/pci/ice1712/amp.c
index e328cfb7620c..e525da2673be 100644
--- a/sound/pci/ice1712/amp.c
+++ b/sound/pci/ice1712/amp.c
@@ -68,8 +68,11 @@ static int __devinit snd_vt1724_amp_init(struct snd_ice1712 *ice)
static int __devinit snd_vt1724_amp_add_controls(struct snd_ice1712 *ice)
{
- /* we use pins 39 and 41 of the VT1616 for left and right read outputs */
- snd_ac97_write_cache(ice->ac97, 0x5a, snd_ac97_read(ice->ac97, 0x5a) & ~0x8000);
+ if (ice->ac97)
+ /* we use pins 39 and 41 of the VT1616 for left and right
+ read outputs */
+ snd_ac97_write_cache(ice->ac97, 0x5a,
+ snd_ac97_read(ice->ac97, 0x5a) & ~0x8000);
return 0;
}
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 6c896dbfd796..2e799a9a494d 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -2076,6 +2076,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
},
{
.subvendor = 0x161f,
+ .subdevice = 0x202f,
+ .name = "Gateway M520",
+ .type = AC97_TUNE_INV_EAPD
+ },
+ {
+ .subvendor = 0x161f,
.subdevice = 0x203a,
.name = "Gateway 4525GZ", /* AD1981B */
.type = AC97_TUNE_INV_EAPD
diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c
index 42d1ab136217..915546a79545 100644
--- a/sound/pci/oxygen/xonar_wm87x6.c
+++ b/sound/pci/oxygen/xonar_wm87x6.c
@@ -177,6 +177,7 @@ static void wm8776_registers_init(struct oxygen *chip)
struct xonar_wm87x6 *data = chip->model_data;
wm8776_write(chip, WM8776_RESET, 0);
+ wm8776_write(chip, WM8776_PHASESWAP, WM8776_PH_MASK);
wm8776_write(chip, WM8776_DACCTRL1, WM8776_DZCEN |
WM8776_PL_LEFT_LEFT | WM8776_PL_RIGHT_RIGHT);
wm8776_write(chip, WM8776_DACMUTE, chip->dac_mute ? WM8776_DMUTE : 0);
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 79c1b3d79f1e..7d45197f5cfd 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -143,7 +143,7 @@
* min : 0xFE : -115.0 dB
* mute: 0xFF
*/
-static const DECLARE_TLV_DB_SCALE(out_tlv, -11500, 50, 1);
+static const DECLARE_TLV_DB_SCALE(out_tlv, -11550, 50, 1);
static const struct snd_kcontrol_new ak4642_snd_controls[] = {
diff --git a/sound/soc/codecs/mxc_hdmi.c b/sound/soc/codecs/mxc_hdmi.c
index 834d785b2c27..9590181d4647 100644
--- a/sound/soc/codecs/mxc_hdmi.c
+++ b/sound/soc/codecs/mxc_hdmi.c
@@ -153,30 +153,26 @@ static struct cea_channel_speaker_allocation channel_allocations[] = {
{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } },
/* Dolby Surround */
{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } },
- /* surround40 */
-{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } },
- /* surround41 */
-{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } },
- /* surround50 */
-{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } },
- /* surround51 */
-{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } },
- /* 6.1 */
-{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } },
- /* surround71 */
-{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } },
-
{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } },
{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } },
{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } },
{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } },
{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } },
+{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } },
+{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } },
+{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } },
+ /* surround51 */
+{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } },
{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } },
{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } },
{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } },
+ /* 6.1 */
+{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } },
{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } },
{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } },
{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } },
+ /* surround71 */
+{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } },
{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } },
{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } },
{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } },
diff --git a/sound/soc/codecs/mxc_spdif.c b/sound/soc/codecs/mxc_spdif.c
index d22f84fa214b..883aa4d26687 100644
--- a/sound/soc/codecs/mxc_spdif.c
+++ b/sound/soc/codecs/mxc_spdif.c
@@ -1138,12 +1138,6 @@ static int mxc_spdif_startup(struct snd_pcm_substream *substream,
/* disable all the interrupts */
spdif_intr_enable(0xffffff, 0);
- /* enable spdif_xtal_clk */
- clk_enable(plat_data->spdif_core_clk);
- spdif_softreset();
- /* disable all the interrupts */
- spdif_intr_enable(0xffffff, 0);
-
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
ret = mxc_spdif_playback_startup(substream, dai);
else
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 2f5ce28d70a0..190720ec029d 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -3159,9 +3159,6 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
int aif0 = 0;
int adctl3 = 0;
- if (codec->dapm.bias_level != SND_SOC_BIAS_OFF)
- return 0;
-
wm8962->bclk = snd_soc_params_to_bclk(params);
if (params_channels(params) == 1)
wm8962->bclk *= 2;
@@ -3463,9 +3460,6 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
if (fll_div.theta || fll_div.lambda)
fll1 |= WM8962_FLL_FRAC;
- /* Stop the FLL while we reconfigure */
- snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, WM8962_FLL_ENA, 0);
-
snd_soc_update_bits(codec, WM8962_FLL_CONTROL_2,
WM8962_FLL_OUTDIV_MASK |
WM8962_FLL_REFCLK_DIV_MASK,
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 9e370d14ad88..8712a9f6d6ec 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -562,14 +562,14 @@ SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 0, 1, 0),
};
static const struct snd_kcontrol_new line2_mix[] = {
-SOC_DAPM_SINGLE("IN2R Switch", WM8993_LINE_MIXER2, 2, 1, 0),
-SOC_DAPM_SINGLE("IN2L Switch", WM8993_LINE_MIXER2, 1, 1, 0),
+SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER2, 2, 1, 0),
+SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER2, 1, 1, 0),
SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0),
};
static const struct snd_kcontrol_new line2n_mix[] = {
-SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
-SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
+SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
+SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
};
static const struct snd_kcontrol_new line2p_mix[] = {
@@ -589,6 +589,8 @@ SND_SOC_DAPM_INPUT("IN2RP:VXRP"),
SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0),
SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0),
+SND_SOC_DAPM_SUPPLY("LINEOUT_VMID_BUF", WM8993_ANTIPOP1, 7, 0, NULL, 0),
+
SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0,
in1l_pga, ARRAY_SIZE(in1l_pga)),
SND_SOC_DAPM_MIXER("IN1R PGA", WM8993_POWER_MANAGEMENT_2, 4, 0,
@@ -794,9 +796,11 @@ static const struct snd_soc_dapm_route lineout1_diff_routes[] = {
};
static const struct snd_soc_dapm_route lineout1_se_routes[] = {
+ { "LINEOUT1N Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT1N Mixer", "Left Output Switch", "Left Output PGA" },
{ "LINEOUT1N Mixer", "Right Output Switch", "Right Output PGA" },
+ { "LINEOUT1P Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT1P Mixer", "Left Output Switch", "Left Output PGA" },
{ "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" },
@@ -804,8 +808,8 @@ static const struct snd_soc_dapm_route lineout1_se_routes[] = {
};
static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
- { "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" },
- { "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" },
+ { "LINEOUT2 Mixer", "IN1L Switch", "IN1L PGA" },
+ { "LINEOUT2 Mixer", "IN1R Switch", "IN1R PGA" },
{ "LINEOUT2 Mixer", "Output Switch", "Right Output PGA" },
{ "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" },
@@ -813,9 +817,11 @@ static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
};
static const struct snd_soc_dapm_route lineout2_se_routes[] = {
+ { "LINEOUT2N Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT2N Mixer", "Left Output Switch", "Left Output PGA" },
{ "LINEOUT2N Mixer", "Right Output Switch", "Right Output PGA" },
+ { "LINEOUT2P Mixer", NULL, "LINEOUT_VMID_BUF" },
{ "LINEOUT2P Mixer", "Right Output Switch", "Right Output PGA" },
{ "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" },
diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile
index 3c851809e26d..adeef06f3c7f 100644
--- a/sound/soc/imx/Makefile
+++ b/sound/soc/imx/Makefile
@@ -19,6 +19,7 @@ snd-soc-imx-wm8962-objs := imx-wm8962.o
snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o
snd-soc-imx-cs42888-objs := imx-cs42888.o
snd-soc-imx-spdif-objs := imx-spdif.o
+snd-soc-imx-si4763-objs := imx-si4763.o
snd-soc-imx-hdmi-objs := imx-hdmi.o imx-hdmi-dai.o imx-hdmi-dma.o hdmi_pcm.o
obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
diff --git a/sound/soc/imx/imx-cs42888.c b/sound/soc/imx/imx-cs42888.c
index 5a22939b8cc0..128c9959a25f 100644
--- a/sound/soc/imx/imx-cs42888.c
+++ b/sound/soc/imx/imx-cs42888.c
@@ -138,7 +138,7 @@ static int config_asrc(struct snd_pcm_substream *substream,
|| !asrc_func)
return -EINVAL;
- if (channel != 2)
+ if ((channel != 2) && (channel != 4) && (channel != 6))
return -EINVAL;
ret = asrc_req_pair(channel, &asrc_esai_data.asrc_index);
diff --git a/sound/soc/imx/imx-esai.c b/sound/soc/imx/imx-esai.c
index daa3a8ae7a11..f11757b0e7cc 100644
--- a/sound/soc/imx/imx-esai.c
+++ b/sound/soc/imx/imx-esai.c
@@ -320,11 +320,11 @@ static int imx_esai_hw_tx_params(struct snd_pcm_substream *substream,
if (iprtd->asrc_enable) {
switch (iprtd->output_bit) {
- case 16:
+ case ASRC_WIDTH_16_BIT:
tfcr |= ESAI_WORD_LEN_16;
tcr |= ESAI_TCR_TSHFD_MSB | ESAI_TCR_TSWS_STL32_WDL16;
break;
- case 24:
+ case ASRC_WIDTH_24_BIT:
tfcr |= ESAI_WORD_LEN_24;
tcr |= ESAI_TCR_TSHFD_MSB | ESAI_TCR_TSWS_STL32_WDL24;
break;
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c
index a37c98b925ac..e9b102db7f01 100644
--- a/sound/soc/imx/imx-ssi.c
+++ b/sound/soc/imx/imx-ssi.c
@@ -1,8 +1,13 @@
/*
* imx-ssi.c -- ALSA Soc Audio Layer
*
+ * Copyright 2010-2012 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
* Copyright 2009 Sascha Hauer <s.hauer@pengutronix.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 as
+ * published by the Free Software Foundation.
* This code is based on code copyrighted by Freescale,
* Liam Girdwood, Javier Martin and probably others.
*
@@ -110,7 +115,7 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
break;
case SND_SOC_DAIFMT_DSP_A:
/* data on rising edge of bclk, frame high 1clk before data */
- strcr |= SSI_STCR_TFSL | SSI_STCR_TEFS;
+ strcr |= SSI_STCR_TFSL | SSI_STCR_TXBIT0 | SSI_STCR_TEFS;
break;
}
@@ -213,28 +218,40 @@ static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
switch (div_id) {
case IMX_SSI_TX_DIV_2:
+ if (div & (~SSI_STCCR_DIV2))
+ return EINVAL;
stccr &= ~SSI_STCCR_DIV2;
stccr |= div;
break;
case IMX_SSI_TX_DIV_PSR:
+ if (div & (~SSI_STCCR_PSR))
+ return EINVAL;
stccr &= ~SSI_STCCR_PSR;
stccr |= div;
break;
case IMX_SSI_TX_DIV_PM:
- stccr &= ~0xff;
+ if (div & (~SSI_STCCR_PM_MASK))
+ return EINVAL;
+ stccr &= ~SSI_STCCR_PM_MASK;
stccr |= SSI_STCCR_PM(div);
break;
case IMX_SSI_RX_DIV_2:
- stccr &= ~SSI_STCCR_DIV2;
- stccr |= div;
+ if (div & (~SSI_SRCCR_DIV2))
+ return EINVAL;
+ srccr &= ~SSI_SRCCR_DIV2;
+ srccr |= div;
break;
case IMX_SSI_RX_DIV_PSR:
- stccr &= ~SSI_STCCR_PSR;
- stccr |= div;
+ if (div & (~SSI_SRCCR_PSR))
+ return EINVAL;
+ srccr &= ~SSI_SRCCR_PSR;
+ srccr |= div;
break;
case IMX_SSI_RX_DIV_PM:
- stccr &= ~0xff;
- stccr |= SSI_STCCR_PM(div);
+ if (div & (~SSI_SRCCR_PM_MASK))
+ return EINVAL;
+ srccr &= ~SSI_SRCCR_PM_MASK;
+ srccr |= SSI_STCCR_PM(div);
break;
default:
return -EINVAL;
@@ -497,7 +514,9 @@ static int imx_ssi_dai_probe(struct snd_soc_dai *dai)
snd_soc_dai_set_drvdata(dai, ssi);
val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) |
- SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize);
+ SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize) |
+ SSI_SFCSR_TFWM1(ssi->dma_params_tx.burstsize) |
+ SSI_SFCSR_RFWM1(ssi->dma_params_rx.burstsize) ;
writel(val, ssi->base + SSI_SFCSR);
return 0;
@@ -567,10 +586,10 @@ static void setup_channel_to_ac97(struct imx_ssi *imx_ssi)
writel(SSI_SCR_SYN | SSI_SCR_NET, base + SSI_SCR);
- writel(SSI_SFCSR_RFWM0(8) |
- SSI_SFCSR_TFWM0(8) |
- SSI_SFCSR_RFWM1(8) |
- SSI_SFCSR_TFWM1(8), base + SSI_SFCSR);
+ writel(SSI_SFCSR_RFWM0(imx_ssi->dma_params_rx.burstsize) |
+ SSI_SFCSR_TFWM0(imx_ssi->dma_params_tx.burstsize) |
+ SSI_SFCSR_RFWM1(imx_ssi->dma_params_rx.burstsize) |
+ SSI_SFCSR_TFWM1(imx_ssi->dma_params_tx.burstsize), base + SSI_SFCSR);
writel(SSI_STCCR_WL(16) | SSI_STCCR_DC(12), base + SSI_STCCR);
writel(SSI_STCCR_WL(16) | SSI_STCCR_DC(12), base + SSI_SRCCR);
diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h
index 1b43c620c735..c57f9fe4edaa 100644
--- a/sound/soc/imx/imx-ssi.h
+++ b/sound/soc/imx/imx-ssi.h
@@ -223,9 +223,6 @@ int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
struct snd_pcm *pcm);
void imx_pcm_free(struct snd_pcm *pcm);
-/*
- * Do not change this as the FIQ handler depends on this size
- */
-#define IMX_SSI_DMABUF_SIZE (64 * 1024)
+#define IMX_SSI_DMABUF_SIZE (256 * 1024)
#endif /* _IMX_SSI_H */
diff --git a/sound/soc/imx/imx-wm8958.c b/sound/soc/imx/imx-wm8958.c
index 328bb0b6ca10..dc7a1f59b37c 100755
--- a/sound/soc/imx/imx-wm8958.c
+++ b/sound/soc/imx/imx-wm8958.c
@@ -26,7 +26,6 @@
#include <linux/io.h>
#include <linux/fsl_devices.h>
#include <linux/slab.h>
-#include <linux/gpio.h>
#include <linux/clk.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -47,14 +46,11 @@ struct imx_priv {
int sysclk; /*mclk from the outside*/
int codec_sysclk;
int dai_hifi;
- int hp_status;
- int hp_irq;
struct platform_device *pdev;
struct wm8994 *wm8958;
};
static struct imx_priv card_priv;
static struct snd_soc_card snd_soc_card_imx;
-
struct clk *codec_mclk;
static struct snd_soc_jack hs_jack;
@@ -109,11 +105,6 @@ static int imx_hifi_hw_params(struct snd_pcm_substream *substream,
int ret = 0;
unsigned int pll_out;
u32 dai_format;
- /* only need to do this once as capture and playback are sync */
-
- if (priv->dai_hifi)
- return 0;
- priv->dai_hifi = 1;
dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM;
@@ -187,71 +178,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
};
-static void headphone_detect_handler(struct work_struct *wor)
-{
-
- struct imx_priv *priv = &card_priv;
- struct platform_device *pdev = priv->pdev;
- struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
- char *envp[3];
- char *buf;
-
- /*sysfs_notify(&pdev->dev.kobj, NULL, "headphone");*/
- priv->hp_status = gpio_get_value(plat->hp_gpio);
-
- /* setup a message for userspace headphone in */
- buf = kmalloc(32, GFP_ATOMIC);
- if (!buf) {
- pr_err("%s kmalloc failed\n", __func__);
- return;
- }
-
- if (priv->hp_status == 0)
- snprintf(buf, 32, "STATE=%d", 2);
- else
- snprintf(buf, 32, "STATE=%d", 0);
-
- envp[0] = "NAME=headphone";
- envp[1] = buf;
- envp[2] = NULL;
- kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, envp);
- kfree(buf);
-
- enable_irq(priv->hp_irq);
-
- return;
-}
-
-static DECLARE_DELAYED_WORK(hp_event, headphone_detect_handler);
-
-static irqreturn_t imx_headphone_detect_handler(int irq, void *data)
-{
- disable_irq_nosync(irq);
- schedule_delayed_work(&hp_event, msecs_to_jiffies(200));
- return IRQ_HANDLED;
-}
-
-static ssize_t show_headphone(struct device_driver *dev, char *buf)
-{
- struct imx_priv *priv = &card_priv;
- struct platform_device *pdev = priv->pdev;
- struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
-
- /* determine whether hp is plugged in */
- priv->hp_status = gpio_get_value(plat->hp_gpio);
-
- if (priv->hp_status)
- strcpy(buf, "speaker\n");
- else
- strcpy(buf, "headphone\n");
-
- /*pr_info("show_headphone hp_status = %d \r",priv->hp_status);*/
-
- return strlen(buf);
-}
-
-static DRIVER_ATTR(headphone, S_IRUGO | S_IWUSR, show_headphone, NULL);
-
static int imx_wm8958_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
@@ -356,7 +282,6 @@ static int __devinit imx_wm8958_probe(struct platform_device *pdev)
priv->pdev = pdev;
priv->wm8958 = wm8958;
- priv->hp_irq = gpio_to_irq(plat->hp_gpio);
imx_audmux_config(plat->src_port, plat->ext_port);
@@ -366,23 +291,9 @@ static int __devinit imx_wm8958_probe(struct platform_device *pdev)
}
priv->sysclk = plat->sysclk;
-
- ret = driver_create_file(pdev->dev.driver, &driver_attr_headphone);
- if (ret < 0) {
- ret = -EINVAL;
- return ret;
- }
-
hs_jack_gpios[0].gpio = plat->hp_gpio;
hs_jack_gpios[0].invert = plat->hp_active_low;
- if (plat->hp_gpio != -1) {
- ret = request_irq(priv->hp_irq,
- imx_headphone_detect_handler,
- IRQ_TYPE_EDGE_BOTH, pdev->name, priv);
- }
-
-
return ret;
}
diff --git a/sound/soc/imx/imx-wm8962.c b/sound/soc/imx/imx-wm8962.c
index aa3122f6d765..76299a659b41 100644
--- a/sound/soc/imx/imx-wm8962.c
+++ b/sound/soc/imx/imx-wm8962.c
@@ -98,9 +98,6 @@ static int imx_hifi_hw_params(struct snd_pcm_substream *substream,
u32 dai_format;
unsigned int pll_out;
- if (codec->dapm.bias_level != SND_SOC_BIAS_OFF)
- return 0;
-
dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM;
@@ -128,8 +125,8 @@ static int imx_hifi_hw_params(struct snd_pcm_substream *substream,
else
pll_out = sample_rate * 256;
- ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL_MCLK,
- WM8962_FLL_MCLK, priv->sysclk,
+ ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL_OSC,
+ WM8962_FLL_OSC, priv->sysclk,
pll_out);
if (ret < 0)
pr_err("Failed to start FLL: %d\n", ret);
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 8ad93ee2e92b..b583e604a1ea 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -668,6 +668,38 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
return 0;
}
+static void pxa_ssp_set_running_bit(struct snd_pcm_substream *substream,
+ struct ssp_device *ssp, int value)
+{
+ uint32_t sscr0 = pxa_ssp_read_reg(ssp, SSCR0);
+ uint32_t sscr1 = pxa_ssp_read_reg(ssp, SSCR1);
+ uint32_t sspsp = pxa_ssp_read_reg(ssp, SSPSP);
+ uint32_t sssr = pxa_ssp_read_reg(ssp, SSSR);
+
+ if (value && (sscr0 & SSCR0_SSE))
+ pxa_ssp_write_reg(ssp, SSCR0, sscr0 & ~SSCR0_SSE);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (value)
+ sscr1 |= SSCR1_TSRE;
+ else
+ sscr1 &= ~SSCR1_TSRE;
+ } else {
+ if (value)
+ sscr1 |= SSCR1_RSRE;
+ else
+ sscr1 &= ~SSCR1_RSRE;
+ }
+
+ pxa_ssp_write_reg(ssp, SSCR1, sscr1);
+
+ if (value) {
+ pxa_ssp_write_reg(ssp, SSSR, sssr);
+ pxa_ssp_write_reg(ssp, SSPSP, sspsp);
+ pxa_ssp_write_reg(ssp, SSCR0, sscr0 | SSCR0_SSE);
+ }
+}
+
static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *cpu_dai)
{
@@ -681,42 +713,21 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
pxa_ssp_enable(ssp);
break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- val = pxa_ssp_read_reg(ssp, SSCR1);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- val |= SSCR1_TSRE;
- else
- val |= SSCR1_RSRE;
- pxa_ssp_write_reg(ssp, SSCR1, val);
+ pxa_ssp_set_running_bit(substream, ssp, 1);
val = pxa_ssp_read_reg(ssp, SSSR);
pxa_ssp_write_reg(ssp, SSSR, val);
break;
case SNDRV_PCM_TRIGGER_START:
- val = pxa_ssp_read_reg(ssp, SSCR1);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- val |= SSCR1_TSRE;
- else
- val |= SSCR1_RSRE;
- pxa_ssp_write_reg(ssp, SSCR1, val);
- pxa_ssp_enable(ssp);
+ pxa_ssp_set_running_bit(substream, ssp, 1);
break;
case SNDRV_PCM_TRIGGER_STOP:
- val = pxa_ssp_read_reg(ssp, SSCR1);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- val &= ~SSCR1_TSRE;
- else
- val &= ~SSCR1_RSRE;
- pxa_ssp_write_reg(ssp, SSCR1, val);
+ pxa_ssp_set_running_bit(substream, ssp, 0);
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
pxa_ssp_disable(ssp);
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- val = pxa_ssp_read_reg(ssp, SSCR1);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- val &= ~SSCR1_TSRE;
- else
- val &= ~SSCR1_RSRE;
- pxa_ssp_write_reg(ssp, SSCR1, val);
+ pxa_ssp_set_running_bit(substream, ssp, 0);
break;
default:
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c
index 16152ed08648..c1290da71c62 100644
--- a/sound/soc/samsung/neo1973_wm8753.c
+++ b/sound/soc/samsung/neo1973_wm8753.c
@@ -425,7 +425,7 @@ static struct snd_soc_dai_link neo1973_dai[] = {
.platform_name = "samsung-audio",
.cpu_dai_name = "s3c24xx-iis",
.codec_dai_name = "wm8753-hifi",
- .codec_name = "wm8753-codec.0-001a",
+ .codec_name = "wm8753.0-001a",
.init = neo1973_wm8753_init,
.ops = &neo1973_hifi_ops,
},
@@ -434,7 +434,7 @@ static struct snd_soc_dai_link neo1973_dai[] = {
.stream_name = "Voice",
.cpu_dai_name = "dfbmcs320-pcm",
.codec_dai_name = "wm8753-voice",
- .codec_name = "wm8753-codec.0-001a",
+ .codec_name = "wm8753.0-001a",
.ops = &neo1973_voice_ops,
},
};
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 5f36274336ae..ad12a4c17b72 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -30,6 +30,7 @@
#include <linux/bitops.h>
#include <linux/debugfs.h>
#include <linux/platform_device.h>
+#include <linux/ctype.h>
#include <linux/slab.h>
#include <sound/ac97_codec.h>
#include <sound/core.h>
@@ -1956,9 +1957,20 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
"%s", card->name);
snprintf(card->snd_card->longname, sizeof(card->snd_card->longname),
"%s", card->long_name ? card->long_name : card->name);
- if (card->driver_name)
- strlcpy(card->snd_card->driver, card->driver_name,
- sizeof(card->snd_card->driver));
+ snprintf(card->snd_card->driver, sizeof(card->snd_card->driver),
+ "%s", card->driver_name ? card->driver_name : card->name);
+ for (i = 0; i < ARRAY_SIZE(card->snd_card->driver); i++) {
+ switch (card->snd_card->driver[i]) {
+ case '_':
+ case '-':
+ case '\0':
+ break;
+ default:
+ if (!isalnum(card->snd_card->driver[i]))
+ card->snd_card->driver[i] = '_';
+ break;
+ }
+ }
if (card->late_probe) {
ret = card->late_probe(card);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 32ab7fc4579a..d5ec2060d121 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -67,6 +67,7 @@ static int dapm_up_seq[] = {
[snd_soc_dapm_out_drv] = 10,
[snd_soc_dapm_hp] = 10,
[snd_soc_dapm_spk] = 10,
+ [snd_soc_dapm_line] = 10,
[snd_soc_dapm_post] = 11,
};
@@ -75,6 +76,7 @@ static int dapm_down_seq[] = {
[snd_soc_dapm_adc] = 1,
[snd_soc_dapm_hp] = 2,
[snd_soc_dapm_spk] = 2,
+ [snd_soc_dapm_line] = 2,
[snd_soc_dapm_out_drv] = 2,
[snd_soc_dapm_pga] = 4,
[snd_soc_dapm_mixer_named_ctl] = 5,
@@ -2615,9 +2617,13 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
* standby.
*/
if (powerdown) {
- snd_soc_dapm_set_bias_level(dapm, SND_SOC_BIAS_PREPARE);
+ if (dapm->bias_level == SND_SOC_BIAS_ON)
+ snd_soc_dapm_set_bias_level(dapm,
+ SND_SOC_BIAS_PREPARE);
dapm_seq_run(dapm, &down_list, 0, false);
- snd_soc_dapm_set_bias_level(dapm, SND_SOC_BIAS_STANDBY);
+ if (dapm->bias_level == SND_SOC_BIAS_PREPARE)
+ snd_soc_dapm_set_bias_level(dapm,
+ SND_SOC_BIAS_STANDBY);
}
}
@@ -2630,7 +2636,9 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card)
list_for_each_entry(codec, &card->codec_dev_list, list) {
soc_dapm_shutdown_codec(&codec->dapm);
- snd_soc_dapm_set_bias_level(&codec->dapm, SND_SOC_BIAS_OFF);
+ if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY)
+ snd_soc_dapm_set_bias_level(&codec->dapm,
+ SND_SOC_BIAS_OFF);
}
}
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index b8dcbf407bbb..506c0fa679f6 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -670,6 +670,9 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
int count = 0, needs_knot = 0;
int err;
+ kfree(subs->rate_list.list);
+ subs->rate_list.list = NULL;
+
list_for_each_entry(fp, &subs->fmt_list, list) {
if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)
return 0;
diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c
index c400ade3ff08..1e7a47a86605 100644
--- a/sound/usb/usx2y/usb_stream.c
+++ b/sound/usb/usx2y/usb_stream.c
@@ -674,7 +674,7 @@ dotry:
inurb->transfer_buffer_length =
inurb->number_of_packets *
inurb->iso_frame_desc[0].length;
- preempt_disable();
+
if (u == 0) {
int now;
struct usb_device *dev = inurb->dev;
@@ -686,19 +686,17 @@ dotry:
}
err = usb_submit_urb(inurb, GFP_ATOMIC);
if (err < 0) {
- preempt_enable();
snd_printk(KERN_ERR"usb_submit_urb(sk->inurb[%i])"
" returned %i\n", u, err);
return err;
}
err = usb_submit_urb(outurb, GFP_ATOMIC);
if (err < 0) {
- preempt_enable();
snd_printk(KERN_ERR"usb_submit_urb(sk->outurb[%i])"
" returned %i\n", u, err);
return err;
}
- preempt_enable();
+
if (inurb->start_frame != outurb->start_frame) {
snd_printd(KERN_DEBUG
"u[%i] start_frames differ in:%u out:%u\n",
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm.S b/tools/perf/bench/mem-memcpy-x86-64-asm.S
index a57b66e853c2..185a96d66dd1 100644
--- a/tools/perf/bench/mem-memcpy-x86-64-asm.S
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm.S
@@ -1,2 +1,8 @@
#include "../../../arch/x86/lib/memcpy_64.S"
+/*
+ * We need to provide note.GNU-stack section, saying that we want
+ * NOT executable stack. Otherwise the final linking will assume that
+ * the ELF stack should not be restricted at all and set it RWX.
+ */
+.section .note.GNU-stack,"",@progbits
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 0239eb87b232..ad2183c98acb 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -348,6 +348,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
data->cpu = data->pid = data->tid = -1;
data->stream_id = data->id = data->time = -1ULL;
+ data->period = 1;
if (event->header.type != PERF_RECORD_SAMPLE) {
if (!sample_id_all)
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 627a02e03c57..fb695991935b 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -158,6 +158,18 @@ struct hist_entry *__hists__add_entry(struct hists *self,
if (!cmp) {
he->period += period;
++he->nr_events;
+
+ /* If the map of an existing hist_entry has
+ * become out-of-date due to an exec() or
+ * similar, update it. Otherwise we will
+ * mis-adjust symbol addresses when computing
+ * the history counter to increment.
+ */
+ if (he->ms.map != entry.ms.map) {
+ he->ms.map = entry.ms.map;
+ if (he->ms.map)
+ he->ms.map->referenced = true;
+ }
goto out;
}
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index f44fa541d56e..0ffbc8e5b4b5 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -122,6 +122,9 @@ static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
}
}
va_end(ap);
+
+ if (n >= (int)size)
+ return size - 1;
return n;
}
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c
index 6c164dc9ee95..bf54c48871dc 100644
--- a/tools/perf/util/trace-event-parse.c
+++ b/tools/perf/util/trace-event-parse.c
@@ -1582,6 +1582,8 @@ process_symbols(struct event *event, struct print_arg *arg, char **tok)
field = malloc_or_die(sizeof(*field));
type = process_arg(event, field, &token);
+ while (type == EVENT_OP)
+ type = process_op(event, field, &token);
if (test_type_token(type, token, EVENT_DELIM, ","))
goto out_free;
diff --git a/tools/usb/ffs-test.c b/tools/usb/ffs-test.c
index b9c798631699..f17dfee1e21b 100644
--- a/tools/usb/ffs-test.c
+++ b/tools/usb/ffs-test.c
@@ -324,7 +324,7 @@ static void *start_thread_helper(void *arg)
ret = t->in(t, t->buf, t->buf_size);
if (ret > 0) {
- ret = t->out(t, t->buf, t->buf_size);
+ ret = t->out(t, t->buf, ret);
name = out_name;
op = "write";
} else {
diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c
index 62a9caf0563c..fb0f6e469bb4 100644
--- a/virt/kvm/iommu.c
+++ b/virt/kvm/iommu.c
@@ -285,6 +285,11 @@ static void kvm_iommu_put_pages(struct kvm *kvm,
}
}
+void kvm_iommu_unmap_pages(struct kvm *kvm, struct kvm_memory_slot *slot)
+{
+ kvm_iommu_put_pages(kvm, slot->base_gfn, slot->npages);
+}
+
static int kvm_iommu_unmap_memslots(struct kvm *kvm)
{
int i, idx;
@@ -293,10 +298,9 @@ static int kvm_iommu_unmap_memslots(struct kvm *kvm)
idx = srcu_read_lock(&kvm->srcu);
slots = kvm_memslots(kvm);
- for (i = 0; i < slots->nmemslots; i++) {
- kvm_iommu_put_pages(kvm, slots->memslots[i].base_gfn,
- slots->memslots[i].npages);
- }
+ for (i = 0; i < slots->nmemslots; i++)
+ kvm_iommu_unmap_pages(kvm, &slots->memslots[i]);
+
srcu_read_unlock(&kvm->srcu, idx);
return 0;
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 96ebc0679415..6b39ba9540e8 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -796,12 +796,13 @@ skip_lpage:
if (r)
goto out_free;
- /* map the pages in iommu page table */
+ /* map/unmap the pages in iommu page table */
if (npages) {
r = kvm_iommu_map_pages(kvm, &new);
if (r)
goto out_free;
- }
+ } else
+ kvm_iommu_unmap_pages(kvm, &old);
r = -ENOMEM;
slots = kzalloc(sizeof(struct kvm_memslots), GFP_KERNEL);