]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branches 'fix/cs42l52', 'fix/mxs', 'fix/samsung', 'fix/wm8978', 'topic/ak4104...
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Wed, 7 Nov 2012 14:56:14 +0000 (15:56 +0100)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Wed, 7 Nov 2012 14:56:14 +0000 (15:56 +0100)
690 files changed:
Documentation/00-INDEX
Documentation/devicetree/bindings/arm/atmel-at91.txt
Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt [new file with mode: 0644]
Documentation/devicetree/bindings/misc/atmel-ssc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt
Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt
Documentation/devicetree/bindings/sound/ak4104.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/cs4271.txt
Documentation/firmware_class/README
Documentation/hwmon/fam15h_power
Documentation/zh_CN/IRQ.txt [new file with mode: 0644]
Documentation/zh_CN/arm64/booting.txt [new file with mode: 0644]
Documentation/zh_CN/arm64/memory.txt [new file with mode: 0644]
MAINTAINERS
Makefile
arch/alpha/include/asm/thread_info.h
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/process.c
arch/alpha/kernel/traps.c
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/Makefile
arch/arm/boot/dts/at91sam9260.dtsi
arch/arm/boot/dts/at91sam9263.dtsi
arch/arm/boot/dts/at91sam9g20ek_common.dtsi
arch/arm/boot/dts/at91sam9g45.dtsi
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/boot/dts/dbx5x0.dtsi
arch/arm/boot/dts/exynos4210-trats.dts
arch/arm/boot/dts/imx23.dtsi
arch/arm/boot/dts/imx28.dtsi
arch/arm/boot/dts/omap3.dtsi
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/mvebu_defconfig
arch/arm/configs/versatile_defconfig
arch/arm/include/asm/flat.h
arch/arm/include/asm/uaccess.h
arch/arm/include/asm/xen/interface.h
arch/arm/include/asm/xen/page.h
arch/arm/include/debug/8250_32.S [new file with mode: 0644]
arch/arm/include/debug/picoxcell.S
arch/arm/include/debug/socfpga.S
arch/arm/kernel/irq.c
arch/arm/kernel/kprobes-test-arm.c
arch/arm/kernel/machine_kexec.c
arch/arm/kernel/perf_event.c
arch/arm/kernel/smp.c
arch/arm/kernel/smp_twd.c
arch/arm/lib/delay.c
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91rm9200_devices.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9260_devices.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9261_devices.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9g45_devices.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/at91sam9rl_devices.c
arch/arm/mach-at91/at91sam9x5.c
arch/arm/mach-at91/at91x40.c
arch/arm/mach-at91/board-neocore926.c
arch/arm/mach-at91/board-sam9261ek.c
arch/arm/mach-at91/board-sam9263ek.c
arch/arm/mach-at91/board-sam9g20ek.c
arch/arm/mach-at91/generic.h
arch/arm/mach-at91/irq.c
arch/arm/mach-at91/setup.c
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-exynos/common.c
arch/arm/mach-exynos/mach-exynos4-dt.c
arch/arm/mach-imx/clk-busy.c
arch/arm/mach-imx/clk-imx25.c
arch/arm/mach-imx/clk-imx27.c
arch/arm/mach-imx/mm-imx3.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/clock33xx_data.c
arch/arm/mach-omap2/mux34xx.c
arch/arm/mach-omap2/pm.h
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/serial.c
arch/arm/mach-s3c24xx/s3c2416.c
arch/arm/mach-s3c24xx/s3c2443.c
arch/arm/mach-s5p64x0/common.c
arch/arm/mach-s5pc100/common.c
arch/arm/mach-s5pv210/common.c
arch/arm/mach-shmobile/setup-r8a7779.c
arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h [deleted file]
arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h [deleted file]
arch/arm/mach-ux500/cpu.c
arch/arm/mm/alignment.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/vmregion.h
arch/arm/plat-mxc/devices/platform-mxc-mmc.c
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/include/plat/omap-serial.h
arch/arm/plat-samsung/include/plat/spi-core.h [new file with mode: 0644]
arch/arm/tools/Makefile
arch/arm/xen/grant-table.c
arch/arm/xen/hypercall.S
arch/frv/Kconfig
arch/frv/boot/Makefile
arch/frv/include/asm/unistd.h
arch/frv/kernel/entry.S
arch/frv/kernel/process.c
arch/frv/mb93090-mb00/pci-dma-nommu.c
arch/ia64/include/asm/Kbuild
arch/ia64/include/asm/kvm_para.h [deleted file]
arch/m68k/include/asm/Kbuild
arch/m68k/include/asm/ptrace.h
arch/m68k/include/asm/setup.h
arch/m68k/include/asm/signal.h
arch/m68k/include/asm/termios.h
arch/m68k/include/asm/unistd.h
arch/m68k/include/uapi/asm/Kbuild
arch/m68k/include/uapi/asm/a.out.h [moved from arch/m68k/include/asm/a.out.h with 100% similarity]
arch/m68k/include/uapi/asm/auxvec.h [moved from arch/m68k/include/asm/auxvec.h with 100% similarity]
arch/m68k/include/uapi/asm/byteorder.h [moved from arch/m68k/include/asm/byteorder.h with 100% similarity]
arch/m68k/include/uapi/asm/cachectl.h [moved from arch/m68k/include/asm/cachectl.h with 100% similarity]
arch/m68k/include/uapi/asm/fcntl.h [moved from arch/m68k/include/asm/fcntl.h with 100% similarity]
arch/m68k/include/uapi/asm/ioctls.h [moved from arch/m68k/include/asm/ioctls.h with 100% similarity]
arch/m68k/include/uapi/asm/msgbuf.h [moved from arch/m68k/include/asm/msgbuf.h with 100% similarity]
arch/m68k/include/uapi/asm/param.h [moved from arch/m68k/include/asm/param.h with 100% similarity]
arch/m68k/include/uapi/asm/poll.h [moved from arch/m68k/include/asm/poll.h with 100% similarity]
arch/m68k/include/uapi/asm/posix_types.h [moved from arch/m68k/include/asm/posix_types.h with 100% similarity]
arch/m68k/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/sembuf.h [moved from arch/m68k/include/asm/sembuf.h with 100% similarity]
arch/m68k/include/uapi/asm/setup.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/shmbuf.h [moved from arch/m68k/include/asm/shmbuf.h with 100% similarity]
arch/m68k/include/uapi/asm/sigcontext.h [moved from arch/m68k/include/asm/sigcontext.h with 100% similarity]
arch/m68k/include/uapi/asm/signal.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/socket.h [moved from arch/m68k/include/asm/socket.h with 100% similarity]
arch/m68k/include/uapi/asm/sockios.h [moved from arch/m68k/include/asm/sockios.h with 100% similarity]
arch/m68k/include/uapi/asm/stat.h [moved from arch/m68k/include/asm/stat.h with 100% similarity]
arch/m68k/include/uapi/asm/swab.h [moved from arch/m68k/include/asm/swab.h with 100% similarity]
arch/m68k/include/uapi/asm/termbits.h [moved from arch/m68k/include/asm/termbits.h with 100% similarity]
arch/m68k/include/uapi/asm/termios.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/m68k/kernel/syscalltable.S
arch/s390/Kconfig
arch/s390/boot/compressed/vmlinux.lds.S
arch/s390/include/asm/perf_event.h
arch/s390/include/uapi/asm/Kbuild
arch/s390/include/uapi/asm/chpid.h
arch/s390/include/uapi/asm/kvm_para.h [new file with mode: 0644]
arch/s390/kernel/cache.c
arch/s390/kernel/head_kdump.S
arch/s390/kernel/perf_cpum_cf.c
arch/s390/kernel/vmlinux.lds.S
arch/tile/Makefile
arch/tile/kernel/module.c
arch/x86/include/asm/efi.h
arch/x86/include/asm/xen/hypervisor.h
arch/x86/include/asm/xen/interface.h
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event_intel_uncore.c
arch/x86/kernel/cpu/perf_event_knc.c
arch/x86/kernel/cpu/perf_event_p6.c
arch/x86/kernel/e820.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/kvm.c
arch/x86/kernel/setup.c
arch/x86/kernel/signal.c
arch/x86/kernel/uprobes.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/x86.c
arch/x86/mm/init.c
arch/x86/mm/init_64.c
arch/x86/oprofile/nmi_int.c
arch/x86/platform/efi/efi.c
arch/x86/platform/efi/efi_64.c
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/xtensa/Kconfig
arch/xtensa/include/asm/io.h
arch/xtensa/include/asm/processor.h
arch/xtensa/include/asm/syscall.h
arch/xtensa/include/asm/unistd.h
arch/xtensa/include/uapi/asm/unistd.h
arch/xtensa/kernel/entry.S
arch/xtensa/kernel/process.c
arch/xtensa/kernel/syscall.c
arch/xtensa/kernel/xtensa_ksyms.c
block/Kconfig
block/blk-cgroup.c
block/blk-core.c
drivers/acpi/glue.c
drivers/acpi/processor_driver.c
drivers/acpi/video.c
drivers/base/Kconfig
drivers/base/dma-coherent.c
drivers/base/dma-contiguous.c
drivers/base/firmware_class.c
drivers/base/power/domain.c
drivers/base/regmap/Kconfig
drivers/base/regmap/internal.h
drivers/base/regmap/regmap-debugfs.c
drivers/base/regmap/regmap.c
drivers/bcma/main.c
drivers/block/Kconfig
drivers/block/cciss.c
drivers/block/floppy.c
drivers/block/loop.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/mtip32xx/mtip32xx.h
drivers/block/xen-blkback/common.h
drivers/block/xen-blkback/xenbus.c
drivers/char/sonypi.c
drivers/cpufreq/cpufreq_stats.c
drivers/cpufreq/powernow-k8.c
drivers/dma/Kconfig
drivers/dma/dw_dmac_regs.h
drivers/dma/imx-dma.c
drivers/dma/sirf-dma.c
drivers/edac/amd64_edac.c
drivers/extcon/extcon-adc-jack.c
drivers/extcon/extcon-class.c
drivers/extcon/extcon-gpio.c
drivers/extcon/extcon-max77693.c
drivers/extcon/extcon-max8997.c
drivers/gpio/gpio-74x164.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-timberdale.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/drm_fb_cma_helper.c
drivers/gpu/drm/drm_info.c
drivers/gpu/drm/drm_platform.c
drivers/gpu/drm/exynos/Kconfig
drivers/gpu/drm/exynos/exynos_drm_connector.c
drivers/gpu/drm/exynos/exynos_drm_encoder.c
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_overlay.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_sdvo_regs.h
drivers/gpu/drm/nouveau/core/core/gpuobj.c
drivers/gpu/drm/nouveau/core/core/mm.c
drivers/gpu/drm/nouveau/core/include/core/mm.h
drivers/gpu/drm/nouveau/core/subdev/bios/base.c
drivers/gpu/drm/nouveau/core/subdev/bios/pll.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c
drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_drm.h
drivers/gpu/drm/nouveau/nouveau_irq.c
drivers/gpu/drm/nouveau/nv04_dac.c
drivers/gpu/drm/nouveau/nv04_dfp.c
drivers/gpu/drm/nouveau/nv04_tv.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/evergreen_cs.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/nid.h
drivers/gpu/drm/radeon/radeon_atpx_handler.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/radeon_gem.c
drivers/gpu/drm/radeon/radeon_legacy_crtc.c
drivers/gpu/drm/radeon/radeon_legacy_encoders.c
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/shmobile/shmob_drm_drv.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/udl/udl_drv.h
drivers/gpu/drm/udl/udl_fb.c
drivers/gpu/drm/udl/udl_transfer.c
drivers/hid/hid-apple.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-microsoft.c
drivers/hid/hid-multitouch.c
drivers/hv/channel.c
drivers/hwmon/fam15h_power.c
drivers/hwmon/gpio-fan.c
drivers/i2c/Makefile
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-nomadik.c
drivers/i2c/busses/i2c-tegra.c
drivers/i2c/i2c-stub.c [moved from drivers/i2c/busses/i2c-stub.c with 75% similarity]
drivers/iio/Kconfig
drivers/iio/Makefile
drivers/infiniband/hw/cxgb4/mem.c
drivers/infiniband/hw/mlx4/alias_GUID.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/mlx4/mcg.c
drivers/input/evdev.c
drivers/input/joydev.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/pxa27x_keypad.c
drivers/input/misc/xen-kbdfront.c
drivers/input/mouse/bcm5974.c
drivers/input/mousedev.c
drivers/input/tablet/wacom_sys.c
drivers/input/tablet/wacom_wac.c
drivers/input/tablet/wacom_wac.h
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/egalax_ts.c
drivers/input/touchscreen/tsc40.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/tegra-smmu.c
drivers/isdn/gigaset/bas-gigaset.c
drivers/md/faulty.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/misc/atmel-ssc.c
drivers/net/bonding/bond_sysfs.c
drivers/net/can/flexcan.c
drivers/net/can/sja1000/peak_pci.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
drivers/net/ethernet/freescale/gianfar_ptp.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/eq.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/nxp/lpc_eth.c
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
drivers/net/ethernet/qlogic/qla3xxx.c
drivers/net/ethernet/ti/Kconfig
drivers/net/ethernet/tile/tilegx.c
drivers/net/phy/Kconfig
drivers/net/phy/Makefile
drivers/net/phy/at803x.c [new file with mode: 0644]
drivers/net/phy/mdio-bitbang.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/ipheth.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/usbnet.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vxlan.c
drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
drivers/net/wireless/ath/ath9k/hif_usb.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/brcm80211/brcmfmac/usb.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/ipw2x00/ipw2200.c
drivers/net/wireless/iwlwifi/dvm/devices.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/rtlwifi/usb.c
drivers/pinctrl/core.c
drivers/pinctrl/pinconf.c
drivers/pinctrl/pinctrl-nomadik.c
drivers/pinctrl/pinctrl-tegra.c
drivers/pinctrl/pinctrl-tegra30.c
drivers/rtc/rtc-imxdi.c
drivers/s390/cio/css.c
drivers/s390/cio/idset.c
drivers/s390/cio/idset.h
drivers/scsi/qla2xxx/qla_mid.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/qla_target.h
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/scsi/qla2xxx/tcm_qla2xxx.h
drivers/spi/spi-mxs.c
drivers/spi/spi-pl022.c
drivers/spi/spi-rspi.c
drivers/staging/android/binder.c
drivers/staging/comedi/drivers/8255_pci.c
drivers/staging/comedi/drivers/amplc_dio200.c
drivers/staging/comedi/drivers/amplc_pc236.c
drivers/staging/comedi/drivers/amplc_pc263.c
drivers/staging/comedi/drivers/das08.c
drivers/staging/comedi/drivers/ni_daq_700.c
drivers/staging/comedi/drivers/ni_labpc.c
drivers/staging/iio/accel/adis16201_core.c
drivers/staging/iio/accel/adis16203_core.c
drivers/staging/iio/accel/adis16204_core.c
drivers/staging/iio/accel/adis16209_core.c
drivers/staging/iio/accel/adis16220_core.c
drivers/staging/iio/accel/adis16240_core.c
drivers/staging/iio/gyro/adis16260_core.c
drivers/staging/iio/imu/adis16400.h
drivers/staging/iio/imu/adis16400_core.c
drivers/staging/ipack/bridges/tpci200.c
drivers/staging/omapdrm/omap_gem.c
drivers/staging/ramster/Kconfig
drivers/staging/tidspbridge/core/tiomap3430.c
drivers/staging/tidspbridge/hw/hw_mmu.c
drivers/staging/tidspbridge/hw/hw_mmu.h
drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h
drivers/staging/tidspbridge/include/dspbridge/host_os.h
drivers/staging/tidspbridge/rmgr/drv.c
drivers/staging/tidspbridge/rmgr/node.c
drivers/staging/zram/zram_drv.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_core.h
drivers/target/iscsi/iscsi_target_login.c
drivers/target/iscsi/iscsi_target_util.c
drivers/target/iscsi/iscsi_target_util.h
drivers/target/target_core_configfs.c
drivers/target/target_core_device.c
drivers/target/target_core_sbc.c
drivers/target/target_core_spc.c
drivers/target/target_core_tmr.c
drivers/target/target_core_transport.c
drivers/thermal/exynos_thermal.c
drivers/thermal/rcar_thermal.c
drivers/tty/serial/omap-serial.c
drivers/usb/core/hub.c
drivers/usb/gadget/net2272.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/xhci-dbg.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/misc/ezusb.c
drivers/usb/musb/musb_dsps.c
drivers/usb/renesas_usbhs/fifo.c
drivers/usb/renesas_usbhs/mod_host.c
drivers/usb/serial/ch341.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/ipw.c
drivers/usb/serial/keyspan.c
drivers/usb/serial/keyspan.h
drivers/usb/serial/mct_u232.c
drivers/usb/serial/metro-usb.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/omninet.c
drivers/usb/serial/opticon.c
drivers/usb/serial/option.c
drivers/usb/serial/qcserial.c
drivers/usb/serial/quatech2.c
drivers/usb/serial/sierra.c
drivers/usb/serial/usb-wwan.h
drivers/usb/serial/usb_wwan.c
drivers/usb/serial/whiteheat.c
drivers/usb/storage/unusual_devs.h
drivers/vhost/net.c
drivers/video/backlight/Kconfig
drivers/video/xen-fbfront.c
drivers/xen/Kconfig
drivers/xen/balloon.c
drivers/xen/dbgp.c
drivers/xen/events.c
drivers/xen/gntdev.c
drivers/xen/grant-table.c
drivers/xen/sys-hypervisor.c
drivers/xen/xen-pciback/vpci.c
drivers/xen/xenbus/xenbus_dev_frontend.c
drivers/xen/xenbus/xenbus_xs.c
fs/bio.c
fs/block_dev.c
fs/btrfs/backref.c
fs/btrfs/backref.h
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/extent_io.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/qgroup.c
fs/btrfs/send.c
fs/btrfs/transaction.c
fs/btrfs/volumes.c
fs/ceph/export.c
fs/char_dev.c
fs/compat_ioctl.c
fs/exec.c
fs/ext4/balloc.c
fs/ext4/bitmap.c
fs/ext4/ext4.h
fs/ext4/ext4_jbd2.c
fs/ext4/extents.c
fs/ext4/ialloc.c
fs/ext4/mballoc.c
fs/ext4/resize.c
fs/ext4/super.c
fs/file.c
fs/jfs/jfs_discard.c
fs/lockd/mon.c
fs/namei.c
fs/nfs/callback.c
fs/nfs/dns_resolve.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/mount_clnt.c
fs/nfs/namespace.c
fs/nfs/nfs4filelayout.c
fs/nfs/nfs4filelayout.h
fs/nfs/nfs4filelayoutdev.c
fs/nfs/nfs4getroot.c
fs/nfs/nfs4namespace.c
fs/nfs/nfs4proc.c
fs/nfs/objlayout/objio_osd.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/super.c
fs/nfs/unlink.c
fs/proc/stat.c
fs/sysfs/dir.c
include/drm/drm_pciids.h
include/linux/atmel-ssc.h
include/linux/dynamic_debug.h
include/linux/extcon.h
include/linux/hashtable.h [new file with mode: 0644]
include/linux/iio/iio.h
include/linux/kvm_host.h
include/linux/memblock.h
include/linux/mfd/max77693.h
include/linux/mfd/wm8994/pdata.h
include/linux/percpu-rwsem.h
include/linux/perf_event.h
include/linux/platform_data/davinci_asp.h
include/linux/raid/Kbuild
include/linux/raid/md_u.h
include/linux/rbtree_augmented.h
include/linux/regmap.h
include/linux/spi/tsc2005.h
include/linux/tcp.h
include/linux/uprobes.h
include/net/cfg80211.h
include/sound/core.h
include/sound/cs4271.h
include/sound/sh_fsi.h
include/sound/tlv320aic32x4.h
include/trace/events/xen.h
include/uapi/linux/raid/Kbuild
include/uapi/linux/raid/md_p.h [moved from include/linux/raid/md_p.h with 100% similarity]
include/uapi/linux/raid/md_u.h [new file with mode: 0644]
include/uapi/linux/tcp.h
include/xen/grant_table.h
include/xen/interface/grant_table.h
include/xen/interface/memory.h
init/main.c
kernel/Makefile
kernel/cgroup.c
kernel/events/uprobes.c
kernel/module_signing.c
kernel/pid_namespace.c
kernel/trace/ring_buffer.c
kernel/workqueue.c
lib/genalloc.c
mm/memblock.c
mm/mmu_notifier.c
mm/page_alloc.c
mm/rmap.c
net/8021q/vlan.c
net/batman-adv/bridge_loop_avoidance.c
net/batman-adv/routing.c
net/batman-adv/types.h
net/bluetooth/smp.c
net/ceph/messenger.c
net/core/skbuff.c
net/ipv4/netfilter/iptable_nat.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_illinois.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_metrics.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_timer.c
net/ipv6/netfilter/ip6table_nat.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/route.c
net/l2tp/l2tp_eth.c
net/mac80211/ibss.c
net/mac80211/iface.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/util.c
net/mac80211/wpa.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/nf_conntrack_h323_main.c
net/netfilter/xt_CT.c
net/netfilter/xt_TEE.c
net/netfilter/xt_nat.c
net/netlink/af_netlink.c
net/sctp/socket.c
net/sunrpc/backchannel_rqst.c
net/sunrpc/xprtsock.c
net/wireless/core.c
net/wireless/mlme.c
net/wireless/reg.c
net/wireless/util.c
security/apparmor/policy.c
security/device_cgroup.c
sound/core/compress_offload.c
sound/core/control.c
sound/core/hwdep.c
sound/core/init.c
sound/core/oss/mixer_oss.c
sound/core/oss/pcm_oss.c
sound/core/pcm.c
sound/core/pcm_native.c
sound/core/rawmidi.c
sound/core/sound.c
sound/core/sound_oss.c
sound/isa/opti9xx/miro.c
sound/pci/als300.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/ice1712/ice1724.c
sound/pci/rme9652/hdspm.c
sound/soc/atmel/sam9g20_wm8731.c
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/ak4104.c
sound/soc/codecs/arizona.h
sound/soc/codecs/cs4271.c
sound/soc/codecs/cs42l52.c
sound/soc/codecs/da9055.c
sound/soc/codecs/si476x.c [new file with mode: 0644]
sound/soc/codecs/tlv320aic32x4.c
sound/soc/codecs/tlv320aic32x4.h
sound/soc/codecs/wm0010.c
sound/soc/codecs/wm2200.c
sound/soc/codecs/wm5102.c
sound/soc/codecs/wm8750.c
sound/soc/codecs/wm8770.c
sound/soc/codecs/wm8958-dsp2.c
sound/soc/codecs/wm8971.c
sound/soc/codecs/wm8978.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8994.h
sound/soc/codecs/wm_adsp.c [new file with mode: 0644]
sound/soc/codecs/wm_adsp.h [new file with mode: 0644]
sound/soc/codecs/wmfw.h [new file with mode: 0644]
sound/soc/davinci/davinci-evm.c
sound/soc/davinci/davinci-mcasp.c
sound/soc/davinci/davinci-mcasp.h
sound/soc/davinci/davinci-pcm.c
sound/soc/davinci/davinci-pcm.h
sound/soc/fsl/Kconfig
sound/soc/fsl/Makefile
sound/soc/fsl/p1022_rdk.c [new file with mode: 0644]
sound/soc/fsl/pcm030-audio-fabric.c
sound/soc/mxs/mxs-saif.c
sound/soc/omap/omap-dmic.c
sound/soc/omap/zoom2.c
sound/soc/samsung/Kconfig
sound/soc/samsung/ac97.c
sound/soc/samsung/bells.c
sound/soc/samsung/i2s.c
sound/soc/samsung/pcm.c
sound/soc/samsung/spdif.c
sound/soc/sh/fsi.c
sound/soc/soc-jack.c
sound/soc/ux500/mop500.c
sound/soc/ux500/ux500_msp_i2s.c
sound/usb/card.c
sound/usb/card.h
sound/usb/mixer.c
sound/usb/mixer_quirks.c
sound/usb/pcm.c
sound/usb/proc.c
sound/usb/stream.c
sound/usb/usbaudio.h
tools/perf/builtin-help.c
tools/perf/builtin-trace.c
tools/perf/util/parse-events-test.c
tools/perf/util/thread.c
tools/testing/ktest/ktest.pl
tools/testing/selftests/epoll/test_epoll.c
tools/vm/page-types.c
usr/gen_init_cpio.c
virt/kvm/kvm_main.c

index f54273e2ac979a386e27c0174e4a9524e60eae5e..ceb1ff735469995b560f0cdf07227407be682235 100644 (file)
@@ -210,6 +210,8 @@ local_ops.txt
        - semantics and behavior of local atomic operations.
 lockdep-design.txt
        - documentation on the runtime locking correctness validator.
+lockup-watchdogs.txt
+       - info on soft and hard lockup detectors (aka nmi_watchdog).
 logo.gif
        - full colour GIF image of Linux logo (penguin - Tux).
 logo.txt
@@ -240,8 +242,6 @@ netlabel/
        - directory with information on the NetLabel subsystem.
 networking/
        - directory with info on various aspects of networking with Linux.
-nmi_watchdog.txt
-       - info on NMI watchdog for SMP systems.
 nommu-mmap.txt
        - documentation about no-mmu memory mapping support.
 numastat.txt
index ecc81e3687153689337859f910cecb33627e8f49..d187e9f7cf1cf8b7fcd5bda6c6507558360a9237 100644 (file)
@@ -8,7 +8,7 @@ PIT Timer required properties:
   shared across all System Controller members.
 
 TC/TCLIB Timer required properties:
-- compatible: Should be "atmel,<chip>-pit".
+- compatible: Should be "atmel,<chip>-tcb".
   <chip> can be "at91rm9200" or "at91sam9x5"
 - reg: Should contain registers location and length
 - interrupts: Should contain all interrupts for the TC block
diff --git a/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt
new file mode 100644 (file)
index 0000000..df70318
--- /dev/null
@@ -0,0 +1,19 @@
+* EETI eGalax Multiple Touch Controller
+
+Required properties:
+- compatible: must be "eeti,egalax_ts"
+- reg: i2c slave address
+- interrupt-parent: the phandle for the interrupt controller
+- interrupts: touch controller interrupt
+- wakeup-gpios: the gpio pin to be used for waking up the controller
+  as well as uased as irq pin
+
+Example:
+
+       egalax_ts@04 {
+               compatible = "eeti,egalax_ts";
+               reg = <0x04>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <9 2>;
+               wakeup-gpios = <&gpio1 9 0>;
+       };
diff --git a/Documentation/devicetree/bindings/misc/atmel-ssc.txt b/Documentation/devicetree/bindings/misc/atmel-ssc.txt
new file mode 100644 (file)
index 0000000..38e51ad
--- /dev/null
@@ -0,0 +1,15 @@
+* Atmel SSC driver.
+
+Required properties:
+- compatible: "atmel,at91rm9200-ssc" or "atmel,at91sam9g45-ssc"
+       - atmel,at91rm9200-ssc: support pdc transfer
+       - atmel,at91sam9g45-ssc: support dma transfer
+- reg: Should contain SSC registers location and length
+- interrupts: Should contain SSC interrupt
+
+Example:
+ssc0: ssc@fffbc000 {
+       compatible = "atmel,at91rm9200-ssc";
+       reg = <0xfffbc000 0x4000>;
+       interrupts = <14 4 5>;
+};
index c8e578263ce2654251aacde50bc1a55fe514e264..683fde93c4fb1ab9dac7d9472f1ad808202d7cf4 100644 (file)
@@ -93,7 +93,7 @@ Valid values for pin and group names are:
 
     With some exceptions, these support nvidia,high-speed-mode,
     nvidia,schmitt, nvidia,low-power-mode, nvidia,pull-down-strength,
-    nvidia,pull-up-strength, nvidia,slew_rate-rising, nvidia,slew_rate-falling.
+    nvidia,pull-up-strength, nvidia,slew-rate-rising, nvidia,slew-rate-falling.
 
     drive_ao1, drive_ao2, drive_at1, drive_at2, drive_cdev1, drive_cdev2,
     drive_csus, drive_dap1, drive_dap2, drive_dap3, drive_dap4, drive_dbg,
index c275b70349c11aedb4e8db6a1982c57bfbfcb619..6f426ed7009e5e43461770787225b398fe68e67f 100644 (file)
@@ -83,7 +83,7 @@ Valid values for pin and group names are:
   drive groups:
 
     These all support nvidia,pull-down-strength, nvidia,pull-up-strength,
-    nvidia,slew_rate-rising, nvidia,slew_rate-falling. Most but not all
+    nvidia,slew-rate-rising, nvidia,slew-rate-falling. Most but not all
     support nvidia,high-speed-mode, nvidia,schmitt, nvidia,low-power-mode.
 
     ao1, ao2, at1, at2, at3, at4, at5, cdev1, cdev2, cec, crt, csus, dap1,
diff --git a/Documentation/devicetree/bindings/sound/ak4104.txt b/Documentation/devicetree/bindings/sound/ak4104.txt
new file mode 100644 (file)
index 0000000..1f8e506
--- /dev/null
@@ -0,0 +1,17 @@
+AK4104 S/PDIF transmitter
+
+This device supports SPI mode only.
+
+Required properties:
+
+  - compatible : "asahi-kasei,ak4104"
+
+  - reg : The chip select number on the SPI bus
+
+Example:
+
+spdif: ak4104@0 {
+       compatible = "asahi-kasei,ak4104";
+       reg = <0>;
+       spi-max-frequency = <5000000>;
+};
index c81b5fd5a5bc80459a1b2d626c9f20b5a86bfbe9..a850fb9c88eab2156ec89f0c76d8ca59073540f8 100644 (file)
@@ -18,6 +18,8 @@ Optional properties:
 
  - reset-gpio:         a GPIO spec to define which pin is connected to the chip's
                !RESET pin
+ - cirrus,amuteb-eq-bmutec:    When given, the Codec's AMUTEB=BMUTEC flag
+                               is enabled.
 
 Examples:
 
index 7eceaff63f5ffb8f45748d0cb1f46b864652b69a..815b711bcd85007569918048b2d3e36fe20fea19 100644 (file)
  High level behavior (mixed):
  ============================
 
- kernel(driver): calls request_firmware(&fw_entry, $FIRMWARE, device)
-
- userspace:
+ 1), kernel(driver):
+       - calls request_firmware(&fw_entry, $FIRMWARE, device)
+       - kernel searchs the fimware image with name $FIRMWARE directly
+       in the below search path of root filesystem:
+               "/lib/firmware/updates/" UTS_RELEASE,
+               "/lib/firmware/updates",
+               "/lib/firmware/" UTS_RELEASE,
+               "/lib/firmware"
+       - If found, goto 7), else goto 2)
+
+ 2), userspace:
        - /sys/class/firmware/xxx/{loading,data} appear.
        - hotplug gets called with a firmware identifier in $FIRMWARE
          and the usual hotplug environment.
                - hotplug: echo 1 > /sys/class/firmware/xxx/loading
 
- kernel: Discard any previous partial load.
3), kernel: Discard any previous partial load.
 
- userspace:
4), userspace:
                - hotplug: cat appropriate_firmware_image > \
                                        /sys/class/firmware/xxx/data
 
- kernel: grows a buffer in PAGE_SIZE increments to hold the image as it
5), kernel: grows a buffer in PAGE_SIZE increments to hold the image as it
         comes in.
 
- userspace:
6), userspace:
                - hotplug: echo 0 > /sys/class/firmware/xxx/loading
 
- kernel: request_firmware() returns and the driver has the firmware
7), kernel: request_firmware() returns and the driver has the firmware
         image in fw_entry->{data,size}. If something went wrong
         request_firmware() returns non-zero and fw_entry is set to
         NULL.
 
- kernel(driver): Driver code calls release_firmware(fw_entry) releasing
8), kernel(driver): Driver code calls release_firmware(fw_entry) releasing
                 the firmware image and any related resource.
 
  High level behavior (driver code):
index a92918e0bd6946f760af42cd984a28ee0e2db642..80654813d04afdf1e76d8388c8c51a1fb31ae825 100644 (file)
@@ -10,7 +10,7 @@ Supported chips:
   BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors
     (not yet published)
 
-Author: Andreas Herrmann <andreas.herrmann3@amd.com>
+Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
 
 Description
 -----------
diff --git a/Documentation/zh_CN/IRQ.txt b/Documentation/zh_CN/IRQ.txt
new file mode 100644 (file)
index 0000000..956026d
--- /dev/null
@@ -0,0 +1,39 @@
+Chinese translated version of Documentation/IRQ.txt
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Eric W. Biederman <ebiederman@xmission.com>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/IRQ.txt 的中文翻译
+
+如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
+交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题,请联系中文版维护者。
+英文版维护者: Eric W. Biederman <ebiederman@xmission.com>
+中文版维护者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版校译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
+
+
+以下为正文
+---------------------------------------------------------------------
+何为 IRQ?
+
+一个 IRQ 是来自某个设备的一个中断请求。目前,它们可以来自一个硬件引脚,
+或来自一个数据包。多个设备可能连接到同个硬件引脚,从而共享一个 IRQ。
+
+一个 IRQ 编号是用于告知硬件中断源的内核标识。通常情况下,这是一个
+全局 irq_desc 数组的索引,但是除了在 linux/interrupt.h 中的实现,
+具体的细节是体系结构特定的。
+
+一个 IRQ 编号是设备上某个可能的中断源的枚举。通常情况下,枚举的编号是
+该引脚在系统内中断控制器的所有输入引脚中的编号。对于 ISA 总线中的情况,
+枚举的是在两个 i8259 中断控制器中 16 个输入引脚。
+
+架构可以对 IRQ 编号指定额外的含义,在硬件涉及任何手工配置的情况下,
+是被提倡的。ISA 的 IRQ 是一个分配这类额外含义的典型例子。
diff --git a/Documentation/zh_CN/arm64/booting.txt b/Documentation/zh_CN/arm64/booting.txt
new file mode 100644 (file)
index 0000000..28fa325
--- /dev/null
@@ -0,0 +1,156 @@
+Chinese translated version of Documentation/arm64/booting.txt
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Will Deacon <will.deacon@arm.com>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/arm64/booting.txt 的中文翻译
+
+如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
+交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题,请联系中文版维护者。
+
+英文版维护者: Will Deacon <will.deacon@arm.com>
+中文版维护者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版校译者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+
+以下为正文
+---------------------------------------------------------------------
+                       启动 AArch64 Linux
+                       ==================
+
+作者: Will Deacon <will.deacon@arm.com>
+日期: 2012 年 09 月 07 日
+
+本文档基于 Russell King 的 ARM 启动文档,且适用于所有公开发布的
+AArch64 Linux 内核代码。
+
+AArch64 异常模型由多个异常级别(EL0 - EL3)组成,对于 EL0 和 EL1
+异常级有对应的安全和非安全模式。EL2 是系统管理级,且仅存在于
+非安全模式下。EL3 是最高特权级,且仅存在于安全模式下。
+
+基于本文档的目的,我们将简单地使用‘引导装载程序’(‘boot loader’)
+这个术语来定义在将控制权交给 Linux 内核前 CPU 上执行的所有软件。
+这可能包含安全监控和系统管理代码,或者它可能只是一些用于准备最小启动
+环境的指令。
+
+基本上,引导装载程序(至少)应实现以下操作:
+
+1、设置和初始化 RAM
+2、设置设备树数据
+3、解压内核映像
+4、调用内核映像
+
+
+1、设置和初始化 RAM
+-----------------
+
+必要性: 强制
+
+引导装载程序应该找到并初始化系统中所有内核用于保持系统变量数据的 RAM。
+这个操作的执行是设备依赖的。(它可能使用内部算法来自动定位和计算所有
+RAM,或可能使用对这个设备已知的 RAM 信息,还可能使用任何引导装载程序
+设计者想到的匹配方法。)
+
+
+2、设置设备树数据
+---------------
+
+必要性: 强制
+
+设备树数据块(dtb)大小必须不大于 2 MB,且位于从内核映像起始算起第一个
+512MB 内的 2MB 边界上。这使得内核可以通过初始页表中的单个节描述符来
+映射此数据块。
+
+
+3、解压内核映像
+-------------
+
+必要性: 可选
+
+AArch64 内核当前没有提供自解压代码,因此如果使用了压缩内核映像文件
+(比如 Image.gz),则需要通过引导装载程序(使用 gzip 等)来进行解压。
+若引导装载程序没有实现这个需求,就要使用非压缩内核映像文件。
+
+
+4、调用内核映像
+-------------
+
+必要性: 强制
+
+已解压的内核映像包含一个 32 字节的头,内容如下:
+
+  u32 magic    = 0x14000008;   /* 跳转到 stext, 小端 */
+  u32 res0     = 0;            /* 保留 */
+  u64 text_offset;             /* 映像装载偏移 */
+  u64 res1     = 0;            /* 保留 */
+  u64 res2     = 0;            /* 保留 */
+
+映像必须位于系统 RAM 起始处的特定偏移(当前是 0x80000)。系统 RAM
+的起始地址必须是以 2MB 对齐的。
+
+在跳转入内核前,必须符合以下状态:
+
+- 停止所有 DMA 设备,这样内存数据就不会因为虚假网络包或磁盘数据而
+  被破坏。这可能可以节省你许多的调试时间。
+
+- 主 CPU 通用寄存器设置
+  x0 = 系统 RAM 中设备树数据块(dtb)的物理地址。
+  x1 = 0 (保留,将来可能使用)
+  x2 = 0 (保留,将来可能使用)
+  x3 = 0 (保留,将来可能使用)
+
+- CPU 模式
+  所有形式的中断必须在 PSTATE.DAIF 中被屏蔽(Debug、SError、IRQ
+  和 FIQ)。
+  CPU 必须处于 EL2(推荐,可访问虚拟化扩展)或非安全 EL1 模式下。
+
+- 高速缓存、MMU
+  MMU 必须关闭。
+  指令缓存开启或关闭都可以。
+  数据缓存必须关闭且无效。
+  外部高速缓存(如果存在)必须配置并禁用。
+
+- 架构计时器
+  CNTFRQ 必须设定为计时器的频率。
+  如果在 EL1 模式下进入内核,则 CNTHCTL_EL2 中的 EL1PCTEN (bit 0)
+  必须置位。
+
+- 一致性
+  通过内核启动的所有 CPU 在内核入口地址上必须处于相同的一致性域中。
+  这可能要根据具体实现来定义初始化过程,以使能每个CPU上对维护操作的
+  接收。
+
+- 系统寄存器
+  在进入内核映像的异常级中,所有构架中可写的系统寄存器必须通过软件
+  在一个更高的异常级别下初始化,以防止在 未知 状态下运行。
+
+引导装载程序必须在每个 CPU 处于以下状态时跳入内核入口:
+
+- 主 CPU 必须直接跳入内核映像的第一条指令。通过此 CPU 传递的设备树
+  数据块必须在每个 CPU 节点中包含以下内容:
+
+    1、‘enable-method’属性。目前,此字段支持的值仅为字符串“spin-table”。
+
+    2、‘cpu-release-addr’标识一个 64-bit、初始化为零的内存位置。
+
+  引导装载程序必须生成这些设备树属性,并在跳入内核入口之前将其插入
+  数据块。
+
+- 任何辅助 CPU 必须在内存保留区(通过设备树中的 /memreserve/ 域传递
+  给内核)中自旋于内核之外,轮询它们的 cpu-release-addr 位置(必须
+  包含在保留区中)。可通过插入 wfe 指令来降低忙循环开销,而主 CPU 将
+  发出 sev 指令。当对 cpu-release-addr 所指位置的读取操作返回非零值
+  时,CPU 必须直接跳入此值所指向的地址。
+
+- 辅助 CPU 通用寄存器设置
+  x0 = 0 (保留,将来可能使用)
+  x1 = 0 (保留,将来可能使用)
+  x2 = 0 (保留,将来可能使用)
+  x3 = 0 (保留,将来可能使用)
diff --git a/Documentation/zh_CN/arm64/memory.txt b/Documentation/zh_CN/arm64/memory.txt
new file mode 100644 (file)
index 0000000..83b5193
--- /dev/null
@@ -0,0 +1,93 @@
+Chinese translated version of Documentation/arm64/memory.txt
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Catalin Marinas <catalin.marinas@arm.com>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/arm64/memory.txt 的中文翻译
+
+如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
+交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题,请联系中文版维护者。
+
+英文版维护者: Catalin Marinas <catalin.marinas@arm.com>
+中文版维护者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版校译者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+
+以下为正文
+---------------------------------------------------------------------
+                    Linux 在 AArch64 中的内存布局
+                    ===========================
+
+作者: Catalin Marinas <catalin.marinas@arm.com>
+日期: 2012 年 02 月 20 日
+
+本文档描述 AArch64 Linux 内核所使用的虚拟内存布局。此构架可以实现
+页大小为 4KB 的 4 级转换表和页大小为 64KB 的 3 级转换表。
+
+AArch64 Linux 使用页大小为 4KB 的 3 级转换表配置,对于用户和内核
+都有 39-bit (512GB) 的虚拟地址空间。对于页大小为 64KB的配置,仅
+使用 2 级转换表,但内存布局相同。
+
+用户地址空间的 63:39 位为 0,而内核地址空间的相应位为 1。TTBRx 的
+选择由虚拟地址的 63 位给出。swapper_pg_dir 仅包含内核(全局)映射,
+而用户 pgd 仅包含用户(非全局)映射。swapper_pgd_dir 地址被写入
+TTBR1 中,且从不写入 TTBR0。
+
+
+AArch64 Linux 内存布局:
+
+起始地址                   结束地址                    大小          用途
+-----------------------------------------------------------------------
+0000000000000000       0000007fffffffff         512GB          用户空间
+
+ffffff8000000000       ffffffbbfffcffff        ~240GB          vmalloc
+
+ffffffbbfffd0000       ffffffbcfffdffff          64KB          [防护页]
+
+ffffffbbfffe0000       ffffffbcfffeffff          64KB          PCI I/O 空间
+
+ffffffbbffff0000       ffffffbcffffffff          64KB          [防护页]
+
+ffffffbc00000000       ffffffbdffffffff           8GB          vmemmap
+
+ffffffbe00000000       ffffffbffbffffff          ~8GB          [防护页,未来用于 vmmemap]
+
+ffffffbffc000000       ffffffbfffffffff          64MB          模块
+
+ffffffc000000000       ffffffffffffffff         256GB          内存空间
+
+
+4KB 页大小的转换表查找:
+
++--------+--------+--------+--------+--------+--------+--------+--------+
+|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
++--------+--------+--------+--------+--------+--------+--------+--------+
+ |                 |         |         |         |         |
+ |                 |         |         |         |         v
+ |                 |         |         |         |   [11:0]  页内偏移
+ |                 |         |         |         +-> [20:12] L3 索引
+ |                 |         |         +-----------> [29:21] L2 索引
+ |                 |         +---------------------> [38:30] L1 索引
+ |                 +-------------------------------> [47:39] L0 索引 (未使用)
+ +-------------------------------------------------> [63] TTBR0/1
+
+
+64KB 页大小的转换表查找:
+
++--------+--------+--------+--------+--------+--------+--------+--------+
+|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
++--------+--------+--------+--------+--------+--------+--------+--------+
+ |                 |    |               |              |
+ |                 |    |               |              v
+ |                 |    |               |            [15:0]  页内偏移
+ |                 |    |               +----------> [28:16] L3 索引
+ |                 |    +--------------------------> [41:29] L2 索引 (仅使用 38:29 )
+ |                 +-------------------------------> [47:42] L1 索引 (未使用)
+ +-------------------------------------------------> [63] TTBR0/1
index 027ec2bfa135d4f5af20801b020c52d1f66a3f3f..59203e77ce9ef8f1a5639e2cad19a006b4e59696 100644 (file)
@@ -503,7 +503,7 @@ F:  include/linux/altera_uart.h
 F:     include/linux/altera_jtaguart.h
 
 AMD FAM15H PROCESSOR POWER MONITORING DRIVER
-M:     Andreas Herrmann <andreas.herrmann3@amd.com>
+M:     Andreas Herrmann <herrmann.der.user@googlemail.com>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/fam15h_power
@@ -637,6 +637,13 @@ W: http://www.arm.linux.org.uk/
 S:     Maintained
 F:     arch/arm/
 
+ARM SUB-ARCHITECTURES
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     MAINTAINED
+F:     arch/arm/mach-*/
+F:     arch/arm/plat-*/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git
+
 ARM PRIMECELL AACI PL041 DRIVER
 M:     Russell King <linux@arm.linux.org.uk>
 S:     Maintained
@@ -2500,6 +2507,7 @@ M:        Joonyoung Shim <jy0922.shim@samsung.com>
 M:     Seung-Woo Kim <sw0312.kim@samsung.com>
 M:     Kyungmin Park <kyungmin.park@samsung.com>
 L:     dri-devel@lists.freedesktop.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git
 S:     Supported
 F:     drivers/gpu/drm/exynos
 F:     include/drm/exynos*
@@ -2802,6 +2810,7 @@ F:        sound/usb/misc/ua101.c
 EXTENSIBLE FIRMWARE INTERFACE (EFI)
 M:     Matt Fleming <matt.fleming@intel.com>
 L:     linux-efi@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git
 S:     Maintained
 F:     Documentation/x86/efi-stub.txt
 F:     arch/ia64/kernel/efi.c
@@ -5061,7 +5070,13 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
 S:     Odd Fixes
 F:     drivers/net/
 F:     include/linux/if_*
-F:     include/linux/*device.h
+F:     include/linux/netdevice.h
+F:     include/linux/arcdevice.h
+F:     include/linux/etherdevice.h
+F:     include/linux/fcdevice.h
+F:     include/linux/fddidevice.h
+F:     include/linux/hippidevice.h
+F:     include/linux/inetdevice.h
 
 NETXEN (1/10) GbE SUPPORT
 M:     Sony Chacko <sony.chacko@qlogic.com>
@@ -5633,7 +5648,7 @@ S:        Maintained
 F:     drivers/pinctrl/spear/
 
 PKTCDVD DRIVER
-M:     Peter Osterlund <petero2@telia.com>
+M:     Jiri Kosina <jkosina@suse.cz>
 S:     Maintained
 F:     drivers/block/pktcdvd.c
 F:     include/linux/pktcdvd.h
index 14c93b39b9291a45d07bd6c4afe8fe792ede241f..a1ccf225c4e95be738bdd6e2b39b01563502b82e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 7
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc4
 NAME = Terrified Chipmunk
 
 # *DOCUMENTATION*
index 4554ecbff7c6527be35fea7d20e255cc0770b653..1f8c72959fb6c7a1a9891833ae8d9b037cb179d5 100644 (file)
@@ -7,6 +7,7 @@
 #include <asm/processor.h>
 #include <asm/types.h>
 #include <asm/hwrpb.h>
+#include <asm/sysinfo.h>
 #endif
 
 #ifndef __ASSEMBLY__
@@ -21,6 +22,7 @@ struct thread_info {
        mm_segment_t            addr_limit;     /* thread address space */
        unsigned                cpu;            /* current CPU */
        int                     preempt_count; /* 0 => preemptable, <0 => BUG */
+       unsigned int            status;         /* thread-synchronous flags */
 
        int bpt_nsaved;
        unsigned long bpt_addr[2];              /* breakpoint handling  */
@@ -63,8 +65,6 @@ register struct thread_info *__current_thread_info __asm__("$8");
  * - these are process state flags and used from assembly
  * - pending work-to-be-done flags come first and must be assigned to be
  *   within bits 0 to 7 to fit in and immediate operand.
- * - ALPHA_UAC_SHIFT below must be kept consistent with the unaligned
- *   control flags.
  *
  * TIF_SYSCALL_TRACE is known to be 0 via blbs.
  */
@@ -72,18 +72,12 @@ register struct thread_info *__current_thread_info __asm__("$8");
 #define TIF_NOTIFY_RESUME      1       /* callback before returning to user */
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
-#define TIF_POLLING_NRFLAG     8       /* poll_idle is polling NEED_RESCHED */
 #define TIF_DIE_IF_KERNEL      9       /* dik recursion lock */
-#define TIF_UAC_NOPRINT                10      /* ! Preserve sequence of following */
-#define TIF_UAC_NOFIX          11      /* ! flags as they match            */
-#define TIF_UAC_SIGBUS         12      /* ! userspace part of 'osf_sysinfo' */
 #define TIF_MEMDIE             13      /* is terminating due to OOM killer */
-#define TIF_RESTORE_SIGMASK    14      /* restore signal mask in do_signal */
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
-#define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 
 /* Work to do on interrupt/exception return.  */
@@ -94,29 +88,63 @@ register struct thread_info *__current_thread_info __asm__("$8");
 #define _TIF_ALLWORK_MASK      (_TIF_WORK_MASK         \
                                 | _TIF_SYSCALL_TRACE)
 
-#define ALPHA_UAC_SHIFT                TIF_UAC_NOPRINT
-#define ALPHA_UAC_MASK         (1 << TIF_UAC_NOPRINT | 1 << TIF_UAC_NOFIX | \
-                                1 << TIF_UAC_SIGBUS)
+#define TS_UAC_NOPRINT         0x0001  /* ! Preserve the following three */
+#define TS_UAC_NOFIX           0x0002  /* ! flags as they match          */
+#define TS_UAC_SIGBUS          0x0004  /* ! userspace part of 'osf_sysinfo' */
+#define TS_RESTORE_SIGMASK     0x0008  /* restore signal mask in do_signal() */
+#define TS_POLLING             0x0010  /* idle task polling need_resched,
+                                          skip sending interrupt */
 
-#define SET_UNALIGN_CTL(task,value)    ({                                   \
-       task_thread_info(task)->flags = ((task_thread_info(task)->flags &    \
-               ~ALPHA_UAC_MASK)                                             \
-               | (((value) << ALPHA_UAC_SHIFT)       & (1<<TIF_UAC_NOPRINT))\
-               | (((value) << (ALPHA_UAC_SHIFT + 1)) & (1<<TIF_UAC_SIGBUS)) \
-               | (((value) << (ALPHA_UAC_SHIFT - 1)) & (1<<TIF_UAC_NOFIX)));\
+#define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING)
+
+#ifndef __ASSEMBLY__
+#define HAVE_SET_RESTORE_SIGMASK       1
+static inline void set_restore_sigmask(void)
+{
+       struct thread_info *ti = current_thread_info();
+       ti->status |= TS_RESTORE_SIGMASK;
+       WARN_ON(!test_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags));
+}
+static inline void clear_restore_sigmask(void)
+{
+       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+}
+static inline bool test_restore_sigmask(void)
+{
+       return current_thread_info()->status & TS_RESTORE_SIGMASK;
+}
+static inline bool test_and_clear_restore_sigmask(void)
+{
+       struct thread_info *ti = current_thread_info();
+       if (!(ti->status & TS_RESTORE_SIGMASK))
+               return false;
+       ti->status &= ~TS_RESTORE_SIGMASK;
+       return true;
+}
+#endif
+
+#define SET_UNALIGN_CTL(task,value)    ({                              \
+       __u32 status = task_thread_info(task)->status & ~UAC_BITMASK;   \
+       if (value & PR_UNALIGN_NOPRINT)                                 \
+               status |= TS_UAC_NOPRINT;                               \
+       if (value & PR_UNALIGN_SIGBUS)                                  \
+               status |= TS_UAC_SIGBUS;                                \
+       if (value & 4)  /* alpha-specific */                            \
+               status |= TS_UAC_NOFIX;                                 \
+       task_thread_info(task)->status = status;                        \
        0; })
 
 #define GET_UNALIGN_CTL(task,value)    ({                              \
-       put_user((task_thread_info(task)->flags & (1 << TIF_UAC_NOPRINT))\
-                 >> ALPHA_UAC_SHIFT                                    \
-                | (task_thread_info(task)->flags & (1 << TIF_UAC_SIGBUS))\
-                >> (ALPHA_UAC_SHIFT + 1)                               \
-                | (task_thread_info(task)->flags & (1 << TIF_UAC_NOFIX))\
-                >> (ALPHA_UAC_SHIFT - 1),                              \
-                (int __user *)(value));                                \
+       __u32 status = task_thread_info(task)->status & ~UAC_BITMASK;   \
+       __u32 res = 0;                                                  \
+       if (status & TS_UAC_NOPRINT)                                    \
+               res |= PR_UNALIGN_NOPRINT;                              \
+       if (status & TS_UAC_SIGBUS)                                     \
+               res |= PR_UNALIGN_SIGBUS;                               \
+       if (status & TS_UAC_NOFIX)                                      \
+               res |= 4;                                               \
+       put_user(res, (int __user *)(value));                           \
        })
 
-#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
-
 #endif /* __KERNEL__ */
 #endif /* _ALPHA_THREAD_INFO_H */
index 9eb090582cf1eb2c557e03025bafc73846fde02f..1e6956a9060809e5b1cfed409d376f2d1e726f43 100644 (file)
@@ -793,8 +793,7 @@ SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer,
        case GSI_UACPROC:
                if (nbytes < sizeof(unsigned int))
                        return -EINVAL;
-               w = (current_thread_info()->flags >> ALPHA_UAC_SHIFT) &
-                       UAC_BITMASK;
+               w = current_thread_info()->status & UAC_BITMASK;
                if (put_user(w, (unsigned int __user *)buffer))
                        return -EFAULT;
                return 1;
@@ -904,24 +903,20 @@ SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer,
                break;
 
        case SSI_NVPAIRS: {
-               unsigned long v, w, i;
-               unsigned int old, new;
+               unsigned __user *p = buffer;
+               unsigned i;
                
-               for (i = 0; i < nbytes; ++i) {
+               for (i = 0, p = buffer; i < nbytes; ++i, p += 2) {
+                       unsigned v, w, status;
 
-                       if (get_user(v, 2*i + (unsigned int __user *)buffer))
-                               return -EFAULT;
-                       if (get_user(w, 2*i + 1 + (unsigned int __user *)buffer))
+                       if (get_user(v, p) || get_user(w, p + 1))
                                return -EFAULT;
                        switch (v) {
                        case SSIN_UACPROC:
-                       again:
-                               old = current_thread_info()->flags;
-                               new = old & ~(UAC_BITMASK << ALPHA_UAC_SHIFT);
-                               new = new | (w & UAC_BITMASK) << ALPHA_UAC_SHIFT;
-                               if (cmpxchg(&current_thread_info()->flags,
-                                           old, new) != old)
-                                       goto again;
+                               w &= UAC_BITMASK;
+                               status = current_thread_info()->status;
+                               status = (status & ~UAC_BITMASK) | w;
+                               current_thread_info()->status = status;
                                break;
  
                        default:
index 4054e0ffe2b25a1055deb3946167755dc73fb201..51987dcf79b83904bd6d5d564db39abe7b7c73f3 100644 (file)
@@ -49,7 +49,7 @@ EXPORT_SYMBOL(pm_power_off);
 void
 cpu_idle(void)
 {
-       set_thread_flag(TIF_POLLING_NRFLAG);
+       current_thread_info()->status |= TS_POLLING;
 
        while (1) {
                /* FIXME -- EV6 and LCA45 know how to power down
index 80d987c0e9aa55889aa3b8ed5d8a25fe9309b1c2..272666d006df1ddd67635caf229221c9b92244c6 100644 (file)
@@ -780,17 +780,17 @@ do_entUnaUser(void __user * va, unsigned long opcode,
        /* Check the UAC bits to decide what the user wants us to do
           with the unaliged access.  */
 
-       if (!test_thread_flag (TIF_UAC_NOPRINT)) {
+       if (!(current_thread_info()->status & TS_UAC_NOPRINT)) {
                if (__ratelimit(&ratelimit)) {
                        printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n",
                               current->comm, task_pid_nr(current),
                               regs->pc - 4, va, opcode, reg);
                }
        }
-       if (test_thread_flag (TIF_UAC_SIGBUS))
+       if ((current_thread_info()->status & TS_UAC_SIGBUS))
                goto give_sigbus;
        /* Not sure why you'd want to use this, but... */
-       if (test_thread_flag (TIF_UAC_NOFIX))
+       if ((current_thread_info()->status & TS_UAC_NOFIX))
                return;
 
        /* Don't bother reading ds in the access check since we already
index 73067efd484530d4021a220fecce329b4752b3c0..ade7e924bef5faaf00de76c0354e025ed4371b35 100644 (file)
@@ -1603,8 +1603,8 @@ config NR_CPUS
        default "4"
 
 config HOTPLUG_CPU
-       bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
-       depends on SMP && HOTPLUG && EXPERIMENTAL
+       bool "Support for hot-pluggable CPUs"
+       depends on SMP && HOTPLUG
        help
          Say Y here to experiment with turning CPUs off and on.  CPUs
          can be controlled through /sys/devices/system/cpu.
@@ -1645,8 +1645,8 @@ config HZ
        default 100
 
 config THUMB2_KERNEL
-       bool "Compile the kernel in Thumb-2 mode (EXPERIMENTAL)"
-       depends on CPU_V7 && !CPU_V6 && !CPU_V6K && EXPERIMENTAL
+       bool "Compile the kernel in Thumb-2 mode"
+       depends on CPU_V7 && !CPU_V6 && !CPU_V6K
        select AEABI
        select ARM_ASM_UNIFIED
        select ARM_UNWIND
@@ -1850,6 +1850,7 @@ config XEN_DOM0
 config XEN
        bool "Xen guest support on ARM (EXPERIMENTAL)"
        depends on EXPERIMENTAL && ARM && OF
+       depends on CPU_V7 && !CPU_V6
        help
          Say Y if you want to run Linux in a Virtual Machine on Xen on ARM.
 
index f023e3acdfbd8c7c17335cfa9518df05119f4ab7..5f914fca911b77b747dd43569b84a76883abcef7 100644 (file)
@@ -21,8 +21,6 @@ endif
 OBJCOPYFLAGS   :=-O binary -R .comment -S
 GZFLAGS                :=-9
 #KBUILD_CFLAGS +=-pipe
-# Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb:
-KBUILD_CFLAGS  +=$(call cc-option,-marm,)
 
 # Never generate .eh_frame
 KBUILD_CFLAGS  += $(call cc-option,-fno-dwarf2-cfi-asm)
@@ -105,17 +103,20 @@ endif
 ifeq ($(CONFIG_THUMB2_KERNEL),y)
 AFLAGS_AUTOIT  :=$(call as-option,-Wa$(comma)-mimplicit-it=always,-Wa$(comma)-mauto-it)
 AFLAGS_NOWARN  :=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W)
-CFLAGS_THUMB2  :=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN)
-AFLAGS_THUMB2  :=$(CFLAGS_THUMB2) -Wa$(comma)-mthumb
+CFLAGS_ISA     :=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN)
+AFLAGS_ISA     :=$(CFLAGS_ISA) -Wa$(comma)-mthumb
 # Work around buggy relocation from gas if requested:
 ifeq ($(CONFIG_THUMB2_AVOID_R_ARM_THM_JUMP11),y)
 CFLAGS_MODULE  +=-fno-optimize-sibling-calls
 endif
+else
+CFLAGS_ISA     :=$(call cc-option,-marm,)
+AFLAGS_ISA     :=$(CFLAGS_ISA)
 endif
 
 # Need -Uarm for gcc < 3.x
-KBUILD_CFLAGS  +=$(CFLAGS_ABI) $(CFLAGS_THUMB2) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
-KBUILD_AFLAGS  +=$(CFLAGS_ABI) $(AFLAGS_THUMB2) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float
+KBUILD_CFLAGS  +=$(CFLAGS_ABI) $(CFLAGS_ISA) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
+KBUILD_AFLAGS  +=$(CFLAGS_ABI) $(AFLAGS_ISA) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float
 
 CHECKFLAGS     += -D__arm__
 
index 3fdab016aa5cfdc9132813f4c5be44348fb1c539..f2aa09eb658e632c7703203d97cd3469d7996259 100644 (file)
@@ -33,7 +33,7 @@ ifeq ($(CONFIG_XIP_KERNEL),y)
 
 $(obj)/xipImage: vmlinux FORCE
        $(call if_changed,objcopy)
-       @echo '  Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))'
+       $(kecho) '  Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))'
 
 $(obj)/Image $(obj)/zImage: FORCE
        @echo 'Kernel configured for XIP (CONFIG_XIP_KERNEL=y)'
@@ -48,14 +48,14 @@ $(obj)/xipImage: FORCE
 
 $(obj)/Image: vmlinux FORCE
        $(call if_changed,objcopy)
-       @echo '  Kernel: $@ is ready'
+       $(kecho) '  Kernel: $@ is ready'
 
 $(obj)/compressed/vmlinux: $(obj)/Image FORCE
        $(Q)$(MAKE) $(build)=$(obj)/compressed $@
 
 $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
        $(call if_changed,objcopy)
-       @echo '  Kernel: $@ is ready'
+       $(kecho) '  Kernel: $@ is ready'
 
 endif
 
@@ -90,7 +90,7 @@ fi
 $(obj)/uImage: $(obj)/zImage FORCE
        @$(check_for_multiple_loadaddr)
        $(call if_changed,uimage)
-       @echo '  Image $@ is ready'
+       $(kecho) '  Image $@ is ready'
 
 $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
        $(Q)$(MAKE) $(build)=$(obj)/bootp $@
@@ -98,7 +98,7 @@ $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
 
 $(obj)/bootpImage: $(obj)/bootp/bootp FORCE
        $(call if_changed,objcopy)
-       @echo '  Kernel: $@ is ready'
+       $(kecho) '  Kernel: $@ is ready'
 
 PHONY += initrd FORCE
 initrd:
index d410581a5a859901b32a49a1f037356c9f22e294..aaa42d8d4f8895233bdaddc00b3bdf69775e0379 100644 (file)
@@ -29,6 +29,7 @@
                tcb0 = &tcb0;
                tcb1 = &tcb1;
                i2c0 = &i2c0;
+               ssc0 = &ssc0;
        };
        cpus {
                cpu@0 {
                                status = "disabled";
                        };
 
+                       ssc0: ssc@fffbc000 {
+                               compatible = "atmel,at91rm9200-ssc";
+                               reg = <0xfffbc000 0x4000>;
+                               interrupts = <14 4 5>;
+                               status = "disable";
+                       };
+
                        adc0: adc@fffe0000 {
                                compatible = "atmel,at91sam9260-adc";
                                reg = <0xfffe0000 0x100>;
index 3e6e5c1abbf37184a44237e464080a52f4312e9f..3b721ee59b109500b688bebff12e098f0aaf05ce 100644 (file)
@@ -25,6 +25,8 @@
                gpio4 = &pioE;
                tcb0 = &tcb0;
                i2c0 = &i2c0;
+               ssc0 = &ssc0;
+               ssc1 = &ssc1;
        };
        cpus {
                cpu@0 {
                                status = "disabled";
                        };
 
+                       ssc0: ssc@fff98000 {
+                               compatible = "atmel,at91rm9200-ssc";
+                               reg = <0xfff98000 0x4000>;
+                               interrupts = <16 4 5>;
+                               status = "disable";
+                       };
+
+                       ssc1: ssc@fff9c000 {
+                               compatible = "atmel,at91rm9200-ssc";
+                               reg = <0xfff9c000 0x4000>;
+                               interrupts = <17 4 5>;
+                               status = "disable";
+                       };
+
                        macb0: ethernet@fffbc000 {
                                compatible = "cdns,at32ap7000-macb", "cdns,macb";
                                reg = <0xfffbc000 0x100>;
index b06c0db273b1fff820543d692b2a0470efe6b8f2..e6391a4e6649cc3787ba14d7ed1d190b2d932964 100644 (file)
                #size-cells = <0>;
 
                btn3 {
-                       label = "Buttin 3";
+                       label = "Button 3";
                        gpios = <&pioA 30 1>;
                        linux,code = <0x103>;
                        gpio-key,wakeup;
                };
 
                btn4 {
-                       label = "Buttin 4";
+                       label = "Button 4";
                        gpios = <&pioA 31 1>;
                        linux,code = <0x104>;
                        gpio-key,wakeup;
index 3add030d61f8651fcf5a0476b11423897de71560..acfa207162ff581eaaf063c4d3154a6f658ea177 100644 (file)
@@ -31,6 +31,8 @@
                tcb1 = &tcb1;
                i2c0 = &i2c0;
                i2c1 = &i2c1;
+               ssc0 = &ssc0;
+               ssc1 = &ssc1;
        };
        cpus {
                cpu@0 {
                                status = "disabled";
                        };
 
+                       ssc0: ssc@fff9c000 {
+                               compatible = "atmel,at91sam9g45-ssc";
+                               reg = <0xfff9c000 0x4000>;
+                               interrupts = <16 4 5>;
+                               status = "disable";
+                       };
+
+                       ssc1: ssc@fffa0000 {
+                               compatible = "atmel,at91sam9g45-ssc";
+                               reg = <0xfffa0000 0x4000>;
+                               interrupts = <17 4 5>;
+                               status = "disable";
+                       };
+
                        adc0: adc@fffb0000 {
                                compatible = "atmel,at91sam9260-adc";
                                reg = <0xfffb0000 0x100>;
index 03fc136421c5e31b01649c9caacdaf134bef4560..69667d0ac347f142a51c5acc704e731763ec2144 100644 (file)
@@ -30,6 +30,7 @@
                i2c0 = &i2c0;
                i2c1 = &i2c1;
                i2c2 = &i2c2;
+               ssc0 = &ssc0;
        };
        cpus {
                cpu@0 {
                                interrupts = <1 4 7>;
                        };
 
+                       ssc0: ssc@f0010000 {
+                               compatible = "atmel,at91sam9g45-ssc";
+                               reg = <0xf0010000 0x4000>;
+                               interrupts = <28 4 5>;
+                               status = "disable";
+                       };
+
                        tcb0: timer@f8008000 {
                                compatible = "atmel,at91sam9x5-tcb";
                                reg = <0xf8008000 0x100>;
index 748ba7aa746cde3e14b8f04105f2dbd86fc6b214..4b0e0ca08f40d3d81b90be09b8cce47b9b225fac 100644 (file)
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x80004000 0x1000>;
                        interrupts = <0 21 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x80122000 0x1000>;
                        interrupts = <0 22 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x80128000 0x1000>;
                        interrupts = <0 55 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x80110000 0x1000>;
                        interrupts = <0 12 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x8012a000 0x1000>;
                        interrupts = <0 51 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        interrupts = <0 60 0x4>;
                        status = "disabled";
                };
+
                sdi@80118000 {
                        compatible = "arm,pl18x", "arm,primecell";
                        reg = <0x80118000 0x1000>;
                        interrupts = <0 50 0x4>;
                        status = "disabled";
                };
+
                sdi@80005000 {
                        compatible = "arm,pl18x", "arm,primecell";
                        reg = <0x80005000 0x1000>;
                        interrupts = <0 41 0x4>;
                        status = "disabled";
                };
+
                sdi@80119000 {
                        compatible = "arm,pl18x", "arm,primecell";
                        reg = <0x80119000 0x1000>;
                        interrupts = <0 59 0x4>;
                        status = "disabled";
                };
+
                sdi@80114000 {
                        compatible = "arm,pl18x", "arm,primecell";
                        reg = <0x80114000 0x1000>;
                        interrupts = <0 99 0x4>;
                        status = "disabled";
                };
+
                sdi@80008000 {
                        compatible = "arm,pl18x", "arm,primecell";
-                       reg = <0x80114000 0x1000>;
+                       reg = <0x80008000 0x1000>;
                        interrupts = <0 100 0x4>;
                        status = "disabled";
                };
index 73567b843e72ae28e9ba4e721c8607a6135bf288..a21511c140712e24c4759293ac66248bbb8ae309 100644 (file)
        compatible = "samsung,trats", "samsung,exynos4210";
 
        memory {
-               reg =  <0x40000000 0x20000000
-                       0x60000000 0x20000000>;
+               reg =  <0x40000000 0x10000000
+                       0x50000000 0x10000000
+                       0x60000000 0x10000000
+                       0x70000000 0x10000000>;
        };
 
        chosen {
index 9ca4ca70c1bcb8f680fde33b924045eb6666839d..6d31aa3834608d41d84d848ec954f00a064a4659 100644 (file)
@@ -69,6 +69,7 @@
                                interrupts = <13>, <56>;
                                interrupt-names = "gpmi-dma", "bch";
                                clocks = <&clks 34>;
+                               clock-names = "gpmi_io";
                                fsl,gpmi-dma-channel = <4>;
                                status = "disabled";
                        };
index e16d631554802f73227de6bcab58368d9e049227..55c57ea6169e02ec9dc81bb8e38407c608678bbd 100644 (file)
@@ -85,6 +85,7 @@
                                interrupts = <88>, <41>;
                                interrupt-names = "gpmi-dma", "bch";
                                clocks = <&clks 50>;
+                               clock-names = "gpmi_io";
                                fsl,gpmi-dma-channel = <4>;
                                status = "disabled";
                        };
index f38ea8771b44fb1b1ffe71830e74bed6d628ef66..696e929d0304ff72580e83510771c1ba0048b91f 100644 (file)
                        interrupt-names = "common", "tx", "rx", "sidetone";
                        interrupt-parent = <&intc>;
                        ti,buffer-size = <1280>;
-                       ti,hwmods = "mcbsp2";
+                       ti,hwmods = "mcbsp2", "mcbsp2_sidetone";
                };
 
                mcbsp3: mcbsp@49024000 {
                        interrupt-names = "common", "tx", "rx", "sidetone";
                        interrupt-parent = <&intc>;
                        ti,buffer-size = <128>;
-                       ti,hwmods = "mcbsp3";
+                       ti,hwmods = "mcbsp3", "mcbsp3_sidetone";
                };
 
                mcbsp4: mcbsp@49026000 {
index 66aa7a6db884c14668be9f20a6d27166c85a8c1f..394ded624e375a8e1e36b04ee5b85cefbf5c9391 100644 (file)
@@ -139,6 +139,7 @@ CONFIG_I2C_IMX=y
 CONFIG_SPI=y
 CONFIG_SPI_IMX=y
 CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_MC9S08DZ60=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_IMX2_WDT=y
@@ -155,6 +156,7 @@ CONFIG_SOC_CAMERA=y
 CONFIG_SOC_CAMERA_OV2640=y
 CONFIG_VIDEO_MX3=y
 CONFIG_FB=y
+CONFIG_LCD_PLATFORM=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_LCD_L4F00242T03=y
index 7bcf850eddcd7f2c843c0b297eda1f24125cc03c..3458752c4bb277da7d3574e050f847add462cc0a 100644 (file)
@@ -1,6 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
-CONFIG_NO_HZ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
@@ -9,10 +9,12 @@ CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_MVEBU=y
-CONFIG_MACH_ARMADA_370_XP=y
+CONFIG_MACH_ARMADA_370=y
+CONFIG_MACH_ARMADA_XP=y
+# CONFIG_CACHE_L2X0 is not set
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_USE_OF=y
+# CONFIG_COMPACTION is not set
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
@@ -23,6 +25,8 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
index cdd4d2bd39620bf97bfecfdc8c0bcc35e0ee0356..2ba9e63d0f177142699a56e4a4b3408cee10df43 100644 (file)
@@ -1,3 +1,4 @@
+CONFIG_ARCH_VERSATILE=y
 CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SYSVIPC=y
index 59426a4595c9cb90bcb765843f89295bd20f6797..e847d23351eda71ada1bc200476ee7f427a4e8ac 100644 (file)
@@ -8,7 +8,7 @@
 #define        flat_argvp_envp_on_stack()              1
 #define        flat_old_ram_flag(flags)                (flags)
 #define        flat_reloc_valid(reloc, size)           ((reloc) <= (size))
-#define        flat_get_addr_from_rp(rp, relval, flags, persistent) get_unaligned(rp)
+#define        flat_get_addr_from_rp(rp, relval, flags, persistent) ((void)persistent,get_unaligned(rp))
 #define        flat_put_addr_at_rp(rp, val, relval)    put_unaligned(val,rp)
 #define        flat_get_relocate_addr(rel)             (rel)
 #define        flat_set_persistent(relval, p)          0
index 77bd79f2ffdbd0344d096ca7fb2db809fb52d387..7e1f76027f666e252c35bd320d4518e110548c47 100644 (file)
@@ -200,8 +200,8 @@ extern int __put_user_8(void *, unsigned long long);
 #define USER_DS                        KERNEL_DS
 
 #define segment_eq(a,b)                (1)
-#define __addr_ok(addr)                (1)
-#define __range_ok(addr,size)  (0)
+#define __addr_ok(addr)                ((void)(addr),1)
+#define __range_ok(addr,size)  ((void)(addr),0)
 #define get_fs()               (KERNEL_DS)
 
 static inline void set_fs(mm_segment_t fs)
index ae05e56dd17d6eb2e270117172dbc327f27b82d2..5000397134b4e5ceb06521ecf1d22622a0918a82 100644 (file)
 
 #ifndef __ASSEMBLY__
 /* Explicitly size integers that represent pfns in the interface with
- * Xen so that we can have one ABI that works for 32 and 64 bit guests. */
+ * Xen so that we can have one ABI that works for 32 and 64 bit guests.
+ * Note that this means that the xen_pfn_t type may be capable of
+ * representing pfn's which the guest cannot represent in its own pfn
+ * type. However since pfn space is controlled by the guest this is
+ * fine since it simply wouldn't be able to create any sure pfns in
+ * the first place.
+ */
 typedef uint64_t xen_pfn_t;
+#define PRI_xen_pfn "llx"
 typedef uint64_t xen_ulong_t;
+#define PRI_xen_ulong "llx"
 /* Guest handles for primitive C types. */
 __DEFINE_GUEST_HANDLE(uchar, unsigned char);
 __DEFINE_GUEST_HANDLE(uint,  unsigned int);
-__DEFINE_GUEST_HANDLE(ulong, unsigned long);
 DEFINE_GUEST_HANDLE(char);
 DEFINE_GUEST_HANDLE(int);
-DEFINE_GUEST_HANDLE(long);
 DEFINE_GUEST_HANDLE(void);
 DEFINE_GUEST_HANDLE(uint64_t);
 DEFINE_GUEST_HANDLE(uint32_t);
index 174202318dfff2779ece119e7b45949b82f429e0..c6b9096cef9593fe6508f13768802e1fba98d64c 100644 (file)
@@ -10,7 +10,7 @@
 #include <xen/interface/grant_table.h>
 
 #define pfn_to_mfn(pfn)                        (pfn)
-#define phys_to_machine_mapping_valid  (1)
+#define phys_to_machine_mapping_valid(pfn) (1)
 #define mfn_to_pfn(mfn)                        (mfn)
 #define mfn_to_virt(m)                 (__va(mfn_to_pfn(m) << PAGE_SHIFT))
 
@@ -30,6 +30,8 @@ typedef struct xpaddr {
 #define XMADDR(x)      ((xmaddr_t) { .maddr = (x) })
 #define XPADDR(x)      ((xpaddr_t) { .paddr = (x) })
 
+#define INVALID_P2M_ENTRY      (~0UL)
+
 static inline xmaddr_t phys_to_machine(xpaddr_t phys)
 {
        unsigned offset = phys.paddr & ~PAGE_MASK;
@@ -74,9 +76,14 @@ static inline int m2p_remove_override(struct page *page, bool clear_pte)
        return 0;
 }
 
+static inline bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+{
+       BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+       return true;
+}
+
 static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 {
-       BUG();
-       return false;
+       return __set_phys_to_machine(pfn, mfn);
 }
 #endif /* _ASM_ARM_XEN_PAGE_H */
diff --git a/arch/arm/include/debug/8250_32.S b/arch/arm/include/debug/8250_32.S
new file mode 100644 (file)
index 0000000..8db01ee
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * 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.
+ *
+ * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit
+ * accesses to the 8250.
+ */
+
+#include <linux/serial_reg.h>
+
+               .macro  senduart,rd,rx
+               str     \rd, [\rx, #UART_TX << UART_SHIFT]
+               .endm
+
+               .macro  busyuart,rd,rx
+1002:          ldr     \rd, [\rx, #UART_LSR << UART_SHIFT]
+               and     \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
+               teq     \rd, #UART_LSR_TEMT | UART_LSR_THRE
+               bne     1002b
+               .endm
+
+               /* The UART's don't have any flow control IO's wired up. */
+               .macro  waituart,rd,rx
+               .endm
index 7419deb1b948f1b8954a6579db72b951b30880bb..bc1f07c49cd4a5628a9e7c2957597589b2d42f2a 100644 (file)
@@ -5,10 +5,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit
- * accesses to the 8250.
  */
-#include <linux/serial_reg.h>
 
 #define UART_SHIFT 2
 #define PICOXCELL_UART1_BASE           0x80230000
                ldr     \rp, =PICOXCELL_UART1_BASE
                .endm
 
-               .macro  senduart,rd,rx
-               str     \rd, [\rx, #UART_TX << UART_SHIFT]
-               .endm
-
-               .macro  busyuart,rd,rx
-1002:          ldr     \rd, [\rx, #UART_LSR << UART_SHIFT]
-               and     \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
-               teq     \rd, #UART_LSR_TEMT | UART_LSR_THRE
-               bne     1002b
-               .endm
-
-               /* The UART's don't have any flow control IO's wired up. */
-               .macro  waituart,rd,rx
-               .endm
+#include "8250_32.S"
index d6f26d23374fbe9e224c7f65e0a0fc6bac85b81b..966b2f994946daf901631bfa690f86535eb70f1b 100644 (file)
@@ -7,6 +7,9 @@
  * published by the Free Software Foundation.
  */
 
+#define UART_SHIFT 2
+#define DEBUG_LL_UART_OFFSET   0x00002000
+
                .macro  addruart, rp, rv, tmp
                mov     \rp, #DEBUG_LL_UART_OFFSET
                orr     \rp, \rp, #0x00c00000
@@ -14,3 +17,5 @@
                orr     \rp, \rp, #0xff000000   @ physical base
                .endm
 
+#include "8250_32.S"
+
index 16cedb42c0c39c0169008e45488b279cd9b32821..896165096d6a936572bdcfd0d21cc23f01cb9ea2 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/list.h>
 #include <linux/kallsyms.h>
 #include <linux/proc_fs.h>
+#include <linux/export.h>
 
 #include <asm/exception.h>
 #include <asm/mach/arch.h>
@@ -109,6 +110,7 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)
        /* Order is clear bits in "clr" then set bits in "set" */
        irq_modify_status(irq, clr, set & ~clr);
 }
+EXPORT_SYMBOL_GPL(set_irq_flags);
 
 void __init init_IRQ(void)
 {
index 38c1a3b103a0684b5b579bb74ca07f38bb91eb13..83931290506704ad226e8a8cb2a15b52a33d4494 100644 (file)
@@ -366,7 +366,9 @@ void kprobe_arm_test_cases(void)
        TEST_UNSUPPORTED(".word 0xe04f0392 @ umaal r0, pc, r2, r3")
        TEST_UNSUPPORTED(".word 0xe0500090 @ undef")
        TEST_UNSUPPORTED(".word 0xe05fff9f @ undef")
+#endif
 
+#if __LINUX_ARM_ARCH__ >= 7
        TEST_RRR(  "mls         r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
        TEST_RRR(  "mlshi       r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
        TEST_RR(   "mls         lr, r",1, VAL2,", r",2, VAL3,", r13")
@@ -456,6 +458,8 @@ void kprobe_arm_test_cases(void)
        TEST_UNSUPPORTED(".word 0xe1700090") /* Unallocated space */
 #if __LINUX_ARM_ARCH__ >= 6
        TEST_UNSUPPORTED("ldrex r2, [sp]")
+#endif
+#if (__LINUX_ARM_ARCH__ >= 7) || defined(CONFIG_CPU_32v6K)
        TEST_UNSUPPORTED("strexd        r0, r2, r3, [sp]")
        TEST_UNSUPPORTED("ldrexd        r2, r3, [sp]")
        TEST_UNSUPPORTED("strexb        r0, r2, [sp]")
index e29c3337ca8142aeb6f4bb755e3947d6aecd4fbe..8ef8c9337809cbe5ccb91b33525c38a379e9e986 100644 (file)
@@ -45,10 +45,9 @@ int machine_kexec_prepare(struct kimage *image)
        for (i = 0; i < image->nr_segments; i++) {
                current_segment = &image->segment[i];
 
-               err = memblock_is_region_memory(current_segment->mem,
-                                               current_segment->memsz);
-               if (err)
-                       return - EINVAL;
+               if (!memblock_is_region_memory(current_segment->mem,
+                                              current_segment->memsz))
+                       return -EINVAL;
 
                err = get_user(header, (__be32*)current_segment->buf);
                if (err)
index 93971b1a4f0bb0d38eebd573f8618e994273b079..53c0304b734a4e6ad7b1806b147baa3d2d43986f 100644 (file)
@@ -96,6 +96,10 @@ armpmu_event_set_period(struct perf_event *event,
        s64 period = hwc->sample_period;
        int ret = 0;
 
+       /* The period may have been changed by PERF_EVENT_IOC_PERIOD */
+       if (unlikely(period != hwc->last_period))
+               left = period - (hwc->last_period - left);
+
        if (unlikely(left <= -period)) {
                left = period;
                local64_set(&hwc->period_left, left);
index 8e20754dd31d5946f5297aae2023ae2c8d5cd572..fbc8b2623d82f08c8c2926375a7b8a31f943361b 100644 (file)
@@ -294,18 +294,24 @@ static void percpu_timer_setup(void);
 asmlinkage void __cpuinit secondary_start_kernel(void)
 {
        struct mm_struct *mm = &init_mm;
-       unsigned int cpu = smp_processor_id();
+       unsigned int cpu;
+
+       /*
+        * The identity mapping is uncached (strongly ordered), so
+        * switch away from it before attempting any exclusive accesses.
+        */
+       cpu_switch_mm(mm->pgd, mm);
+       enter_lazy_tlb(mm, current);
+       local_flush_tlb_all();
 
        /*
         * All kernel threads share the same mm context; grab a
         * reference and switch to it.
         */
+       cpu = smp_processor_id();
        atomic_inc(&mm->mm_count);
        current->active_mm = mm;
        cpumask_set_cpu(cpu, mm_cpumask(mm));
-       cpu_switch_mm(mm->pgd, mm);
-       enter_lazy_tlb(mm, current);
-       local_flush_tlb_all();
 
        printk("CPU%u: Booted secondary processor\n", cpu);
 
index e1f906989bb8161963d8a714073a8d84a8e2c2e6..b22d700fea2751c60b5dbad689ee0b18305108b3 100644 (file)
@@ -42,10 +42,10 @@ static void twd_set_mode(enum clock_event_mode mode,
 
        switch (mode) {
        case CLOCK_EVT_MODE_PERIODIC:
-               /* timer load already set up */
                ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
                        | TWD_TIMER_CONTROL_PERIODIC;
-               __raw_writel(twd_timer_rate / HZ, twd_base + TWD_TIMER_LOAD);
+               __raw_writel(DIV_ROUND_CLOSEST(twd_timer_rate, HZ),
+                       twd_base + TWD_TIMER_LOAD);
                break;
        case CLOCK_EVT_MODE_ONESHOT:
                /* period set, and timer enabled in 'next_event' hook */
index 9d0a30032d7f0f2ae50f0cbe9eebb80d6da827a3..0dc53854a5d8eb423e468fe255cb0f7c1fa30e15 100644 (file)
@@ -45,6 +45,7 @@ int read_current_timer(unsigned long *timer_val)
        *timer_val = delay_timer->read_current_timer();
        return 0;
 }
+EXPORT_SYMBOL_GPL(read_current_timer);
 
 static void __timer_delay(unsigned long cycles)
 {
index b14207101938adb03c852a708a2261e4a58d6f3d..043624219b55a25ebdc50c86a7399dda604392a3 100644 (file)
@@ -21,19 +21,13 @@ config SOC_AT91SAM9
        bool
        select CPU_ARM926T
        select GENERIC_CLOCKEVENTS
+       select MULTI_IRQ_HANDLER
+       select SPARSE_IRQ
 
 menu "Atmel AT91 System-on-Chip"
 
 comment "Atmel AT91 Processor"
 
-config SOC_AT91SAM9
-       bool
-       select AT91_SAM9_SMC
-       select AT91_SAM9_TIME
-       select CPU_ARM926T
-       select MULTI_IRQ_HANDLER
-       select SPARSE_IRQ
-
 config SOC_AT91RM9200
        bool "AT91RM9200"
        select CPU_ARM920T
index b4f0565aff638af135c7797b430bbfeb2a29b439..af47c75db513b58a88be84e52f2e681ec863908c 100644 (file)
@@ -184,10 +184,13 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tc3_clk),
        CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
        CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200", &twi_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.2", &ssc2_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffd0000.ssc", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffd4000.ssc", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffd8000.ssc", &ssc2_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200.0", &twi_clk),
        /* fake hclk clock */
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
index a563189cdfc3e1bfd4bdc2e71049073de01cd712..f40925a552a1534c18c47ec37e2c98c61cdc2d81 100644 (file)
@@ -479,7 +479,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91rm9200_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -512,7 +512,7 @@ static struct resource twi_resources[] = {
 
 static struct platform_device at91rm9200_twi_device = {
        .name           = "i2c-at91rm9200",
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
@@ -752,7 +752,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91rm9200_ssc0_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 0,
        .dev    = {
                .dma_mask               = &ssc0_dmamask,
@@ -794,7 +794,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91rm9200_ssc1_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 1,
        .dev    = {
                .dma_mask               = &ssc1_dmamask,
@@ -836,7 +836,7 @@ static struct resource ssc2_resources[] = {
 };
 
 static struct platform_device at91rm9200_ssc2_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 2,
        .dev    = {
                .dma_mask               = &ssc2_dmamask,
index ad29f93f20cab175555cd2a8c2974deff0fe31fd..a41eb3d23f68dc282cc51117427ea446db7b97e5 100644 (file)
@@ -210,9 +210,10 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tc3_clk),
        CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
        CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20", &twi_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffbc000.ssc", &ssc_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi_clk),
        /* more usart lookup table for DT entries */
        CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
        CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk),
index a76b8684f52d07328fcfe2f4a08726124b643f5a..df7bebf07f101b973557fa15ce31516801e5a38d 100644 (file)
@@ -389,7 +389,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91sam9260_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -421,7 +421,7 @@ static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91sam9260_twi_device = {
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
@@ -742,7 +742,7 @@ static struct resource ssc_resources[] = {
 };
 
 static struct platform_device at91sam9260_ssc_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 0,
        .dev    = {
                .dma_mask               = &ssc_dmamask,
@@ -768,6 +768,14 @@ static inline void configure_ssc_pins(unsigned pins)
                at91_set_A_periph(AT91_PIN_PB21, 1);
 }
 
+static struct platform_device at91sam9260_ssc_dai_device = {
+       .name   = "atmel-ssc-dai",
+       .id     = 0,
+       .dev    = {
+               .parent = &(at91sam9260_ssc_device.dev),
+       },
+};
+
 /*
  * SSC controllers are accessed through library code, instead of any
  * kind of all-singing/all-dancing driver.  For example one could be
@@ -792,6 +800,7 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins)
        }
 
        platform_device_register(pdev);
+       platform_device_register(&at91sam9260_ssc_dai_device);
 }
 
 #else
index 8d999eb1a137f1ed72529d296774c084d17da1a4..7fcbe05833426b7b648a145b796619f4e47d7d5b 100644 (file)
@@ -174,12 +174,15 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
        CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
        CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.2", &ssc2_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffbc000.ssc", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffc0000.ssc", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffc4000.ssc", &ssc2_clk),
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261", &twi_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261.0", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
        CLKDEV_CON_ID("pioB", &pioB_clk),
        CLKDEV_CON_ID("pioC", &pioC_clk),
index 9752f17efba9926501a23b8e5209fbabcdfedc6d..d8afd2130b7994dccfe38138ba980ab3269ff4d5 100644 (file)
@@ -285,7 +285,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91sam9261_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -317,7 +317,7 @@ static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91sam9261_twi_device = {
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
@@ -706,7 +706,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91sam9261_ssc0_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 0,
        .dev    = {
                .dma_mask               = &ssc0_dmamask,
@@ -748,7 +748,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91sam9261_ssc1_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 1,
        .dev    = {
                .dma_mask               = &ssc1_dmamask,
@@ -790,7 +790,7 @@ static struct resource ssc2_resources[] = {
 };
 
 static struct platform_device at91sam9261_ssc2_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 2,
        .dev    = {
                .dma_mask               = &ssc2_dmamask,
index 6a01d0360dfb8940cbaaa2affc9bb58f88d702d9..c0f4c8c1f4ed59ad31cd004a317e7f436181285c 100644 (file)
@@ -186,14 +186,16 @@ static struct clk *periph_clocks[] __initdata = {
 static struct clk_lookup periph_clocks_lookups[] = {
        /* One additional fake clock for macb_hclk */
        CLKDEV_CON_ID("hclk", &macb_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fff98000.ssc", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fff9c000.ssc", &ssc1_clk),
        CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.0", &mmc0_clk),
        CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.1", &mmc1_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
        /* fake hclk clock */
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
index 8dde220b42b69c785c70118a16e48a1aa20acb95..025c9704bfe6c8763e1ec8fc119cacf885270a87 100644 (file)
@@ -567,7 +567,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91sam9263_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -600,7 +600,7 @@ static struct resource twi_resources[] = {
 
 static struct platform_device at91sam9263_twi_device = {
        .name           = "i2c-at91sam9260",
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
@@ -1199,7 +1199,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91sam9263_ssc0_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 0,
        .dev    = {
                .dma_mask               = &ssc0_dmamask,
@@ -1241,7 +1241,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91sam9263_ssc1_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 1,
        .dev    = {
                .dma_mask               = &ssc1_dmamask,
index 84af1b506d92a0b1e9e88c885b1d57be95fbf40b..a4282d3742bf11098fed3a8101285b94eafeddbe 100644 (file)
@@ -239,8 +239,10 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tcb0_clk),
        CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi0_clk),
        CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.1", &twi1_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91sam9g45_ssc.0", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91sam9g45_ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fff9c000.ssc", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffa0000.ssc", &ssc1_clk),
        CLKDEV_CON_DEV_ID(NULL, "atmel-trng", &trng_clk),
        CLKDEV_CON_DEV_ID(NULL, "atmel_sha", &aestdessha_clk),
        CLKDEV_CON_DEV_ID(NULL, "atmel_tdes", &aestdessha_clk),
index b1596072dcc23cd1414a8449eb4c25a35ed11222..27e3bf64a8bc3c2c845b9869252f3be01f30b296 100644 (file)
@@ -1459,7 +1459,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91sam9g45_ssc0_device = {
-       .name   = "ssc",
+       .name   = "at91sam9g45_ssc",
        .id     = 0,
        .dev    = {
                .dma_mask               = &ssc0_dmamask,
@@ -1501,7 +1501,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91sam9g45_ssc1_device = {
-       .name   = "ssc",
+       .name   = "at91sam9g45_ssc",
        .id     = 1,
        .dev    = {
                .dma_mask               = &ssc1_dmamask,
index 72e908412222615134fc0530cc339348093f76be..b683fdc699f12e1a97dc3c60fdf07f9abd7a02f1 100644 (file)
@@ -184,8 +184,10 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
        CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
        CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
-       CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.0", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffc0000.ssc", &ssc0_clk),
+       CLKDEV_CON_DEV_ID("pclk", "fffc4000.ssc", &ssc1_clk),
        CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi0_clk),
        CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.1", &twi1_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
index d6ca0543ce8d7f1054d8f25614cd17369efe283d..b656110e8afe6fec0a55fa15edc3084301f54409 100644 (file)
@@ -314,7 +314,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91sam9rl_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -347,7 +347,7 @@ static struct resource twi_resources[] = {
 
 static struct platform_device at91sam9rl_twi_device = {
        .name           = "i2c-at91sam9g20",
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
@@ -832,7 +832,7 @@ static struct resource ssc0_resources[] = {
 };
 
 static struct platform_device at91sam9rl_ssc0_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 0,
        .dev    = {
                .dma_mask               = &ssc0_dmamask,
@@ -874,7 +874,7 @@ static struct resource ssc1_resources[] = {
 };
 
 static struct platform_device at91sam9rl_ssc1_device = {
-       .name   = "ssc",
+       .name   = "at91rm9200_ssc",
        .id     = 1,
        .dev    = {
                .dma_mask               = &ssc1_dmamask,
index e5035380dcbce16e806fb460625fd73d9a3c1153..18fbbb27f97fcbb7a191867af7edaa0c2c1f4e8a 100644 (file)
@@ -231,6 +231,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t0_clk", "f800c000.timer", &tcb0_clk),
        CLKDEV_CON_DEV_ID("dma_clk", "ffffec00.dma-controller", &dma0_clk),
        CLKDEV_CON_DEV_ID("dma_clk", "ffffee00.dma-controller", &dma1_clk),
+       CLKDEV_CON_DEV_ID("pclk", "f0010000.ssc", &ssc_clk),
        CLKDEV_CON_DEV_ID(NULL, "f8010000.i2c", &twi0_clk),
        CLKDEV_CON_DEV_ID(NULL, "f8014000.i2c", &twi1_clk),
        CLKDEV_CON_DEV_ID(NULL, "f8018000.i2c", &twi2_clk),
index 6bd7300a2bc507855f28153e5871a4fcb6c4d5ed..bb7f54474b92e7f7fef65e1c504dbf4544c84992 100644 (file)
@@ -88,6 +88,6 @@ void __init at91x40_init_interrupts(unsigned int priority[NR_AIC_IRQS])
        if (!priority)
                priority = at91x40_default_irq_priority;
 
-       at91_aic_init(priority);
+       at91_aic_init(priority, at91_extern_irq);
 }
 
index 9cda3fd346ae3e4657cf415b6dbe1e4040c20db5..6960778af4c2c07eae98b998962c327d4af1632c 100644 (file)
@@ -129,7 +129,7 @@ static struct spi_board_info neocore926_spi_devices[] = {
                .max_speed_hz   = 125000 * 16,
                .bus_num        = 0,
                .platform_data  = &ads_info,
-               .irq            = AT91SAM9263_ID_IRQ1,
+               .irq            = NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1,
        },
 #endif
 };
index 27b3af1a3047e4bcf209e602f1fcc23a1561de0d..a9167dd45f96b68af3e216d90ececba5150b5f32 100644 (file)
@@ -309,7 +309,7 @@ static struct spi_board_info ek_spi_devices[] = {
                .max_speed_hz   = 125000 * 26,  /* (max sample rate @ 3V) * (cmd + data + overhead) */
                .bus_num        = 0,
                .platform_data  = &ads_info,
-               .irq            = AT91SAM9261_ID_IRQ0,
+               .irq            = NR_IRQS_LEGACY + AT91SAM9261_ID_IRQ0,
                .controller_data = (void *) AT91_PIN_PA28,      /* CS pin */
        },
 #endif
index 073e17403d982dad660126f0323754d0b36532c4..b87dbe2be0d63e71a700e116df0a3f06a389a8b3 100644 (file)
@@ -132,7 +132,7 @@ static struct spi_board_info ek_spi_devices[] = {
                .max_speed_hz   = 125000 * 26,  /* (max sample rate @ 3V) * (cmd + data + overhead) */
                .bus_num        = 0,
                .platform_data  = &ads_info,
-               .irq            = AT91SAM9263_ID_IRQ1,
+               .irq            = NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1,
        },
 #endif
 };
index 3ab2b86a3762a67da9b808386d39c51fb8cd2544..5b6a6f9a94f49f9c6ccc6e670fffa65a9f6c2122 100644 (file)
@@ -353,6 +353,22 @@ static struct i2c_board_info __initdata ek_i2c_devices[] = {
         },
 };
 
+static struct platform_device sam9g20ek_pcm_device = {
+       .name   = "atmel-pcm-audio",
+       .id = -1,
+};
+
+static struct platform_device sam9g20ek_audio_device = {
+       .name   = "at91sam9g20ek-audio",
+       .id     = -1,
+};
+
+static void __init ek_add_device_audio(void)
+{
+       platform_device_register(&sam9g20ek_pcm_device);
+       platform_device_register(&sam9g20ek_audio_device);
+}
+
 
 static void __init ek_board_init(void)
 {
@@ -394,6 +410,7 @@ static void __init ek_board_init(void)
        at91_set_B_periph(AT91_PIN_PC1, 0);
        /* SSC (for WM8731) */
        at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX);
+       ek_add_device_audio();
 }
 
 MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
index f49650677653a0f0488e6c64346fcf07e46ae555..b62f560e6c75fbe838200cb03b3347a8c3a15241 100644 (file)
@@ -26,7 +26,8 @@ extern void __init at91_dt_initialize(void);
 extern void __init at91_init_irq_default(void);
 extern void __init at91_init_interrupts(unsigned int priority[]);
 extern void __init at91x40_init_interrupts(unsigned int priority[]);
-extern void __init at91_aic_init(unsigned int priority[]);
+extern void __init at91_aic_init(unsigned int priority[],
+                                unsigned int ext_irq_mask);
 extern int  __init at91_aic_of_init(struct device_node *node,
                                    struct device_node *parent);
 extern int  __init at91_aic5_of_init(struct device_node *node,
index 1e02c0e49dccb76949be0fc9d855a5a3bb3504bc..febc2ee901a544458a9a47c0e55473263a7c54a6 100644 (file)
@@ -502,14 +502,19 @@ int __init at91_aic5_of_init(struct device_node *node,
 /*
  * Initialize the AIC interrupt controller.
  */
-void __init at91_aic_init(unsigned int *priority)
+void __init at91_aic_init(unsigned int *priority, unsigned int ext_irq_mask)
 {
        unsigned int i;
        int irq_base;
 
-       if (at91_aic_pm_init())
+       at91_extern_irq = kzalloc(BITS_TO_LONGS(n_irqs)
+                                 * sizeof(*at91_extern_irq), GFP_KERNEL);
+
+       if (at91_aic_pm_init() || at91_extern_irq == NULL)
                panic("Unable to allocate bit maps\n");
 
+       *at91_extern_irq = ext_irq_mask;
+
        at91_aic_base = ioremap(AT91_AIC, 512);
        if (!at91_aic_base)
                panic("Unable to ioremap AIC registers\n");
index da9881b161e1e15dc0693a74c2ce2716a0ebd5d3..0b32c81730a571484a600577e3037aa5d1573c65 100644 (file)
@@ -47,7 +47,7 @@ void __init at91_init_irq_default(void)
 void __init at91_init_interrupts(unsigned int *priority)
 {
        /* Initialize the AIC interrupt controller */
-       at91_aic_init(priority);
+       at91_aic_init(priority, at91_extern_irq);
 
        /* Enable GPIO interrupts */
        at91_gpio_irq_setup();
@@ -151,7 +151,7 @@ static void __init soc_detect(u32 dbgu_base)
        }
 
        /* at91sam9g10 */
-       if ((cidr & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {
+       if ((socid & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {
                at91_soc_initdata.type = AT91_SOC_SAM9G10;
                at91_boot_soc = at91sam9261_soc;
        }
index 32ee3f89596738d988a00105c0358d4ff1a61f1b..d9bc3fa7bb228a8c9e7f2feca9bac83b88ac16f5 100644 (file)
@@ -762,16 +762,19 @@ static u8 da850_iis_serializer_direction[] = {
 };
 
 static struct snd_platform_data da850_evm_snd_data = {
-       .tx_dma_offset  = 0x2000,
-       .rx_dma_offset  = 0x2000,
-       .op_mode        = DAVINCI_MCASP_IIS_MODE,
-       .num_serializer = ARRAY_SIZE(da850_iis_serializer_direction),
-       .tdm_slots      = 2,
-       .serial_dir     = da850_iis_serializer_direction,
-       .asp_chan_q     = EVENTQ_0,
-       .version        = MCASP_VERSION_2,
-       .txnumevt       = 1,
-       .rxnumevt       = 1,
+       .tx_dma_offset          = 0x2000,
+       .rx_dma_offset          = 0x2000,
+       .op_mode                = DAVINCI_MCASP_IIS_MODE,
+       .num_serializer         = ARRAY_SIZE(da850_iis_serializer_direction),
+       .tdm_slots              = 2,
+       .serial_dir             = da850_iis_serializer_direction,
+       .asp_chan_q             = EVENTQ_0,
+       .ram_chan_q             = EVENTQ_1,
+       .version                = MCASP_VERSION_2,
+       .txnumevt               = 1,
+       .rxnumevt               = 1,
+       .sram_size_playback     = SZ_8K,
+       .sram_size_capture      = SZ_8K,
 };
 
 static const short da850_evm_mcasp_pins[] __initconst = {
@@ -1509,6 +1512,7 @@ static __init void da850_evm_init(void)
                pr_warning("da850_evm_init: mcasp mux setup failed: %d\n",
                                ret);
 
+       da850_evm_snd_data.sram_pool = sram_get_gen_pool();
        da8xx_register_mcasp(0, &da850_evm_snd_data);
 
        ret = davinci_cfg_reg_list(da850_lcdcntl_pins);
index 715b690e5009608c9d9bfa42b1bb6e2d595b79ee..1947be8e5f5bffec59d1542e8ebbbc6bbce36970 100644 (file)
@@ -47,6 +47,7 @@
 #include <plat/fimc-core.h>
 #include <plat/iic-core.h>
 #include <plat/tv-core.h>
+#include <plat/spi-core.h>
 #include <plat/regs-serial.h>
 
 #include "common.h"
@@ -346,6 +347,8 @@ static void __init exynos4_map_io(void)
 
        s5p_fb_setname(0, "exynos4-fb");
        s5p_hdmi_setname("exynos4-hdmi");
+
+       s3c64xx_spi_setname("exynos4210-spi");
 }
 
 static void __init exynos5_map_io(void)
@@ -366,6 +369,8 @@ static void __init exynos5_map_io(void)
        s3c_i2c0_setname("s3c2440-i2c");
        s3c_i2c1_setname("s3c2440-i2c");
        s3c_i2c2_setname("s3c2440-i2c");
+
+       s3c64xx_spi_setname("exynos4210-spi");
 }
 
 static void __init exynos4_init_clocks(int xtal)
index e58d786faf78c773636f10b168415df2c0ac61ef..eadf4b59e7d28e6ae1d254f0f86a398759d5f9bc 100644 (file)
@@ -99,6 +99,7 @@ static char const *exynos4_dt_compat[] __initdata = {
 
 DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)")
        /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
+       .smp            = smp_ops(exynos_smp_ops),
        .init_irq       = exynos4_init_irq,
        .map_io         = exynos4_dt_map_io,
        .handle_irq     = gic_handle_irq,
index 1a7a8dd045a13ab6481bcc653e877d899b0597b7..1ab91b5209e6503e7742450c4dc424a15b2e651c 100644 (file)
@@ -108,7 +108,7 @@ struct clk *imx_clk_busy_divider(const char *name, const char *parent_name,
        busy->div.hw.init = &init;
 
        clk = clk_register(NULL, &busy->div.hw);
-       if (!clk)
+       if (IS_ERR(clk))
                kfree(busy);
 
        return clk;
index d20d4795f4eaebeb633c73ec441c36a661949a47..01e2f843bf2e0d65910bf0951f12555077f7693e 100644 (file)
@@ -127,8 +127,8 @@ int __init mx25_clocks_init(void)
        clk[esdhc2_ipg_per] = imx_clk_gate("esdhc2_ipg_per", "per4", ccm(CCM_CGCR0),  4);
        clk[gpt_ipg_per] = imx_clk_gate("gpt_ipg_per", "per5", ccm(CCM_CGCR0),  5);
        clk[i2c_ipg_per] = imx_clk_gate("i2c_ipg_per", "per6", ccm(CCM_CGCR0),  6);
-       clk[lcdc_ipg_per] = imx_clk_gate("lcdc_ipg_per", "per8", ccm(CCM_CGCR0),  7);
-       clk[nfc_ipg_per] = imx_clk_gate("nfc_ipg_per", "ipg_per", ccm(CCM_CGCR0),  8);
+       clk[lcdc_ipg_per] = imx_clk_gate("lcdc_ipg_per", "per7", ccm(CCM_CGCR0),  7);
+       clk[nfc_ipg_per] = imx_clk_gate("nfc_ipg_per", "per8", ccm(CCM_CGCR0),  8);
        clk[ssi1_ipg_per] = imx_clk_gate("ssi1_ipg_per", "per13", ccm(CCM_CGCR0), 13);
        clk[ssi2_ipg_per] = imx_clk_gate("ssi2_ipg_per", "per14", ccm(CCM_CGCR0), 14);
        clk[uart_ipg_per] = imx_clk_gate("uart_ipg_per", "per15", ccm(CCM_CGCR0), 15);
index 3b6b640eed247ea1b7848c7a7fa01801f0190cde..366e5d59d886f7cd43bb79bfe50a70c9fa6a6c5b 100644 (file)
@@ -109,7 +109,7 @@ int __init mx27_clocks_init(unsigned long fref)
        clk[per3_div] = imx_clk_divider("per3_div", "mpll_main2", CCM_PCDR1, 16, 6);
        clk[per4_div] = imx_clk_divider("per4_div", "mpll_main2", CCM_PCDR1, 24, 6);
        clk[vpu_sel] = imx_clk_mux("vpu_sel", CCM_CSCR, 21, 1, vpu_sel_clks, ARRAY_SIZE(vpu_sel_clks));
-       clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 3);
+       clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 6);
        clk[usb_div] = imx_clk_divider("usb_div", "spll", CCM_CSCR, 28, 3);
        clk[cpu_sel] = imx_clk_mux("cpu_sel", CCM_CSCR, 15, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks));
        clk[clko_sel] = imx_clk_mux("clko_sel", CCM_CCSR, 0, 5, clko_sel_clks, ARRAY_SIZE(clko_sel_clks));
@@ -121,7 +121,7 @@ int __init mx27_clocks_init(unsigned long fref)
        clk[ssi1_sel] = imx_clk_mux("ssi1_sel", CCM_CSCR, 22, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
        clk[ssi2_sel] = imx_clk_mux("ssi2_sel", CCM_CSCR, 23, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
        clk[ssi1_div] = imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6);
-       clk[ssi2_div] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 3);
+       clk[ssi2_div] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 6);
        clk[clko_en] = imx_clk_gate("clko_en", "clko_div", CCM_PCCR0, 0);
        clk[ssi2_ipg_gate] = imx_clk_gate("ssi2_ipg_gate", "ipg", CCM_PCCR0, 0);
        clk[ssi1_ipg_gate] = imx_clk_gate("ssi1_ipg_gate", "ipg", CCM_PCCR0, 1);
index 9d2c843bde02438ccd79b2b5552397b97aeb1b65..b5deb0554552d1bbe586fcf2b7fd2d1bc0a33c06 100644 (file)
@@ -108,9 +108,8 @@ void __init imx3_init_l2x0(void)
        }
 
        l2x0_base = ioremap(MX3x_L2CC_BASE_ADDR, 4096);
-       if (IS_ERR(l2x0_base)) {
-               printk(KERN_ERR "remapping L2 cache area failed with %ld\n",
-                               PTR_ERR(l2x0_base));
+       if (!l2x0_base) {
+               printk(KERN_ERR "remapping L2 cache area failed\n");
                return;
        }
 
index 2a1a898c7f90c661ec641aead23acd8d00a634cb..d669e227e00c18ac1c9783fd4e370d6f3b9e51e6 100644 (file)
@@ -11,7 +11,6 @@ config ARCH_OMAP2PLUS_TYPICAL
        select I2C_OMAP
        select MENELAUS if ARCH_OMAP2
        select NEON if ARCH_OMAP3 || ARCH_OMAP4 || SOC_OMAP5
-       select PINCTRL
        select PM_RUNTIME
        select REGULATOR
        select SERIAL_OMAP
index 388c431c745a0e4134c847f96f84b73912053bf7..d41ab98890ffcc45731c7625b3ad7f44d53bb855 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
 #include <linux/opp.h>
+#include <linux/cpu.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -444,27 +445,31 @@ static struct omap_board_mux board_mux[] __initdata = {
 };
 #endif
 
-static void __init beagle_opp_init(void)
+static int __init beagle_opp_init(void)
 {
        int r = 0;
 
-       /* Initialize the omap3 opp table */
-       if (omap3_opp_init()) {
+       if (!machine_is_omap3_beagle())
+               return 0;
+
+       /* Initialize the omap3 opp table if not already created. */
+       r = omap3_opp_init();
+       if (IS_ERR_VALUE(r) && (r != -EEXIST)) {
                pr_err("%s: opp default init failed\n", __func__);
-               return;
+               return r;
        }
 
        /* Custom OPP enabled for all xM versions */
        if (cpu_is_omap3630()) {
                struct device *mpu_dev, *iva_dev;
 
-               mpu_dev = omap_device_get_by_hwmod_name("mpu");
+               mpu_dev = get_cpu_device(0);
                iva_dev = omap_device_get_by_hwmod_name("iva");
 
                if (IS_ERR(mpu_dev) || IS_ERR(iva_dev)) {
                        pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n",
                                __func__, mpu_dev, iva_dev);
-                       return;
+                       return -ENODEV;
                }
                /* Enable MPU 1GHz and lower opps */
                r = opp_enable(mpu_dev, 800000000);
@@ -484,8 +489,9 @@ static void __init beagle_opp_init(void)
                        opp_disable(iva_dev, 660000000);
                }
        }
-       return;
+       return 0;
 }
+device_initcall(beagle_opp_init);
 
 static void __init omap3_beagle_init(void)
 {
@@ -522,8 +528,6 @@ static void __init omap3_beagle_init(void)
        /* Ensure SDRC pins are mux'd for self-refresh */
        omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
        omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
-
-       beagle_opp_init();
 }
 
 MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
index 114ab4b8e0e356883192bb847237172df9d46ab3..1a45d6bd253921a9b8e8f646f568c868a0b4df85 100644 (file)
@@ -1073,6 +1073,8 @@ static struct omap_clk am33xx_clks[] = {
        CLK(NULL,       "gfx_fck_div_ck",       &gfx_fck_div_ck,        CK_AM33XX),
        CLK(NULL,       "sysclkout_pre_ck",     &sysclkout_pre_ck,      CK_AM33XX),
        CLK(NULL,       "clkout2_ck",           &clkout2_ck,    CK_AM33XX),
+       CLK(NULL,       "timer_32k_ck",         &clkdiv32k_ick, CK_AM33XX),
+       CLK(NULL,       "timer_sys_ck",         &sys_clkin_ck,  CK_AM33XX),
 };
 
 int __init am33xx_clk_init(void)
index 17f80e4ab162e4f2d4f15f8d99ccfa03496e225b..c47140bbbec4d8a5243110a68703d2861a7f3cb0 100644 (file)
@@ -614,16 +614,16 @@ static struct omap_mux __initdata omap3_muxmodes[] = {
                "sys_off_mode", NULL, NULL, NULL,
                "gpio_9", NULL, NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART1_CTS, 150,
-               "uart1_cts", NULL, NULL, NULL,
+               "uart1_cts", "ssi1_rdy_tx", NULL, NULL,
                "gpio_150", "hsusb3_tll_clk", NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART1_RTS, 149,
-               "uart1_rts", NULL, NULL, NULL,
+               "uart1_rts", "ssi1_flag_tx", NULL, NULL,
                "gpio_149", NULL, NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART1_RX, 151,
-               "uart1_rx", NULL, "mcbsp1_clkr", "mcspi4_clk",
+               "uart1_rx", "ss1_wake_tx", "mcbsp1_clkr", "mcspi4_clk",
                "gpio_151", NULL, NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART1_TX, 148,
-               "uart1_tx", NULL, NULL, NULL,
+               "uart1_tx", "ssi1_dat_tx", NULL, NULL,
                "gpio_148", NULL, NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART2_CTS, 144,
                "uart2_cts", "mcbsp3_dx", "gpt9_pwm_evt", NULL,
index 686137d164dac9faee69b2293e524fa08c69bcea..67d66131cfa796c9f0724e43a2820a0752e1fa73 100644 (file)
@@ -91,6 +91,7 @@ extern void omap3_save_scratchpad_contents(void);
 
 #define PM_RTA_ERRATUM_i608            (1 << 0)
 #define PM_SDRC_WAKEUP_ERRATUM_i583    (1 << 1)
+#define PM_PER_MEMORIES_ERRATUM_i582   (1 << 2)
 
 #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
 extern u16 pm34xx_errata;
index ba670db1fd37416a8da3e1d343b319afa8161adf..3a904de4313ec82deb6b4f2e61d460e318ef0e87 100644 (file)
@@ -652,14 +652,17 @@ static void __init pm_errata_configure(void)
                /* Enable the l2 cache toggling in sleep logic */
                enable_omap3630_toggle_l2_on_restore();
                if (omap_rev() < OMAP3630_REV_ES1_2)
-                       pm34xx_errata |= PM_SDRC_WAKEUP_ERRATUM_i583;
+                       pm34xx_errata |= (PM_SDRC_WAKEUP_ERRATUM_i583 |
+                                         PM_PER_MEMORIES_ERRATUM_i582);
+       } else if (cpu_is_omap34xx()) {
+               pm34xx_errata |= PM_PER_MEMORIES_ERRATUM_i582;
        }
 }
 
 int __init omap3_pm_init(void)
 {
        struct power_state *pwrst, *tmp;
-       struct clockdomain *neon_clkdm, *mpu_clkdm;
+       struct clockdomain *neon_clkdm, *mpu_clkdm, *per_clkdm, *wkup_clkdm;
        int ret;
 
        if (!omap3_has_io_chain_ctrl())
@@ -711,6 +714,8 @@ int __init omap3_pm_init(void)
 
        neon_clkdm = clkdm_lookup("neon_clkdm");
        mpu_clkdm = clkdm_lookup("mpu_clkdm");
+       per_clkdm = clkdm_lookup("per_clkdm");
+       wkup_clkdm = clkdm_lookup("wkup_clkdm");
 
 #ifdef CONFIG_SUSPEND
        omap_pm_suspend = omap3_pm_suspend;
@@ -727,6 +732,27 @@ int __init omap3_pm_init(void)
        if (IS_PM34XX_ERRATUM(PM_RTA_ERRATUM_i608))
                omap3630_ctrl_disable_rta();
 
+       /*
+        * The UART3/4 FIFO and the sidetone memory in McBSP2/3 are
+        * not correctly reset when the PER powerdomain comes back
+        * from OFF or OSWR when the CORE powerdomain is kept active.
+        * See OMAP36xx Erratum i582 "PER Domain reset issue after
+        * Domain-OFF/OSWR Wakeup".  This wakeup dependency is not a
+        * complete workaround.  The kernel must also prevent the PER
+        * powerdomain from going to OSWR/OFF while the CORE
+        * powerdomain is not going to OSWR/OFF.  And if PER last
+        * power state was off while CORE last power state was ON, the
+        * UART3/4 and McBSP2/3 SIDETONE devices need to run a
+        * self-test using their loopback tests; if that fails, those
+        * devices are unusable until the PER/CORE can complete a transition
+        * from ON to OSWR/OFF and then back to ON.
+        *
+        * XXX Technically this workaround is only needed if off-mode
+        * or OSWR is enabled.
+        */
+       if (IS_PM34XX_ERRATUM(PM_PER_MEMORIES_ERRATUM_i582))
+               clkdm_add_wkdep(per_clkdm, wkup_clkdm);
+
        clkdm_add_wkdep(neon_clkdm, mpu_clkdm);
        if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
                omap3_secure_ram_storage =
index 0405c8190803a34ef666dd197a15f18dccdcad8f..a507cd6cf4f12259ab6a0bbad75fdc2e38bbe3a8 100644 (file)
@@ -329,6 +329,11 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
 
        oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
 
+       if (console_uart_id == bdata->id) {
+               omap_device_enable(pdev);
+               pm_runtime_set_active(&pdev->dev);
+       }
+
        oh->dev_attr = uart;
 
        if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads)
index ed5a95ece9eb2d365b7152cdb4bd5cfe508e672b..77ee0b732237d93de59c80632279a00dbf5dc2bd 100644 (file)
@@ -61,6 +61,7 @@
 #include <plat/nand-core.h>
 #include <plat/adc-core.h>
 #include <plat/rtc-core.h>
+#include <plat/spi-core.h>
 
 static struct map_desc s3c2416_iodesc[] __initdata = {
        IODESC_ENT(WATCHDOG),
@@ -132,6 +133,7 @@ void __init s3c2416_map_io(void)
        /* initialize device information early */
        s3c2416_default_sdhci0();
        s3c2416_default_sdhci1();
+       s3c64xx_spi_setname("s3c2443-spi");
 
        iotable_init(s3c2416_iodesc, ARRAY_SIZE(s3c2416_iodesc));
 }
index ab648ad8fa508651624054ca2d9693f9d34fb1e5..165b6a6b3daaa9450201db7b0c721f76c62574f2 100644 (file)
@@ -43,6 +43,7 @@
 #include <plat/nand-core.h>
 #include <plat/adc-core.h>
 #include <plat/rtc-core.h>
+#include <plat/spi-core.h>
 
 static struct map_desc s3c2443_iodesc[] __initdata = {
        IODESC_ENT(WATCHDOG),
@@ -100,6 +101,9 @@ void __init s3c2443_map_io(void)
        s3c24xx_gpiocfg_default.set_pull = s3c2443_gpio_setpull;
        s3c24xx_gpiocfg_default.get_pull = s3c2443_gpio_getpull;
 
+       /* initialize device information early */
+       s3c64xx_spi_setname("s3c2443-spi");
+
        iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc));
 }
 
index 6e6a0a9d6778b0b1fe41a6857cef015ee55bc39d..111e404a81fd44a8627025c975898e12f20598b7 100644 (file)
@@ -44,6 +44,7 @@
 #include <plat/sdhci.h>
 #include <plat/adc-core.h>
 #include <plat/fb-core.h>
+#include <plat/spi-core.h>
 #include <plat/gpio-cfg.h>
 #include <plat/regs-irqtype.h>
 #include <plat/regs-serial.h>
@@ -179,6 +180,7 @@ void __init s5p6440_map_io(void)
        /* initialize any device information early */
        s3c_adc_setname("s3c64xx-adc");
        s3c_fb_setname("s5p64x0-fb");
+       s3c64xx_spi_setname("s5p64x0-spi");
 
        s5p64x0_default_sdhci0();
        s5p64x0_default_sdhci1();
@@ -193,6 +195,7 @@ void __init s5p6450_map_io(void)
        /* initialize any device information early */
        s3c_adc_setname("s3c64xx-adc");
        s3c_fb_setname("s5p64x0-fb");
+       s3c64xx_spi_setname("s5p64x0-spi");
 
        s5p64x0_default_sdhci0();
        s5p64x0_default_sdhci1();
index 621908658861596a43e4817f6978e352eab7604d..cc6e561c99588430f7e3b99993d761ffebecf949 100644 (file)
@@ -45,6 +45,7 @@
 #include <plat/fb-core.h>
 #include <plat/iic-core.h>
 #include <plat/onenand-core.h>
+#include <plat/spi-core.h>
 #include <plat/regs-serial.h>
 #include <plat/watchdog-reset.h>
 
@@ -165,6 +166,8 @@ void __init s5pc100_map_io(void)
        s3c_onenand_setname("s5pc100-onenand");
        s3c_fb_setname("s5pc100-fb");
        s3c_cfcon_setname("s5pc100-pata");
+
+       s3c64xx_spi_setname("s5pc100-spi");
 }
 
 void __init s5pc100_init_clocks(int xtal)
index 4c9e9027df9aed2cbd0314ec1cebc0d80a1d3530..a0c50efe8145f167b4482a814e15329d7f32db27 100644 (file)
@@ -43,6 +43,7 @@
 #include <plat/iic-core.h>
 #include <plat/keypad-core.h>
 #include <plat/tv-core.h>
+#include <plat/spi-core.h>
 #include <plat/regs-serial.h>
 
 #include "common.h"
@@ -196,6 +197,8 @@ void __init s5pv210_map_io(void)
 
        /* setup TV devices */
        s5p_hdmi_setname("s5pv210-hdmi");
+
+       s3c64xx_spi_setname("s5pv210-spi");
 }
 
 void __init s5pv210_init_clocks(int xtal)
index 2917668f0091c1042a70e512f50c12bacdb3ebb2..ebbffc25f24fc1ad48c75d36ee10d36709cc7a1e 100644 (file)
@@ -247,7 +247,7 @@ void __init r8a7779_add_standard_devices(void)
 {
 #ifdef CONFIG_CACHE_L2X0
        /* Early BRESP enable, Shared attribute override enable, 64K*16way */
-       l2x0_init((void __iomem __force *)(0xf0100000), 0x40470000, 0x82000fff);
+       l2x0_init(IOMEM(0xf0100000), 0x40470000, 0x82000fff);
 #endif
        r8a7779_pm_init();
 
diff --git a/arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h b/arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h b/arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h
deleted file mode 100644 (file)
index e69de29..0000000
index 2236cbd03cd79c11d897353d33401ddc4a3c962e..1f3fbc2bb7768a4389e8c7796affdfb65f521d1b 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/stat.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
+#include <linux/irq.h>
 #include <linux/platform_data/clk-ux500.h>
 
 #include <asm/hardware/gic.h>
index b9f60ebe3bc4f13f3dc13e4e4531da549890eca4..023f443784ec0b1fd438e7a9637702ef1e58fbaf 100644 (file)
@@ -856,8 +856,10 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
                if (thumb2_32b) {
                        offset.un = 0;
                        handler = do_alignment_t32_to_handler(&instr, regs, &offset);
-               } else
+               } else {
+                       offset.un = 0;
                        handler = do_alignment_ldmstm;
+               }
                break;
 
        default:
index 477a2d23ddf17efb95af55cebbc25d35793a417d..58bc3e4d3bd0a76094d8a2a40c0be9bece4eaf7a 100644 (file)
@@ -610,7 +610,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
                         gfp_t gfp, pgprot_t prot, bool is_coherent, const void *caller)
 {
        u64 mask = get_coherent_dma_mask(dev);
-       struct page *page;
+       struct page *page = NULL;
        void *addr;
 
 #ifdef CONFIG_DMA_API_DEBUG
index bf312c354a214761646a3a3738fb6080b84fff33..0f5a5f2a2c7bbc1bb79668ac291dde283741be7a 100644 (file)
@@ -17,7 +17,6 @@ struct arm_vmregion {
        struct list_head        vm_list;
        unsigned long           vm_start;
        unsigned long           vm_end;
-       void                    *priv;
        int                     vm_active;
        const void              *caller;
 };
index 540d3a7d92dfaacf8fd82cbd745327c7d2e094a9..e7b920b58675d79bab4b1ef598b18e0f05fb14ed 100644 (file)
@@ -55,7 +55,7 @@ struct platform_device *__init imx_add_mxc_mmc(
        struct resource res[] = {
                {
                        .start = data->iobase,
-                       .end = data->iobase + SZ_4K - 1,
+                       .end = data->iobase + data->iosize - 1,
                        .flags = IORESOURCE_MEM,
                }, {
                        .start = data->irq,
index 7cd56ed5cd949b25c0ae4ad02729241006b42783..82fcb206b5b25c679434c8217b72978c2a68df1f 100644 (file)
@@ -26,6 +26,7 @@ config ARCH_OMAP2PLUS
        select CLKDEV_LOOKUP
        select GENERIC_IRQ_CHIP
        select OMAP_DM_TIMER
+       select PINCTRL
        select PROC_DEVICETREE if PROC_FS
        select SPARSE_IRQ
        select USE_OF
index f4a4cd014795d676d85ffdc05622a4ac3e889a5c..1957a8516e938e2d9f42b690903211095e6ed959 100644 (file)
 #define OMAP_UART_WER_MOD_WKUP 0X7F
 
 /* Enable XON/XOFF flow control on output */
-#define OMAP_UART_SW_TX                0x8
+#define OMAP_UART_SW_TX                0x04
 
 /* Enable XON/XOFF flow control on input */
-#define OMAP_UART_SW_RX                0x2
+#define OMAP_UART_SW_RX                0x04
 
 #define OMAP_UART_SYSC_RESET   0X07
 #define OMAP_UART_TCR_TRIG     0X0F
diff --git a/arch/arm/plat-samsung/include/plat/spi-core.h b/arch/arm/plat-samsung/include/plat/spi-core.h
new file mode 100644 (file)
index 0000000..0b9428a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.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.
+ */
+
+#ifndef __PLAT_S3C_SPI_CORE_H
+#define __PLAT_S3C_SPI_CORE_H
+
+/* These functions are only for use with the core support code, such as
+ * the cpu specific initialisation code
+ */
+
+/* re-define device name depending on support. */
+static inline void s3c64xx_spi_setname(char *name)
+{
+#ifdef CONFIG_S3C64XX_DEV_SPI0
+       s3c64xx_device_spi0.name = name;
+#endif
+#ifdef CONFIG_S3C64XX_DEV_SPI1
+       s3c64xx_device_spi1.name = name;
+#endif
+#ifdef CONFIG_S3C64XX_DEV_SPI2
+       s3c64xx_device_spi2.name = name;
+#endif
+}
+
+#endif /* __PLAT_S3C_SPI_CORE_H */
index 635cb1865e4d56af08b8579eb72dbaadfa77f211..cd60a81163e938a78b55b40fa9df6009408f5b57 100644 (file)
@@ -5,6 +5,6 @@
 #
 
 include/generated/mach-types.h: $(src)/gen-mach-types $(src)/mach-types
-       @echo '  Generating $@'
+       $(kecho) '  Generating $@'
        @mkdir -p $(dir $@)
        $(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; }
index dbd1330c01966c20667853b6d9de97754b869d91..859a9bb002d54875e5089a940442d5015a9fe1a4 100644 (file)
@@ -33,7 +33,7 @@
 #include <xen/page.h>
 #include <xen/grant_table.h>
 
-int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
+int arch_gnttab_map_shared(xen_pfn_t *frames, unsigned long nr_gframes,
                           unsigned long max_nr_gframes,
                           void **__shared)
 {
index 074f5ed101b9d17bf49c2a0cd13b078408fcb64c..71f723984cbd94eced133e49bc7fd0db8dbdf92b 100644 (file)
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include <asm/opcodes-virt.h>
 #include <xen/interface/xen.h>
 
 
-/* HVC 0xEA1 */
-#ifdef CONFIG_THUMB2_KERNEL
-#define xen_hvc .word 0xf7e08ea1
-#else
-#define xen_hvc .word 0xe140ea71
-#endif
+#define XEN_IMM 0xEA1
 
 #define HYPERCALL_SIMPLE(hypercall)            \
 ENTRY(HYPERVISOR_##hypercall)                  \
        mov r12, #__HYPERVISOR_##hypercall;     \
-       xen_hvc;                                                        \
+       __HVC(XEN_IMM);                                         \
        mov pc, lr;                                                     \
 ENDPROC(HYPERVISOR_##hypercall)
 
@@ -76,7 +72,7 @@ ENTRY(HYPERVISOR_##hypercall)                 \
        stmdb sp!, {r4}                                         \
        ldr r4, [sp, #4]                                        \
        mov r12, #__HYPERVISOR_##hypercall;     \
-       xen_hvc                                                         \
+       __HVC(XEN_IMM);                                         \
        ldm sp!, {r4}                                           \
        mov pc, lr                                                      \
 ENDPROC(HYPERVISOR_##hypercall)
@@ -100,7 +96,7 @@ ENTRY(privcmd_call)
        mov r2, r3
        ldr r3, [sp, #8]
        ldr r4, [sp, #4]
-       xen_hvc
+       __HVC(XEN_IMM)
        ldm sp!, {r4}
        mov pc, lr
 ENDPROC(privcmd_call);
index b7412504f08a2c91635c6f75da624a59b6a6a953..df2eb4bd9fa2abbaa06c6978537fcabc88c22cf7 100644 (file)
@@ -13,6 +13,7 @@ config FRV
        select GENERIC_CPU_DEVICES
        select ARCH_WANT_IPC_PARSE_VERSION
        select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
 
 config ZONE_DMA
        bool
index 6ae3254da01976b6fdaa374f588c3c58a081058c..636d5bbcd53f31ca5cbbb96ca9f3e29f501fdfff 100644 (file)
@@ -17,6 +17,8 @@ PARAMS_PHYS    = 0x0207c000
 INITRD_PHYS     = 0x02180000
 INITRD_VIRT     = 0x02180000
 
+OBJCOPYFLAGS   :=-O binary -R .note -R .note.gnu.build-id -R .comment
+
 #
 # If you don't define ZRELADDR above,
 # then it defaults to ZTEXTADDR
@@ -32,18 +34,18 @@ Image: $(obj)/Image
 targets: $(obj)/Image
 
 $(obj)/Image: vmlinux FORCE
-       $(OBJCOPY) -O binary -R .note -R .comment -S vmlinux $@
+       $(OBJCOPY) $(OBJCOPYFLAGS) -S vmlinux $@
 
 #$(obj)/Image: $(CONFIGURE) $(SYSTEM)
-#      $(OBJCOPY) -O binary -R .note -R .comment -g -S $(SYSTEM) $@
+#      $(OBJCOPY) $(OBJCOPYFLAGS) -g -S $(SYSTEM) $@
 
 bzImage: zImage
 
 zImage:        $(CONFIGURE) compressed/$(LINUX)
-       $(OBJCOPY) -O binary -R .note -R .comment -S compressed/$(LINUX) $@
+       $(OBJCOPY) $(OBJCOPYFLAGS) -S compressed/$(LINUX) $@
 
 bootpImage: bootp/bootp
-       $(OBJCOPY) -O binary -R .note -R .comment -S bootp/bootp $@
+       $(OBJCOPY) $(OBJCOPYFLAGS) -S bootp/bootp $@
 
 compressed/$(LINUX): $(LINUX) dep
        @$(MAKE) -C compressed $(LINUX)
index 266a5b25a0c1698347715c91fd45b7e95b8eb864..2358634caccaa6b50a8cad83fb0601e1350e71d0 100644 (file)
@@ -30,7 +30,6 @@
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_SYS_EXECVE
-#define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
index ee0beb354e4df38e0c067410e8f9643deec2856f..dfcd263c05176ea6cdbf3c169070a93fe79b8f5b 100644 (file)
@@ -869,11 +869,6 @@ ret_from_kernel_thread:
        call            schedule_tail
        calll.p         @(gr21,gr0)
        or              gr20,gr20,gr8
-       bra             sys_exit
-
-       .globl          ret_from_kernel_execve
-ret_from_kernel_execve:
-       ori             gr28,0,sp
        bra             __syscall_exit
 
 ###################################################################################################
@@ -1080,27 +1075,10 @@ __entry_return_from_kernel_interrupt:
        subicc          gr5,#0,gr0,icc0
        beq             icc0,#0,__entry_return_direct
 
-__entry_preempt_need_resched:
-       ldi             @(gr15,#TI_FLAGS),gr4
-       andicc          gr4,#_TIF_NEED_RESCHED,gr0,icc0
-       beq             icc0,#1,__entry_return_direct
-
-       setlos          #PREEMPT_ACTIVE,gr5
-       sti             gr5,@(gr15,#TI_FLAGS)
-
-       andi            gr23,#~PSR_PIL,gr23
-       movgs           gr23,psr
-
-       call            schedule
-       sti             gr0,@(gr15,#TI_PRE_COUNT)
-
-       movsg           psr,gr23
-       ori             gr23,#PSR_PIL_14,gr23
-       movgs           gr23,psr
-       bra             __entry_preempt_need_resched
-#else
-       bra             __entry_return_direct
+       subcc           gr0,gr0,gr0,icc2                /* set Z and clear C */
+       call            preempt_schedule_irq
 #endif
+       bra             __entry_return_direct
 
 
 ###############################################################################
index e1e3aa196aa4c25adcb33ed09fe1296b4be8e69d..7e33215f1d8fabfd28a1aa5c5144a8e73f621a90 100644 (file)
@@ -181,6 +181,9 @@ int copy_thread(unsigned long clone_flags,
        childregs = (struct pt_regs *)
                (task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE);
 
+       /* set up the userspace frame (the only place that the USP is stored) */
+       *childregs = *__kernel_frame0_ptr;
+
        p->set_child_tid = p->clear_child_tid = NULL;
 
        p->thread.frame  = childregs;
@@ -191,10 +194,8 @@ int copy_thread(unsigned long clone_flags,
        p->thread.frame0 = childregs;
 
        if (unlikely(!regs)) {
-               memset(childregs, 0, sizeof(struct pt_regs));
                childregs->gr9 = usp; /* function */
                childregs->gr8 = arg;
-               childregs->psr = PSR_S;
                p->thread.pc = (unsigned long) ret_from_kernel_thread;
                save_user_regs(p->thread.user);
                return 0;
index e47857f889b6d2a18dcf839249bae5f7af66f334..b99c2a7cc7a41f6a0398c4a34715749d2a935afc 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/types.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/dma-mapping.h>
 #include <linux/list.h>
 #include <linux/pci.h>
index 4a159da23633dbf359c9886513958ce49e842ce7..dd02f09b6eda6e2b41f1dd643a6ff550625a15e0 100644 (file)
@@ -1,3 +1,4 @@
 
 generic-y += clkdev.h
 generic-y += exec.h
+generic-y += kvm_para.h
diff --git a/arch/ia64/include/asm/kvm_para.h b/arch/ia64/include/asm/kvm_para.h
deleted file mode 100644 (file)
index 47c00f9..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2007 Xiantao Zhang <xiantao.zhang@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- */
-#ifndef __IA64_KVM_PARA_H
-#define __IA64_KVM_PARA_H
-
-#include <uapi/asm/kvm_para.h>
-
-
-static inline unsigned int kvm_arch_para_features(void)
-{
-       return 0;
-}
-
-static inline bool kvm_check_and_clear_guest_paused(void)
-{
-       return false;
-}
-
-#endif
index ecb540810ab3ace200ae66368d700d97b4abf0d2..88fa3ac86fae9af988331112cba87ff711eb3555 100644 (file)
@@ -1,5 +1,3 @@
-include include/asm-generic/Kbuild.asm
-header-y += cachectl.h
 
 generic-y += bitsperlong.h
 generic-y += clkdev.h
index 5e08b597f012192e8a5f8cd4cc4d0a20690b485d..0f717045bddef4094584fe9c5be624e9ee2d4927 100644 (file)
@@ -1,82 +1,10 @@
 #ifndef _M68K_PTRACE_H
 #define _M68K_PTRACE_H
 
-#define PT_D1     0
-#define PT_D2     1
-#define PT_D3     2
-#define PT_D4     3
-#define PT_D5     4
-#define PT_D6     5
-#define PT_D7     6
-#define PT_A0     7
-#define PT_A1     8
-#define PT_A2     9
-#define PT_A3     10
-#define PT_A4     11
-#define PT_A5     12
-#define PT_A6     13
-#define PT_D0     14
-#define PT_USP    15
-#define PT_ORIG_D0 16
-#define PT_SR     17
-#define PT_PC     18
+#include <uapi/asm/ptrace.h>
 
 #ifndef __ASSEMBLY__
 
-/* this struct defines the way the registers are stored on the
-   stack during a system call. */
-
-struct pt_regs {
-  long     d1;
-  long     d2;
-  long     d3;
-  long     d4;
-  long     d5;
-  long     a0;
-  long     a1;
-  long     a2;
-  long     d0;
-  long     orig_d0;
-  long     stkadj;
-#ifdef CONFIG_COLDFIRE
-  unsigned format :  4; /* frame format specifier */
-  unsigned vector : 12; /* vector offset */
-  unsigned short sr;
-  unsigned long  pc;
-#else
-  unsigned short sr;
-  unsigned long  pc;
-  unsigned format :  4; /* frame format specifier */
-  unsigned vector : 12; /* vector offset */
-#endif
-};
-
-/*
- * This is the extended stack used by signal handlers and the context
- * switcher: it's pushed after the normal "struct pt_regs".
- */
-struct switch_stack {
-       unsigned long  d6;
-       unsigned long  d7;
-       unsigned long  a3;
-       unsigned long  a4;
-       unsigned long  a5;
-       unsigned long  a6;
-       unsigned long  retpc;
-};
-
-/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
-#define PTRACE_GETREGS            12
-#define PTRACE_SETREGS            13
-#define PTRACE_GETFPREGS          14
-#define PTRACE_SETFPREGS          15
-
-#define PTRACE_GET_THREAD_AREA    25
-
-#define PTRACE_SINGLEBLOCK     33      /* resume execution until next branch */
-
-#ifdef __KERNEL__
-
 #ifndef PS_S
 #define PS_S  (0x2000)
 #define PS_M  (0x1000)
@@ -94,6 +22,5 @@ struct switch_stack {
 #define arch_has_block_step()  (1)
 #endif
 
-#endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 #endif /* _M68K_PTRACE_H */
index 00c2c5397d37ee787eaeac0df751e220c3cefa26..65e78a2dad64a9840fdb96bdc898e8b848f52331 100644 (file)
 **   Redesign of the boot information structure; moved boot information
 **   structure to bootinfo.h
 */
-
 #ifndef _M68K_SETUP_H
 #define _M68K_SETUP_H
 
+#include <uapi/asm/setup.h>
 
 
-    /*
-     *  Linux/m68k Architectures
-     */
-
-#define MACH_AMIGA    1
-#define MACH_ATARI    2
-#define MACH_MAC      3
-#define MACH_APOLLO   4
-#define MACH_SUN3     5
-#define MACH_MVME147  6
-#define MACH_MVME16x  7
-#define MACH_BVME6000 8
-#define MACH_HP300    9
-#define MACH_Q40     10
-#define MACH_SUN3X   11
-#define MACH_M54XX   12
-
-#define COMMAND_LINE_SIZE 256
-
-#ifdef __KERNEL__
-
 #define CL_SIZE COMMAND_LINE_SIZE
 
 #ifndef __ASSEMBLY__
@@ -194,63 +173,6 @@ extern unsigned long m68k_machtype;
 #  define MACH_TYPE (m68k_machtype)
 #endif
 
-#endif /* __KERNEL__ */
-
-
-    /*
-     *  CPU, FPU and MMU types
-     *
-     *  Note: we may rely on the following equalities:
-     *
-     *      CPU_68020 == MMU_68851
-     *      CPU_68030 == MMU_68030
-     *      CPU_68040 == FPU_68040 == MMU_68040
-     *      CPU_68060 == FPU_68060 == MMU_68060
-     */
-
-#define CPUB_68020     0
-#define CPUB_68030     1
-#define CPUB_68040     2
-#define CPUB_68060     3
-#define CPUB_COLDFIRE  4
-
-#define CPU_68020      (1<<CPUB_68020)
-#define CPU_68030      (1<<CPUB_68030)
-#define CPU_68040      (1<<CPUB_68040)
-#define CPU_68060      (1<<CPUB_68060)
-#define CPU_COLDFIRE   (1<<CPUB_COLDFIRE)
-
-#define FPUB_68881     0
-#define FPUB_68882     1
-#define FPUB_68040     2                       /* Internal FPU */
-#define FPUB_68060     3                       /* Internal FPU */
-#define FPUB_SUNFPA    4                       /* Sun-3 FPA */
-#define FPUB_COLDFIRE  5                       /* ColdFire FPU */
-
-#define FPU_68881      (1<<FPUB_68881)
-#define FPU_68882      (1<<FPUB_68882)
-#define FPU_68040      (1<<FPUB_68040)
-#define FPU_68060      (1<<FPUB_68060)
-#define FPU_SUNFPA     (1<<FPUB_SUNFPA)
-#define FPU_COLDFIRE   (1<<FPUB_COLDFIRE)
-
-#define MMUB_68851     0
-#define MMUB_68030     1                       /* Internal MMU */
-#define MMUB_68040     2                       /* Internal MMU */
-#define MMUB_68060     3                       /* Internal MMU */
-#define MMUB_APOLLO    4                       /* Custom Apollo */
-#define MMUB_SUN3      5                       /* Custom Sun-3 */
-#define MMUB_COLDFIRE  6                       /* Internal MMU */
-
-#define MMU_68851      (1<<MMUB_68851)
-#define MMU_68030      (1<<MMUB_68030)
-#define MMU_68040      (1<<MMUB_68040)
-#define MMU_68060      (1<<MMUB_68060)
-#define MMU_SUN3       (1<<MMUB_SUN3)
-#define MMU_APOLLO     (1<<MMUB_APOLLO)
-#define MMU_COLDFIRE   (1<<MMUB_COLDFIRE)
-
-#ifdef __KERNEL__
 
 #ifndef __ASSEMBLY__
 extern unsigned long m68k_cputype;
@@ -385,6 +307,4 @@ extern int m68k_realnum_memory;             /* real # of memory blocks found */
 extern struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
 #endif
 
-#endif /* __KERNEL__ */
-
 #endif /* _M68K_SETUP_H */
index 60e88660169c4575f53bb26d429b095abfd04a4e..67e489d8d1bd6450945b3b5a4320eaa4d1840953 100644 (file)
@@ -1,12 +1,8 @@
 #ifndef _M68K_SIGNAL_H
 #define _M68K_SIGNAL_H
 
-#include <linux/types.h>
+#include <uapi/asm/signal.h>
 
-/* Avoid too many header ordering problems.  */
-struct siginfo;
-
-#ifdef __KERNEL__
 /* Most things should be clean enough to redefine this at will, if care
    is taken to make libc match.  */
 
@@ -20,92 +16,6 @@ typedef struct {
        unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-#define NSIG           32
-typedef unsigned long sigset_t;
-
-#endif /* __KERNEL__ */
-
-#define SIGHUP          1
-#define SIGINT          2
-#define SIGQUIT                 3
-#define SIGILL          4
-#define SIGTRAP                 5
-#define SIGABRT                 6
-#define SIGIOT          6
-#define SIGBUS          7
-#define SIGFPE          8
-#define SIGKILL                 9
-#define SIGUSR1                10
-#define SIGSEGV                11
-#define SIGUSR2                12
-#define SIGPIPE                13
-#define SIGALRM                14
-#define SIGTERM                15
-#define SIGSTKFLT      16
-#define SIGCHLD                17
-#define SIGCONT                18
-#define SIGSTOP                19
-#define SIGTSTP                20
-#define SIGTTIN                21
-#define SIGTTOU                22
-#define SIGURG         23
-#define SIGXCPU                24
-#define SIGXFSZ                25
-#define SIGVTALRM      26
-#define SIGPROF                27
-#define SIGWINCH       28
-#define SIGIO          29
-#define SIGPOLL                SIGIO
-/*
-#define SIGLOST                29
-*/
-#define SIGPWR         30
-#define SIGSYS         31
-#define        SIGUNUSED       31
-
-/* These should not be considered constants from userland.  */
-#define SIGRTMIN       32
-#define SIGRTMAX       _NSIG
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP   0x00000001
-#define SA_NOCLDWAIT   0x00000002
-#define SA_SIGINFO     0x00000004
-#define SA_ONSTACK     0x08000000
-#define SA_RESTART     0x10000000
-#define SA_NODEFER     0x40000000
-#define SA_RESETHAND   0x80000000
-
-#define SA_NOMASK      SA_NODEFER
-#define SA_ONESHOT     SA_RESETHAND
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
-#define MINSIGSTKSZ    2048
-#define SIGSTKSZ       8192
-
-#include <asm-generic/signal-defs.h>
-
-#ifdef __KERNEL__
 struct old_sigaction {
        __sighandler_t sa_handler;
        old_sigset_t sa_mask;
@@ -123,31 +33,6 @@ struct sigaction {
 struct k_sigaction {
        struct sigaction sa;
 };
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-struct sigaction {
-       union {
-         __sighandler_t _sa_handler;
-         void (*_sa_sigaction)(int, struct siginfo *, void *);
-       } _u;
-       sigset_t sa_mask;
-       unsigned long sa_flags;
-       void (*sa_restorer)(void);
-};
-
-#define sa_handler     _u._sa_handler
-#define sa_sigaction   _u._sa_sigaction
-
-#endif /* __KERNEL__ */
-
-typedef struct sigaltstack {
-       void __user *ss_sp;
-       int ss_flags;
-       size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
 #include <asm/sigcontext.h>
 
 #ifndef CONFIG_CPU_HAS_NO_BITFIELDS
@@ -208,5 +93,4 @@ struct pt_regs;
 extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie);
 #endif /* __uClinux__ */
 
-#endif /* __KERNEL__ */
 #endif /* _M68K_SIGNAL_H */
index 0823032e404572fe7bbeca5a639fddd0595248b2..ad8efb098663ee41a28487f385c84642c4f4bf0f 100644 (file)
@@ -1,27 +1,8 @@
 #ifndef _M68K_TERMIOS_H
 #define _M68K_TERMIOS_H
 
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
+#include <uapi/asm/termios.h>
 
-struct winsize {
-       unsigned short ws_row;
-       unsigned short ws_col;
-       unsigned short ws_xpixel;
-       unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
-       unsigned short c_iflag;         /* input mode flags */
-       unsigned short c_oflag;         /* output mode flags */
-       unsigned short c_cflag;         /* control mode flags */
-       unsigned short c_lflag;         /* local mode flags */
-       unsigned char c_line;           /* line discipline */
-       unsigned char c_cc[NCC];        /* control characters */
-};
-
-#ifdef __KERNEL__
 /*     intr=^C         quit=^|         erase=del       kill=^U
        eof=^D          vtime=\0        vmin=\1         sxtc=\0
        start=^Q        stop=^S         susp=^Z         eol=\0
@@ -29,27 +10,6 @@ struct termio {
        eol2=\0
 */
 #define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
-#endif
-
-/* modem lines */
-#define TIOCM_LE       0x001
-#define TIOCM_DTR      0x002
-#define TIOCM_RTS      0x004
-#define TIOCM_ST       0x008
-#define TIOCM_SR       0x010
-#define TIOCM_CTS      0x020
-#define TIOCM_CAR      0x040
-#define TIOCM_RNG      0x080
-#define TIOCM_DSR      0x100
-#define TIOCM_CD       TIOCM_CAR
-#define TIOCM_RI       TIOCM_RNG
-#define TIOCM_OUT1     0x2000
-#define TIOCM_OUT2     0x4000
-#define TIOCM_LOOP     0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-#ifdef __KERNEL__
 
 /*
  * Translate a "termio" structure into a "termios". Ugh.
@@ -87,6 +47,4 @@ struct termio {
 #define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
 #define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
-#endif /* __KERNEL__ */
-
 #endif /* _M68K_TERMIOS_H */
index c702ad71679195f501f540b7ed5b32108f920813..5fc7f7bec1c807ced0c300d5f6f4747cf781c024 100644 (file)
 #ifndef _ASM_M68K_UNISTD_H_
 #define _ASM_M68K_UNISTD_H_
 
-/*
- * This file contains the system call numbers.
- */
-
-#define __NR_restart_syscall     0
-#define __NR_exit                1
-#define __NR_fork                2
-#define __NR_read                3
-#define __NR_write               4
-#define __NR_open                5
-#define __NR_close               6
-#define __NR_waitpid             7
-#define __NR_creat               8
-#define __NR_link                9
-#define __NR_unlink             10
-#define __NR_execve             11
-#define __NR_chdir              12
-#define __NR_time               13
-#define __NR_mknod              14
-#define __NR_chmod              15
-#define __NR_chown              16
-/*#define __NR_break            17*/
-#define __NR_oldstat            18
-#define __NR_lseek              19
-#define __NR_getpid             20
-#define __NR_mount              21
-#define __NR_umount             22
-#define __NR_setuid             23
-#define __NR_getuid             24
-#define __NR_stime              25
-#define __NR_ptrace             26
-#define __NR_alarm              27
-#define __NR_oldfstat           28
-#define __NR_pause              29
-#define __NR_utime              30
-/*#define __NR_stty             31*/
-/*#define __NR_gtty             32*/
-#define __NR_access             33
-#define __NR_nice               34
-/*#define __NR_ftime            35*/
-#define __NR_sync               36
-#define __NR_kill               37
-#define __NR_rename             38
-#define __NR_mkdir              39
-#define __NR_rmdir              40
-#define __NR_dup                41
-#define __NR_pipe               42
-#define __NR_times              43
-/*#define __NR_prof             44*/
-#define __NR_brk                45
-#define __NR_setgid             46
-#define __NR_getgid             47
-#define __NR_signal             48
-#define __NR_geteuid            49
-#define __NR_getegid            50
-#define __NR_acct               51
-#define __NR_umount2            52
-/*#define __NR_lock             53*/
-#define __NR_ioctl              54
-#define __NR_fcntl              55
-/*#define __NR_mpx              56*/
-#define __NR_setpgid            57
-/*#define __NR_ulimit           58*/
-/*#define __NR_oldolduname      59*/
-#define __NR_umask              60
-#define __NR_chroot             61
-#define __NR_ustat              62
-#define __NR_dup2               63
-#define __NR_getppid            64
-#define __NR_getpgrp            65
-#define __NR_setsid             66
-#define __NR_sigaction          67
-#define __NR_sgetmask           68
-#define __NR_ssetmask           69
-#define __NR_setreuid           70
-#define __NR_setregid           71
-#define __NR_sigsuspend                 72
-#define __NR_sigpending                 73
-#define __NR_sethostname        74
-#define __NR_setrlimit          75
-#define __NR_getrlimit          76
-#define __NR_getrusage          77
-#define __NR_gettimeofday       78
-#define __NR_settimeofday       79
-#define __NR_getgroups          80
-#define __NR_setgroups          81
-#define __NR_select             82
-#define __NR_symlink            83
-#define __NR_oldlstat           84
-#define __NR_readlink           85
-#define __NR_uselib             86
-#define __NR_swapon             87
-#define __NR_reboot             88
-#define __NR_readdir            89
-#define __NR_mmap               90
-#define __NR_munmap             91
-#define __NR_truncate           92
-#define __NR_ftruncate          93
-#define __NR_fchmod             94
-#define __NR_fchown             95
-#define __NR_getpriority        96
-#define __NR_setpriority        97
-/*#define __NR_profil           98*/
-#define __NR_statfs             99
-#define __NR_fstatfs           100
-/*#define __NR_ioperm          101*/
-#define __NR_socketcall                102
-#define __NR_syslog            103
-#define __NR_setitimer         104
-#define __NR_getitimer         105
-#define __NR_stat              106
-#define __NR_lstat             107
-#define __NR_fstat             108
-/*#define __NR_olduname                109*/
-/*#define __NR_iopl            110*/ /* not supported */
-#define __NR_vhangup           111
-/*#define __NR_idle            112*/ /* Obsolete */
-/*#define __NR_vm86            113*/ /* not supported */
-#define __NR_wait4             114
-#define __NR_swapoff           115
-#define __NR_sysinfo           116
-#define __NR_ipc               117
-#define __NR_fsync             118
-#define __NR_sigreturn         119
-#define __NR_clone             120
-#define __NR_setdomainname     121
-#define __NR_uname             122
-#define __NR_cacheflush                123
-#define __NR_adjtimex          124
-#define __NR_mprotect          125
-#define __NR_sigprocmask       126
-#define __NR_create_module     127
-#define __NR_init_module       128
-#define __NR_delete_module     129
-#define __NR_get_kernel_syms   130
-#define __NR_quotactl          131
-#define __NR_getpgid           132
-#define __NR_fchdir            133
-#define __NR_bdflush           134
-#define __NR_sysfs             135
-#define __NR_personality       136
-/*#define __NR_afs_syscall     137*/ /* Syscall for Andrew File System */
-#define __NR_setfsuid          138
-#define __NR_setfsgid          139
-#define __NR__llseek           140
-#define __NR_getdents          141
-#define __NR__newselect                142
-#define __NR_flock             143
-#define __NR_msync             144
-#define __NR_readv             145
-#define __NR_writev            146
-#define __NR_getsid            147
-#define __NR_fdatasync         148
-#define __NR__sysctl           149
-#define __NR_mlock             150
-#define __NR_munlock           151
-#define __NR_mlockall          152
-#define __NR_munlockall                153
-#define __NR_sched_setparam            154
-#define __NR_sched_getparam            155
-#define __NR_sched_setscheduler                156
-#define __NR_sched_getscheduler                157
-#define __NR_sched_yield               158
-#define __NR_sched_get_priority_max    159
-#define __NR_sched_get_priority_min    160
-#define __NR_sched_rr_get_interval     161
-#define __NR_nanosleep         162
-#define __NR_mremap            163
-#define __NR_setresuid         164
-#define __NR_getresuid         165
-#define __NR_getpagesize       166
-#define __NR_query_module      167
-#define __NR_poll              168
-#define __NR_nfsservctl                169
-#define __NR_setresgid         170
-#define __NR_getresgid         171
-#define __NR_prctl             172
-#define __NR_rt_sigreturn      173
-#define __NR_rt_sigaction      174
-#define __NR_rt_sigprocmask    175
-#define __NR_rt_sigpending     176
-#define __NR_rt_sigtimedwait   177
-#define __NR_rt_sigqueueinfo   178
-#define __NR_rt_sigsuspend     179
-#define __NR_pread64           180
-#define __NR_pwrite64          181
-#define __NR_lchown            182
-#define __NR_getcwd            183
-#define __NR_capget            184
-#define __NR_capset            185
-#define __NR_sigaltstack       186
-#define __NR_sendfile          187
-#define __NR_getpmsg           188     /* some people actually want streams */
-#define __NR_putpmsg           189     /* some people actually want streams */
-#define __NR_vfork             190
-#define __NR_ugetrlimit                191
-#define __NR_mmap2             192
-#define __NR_truncate64                193
-#define __NR_ftruncate64       194
-#define __NR_stat64            195
-#define __NR_lstat64           196
-#define __NR_fstat64           197
-#define __NR_chown32           198
-#define __NR_getuid32          199
-#define __NR_getgid32          200
-#define __NR_geteuid32         201
-#define __NR_getegid32         202
-#define __NR_setreuid32                203
-#define __NR_setregid32                204
-#define __NR_getgroups32       205
-#define __NR_setgroups32       206
-#define __NR_fchown32          207
-#define __NR_setresuid32       208
-#define __NR_getresuid32       209
-#define __NR_setresgid32       210
-#define __NR_getresgid32       211
-#define __NR_lchown32          212
-#define __NR_setuid32          213
-#define __NR_setgid32          214
-#define __NR_setfsuid32                215
-#define __NR_setfsgid32                216
-#define __NR_pivot_root                217
-/* 218*/
-/* 219*/
-#define __NR_getdents64                220
-#define __NR_gettid            221
-#define __NR_tkill             222
-#define __NR_setxattr          223
-#define __NR_lsetxattr         224
-#define __NR_fsetxattr         225
-#define __NR_getxattr          226
-#define __NR_lgetxattr         227
-#define __NR_fgetxattr         228
-#define __NR_listxattr         229
-#define __NR_llistxattr                230
-#define __NR_flistxattr                231
-#define __NR_removexattr       232
-#define __NR_lremovexattr      233
-#define __NR_fremovexattr      234
-#define __NR_futex             235
-#define __NR_sendfile64                236
-#define __NR_mincore           237
-#define __NR_madvise           238
-#define __NR_fcntl64           239
-#define __NR_readahead         240
-#define __NR_io_setup          241
-#define __NR_io_destroy                242
-#define __NR_io_getevents      243
-#define __NR_io_submit         244
-#define __NR_io_cancel         245
-#define __NR_fadvise64         246
-#define __NR_exit_group                247
-#define __NR_lookup_dcookie    248
-#define __NR_epoll_create      249
-#define __NR_epoll_ctl         250
-#define __NR_epoll_wait                251
-#define __NR_remap_file_pages  252
-#define __NR_set_tid_address   253
-#define __NR_timer_create      254
-#define __NR_timer_settime     255
-#define __NR_timer_gettime     256
-#define __NR_timer_getoverrun  257
-#define __NR_timer_delete      258
-#define __NR_clock_settime     259
-#define __NR_clock_gettime     260
-#define __NR_clock_getres      261
-#define __NR_clock_nanosleep   262
-#define __NR_statfs64          263
-#define __NR_fstatfs64         264
-#define __NR_tgkill            265
-#define __NR_utimes            266
-#define __NR_fadvise64_64      267
-#define __NR_mbind             268
-#define __NR_get_mempolicy     269
-#define __NR_set_mempolicy     270
-#define __NR_mq_open           271
-#define __NR_mq_unlink         272
-#define __NR_mq_timedsend      273
-#define __NR_mq_timedreceive   274
-#define __NR_mq_notify         275
-#define __NR_mq_getsetattr     276
-#define __NR_waitid            277
-/*#define __NR_vserver         278*/
-#define __NR_add_key           279
-#define __NR_request_key       280
-#define __NR_keyctl            281
-#define __NR_ioprio_set                282
-#define __NR_ioprio_get                283
-#define __NR_inotify_init      284
-#define __NR_inotify_add_watch 285
-#define __NR_inotify_rm_watch  286
-#define __NR_migrate_pages     287
-#define __NR_openat            288
-#define __NR_mkdirat           289
-#define __NR_mknodat           290
-#define __NR_fchownat          291
-#define __NR_futimesat         292
-#define __NR_fstatat64         293
-#define __NR_unlinkat          294
-#define __NR_renameat          295
-#define __NR_linkat            296
-#define __NR_symlinkat         297
-#define __NR_readlinkat                298
-#define __NR_fchmodat          299
-#define __NR_faccessat         300
-#define __NR_pselect6          301
-#define __NR_ppoll             302
-#define __NR_unshare           303
-#define __NR_set_robust_list   304
-#define __NR_get_robust_list   305
-#define __NR_splice            306
-#define __NR_sync_file_range   307
-#define __NR_tee               308
-#define __NR_vmsplice          309
-#define __NR_move_pages                310
-#define __NR_sched_setaffinity 311
-#define __NR_sched_getaffinity 312
-#define __NR_kexec_load                313
-#define __NR_getcpu            314
-#define __NR_epoll_pwait       315
-#define __NR_utimensat         316
-#define __NR_signalfd          317
-#define __NR_timerfd_create    318
-#define __NR_eventfd           319
-#define __NR_fallocate         320
-#define __NR_timerfd_settime   321
-#define __NR_timerfd_gettime   322
-#define __NR_signalfd4         323
-#define __NR_eventfd2          324
-#define __NR_epoll_create1     325
-#define __NR_dup3              326
-#define __NR_pipe2             327
-#define __NR_inotify_init1     328
-#define __NR_preadv            329
-#define __NR_pwritev           330
-#define __NR_rt_tgsigqueueinfo 331
-#define __NR_perf_event_open   332
-#define __NR_get_thread_area   333
-#define __NR_set_thread_area   334
-#define __NR_atomic_cmpxchg_32 335
-#define __NR_atomic_barrier    336
-#define __NR_fanotify_init     337
-#define __NR_fanotify_mark     338
-#define __NR_prlimit64         339
-#define __NR_name_to_handle_at 340
-#define __NR_open_by_handle_at 341
-#define __NR_clock_adjtime     342
-#define __NR_syncfs            343
-#define __NR_setns             344
-#define __NR_process_vm_readv  345
-#define __NR_process_vm_writev 346
+#include <uapi/asm/unistd.h>
 
-#ifdef __KERNEL__
 
-#define NR_syscalls            347
+#define NR_syscalls            348
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
-#endif /* __KERNEL__ */
 #endif /* _ASM_M68K_UNISTD_H_ */
index baebb3da1d44160fc6f6f259886656e6f494b167..972bce120e1e94b8550408f788e0502ecd3d308f 100644 (file)
@@ -1,3 +1,26 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += a.out.h
+header-y += auxvec.h
+header-y += byteorder.h
+header-y += cachectl.h
+header-y += fcntl.h
+header-y += ioctls.h
+header-y += msgbuf.h
+header-y += param.h
+header-y += poll.h
+header-y += posix_types.h
+header-y += ptrace.h
+header-y += sembuf.h
+header-y += setup.h
+header-y += shmbuf.h
+header-y += sigcontext.h
+header-y += signal.h
+header-y += socket.h
+header-y += sockios.h
+header-y += stat.h
+header-y += swab.h
+header-y += termbits.h
+header-y += termios.h
+header-y += unistd.h
diff --git a/arch/m68k/include/uapi/asm/ptrace.h b/arch/m68k/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..caf92fd
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef _UAPI_M68K_PTRACE_H
+#define _UAPI_M68K_PTRACE_H
+
+#define PT_D1     0
+#define PT_D2     1
+#define PT_D3     2
+#define PT_D4     3
+#define PT_D5     4
+#define PT_D6     5
+#define PT_D7     6
+#define PT_A0     7
+#define PT_A1     8
+#define PT_A2     9
+#define PT_A3     10
+#define PT_A4     11
+#define PT_A5     12
+#define PT_A6     13
+#define PT_D0     14
+#define PT_USP    15
+#define PT_ORIG_D0 16
+#define PT_SR     17
+#define PT_PC     18
+
+#ifndef __ASSEMBLY__
+
+/* this struct defines the way the registers are stored on the
+   stack during a system call. */
+
+struct pt_regs {
+  long     d1;
+  long     d2;
+  long     d3;
+  long     d4;
+  long     d5;
+  long     a0;
+  long     a1;
+  long     a2;
+  long     d0;
+  long     orig_d0;
+  long     stkadj;
+#ifdef CONFIG_COLDFIRE
+  unsigned format :  4; /* frame format specifier */
+  unsigned vector : 12; /* vector offset */
+  unsigned short sr;
+  unsigned long  pc;
+#else
+  unsigned short sr;
+  unsigned long  pc;
+  unsigned format :  4; /* frame format specifier */
+  unsigned vector : 12; /* vector offset */
+#endif
+};
+
+/*
+ * This is the extended stack used by signal handlers and the context
+ * switcher: it's pushed after the normal "struct pt_regs".
+ */
+struct switch_stack {
+       unsigned long  d6;
+       unsigned long  d7;
+       unsigned long  a3;
+       unsigned long  a4;
+       unsigned long  a5;
+       unsigned long  a6;
+       unsigned long  retpc;
+};
+
+/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13
+#define PTRACE_GETFPREGS          14
+#define PTRACE_SETFPREGS          15
+
+#define PTRACE_GET_THREAD_AREA    25
+
+#define PTRACE_SINGLEBLOCK     33      /* resume execution until next branch */
+
+#endif /* __ASSEMBLY__ */
+#endif /* _UAPI_M68K_PTRACE_H */
diff --git a/arch/m68k/include/uapi/asm/setup.h b/arch/m68k/include/uapi/asm/setup.h
new file mode 100644 (file)
index 0000000..85579bf
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+** asm/setup.h -- Definition of the Linux/m68k setup information
+**
+** Copyright 1992 by Greg Harp
+**
+** This file is subject to the terms and conditions of the GNU General Public
+** License.  See the file COPYING in the main directory of this archive
+** for more details.
+**
+** Created 09/29/92 by Greg Harp
+**
+** 5/2/94 Roman Hodek:
+**   Added bi_atari part of the machine dependent union bi_un; for now it
+**   contains just a model field to distinguish between TT and Falcon.
+** 26/7/96 Roman Zippel:
+**   Renamed to setup.h; added some useful macros to allow gcc some
+**   optimizations if possible.
+** 5/10/96 Geert Uytterhoeven:
+**   Redesign of the boot information structure; moved boot information
+**   structure to bootinfo.h
+*/
+
+#ifndef _UAPI_M68K_SETUP_H
+#define _UAPI_M68K_SETUP_H
+
+
+
+    /*
+     *  Linux/m68k Architectures
+     */
+
+#define MACH_AMIGA    1
+#define MACH_ATARI    2
+#define MACH_MAC      3
+#define MACH_APOLLO   4
+#define MACH_SUN3     5
+#define MACH_MVME147  6
+#define MACH_MVME16x  7
+#define MACH_BVME6000 8
+#define MACH_HP300    9
+#define MACH_Q40     10
+#define MACH_SUN3X   11
+#define MACH_M54XX   12
+
+#define COMMAND_LINE_SIZE 256
+
+
+
+    /*
+     *  CPU, FPU and MMU types
+     *
+     *  Note: we may rely on the following equalities:
+     *
+     *      CPU_68020 == MMU_68851
+     *      CPU_68030 == MMU_68030
+     *      CPU_68040 == FPU_68040 == MMU_68040
+     *      CPU_68060 == FPU_68060 == MMU_68060
+     */
+
+#define CPUB_68020     0
+#define CPUB_68030     1
+#define CPUB_68040     2
+#define CPUB_68060     3
+#define CPUB_COLDFIRE  4
+
+#define CPU_68020      (1<<CPUB_68020)
+#define CPU_68030      (1<<CPUB_68030)
+#define CPU_68040      (1<<CPUB_68040)
+#define CPU_68060      (1<<CPUB_68060)
+#define CPU_COLDFIRE   (1<<CPUB_COLDFIRE)
+
+#define FPUB_68881     0
+#define FPUB_68882     1
+#define FPUB_68040     2                       /* Internal FPU */
+#define FPUB_68060     3                       /* Internal FPU */
+#define FPUB_SUNFPA    4                       /* Sun-3 FPA */
+#define FPUB_COLDFIRE  5                       /* ColdFire FPU */
+
+#define FPU_68881      (1<<FPUB_68881)
+#define FPU_68882      (1<<FPUB_68882)
+#define FPU_68040      (1<<FPUB_68040)
+#define FPU_68060      (1<<FPUB_68060)
+#define FPU_SUNFPA     (1<<FPUB_SUNFPA)
+#define FPU_COLDFIRE   (1<<FPUB_COLDFIRE)
+
+#define MMUB_68851     0
+#define MMUB_68030     1                       /* Internal MMU */
+#define MMUB_68040     2                       /* Internal MMU */
+#define MMUB_68060     3                       /* Internal MMU */
+#define MMUB_APOLLO    4                       /* Custom Apollo */
+#define MMUB_SUN3      5                       /* Custom Sun-3 */
+#define MMUB_COLDFIRE  6                       /* Internal MMU */
+
+#define MMU_68851      (1<<MMUB_68851)
+#define MMU_68030      (1<<MMUB_68030)
+#define MMU_68040      (1<<MMUB_68040)
+#define MMU_68060      (1<<MMUB_68060)
+#define MMU_SUN3       (1<<MMUB_SUN3)
+#define MMU_APOLLO     (1<<MMUB_APOLLO)
+#define MMU_COLDFIRE   (1<<MMUB_COLDFIRE)
+
+
+#endif /* _UAPI_M68K_SETUP_H */
diff --git a/arch/m68k/include/uapi/asm/signal.h b/arch/m68k/include/uapi/asm/signal.h
new file mode 100644 (file)
index 0000000..2b450f3
--- /dev/null
@@ -0,0 +1,118 @@
+#ifndef _UAPI_M68K_SIGNAL_H
+#define _UAPI_M68K_SIGNAL_H
+
+#include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+
+#ifndef __KERNEL__
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+#define NSIG           32
+typedef unsigned long sigset_t;
+
+#endif /* __KERNEL__ */
+
+#define SIGHUP          1
+#define SIGINT          2
+#define SIGQUIT                 3
+#define SIGILL          4
+#define SIGTRAP                 5
+#define SIGABRT                 6
+#define SIGIOT          6
+#define SIGBUS          7
+#define SIGFPE          8
+#define SIGKILL                 9
+#define SIGUSR1                10
+#define SIGSEGV                11
+#define SIGUSR2                12
+#define SIGPIPE                13
+#define SIGALRM                14
+#define SIGTERM                15
+#define SIGSTKFLT      16
+#define SIGCHLD                17
+#define SIGCONT                18
+#define SIGSTOP                19
+#define SIGTSTP                20
+#define SIGTTIN                21
+#define SIGTTOU                22
+#define SIGURG         23
+#define SIGXCPU                24
+#define SIGXFSZ                25
+#define SIGVTALRM      26
+#define SIGPROF                27
+#define SIGWINCH       28
+#define SIGIO          29
+#define SIGPOLL                SIGIO
+/*
+#define SIGLOST                29
+*/
+#define SIGPWR         30
+#define SIGSYS         31
+#define        SIGUNUSED       31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN       32
+#define SIGRTMAX       _NSIG
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP   0x00000001
+#define SA_NOCLDWAIT   0x00000002
+#define SA_SIGINFO     0x00000004
+#define SA_ONSTACK     0x08000000
+#define SA_RESTART     0x10000000
+#define SA_NODEFER     0x40000000
+#define SA_RESETHAND   0x80000000
+
+#define SA_NOMASK      SA_NODEFER
+#define SA_ONESHOT     SA_RESETHAND
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK     1
+#define SS_DISABLE     2
+
+#define MINSIGSTKSZ    2048
+#define SIGSTKSZ       8192
+
+#include <asm-generic/signal-defs.h>
+
+#ifndef __KERNEL__
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+       union {
+         __sighandler_t _sa_handler;
+         void (*_sa_sigaction)(int, struct siginfo *, void *);
+       } _u;
+       sigset_t sa_mask;
+       unsigned long sa_flags;
+       void (*sa_restorer)(void);
+};
+
+#define sa_handler     _u._sa_handler
+#define sa_sigaction   _u._sa_sigaction
+
+#endif /* __KERNEL__ */
+
+typedef struct sigaltstack {
+       void __user *ss_sp;
+       int ss_flags;
+       size_t ss_size;
+} stack_t;
+
+#endif /* _UAPI_M68K_SIGNAL_H */
diff --git a/arch/m68k/include/uapi/asm/termios.h b/arch/m68k/include/uapi/asm/termios.h
new file mode 100644 (file)
index 0000000..ce2142c
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef _UAPI_M68K_TERMIOS_H
+#define _UAPI_M68K_TERMIOS_H
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+       unsigned short ws_row;
+       unsigned short ws_col;
+       unsigned short ws_xpixel;
+       unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+       unsigned short c_iflag;         /* input mode flags */
+       unsigned short c_oflag;         /* output mode flags */
+       unsigned short c_cflag;         /* control mode flags */
+       unsigned short c_lflag;         /* local mode flags */
+       unsigned char c_line;           /* line discipline */
+       unsigned char c_cc[NCC];        /* control characters */
+};
+
+
+/* modem lines */
+#define TIOCM_LE       0x001
+#define TIOCM_DTR      0x002
+#define TIOCM_RTS      0x004
+#define TIOCM_ST       0x008
+#define TIOCM_SR       0x010
+#define TIOCM_CTS      0x020
+#define TIOCM_CAR      0x040
+#define TIOCM_RNG      0x080
+#define TIOCM_DSR      0x100
+#define TIOCM_CD       TIOCM_CAR
+#define TIOCM_RI       TIOCM_RNG
+#define TIOCM_OUT1     0x2000
+#define TIOCM_OUT2     0x4000
+#define TIOCM_LOOP     0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+
+#endif /* _UAPI_M68K_TERMIOS_H */
diff --git a/arch/m68k/include/uapi/asm/unistd.h b/arch/m68k/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..b94bfbf
--- /dev/null
@@ -0,0 +1,357 @@
+#ifndef _UAPI_ASM_M68K_UNISTD_H_
+#define _UAPI_ASM_M68K_UNISTD_H_
+
+/*
+ * This file contains the system call numbers.
+ */
+
+#define __NR_restart_syscall     0
+#define __NR_exit                1
+#define __NR_fork                2
+#define __NR_read                3
+#define __NR_write               4
+#define __NR_open                5
+#define __NR_close               6
+#define __NR_waitpid             7
+#define __NR_creat               8
+#define __NR_link                9
+#define __NR_unlink             10
+#define __NR_execve             11
+#define __NR_chdir              12
+#define __NR_time               13
+#define __NR_mknod              14
+#define __NR_chmod              15
+#define __NR_chown              16
+/*#define __NR_break            17*/
+#define __NR_oldstat            18
+#define __NR_lseek              19
+#define __NR_getpid             20
+#define __NR_mount              21
+#define __NR_umount             22
+#define __NR_setuid             23
+#define __NR_getuid             24
+#define __NR_stime              25
+#define __NR_ptrace             26
+#define __NR_alarm              27
+#define __NR_oldfstat           28
+#define __NR_pause              29
+#define __NR_utime              30
+/*#define __NR_stty             31*/
+/*#define __NR_gtty             32*/
+#define __NR_access             33
+#define __NR_nice               34
+/*#define __NR_ftime            35*/
+#define __NR_sync               36
+#define __NR_kill               37
+#define __NR_rename             38
+#define __NR_mkdir              39
+#define __NR_rmdir              40
+#define __NR_dup                41
+#define __NR_pipe               42
+#define __NR_times              43
+/*#define __NR_prof             44*/
+#define __NR_brk                45
+#define __NR_setgid             46
+#define __NR_getgid             47
+#define __NR_signal             48
+#define __NR_geteuid            49
+#define __NR_getegid            50
+#define __NR_acct               51
+#define __NR_umount2            52
+/*#define __NR_lock             53*/
+#define __NR_ioctl              54
+#define __NR_fcntl              55
+/*#define __NR_mpx              56*/
+#define __NR_setpgid            57
+/*#define __NR_ulimit           58*/
+/*#define __NR_oldolduname      59*/
+#define __NR_umask              60
+#define __NR_chroot             61
+#define __NR_ustat              62
+#define __NR_dup2               63
+#define __NR_getppid            64
+#define __NR_getpgrp            65
+#define __NR_setsid             66
+#define __NR_sigaction          67
+#define __NR_sgetmask           68
+#define __NR_ssetmask           69
+#define __NR_setreuid           70
+#define __NR_setregid           71
+#define __NR_sigsuspend                 72
+#define __NR_sigpending                 73
+#define __NR_sethostname        74
+#define __NR_setrlimit          75
+#define __NR_getrlimit          76
+#define __NR_getrusage          77
+#define __NR_gettimeofday       78
+#define __NR_settimeofday       79
+#define __NR_getgroups          80
+#define __NR_setgroups          81
+#define __NR_select             82
+#define __NR_symlink            83
+#define __NR_oldlstat           84
+#define __NR_readlink           85
+#define __NR_uselib             86
+#define __NR_swapon             87
+#define __NR_reboot             88
+#define __NR_readdir            89
+#define __NR_mmap               90
+#define __NR_munmap             91
+#define __NR_truncate           92
+#define __NR_ftruncate          93
+#define __NR_fchmod             94
+#define __NR_fchown             95
+#define __NR_getpriority        96
+#define __NR_setpriority        97
+/*#define __NR_profil           98*/
+#define __NR_statfs             99
+#define __NR_fstatfs           100
+/*#define __NR_ioperm          101*/
+#define __NR_socketcall                102
+#define __NR_syslog            103
+#define __NR_setitimer         104
+#define __NR_getitimer         105
+#define __NR_stat              106
+#define __NR_lstat             107
+#define __NR_fstat             108
+/*#define __NR_olduname                109*/
+/*#define __NR_iopl            110*/ /* not supported */
+#define __NR_vhangup           111
+/*#define __NR_idle            112*/ /* Obsolete */
+/*#define __NR_vm86            113*/ /* not supported */
+#define __NR_wait4             114
+#define __NR_swapoff           115
+#define __NR_sysinfo           116
+#define __NR_ipc               117
+#define __NR_fsync             118
+#define __NR_sigreturn         119
+#define __NR_clone             120
+#define __NR_setdomainname     121
+#define __NR_uname             122
+#define __NR_cacheflush                123
+#define __NR_adjtimex          124
+#define __NR_mprotect          125
+#define __NR_sigprocmask       126
+#define __NR_create_module     127
+#define __NR_init_module       128
+#define __NR_delete_module     129
+#define __NR_get_kernel_syms   130
+#define __NR_quotactl          131
+#define __NR_getpgid           132
+#define __NR_fchdir            133
+#define __NR_bdflush           134
+#define __NR_sysfs             135
+#define __NR_personality       136
+/*#define __NR_afs_syscall     137*/ /* Syscall for Andrew File System */
+#define __NR_setfsuid          138
+#define __NR_setfsgid          139
+#define __NR__llseek           140
+#define __NR_getdents          141
+#define __NR__newselect                142
+#define __NR_flock             143
+#define __NR_msync             144
+#define __NR_readv             145
+#define __NR_writev            146
+#define __NR_getsid            147
+#define __NR_fdatasync         148
+#define __NR__sysctl           149
+#define __NR_mlock             150
+#define __NR_munlock           151
+#define __NR_mlockall          152
+#define __NR_munlockall                153
+#define __NR_sched_setparam            154
+#define __NR_sched_getparam            155
+#define __NR_sched_setscheduler                156
+#define __NR_sched_getscheduler                157
+#define __NR_sched_yield               158
+#define __NR_sched_get_priority_max    159
+#define __NR_sched_get_priority_min    160
+#define __NR_sched_rr_get_interval     161
+#define __NR_nanosleep         162
+#define __NR_mremap            163
+#define __NR_setresuid         164
+#define __NR_getresuid         165
+#define __NR_getpagesize       166
+#define __NR_query_module      167
+#define __NR_poll              168
+#define __NR_nfsservctl                169
+#define __NR_setresgid         170
+#define __NR_getresgid         171
+#define __NR_prctl             172
+#define __NR_rt_sigreturn      173
+#define __NR_rt_sigaction      174
+#define __NR_rt_sigprocmask    175
+#define __NR_rt_sigpending     176
+#define __NR_rt_sigtimedwait   177
+#define __NR_rt_sigqueueinfo   178
+#define __NR_rt_sigsuspend     179
+#define __NR_pread64           180
+#define __NR_pwrite64          181
+#define __NR_lchown            182
+#define __NR_getcwd            183
+#define __NR_capget            184
+#define __NR_capset            185
+#define __NR_sigaltstack       186
+#define __NR_sendfile          187
+#define __NR_getpmsg           188     /* some people actually want streams */
+#define __NR_putpmsg           189     /* some people actually want streams */
+#define __NR_vfork             190
+#define __NR_ugetrlimit                191
+#define __NR_mmap2             192
+#define __NR_truncate64                193
+#define __NR_ftruncate64       194
+#define __NR_stat64            195
+#define __NR_lstat64           196
+#define __NR_fstat64           197
+#define __NR_chown32           198
+#define __NR_getuid32          199
+#define __NR_getgid32          200
+#define __NR_geteuid32         201
+#define __NR_getegid32         202
+#define __NR_setreuid32                203
+#define __NR_setregid32                204
+#define __NR_getgroups32       205
+#define __NR_setgroups32       206
+#define __NR_fchown32          207
+#define __NR_setresuid32       208
+#define __NR_getresuid32       209
+#define __NR_setresgid32       210
+#define __NR_getresgid32       211
+#define __NR_lchown32          212
+#define __NR_setuid32          213
+#define __NR_setgid32          214
+#define __NR_setfsuid32                215
+#define __NR_setfsgid32                216
+#define __NR_pivot_root                217
+/* 218*/
+/* 219*/
+#define __NR_getdents64                220
+#define __NR_gettid            221
+#define __NR_tkill             222
+#define __NR_setxattr          223
+#define __NR_lsetxattr         224
+#define __NR_fsetxattr         225
+#define __NR_getxattr          226
+#define __NR_lgetxattr         227
+#define __NR_fgetxattr         228
+#define __NR_listxattr         229
+#define __NR_llistxattr                230
+#define __NR_flistxattr                231
+#define __NR_removexattr       232
+#define __NR_lremovexattr      233
+#define __NR_fremovexattr      234
+#define __NR_futex             235
+#define __NR_sendfile64                236
+#define __NR_mincore           237
+#define __NR_madvise           238
+#define __NR_fcntl64           239
+#define __NR_readahead         240
+#define __NR_io_setup          241
+#define __NR_io_destroy                242
+#define __NR_io_getevents      243
+#define __NR_io_submit         244
+#define __NR_io_cancel         245
+#define __NR_fadvise64         246
+#define __NR_exit_group                247
+#define __NR_lookup_dcookie    248
+#define __NR_epoll_create      249
+#define __NR_epoll_ctl         250
+#define __NR_epoll_wait                251
+#define __NR_remap_file_pages  252
+#define __NR_set_tid_address   253
+#define __NR_timer_create      254
+#define __NR_timer_settime     255
+#define __NR_timer_gettime     256
+#define __NR_timer_getoverrun  257
+#define __NR_timer_delete      258
+#define __NR_clock_settime     259
+#define __NR_clock_gettime     260
+#define __NR_clock_getres      261
+#define __NR_clock_nanosleep   262
+#define __NR_statfs64          263
+#define __NR_fstatfs64         264
+#define __NR_tgkill            265
+#define __NR_utimes            266
+#define __NR_fadvise64_64      267
+#define __NR_mbind             268
+#define __NR_get_mempolicy     269
+#define __NR_set_mempolicy     270
+#define __NR_mq_open           271
+#define __NR_mq_unlink         272
+#define __NR_mq_timedsend      273
+#define __NR_mq_timedreceive   274
+#define __NR_mq_notify         275
+#define __NR_mq_getsetattr     276
+#define __NR_waitid            277
+/*#define __NR_vserver         278*/
+#define __NR_add_key           279
+#define __NR_request_key       280
+#define __NR_keyctl            281
+#define __NR_ioprio_set                282
+#define __NR_ioprio_get                283
+#define __NR_inotify_init      284
+#define __NR_inotify_add_watch 285
+#define __NR_inotify_rm_watch  286
+#define __NR_migrate_pages     287
+#define __NR_openat            288
+#define __NR_mkdirat           289
+#define __NR_mknodat           290
+#define __NR_fchownat          291
+#define __NR_futimesat         292
+#define __NR_fstatat64         293
+#define __NR_unlinkat          294
+#define __NR_renameat          295
+#define __NR_linkat            296
+#define __NR_symlinkat         297
+#define __NR_readlinkat                298
+#define __NR_fchmodat          299
+#define __NR_faccessat         300
+#define __NR_pselect6          301
+#define __NR_ppoll             302
+#define __NR_unshare           303
+#define __NR_set_robust_list   304
+#define __NR_get_robust_list   305
+#define __NR_splice            306
+#define __NR_sync_file_range   307
+#define __NR_tee               308
+#define __NR_vmsplice          309
+#define __NR_move_pages                310
+#define __NR_sched_setaffinity 311
+#define __NR_sched_getaffinity 312
+#define __NR_kexec_load                313
+#define __NR_getcpu            314
+#define __NR_epoll_pwait       315
+#define __NR_utimensat         316
+#define __NR_signalfd          317
+#define __NR_timerfd_create    318
+#define __NR_eventfd           319
+#define __NR_fallocate         320
+#define __NR_timerfd_settime   321
+#define __NR_timerfd_gettime   322
+#define __NR_signalfd4         323
+#define __NR_eventfd2          324
+#define __NR_epoll_create1     325
+#define __NR_dup3              326
+#define __NR_pipe2             327
+#define __NR_inotify_init1     328
+#define __NR_preadv            329
+#define __NR_pwritev           330
+#define __NR_rt_tgsigqueueinfo 331
+#define __NR_perf_event_open   332
+#define __NR_get_thread_area   333
+#define __NR_set_thread_area   334
+#define __NR_atomic_cmpxchg_32 335
+#define __NR_atomic_barrier    336
+#define __NR_fanotify_init     337
+#define __NR_fanotify_mark     338
+#define __NR_prlimit64         339
+#define __NR_name_to_handle_at 340
+#define __NR_open_by_handle_at 341
+#define __NR_clock_adjtime     342
+#define __NR_syncfs            343
+#define __NR_setns             344
+#define __NR_process_vm_readv  345
+#define __NR_process_vm_writev 346
+#define __NR_kcmp              347
+
+#endif /* _UAPI_ASM_M68K_UNISTD_H_ */
index ce827b376110a6a815b4ccece0a066e5ad66cc59..4fc2e29b771b51eb2e2189a4c050c5e05510bc2b 100644 (file)
@@ -367,4 +367,5 @@ ENTRY(sys_call_table)
        .long sys_setns
        .long sys_process_vm_readv      /* 345 */
        .long sys_process_vm_writev
+       .long sys_kcmp
 
index 3f3d9ca7a5b68fefdb333818fe6189d8c6cbf3ae..5dba755a43e60911ae2a5b922bde0c9f4a70b6f1 100644 (file)
@@ -130,6 +130,7 @@ config S390
        select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
        select HAVE_UID16 if 32BIT
        select ARCH_WANT_IPC_PARSE_VERSION
+       select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_TIME_VSYSCALL_OLD
        select GENERIC_CLOCKEVENTS
index d80f79d8dd9cd03d237ee2e7af1531abba69f2b2..8e1fb82392873669ce34b03ed34f18b64cc5b2de 100644 (file)
@@ -5,7 +5,7 @@ OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
 OUTPUT_ARCH(s390:64-bit)
 #else
 OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
-OUTPUT_ARCH(s390)
+OUTPUT_ARCH(s390:31-bit)
 #endif
 
 ENTRY(startup)
index 7941968e12b48ced12b4122918f111485de1dc4e..5f0173a31693b19700b8afa92b60db199bfcb749 100644 (file)
@@ -9,7 +9,7 @@
 #include <asm/cpu_mf.h>
 
 /* CPU-measurement counter facility */
-#define PERF_CPUM_CF_MAX_CTR           160
+#define PERF_CPUM_CF_MAX_CTR           256
 
 /* Per-CPU flags for PMU states */
 #define PMU_F_RESERVED                 0x1000
index 59b67ed423b422bb6ed353f516b796278f5bcb38..7bf68fff7c5d28cd2255d8d86189eb55368ddd71 100644 (file)
@@ -1,8 +1,6 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
-generic-y += kvm_para.h
-
 header-y += auxvec.h
 header-y += bitsperlong.h
 header-y += byteorder.h
index 581992dfae27b605e49a8a6f5d2972cc0646fadc..6b4fb29cc197e5d9544fd124e61a742a41114464 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    Copyright IBM Corp. 2007
+ *    Copyright IBM Corp. 2007, 2012
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
 
 #define __MAX_CHPID 255
 
 struct chp_id {
-       u8 reserved1;
-       u8 cssid;
-       u8 reserved2;
-       u8 id;
+       __u8 reserved1;
+       __u8 cssid;
+       __u8 reserved2;
+       __u8 id;
 } __attribute__((packed));
 
 
diff --git a/arch/s390/include/uapi/asm/kvm_para.h b/arch/s390/include/uapi/asm/kvm_para.h
new file mode 100644 (file)
index 0000000..ff1f4e7
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * User API definitions for paravirtual devices on s390
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License (version 2 only)
+ * as published by the Free Software Foundation.
+ *
+ *    Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
+ */
index 8df8d8a19c986e1b2fea8db91cf59d329fc3b877..64b24650e4f8c1d43f5cf151b46478f5a602e277 100644 (file)
@@ -59,8 +59,8 @@ enum {
 
 enum {
        CACHE_TI_UNIFIED = 0,
-       CACHE_TI_INSTRUCTION = 0,
-       CACHE_TI_DATA,
+       CACHE_TI_DATA = 0,
+       CACHE_TI_INSTRUCTION,
 };
 
 struct cache_info {
@@ -121,7 +121,10 @@ static int __init cache_add(int level, int private, int type)
        cache = kzalloc(sizeof(*cache), GFP_KERNEL);
        if (!cache)
                return -ENOMEM;
-       ti = type == CACHE_TYPE_DATA ? CACHE_TI_DATA : CACHE_TI_UNIFIED;
+       if (type == CACHE_TYPE_INSTRUCTION)
+               ti = CACHE_TI_INSTRUCTION;
+       else
+               ti = CACHE_TI_UNIFIED;
        cache->size = ecag(EXTRACT_SIZE, level, ti);
        cache->line_size = ecag(EXTRACT_LINE_SIZE, level, ti);
        cache->associativity = ecag(EXTRACT_ASSOCIATIVITY, level, ti);
index acaaaf4b7055e2d50122f43e6f695771a6f781cd..085a95eb315f480dc2edb492fc58a80dde0ae7d5 100644 (file)
 .align 2
 startup_kdump_relocated:
        basr    %r13,0
-0:
-       mvc     0(8,%r0),.Lrestart_psw-0b(%r13) # Setup restart PSW
-       sam31                                   # Switch to 31 bit addr mode
-       sr      %r1,%r1                         # Erase register r1
-       sr      %r2,%r2                         # Erase register r2
-       sigp    %r1,%r2,SIGP_SET_ARCHITECTURE   # Switch to 31 bit arch mode
-       lpsw    0                               # Start new kernel...
+0:     lpswe   .Lrestart_psw-0b(%r13)          # Start new kernel...
 .align 8
 .Lrestart_psw:
-       .long   0x00080000,0x80000000 + startup
+       .quad   0x0000000080000000,0x0000000000000000 + startup
 #else
 .align 2
 .Lep_startup_kdump:
index 9871b1971ed7602a7efef88fc62d019dde3b98c4..c4e7269d4a0980d8736c5a9c32e916cb581b0a58 100644 (file)
@@ -94,7 +94,7 @@ static int get_counter_set(u64 event)
                set = CPUMF_CTR_SET_USER;
        else if (event < 128)
                set = CPUMF_CTR_SET_CRYPTO;
-       else if (event < 160)
+       else if (event < 256)
                set = CPUMF_CTR_SET_EXT;
 
        return set;
@@ -138,6 +138,10 @@ static int validate_ctr_version(const struct hw_perf_event *hwc)
        case CPUMF_CTR_SET_EXT:
                if (cpuhw->info.csvn < 1)
                        err = -EOPNOTSUPP;
+               if ((cpuhw->info.csvn == 1 && hwc->config > 159) ||
+                   (cpuhw->info.csvn == 2 && hwc->config > 175) ||
+                   (cpuhw->info.csvn  > 2 && hwc->config > 255))
+                       err = -EOPNOTSUPP;
                break;
        }
 
index de8fa9bbd35ee9787537e93c18b561b75cacf72f..79cb51adc7419b52245d444c74e2c9378eaf99ab 100644 (file)
@@ -8,7 +8,7 @@
 
 #ifndef CONFIG_64BIT
 OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
-OUTPUT_ARCH(s390)
+OUTPUT_ARCH(s390:31-bit)
 ENTRY(startup)
 jiffies = jiffies_64 + 4;
 #else
index 55640cf92597b11f943173928b4d7d7437d4be14..3d15364c60714bf661da140c8f6e67cde20001b3 100644 (file)
@@ -26,6 +26,10 @@ $(error Set TILERA_ROOT or CROSS_COMPILE when building $(ARCH) on $(HOST_ARCH))
   endif
 endif
 
+# The tile compiler may emit .eh_frame information for backtracing.
+# In kernel modules, this causes load failures due to unsupported relocations.
+KBUILD_CFLAGS   += -fno-asynchronous-unwind-tables
+
 ifneq ($(CONFIG_DEBUG_EXTRA_FLAGS),"")
 KBUILD_CFLAGS   += $(CONFIG_DEBUG_EXTRA_FLAGS)
 endif
index 001cbfa10ac6364a9136b9d4440bfe69730a08be..243ffebe38d69a510f16e53083c49b46f3e6531b 100644 (file)
 #include <asm/homecache.h>
 #include <arch/opcode.h>
 
-#ifdef __tilegx__
-# define Elf_Rela Elf64_Rela
-# define ELF_R_SYM ELF64_R_SYM
-# define ELF_R_TYPE ELF64_R_TYPE
-#else
-# define Elf_Rela Elf32_Rela
-# define ELF_R_SYM ELF32_R_SYM
-# define ELF_R_TYPE ELF32_R_TYPE
-#endif
-
 #ifdef MODULE_DEBUG
 #define DEBUGP printk
 #else
index c9dcc181d4d1a814c10d6822d0801c7a1b2d7196..6e8fdf5ad1135c0100c8b7a5220bb79db2359ddb 100644 (file)
@@ -35,7 +35,7 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...);
 #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6)      \
        efi_call_virt(f, a1, a2, a3, a4, a5, a6)
 
-#define efi_ioremap(addr, size, type)          ioremap_cache(addr, size)
+#define efi_ioremap(addr, size, type, attr)    ioremap_cache(addr, size)
 
 #else /* !CONFIG_X86_32 */
 
@@ -89,7 +89,7 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3,
                  (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6))
 
 extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
-                                u32 type);
+                                u32 type, u64 attribute);
 
 #endif /* CONFIG_X86_32 */
 
@@ -98,6 +98,8 @@ extern void efi_set_executable(efi_memory_desc_t *md, bool executable);
 extern int efi_memblock_x86_reserve_range(void);
 extern void efi_call_phys_prelog(void);
 extern void efi_call_phys_epilog(void);
+extern void efi_unmap_memmap(void);
+extern void efi_memory_uc(u64 addr, unsigned long size);
 
 #ifndef CONFIG_EFI
 /*
index 66d0fff1ee8481ce0669cd5b0a137dde5d7dff8d..125f344f06a90e4d09dc4feab417042be9910e2a 100644 (file)
@@ -33,7 +33,6 @@
 #ifndef _ASM_X86_XEN_HYPERVISOR_H
 #define _ASM_X86_XEN_HYPERVISOR_H
 
-/* arch/i386/kernel/setup.c */
 extern struct shared_info *HYPERVISOR_shared_info;
 extern struct start_info *xen_start_info;
 
index 6d2f75a82a14bca62162f38cde9fff8e6404bec9..54d52ff1304a3496bc240ef193030adbb73ec4bb 100644 (file)
  * with Xen so that on ARM we can have one ABI that works for 32 and 64
  * bit guests. */
 typedef unsigned long xen_pfn_t;
+#define PRI_xen_pfn "lx"
 typedef unsigned long xen_ulong_t;
+#define PRI_xen_ulong "lx"
 /* Guest handles for primitive C types. */
 __DEFINE_GUEST_HANDLE(uchar, unsigned char);
 __DEFINE_GUEST_HANDLE(uint,  unsigned int);
-__DEFINE_GUEST_HANDLE(ulong, unsigned long);
 DEFINE_GUEST_HANDLE(char);
 DEFINE_GUEST_HANDLE(int);
-DEFINE_GUEST_HANDLE(long);
 DEFINE_GUEST_HANDLE(void);
 DEFINE_GUEST_HANDLE(uint64_t);
 DEFINE_GUEST_HANDLE(uint32_t);
index c265593ec2cdc3df35fda1586aaf91514fab62fa..1817fa911024f07151d3edf91bd350722c9f79f8 100644 (file)
@@ -2257,6 +2257,9 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void)
                        continue;
 
                cfg = irq_cfg(irq);
+               if (!cfg)
+                       continue;
+
                raw_spin_lock(&desc->lock);
 
                /*
index 3373f84d139750276cf33a3a6bf757c171975a40..4a3374e61a93a033f24f03941b99c03e3906a726 100644 (file)
@@ -208,12 +208,14 @@ static bool check_hw_exists(void)
        }
 
        /*
-        * Now write a value and read it back to see if it matches,
-        * this is needed to detect certain hardware emulators (qemu/kvm)
-        * that don't trap on the MSR access and always return 0s.
+        * Read the current value, change it and read it back to see if it
+        * matches, this is needed to detect certain hardware emulators
+        * (qemu/kvm) that don't trap on the MSR access and always return 0s.
         */
-       val = 0xabcdUL;
        reg = x86_pmu_event_addr(0);
+       if (rdmsrl_safe(reg, &val))
+               goto msr_fail;
+       val ^= 0xffffUL;
        ret = wrmsrl_safe(reg, val);
        ret |= rdmsrl_safe(reg, &val_new);
        if (ret || val != val_new)
index 99d96a4978b56630115c2de5b465ca5eca0ffee0..3cf3d97cce3a7ab0b02c678f2535dc5ec03d09bb 100644 (file)
@@ -118,22 +118,24 @@ static void snbep_uncore_pci_disable_box(struct intel_uncore_box *box)
 {
        struct pci_dev *pdev = box->pci_dev;
        int box_ctl = uncore_pci_box_ctl(box);
-       u32 config;
+       u32 config = 0;
 
-       pci_read_config_dword(pdev, box_ctl, &config);
-       config |= SNBEP_PMON_BOX_CTL_FRZ;
-       pci_write_config_dword(pdev, box_ctl, config);
+       if (!pci_read_config_dword(pdev, box_ctl, &config)) {
+               config |= SNBEP_PMON_BOX_CTL_FRZ;
+               pci_write_config_dword(pdev, box_ctl, config);
+       }
 }
 
 static void snbep_uncore_pci_enable_box(struct intel_uncore_box *box)
 {
        struct pci_dev *pdev = box->pci_dev;
        int box_ctl = uncore_pci_box_ctl(box);
-       u32 config;
+       u32 config = 0;
 
-       pci_read_config_dword(pdev, box_ctl, &config);
-       config &= ~SNBEP_PMON_BOX_CTL_FRZ;
-       pci_write_config_dword(pdev, box_ctl, config);
+       if (!pci_read_config_dword(pdev, box_ctl, &config)) {
+               config &= ~SNBEP_PMON_BOX_CTL_FRZ;
+               pci_write_config_dword(pdev, box_ctl, config);
+       }
 }
 
 static void snbep_uncore_pci_enable_event(struct intel_uncore_box *box, struct perf_event *event)
@@ -156,7 +158,7 @@ static u64 snbep_uncore_pci_read_counter(struct intel_uncore_box *box, struct pe
 {
        struct pci_dev *pdev = box->pci_dev;
        struct hw_perf_event *hwc = &event->hw;
-       u64 count;
+       u64 count = 0;
 
        pci_read_config_dword(pdev, hwc->event_base, (u32 *)&count);
        pci_read_config_dword(pdev, hwc->event_base + 4, (u32 *)&count + 1);
@@ -603,11 +605,12 @@ static struct pci_driver snbep_uncore_pci_driver = {
 /*
  * build pci bus to socket mapping
  */
-static void snbep_pci2phy_map_init(void)
+static int snbep_pci2phy_map_init(void)
 {
        struct pci_dev *ubox_dev = NULL;
        int i, bus, nodeid;
-       u32 config;
+       int err = 0;
+       u32 config = 0;
 
        while (1) {
                /* find the UBOX device */
@@ -618,10 +621,14 @@ static void snbep_pci2phy_map_init(void)
                        break;
                bus = ubox_dev->bus->number;
                /* get the Node ID of the local register */
-               pci_read_config_dword(ubox_dev, 0x40, &config);
+               err = pci_read_config_dword(ubox_dev, 0x40, &config);
+               if (err)
+                       break;
                nodeid = config;
                /* get the Node ID mapping */
-               pci_read_config_dword(ubox_dev, 0x54, &config);
+               err = pci_read_config_dword(ubox_dev, 0x54, &config);
+               if (err)
+                       break;
                /*
                 * every three bits in the Node ID mapping register maps
                 * to a particular node.
@@ -633,7 +640,11 @@ static void snbep_pci2phy_map_init(void)
                        }
                }
        };
-       return;
+
+       if (ubox_dev)
+               pci_dev_put(ubox_dev);
+
+       return err ? pcibios_err_to_errno(err) : 0;
 }
 /* end of Sandy Bridge-EP uncore support */
 
@@ -1547,7 +1558,6 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)
 {
        struct hw_perf_event *hwc = &event->hw;
        struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-       int port;
 
        /* adjust the main event selector and extra register index */
        if (reg1->idx % 2) {
@@ -1559,7 +1569,6 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)
        }
 
        /* adjust extra register config */
-       port = reg1->idx / 6 + box->pmu->pmu_idx * 4;
        switch (reg1->idx % 6) {
        case 2:
                /* shift the 8~15 bits to the 0~7 bits */
@@ -2578,9 +2587,11 @@ static int __init uncore_pci_init(void)
 
        switch (boot_cpu_data.x86_model) {
        case 45: /* Sandy Bridge-EP */
+               ret = snbep_pci2phy_map_init();
+               if (ret)
+                       return ret;
                pci_uncores = snbep_pci_uncores;
                uncore_pci_driver = &snbep_uncore_pci_driver;
-               snbep_pci2phy_map_init();
                break;
        default:
                return 0;
@@ -2926,6 +2937,9 @@ static int __init intel_uncore_init(void)
        if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
                return -ENODEV;
 
+       if (cpu_has_hypervisor)
+               return -ENODEV;
+
        ret = uncore_pci_init();
        if (ret)
                goto fail;
index 7c46bfdbc3732f87b005ecb7196a635eba5db546..4b7731bf23a812a4631aa7c53196068924b52ee7 100644 (file)
@@ -3,6 +3,8 @@
 #include <linux/perf_event.h>
 #include <linux/types.h>
 
+#include <asm/hardirq.h>
+
 #include "perf_event.h"
 
 static const u64 knc_perfmon_event_map[] =
@@ -173,30 +175,100 @@ static void knc_pmu_enable_all(int added)
 static inline void
 knc_pmu_disable_event(struct perf_event *event)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        u64 val;
 
        val = hwc->config;
-       if (cpuc->enabled)
-               val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
+       val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
 
        (void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
 }
 
 static void knc_pmu_enable_event(struct perf_event *event)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        u64 val;
 
        val = hwc->config;
-       if (cpuc->enabled)
-               val |= ARCH_PERFMON_EVENTSEL_ENABLE;
+       val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 
        (void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
 }
 
+static inline u64 knc_pmu_get_status(void)
+{
+       u64 status;
+
+       rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_STATUS, status);
+
+       return status;
+}
+
+static inline void knc_pmu_ack_status(u64 ack)
+{
+       wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_OVF_CONTROL, ack);
+}
+
+static int knc_pmu_handle_irq(struct pt_regs *regs)
+{
+       struct perf_sample_data data;
+       struct cpu_hw_events *cpuc;
+       int handled = 0;
+       int bit, loops;
+       u64 status;
+
+       cpuc = &__get_cpu_var(cpu_hw_events);
+
+       knc_pmu_disable_all();
+
+       status = knc_pmu_get_status();
+       if (!status) {
+               knc_pmu_enable_all(0);
+               return handled;
+       }
+
+       loops = 0;
+again:
+       knc_pmu_ack_status(status);
+       if (++loops > 100) {
+               WARN_ONCE(1, "perf: irq loop stuck!\n");
+               perf_event_print_debug();
+               goto done;
+       }
+
+       inc_irq_stat(apic_perf_irqs);
+
+       for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
+               struct perf_event *event = cpuc->events[bit];
+
+               handled++;
+
+               if (!test_bit(bit, cpuc->active_mask))
+                       continue;
+
+               if (!intel_pmu_save_and_restart(event))
+                       continue;
+
+               perf_sample_data_init(&data, 0, event->hw.last_period);
+
+               if (perf_event_overflow(event, &data, regs))
+                       x86_pmu_stop(event, 0);
+       }
+
+       /*
+        * Repeat if there is more work to be done:
+        */
+       status = knc_pmu_get_status();
+       if (status)
+               goto again;
+
+done:
+       knc_pmu_enable_all(0);
+
+       return handled;
+}
+
+
 PMU_FORMAT_ATTR(event, "config:0-7"    );
 PMU_FORMAT_ATTR(umask, "config:8-15"   );
 PMU_FORMAT_ATTR(edge,  "config:18"     );
@@ -214,7 +286,7 @@ static struct attribute *intel_knc_formats_attr[] = {
 
 static __initconst struct x86_pmu knc_pmu = {
        .name                   = "knc",
-       .handle_irq             = x86_pmu_handle_irq,
+       .handle_irq             = knc_pmu_handle_irq,
        .disable_all            = knc_pmu_disable_all,
        .enable_all             = knc_pmu_enable_all,
        .enable                 = knc_pmu_enable_event,
@@ -226,12 +298,11 @@ static __initconst struct x86_pmu knc_pmu = {
        .event_map              = knc_pmu_event_map,
        .max_events             = ARRAY_SIZE(knc_perfmon_event_map),
        .apic                   = 1,
-       .max_period             = (1ULL << 31) - 1,
+       .max_period             = (1ULL << 39) - 1,
        .version                = 0,
        .num_counters           = 2,
-       /* in theory 40 bits, early silicon is buggy though */
-       .cntval_bits            = 32,
-       .cntval_mask            = (1ULL << 32) - 1,
+       .cntval_bits            = 40,
+       .cntval_mask            = (1ULL << 40) - 1,
        .get_event_constraints  = x86_get_event_constraints,
        .event_constraints      = knc_event_constraints,
        .format_attrs           = intel_knc_formats_attr,
index e4dd0f7a04535f09b83d47d95868bcc1c152dff3..7d0270bd793ebd8580d63e21a1be521b2aeea91f 100644 (file)
  */
 static const u64 p6_perfmon_event_map[] =
 {
-  [PERF_COUNT_HW_CPU_CYCLES]           = 0x0079,
-  [PERF_COUNT_HW_INSTRUCTIONS]         = 0x00c0,
-  [PERF_COUNT_HW_CACHE_REFERENCES]     = 0x0f2e,
-  [PERF_COUNT_HW_CACHE_MISSES]         = 0x012e,
-  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x00c4,
-  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x00c5,
-  [PERF_COUNT_HW_BUS_CYCLES]           = 0x0062,
+  [PERF_COUNT_HW_CPU_CYCLES]           = 0x0079,       /* CPU_CLK_UNHALTED */
+  [PERF_COUNT_HW_INSTRUCTIONS]         = 0x00c0,       /* INST_RETIRED     */
+  [PERF_COUNT_HW_CACHE_REFERENCES]     = 0x0f2e,       /* L2_RQSTS:M:E:S:I */
+  [PERF_COUNT_HW_CACHE_MISSES]         = 0x012e,       /* L2_RQSTS:I       */
+  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x00c4,       /* BR_INST_RETIRED  */
+  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x00c5,       /* BR_MISS_PRED_RETIRED */
+  [PERF_COUNT_HW_BUS_CYCLES]           = 0x0062,       /* BUS_DRDY_CLOCKS  */
+  [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x00a2,    /* RESOURCE_STALLS  */
+
+};
+
+static __initconst u64 p6_hw_cache_event_ids
+                               [PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_COUNT_HW_CACHE_OP_MAX]
+                               [PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(L1D) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0043,  /* DATA_MEM_REFS       */
+                [ C(RESULT_MISS)   ] = 0x0045, /* DCU_LINES_IN        */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0x0f29,  /* L2_LD:M:E:S:I       */
+       },
+        [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+        },
+ },
+ [ C(L1I ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0080,  /* IFU_IFETCH         */
+               [ C(RESULT_MISS)   ] = 0x0f28,  /* L2_IFETCH:M:E:S:I  */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0x0025,  /* L2_M_LINES_INM     */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(DTLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0043,  /* DATA_MEM_REFS      */
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(ITLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0080,  /* IFU_IFETCH         */
+               [ C(RESULT_MISS)   ] = 0x0085,  /* ITLB_MISS          */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(BPU ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x00c4,  /* BR_INST_RETIRED      */
+               [ C(RESULT_MISS)   ] = 0x00c5,  /* BR_MISS_PRED_RETIRED */
+        },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
 };
 
 static u64 p6_pmu_event_map(int hw_event)
@@ -34,7 +127,7 @@ static struct event_constraint p6_event_constraints[] =
 {
        INTEL_EVENT_CONSTRAINT(0xc1, 0x1),      /* FLOPS */
        INTEL_EVENT_CONSTRAINT(0x10, 0x1),      /* FP_COMP_OPS_EXE */
-       INTEL_EVENT_CONSTRAINT(0x11, 0x1),      /* FP_ASSIST */
+       INTEL_EVENT_CONSTRAINT(0x11, 0x2),      /* FP_ASSIST */
        INTEL_EVENT_CONSTRAINT(0x12, 0x2),      /* MUL */
        INTEL_EVENT_CONSTRAINT(0x13, 0x2),      /* DIV */
        INTEL_EVENT_CONSTRAINT(0x14, 0x1),      /* CYCLES_DIV_BUSY */
@@ -64,25 +157,25 @@ static void p6_pmu_enable_all(int added)
 static inline void
 p6_pmu_disable_event(struct perf_event *event)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        u64 val = P6_NOP_EVENT;
 
-       if (cpuc->enabled)
-               val |= ARCH_PERFMON_EVENTSEL_ENABLE;
-
        (void)wrmsrl_safe(hwc->config_base, val);
 }
 
 static void p6_pmu_enable_event(struct perf_event *event)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        u64 val;
 
        val = hwc->config;
-       if (cpuc->enabled)
-               val |= ARCH_PERFMON_EVENTSEL_ENABLE;
+
+       /*
+        * p6 only has a global event enable, set on PerfEvtSel0
+        * We "disable" events by programming P6_NOP_EVENT
+        * and we rely on p6_pmu_enable_all() being called
+        * to actually enable the events.
+        */
 
        (void)wrmsrl_safe(hwc->config_base, val);
 }
@@ -158,5 +251,9 @@ __init int p6_pmu_init(void)
 
        x86_pmu = p6_pmu;
 
+       memcpy(hw_cache_event_ids, p6_hw_cache_event_ids,
+               sizeof(hw_cache_event_ids));
+
+
        return 0;
 }
index ed858e9e9a7461aa9b4f8aa42a52c79d57d84507..df06ade26bef8485af1a66d797370385d0012e52 100644 (file)
@@ -1077,6 +1077,9 @@ void __init memblock_x86_fill(void)
                memblock_add(ei->addr, ei->size);
        }
 
+       /* throw away partial pages */
+       memblock_trim_memory(PAGE_SIZE);
+
        memblock_dump_all();
 }
 
index a1193aef6d7d2ef1af31a4b257ed0e161876ad19..88b725aa1d52463d7534882a187da4c392bf3947 100644 (file)
@@ -1035,7 +1035,7 @@ ENTRY(xen_sysenter_target)
 
 ENTRY(xen_hypervisor_callback)
        CFI_STARTPROC
-       pushl_cfi $0
+       pushl_cfi $-1 /* orig_ax = -1 => not a system call */
        SAVE_ALL
        TRACE_IRQS_OFF
 
@@ -1077,14 +1077,16 @@ ENTRY(xen_failsafe_callback)
 2:     mov 8(%esp),%es
 3:     mov 12(%esp),%fs
 4:     mov 16(%esp),%gs
+       /* EAX == 0 => Category 1 (Bad segment)
+          EAX != 0 => Category 2 (Bad IRET) */
        testl %eax,%eax
        popl_cfi %eax
        lea 16(%esp),%esp
        CFI_ADJUST_CFA_OFFSET -16
        jz 5f
        addl $16,%esp
-       jmp iret_exc            # EAX != 0 => Category 2 (Bad IRET)
-5:     pushl_cfi $0            # EAX == 0 => Category 1 (Bad segment)
+       jmp iret_exc
+5:     pushl_cfi $-1 /* orig_ax = -1 => not a system call */
        SAVE_ALL
        jmp ret_from_exception
        CFI_ENDPROC
index 0c58952d64e8723b4486ce620c8b11bcfe8d01f5..b51b2c7ee51fcbc3738ed8bd05fb4fd67d9fe1ab 100644 (file)
@@ -1435,7 +1435,7 @@ ENTRY(xen_failsafe_callback)
        CFI_RESTORE r11
        addq $0x30,%rsp
        CFI_ADJUST_CFA_OFFSET -0x30
-       pushq_cfi $0
+       pushq_cfi $-1 /* orig_ax = -1 => not a system call */
        SAVE_ALL
        jmp error_exit
        CFI_ENDPROC
index b3e5e51bc907ef4da71549ff7e2214467721af0a..4180a874c764d4df9d514648082eee5ac6907930 100644 (file)
@@ -247,7 +247,10 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code)
                break;
        case KVM_PV_REASON_PAGE_NOT_PRESENT:
                /* page is swapped out by the host. */
+               rcu_irq_enter();
+               exit_idle();
                kvm_async_pf_task_wait((u32)read_cr2());
+               rcu_irq_exit();
                break;
        case KVM_PV_REASON_PAGE_READY:
                rcu_irq_enter();
index 468e98dfd44e72fd7d0b29690b4bb777356a52a5..ca45696f30fb8a01a4d6852388d08ab19d4bb778 100644 (file)
@@ -921,18 +921,19 @@ void __init setup_arch(char **cmdline_p)
 #ifdef CONFIG_X86_64
        if (max_pfn > max_low_pfn) {
                int i;
-               for (i = 0; i < e820.nr_map; i++) {
-                       struct e820entry *ei = &e820.map[i];
+               unsigned long start, end;
+               unsigned long start_pfn, end_pfn;
 
-                       if (ei->addr + ei->size <= 1UL << 32)
-                               continue;
+               for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn,
+                                                        NULL) {
 
-                       if (ei->type == E820_RESERVED)
+                       end = PFN_PHYS(end_pfn);
+                       if (end <= (1UL<<32))
                                continue;
 
+                       start = PFN_PHYS(start_pfn);
                        max_pfn_mapped = init_memory_mapping(
-                               ei->addr < 1UL << 32 ? 1UL << 32 : ei->addr,
-                               ei->addr + ei->size);
+                                               max((1UL<<32), start), end);
                }
 
                /* can we preseve max_low_pfn ?*/
@@ -1048,6 +1049,18 @@ void __init setup_arch(char **cmdline_p)
        arch_init_ideal_nops();
 
        register_refined_jiffies(CLOCK_TICK_RATE);
+
+#ifdef CONFIG_EFI
+       /* Once setup is done above, disable efi_enabled on mismatched
+        * firmware/kernel archtectures since there is no support for
+        * runtime services.
+        */
+       if (efi_enabled && IS_ENABLED(CONFIG_X86_64) != efi_64bit) {
+               pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
+               efi_unmap_memmap();
+               efi_enabled = 0;
+       }
+#endif
 }
 
 #ifdef CONFIG_X86_32
index 29ad351804e9324d3aaf59c07c86d274958516b3..70b27ee6118e12c8411c7903e2254aeff44cd90e 100644 (file)
@@ -824,10 +824,8 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
                mce_notify_process();
 #endif /* CONFIG_X86_64 && CONFIG_X86_MCE */
 
-       if (thread_info_flags & _TIF_UPROBE) {
-               clear_thread_flag(TIF_UPROBE);
+       if (thread_info_flags & _TIF_UPROBE)
                uprobe_notify_resume(regs);
-       }
 
        /* deal with pending signal delivery */
        if (thread_info_flags & _TIF_SIGPENDING)
index 9538f00827a9b25257debf63aaa438ef6e40d68b..aafa5557b3964a57bf0abbdd9c849786688f1ce9 100644 (file)
@@ -651,31 +651,19 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
 
 /*
  * Skip these instructions as per the currently known x86 ISA.
- * 0x66* { 0x90 | 0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0 }
+ * rep=0x66*; nop=0x90
  */
 static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
 {
        int i;
 
        for (i = 0; i < MAX_UINSN_BYTES; i++) {
-               if ((auprobe->insn[i] == 0x66))
+               if (auprobe->insn[i] == 0x66)
                        continue;
 
                if (auprobe->insn[i] == 0x90)
                        return true;
 
-               if (i == (MAX_UINSN_BYTES - 1))
-                       break;
-
-               if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x1f))
-                       return true;
-
-               if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x19))
-                       return true;
-
-               if ((auprobe->insn[i] == 0x87) && (auprobe->insn[i+1] == 0xc0))
-                       return true;
-
                break;
        }
        return false;
index c6e6b721b6ee3a38d6267ee8867bd029fbdc6d6a..43e9fadca5d080a4e98a65735cbe071102742911 100644 (file)
@@ -1311,7 +1311,7 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
        vcpu->arch.apic_base = value;
        if (apic_x2apic_mode(apic)) {
                u32 id = kvm_apic_id(apic);
-               u32 ldr = ((id & ~0xf) << 16) | (1 << (id & 0xf));
+               u32 ldr = ((id >> 4) << 16) | (1 << (id & 0xf));
                kvm_apic_set_ldr(apic, ldr);
        }
        apic->base_address = apic->vcpu->arch.apic_base &
index d289fee1ffb8631c0b93f663104965fe7def7b11..6f85fe0bf958987f0275f1fa25e2b9e5240aad02 100644 (file)
@@ -2497,8 +2497,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
                }
        }
 
-       if (!is_error_pfn(pfn))
-               kvm_release_pfn_clean(pfn);
+       kvm_release_pfn_clean(pfn);
 }
 
 static void nonpaging_new_cr3(struct kvm_vcpu *vcpu)
index 1eefebe5d72758873df0d13e4ae8c686a7d016ee..224a7e78cb6c40330dfebc943e315c0a7231efa1 100644 (file)
@@ -3779,7 +3779,7 @@ static int write_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
 {
        struct kvm_mmio_fragment *frag = &vcpu->mmio_fragments[0];
 
-       memcpy(vcpu->run->mmio.data, frag->data, frag->len);
+       memcpy(vcpu->run->mmio.data, frag->data, min(8u, frag->len));
        return X86EMUL_CONTINUE;
 }
 
@@ -3832,18 +3832,11 @@ mmio:
        bytes -= handled;
        val += handled;
 
-       while (bytes) {
-               unsigned now = min(bytes, 8U);
-
-               frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++];
-               frag->gpa = gpa;
-               frag->data = val;
-               frag->len = now;
-
-               gpa += now;
-               val += now;
-               bytes -= now;
-       }
+       WARN_ON(vcpu->mmio_nr_fragments >= KVM_MAX_MMIO_FRAGMENTS);
+       frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++];
+       frag->gpa = gpa;
+       frag->data = val;
+       frag->len = bytes;
        return X86EMUL_CONTINUE;
 }
 
@@ -3890,7 +3883,7 @@ int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr,
        vcpu->mmio_needed = 1;
        vcpu->mmio_cur_fragment = 0;
 
-       vcpu->run->mmio.len = vcpu->mmio_fragments[0].len;
+       vcpu->run->mmio.len = min(8u, vcpu->mmio_fragments[0].len);
        vcpu->run->mmio.is_write = vcpu->mmio_is_write = ops->write;
        vcpu->run->exit_reason = KVM_EXIT_MMIO;
        vcpu->run->mmio.phys_addr = gpa;
@@ -5522,28 +5515,44 @@ static int complete_emulated_pio(struct kvm_vcpu *vcpu)
  *
  * read:
  *   for each fragment
- *     write gpa, len
- *     exit
- *     copy data
+ *     for each mmio piece in the fragment
+ *       write gpa, len
+ *       exit
+ *       copy data
  *   execute insn
  *
  * write:
  *   for each fragment
- *      write gpa, len
- *      copy data
- *      exit
+ *     for each mmio piece in the fragment
+ *       write gpa, len
+ *       copy data
+ *       exit
  */
 static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
 {
        struct kvm_run *run = vcpu->run;
        struct kvm_mmio_fragment *frag;
+       unsigned len;
 
        BUG_ON(!vcpu->mmio_needed);
 
        /* Complete previous fragment */
-       frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment++];
+       frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment];
+       len = min(8u, frag->len);
        if (!vcpu->mmio_is_write)
-               memcpy(frag->data, run->mmio.data, frag->len);
+               memcpy(frag->data, run->mmio.data, len);
+
+       if (frag->len <= 8) {
+               /* Switch to the next fragment. */
+               frag++;
+               vcpu->mmio_cur_fragment++;
+       } else {
+               /* Go forward to the next mmio piece. */
+               frag->data += len;
+               frag->gpa += len;
+               frag->len -= len;
+       }
+
        if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) {
                vcpu->mmio_needed = 0;
                if (vcpu->mmio_is_write)
@@ -5551,13 +5560,12 @@ static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
                vcpu->mmio_read_completed = 1;
                return complete_emulated_io(vcpu);
        }
-       /* Initiate next fragment */
-       ++frag;
+
        run->exit_reason = KVM_EXIT_MMIO;
        run->mmio.phys_addr = frag->gpa;
        if (vcpu->mmio_is_write)
-               memcpy(run->mmio.data, frag->data, frag->len);
-       run->mmio.len = frag->len;
+               memcpy(run->mmio.data, frag->data, min(8u, frag->len));
+       run->mmio.len = min(8u, frag->len);
        run->mmio.is_write = vcpu->mmio_is_write;
        vcpu->arch.complete_userspace_io = complete_emulated_mmio;
        return 0;
index ab1f6a93b527c9bd50acc12a52e9ce157f2cc48b..d7aea41563b372437eb227a499259be23d755564 100644 (file)
@@ -35,40 +35,44 @@ struct map_range {
        unsigned page_size_mask;
 };
 
-static void __init find_early_table_space(struct map_range *mr, unsigned long end,
-                                         int use_pse, int use_gbpages)
+/*
+ * First calculate space needed for kernel direct mapping page tables to cover
+ * mr[0].start to mr[nr_range - 1].end, while accounting for possible 2M and 1GB
+ * pages. Then find enough contiguous space for those page tables.
+ */
+static void __init find_early_table_space(struct map_range *mr, int nr_range)
 {
-       unsigned long puds, pmds, ptes, tables, start = 0, good_end = end;
+       int i;
+       unsigned long puds = 0, pmds = 0, ptes = 0, tables;
+       unsigned long start = 0, good_end;
        phys_addr_t base;
 
-       puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
-       tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
-
-       if (use_gbpages) {
-               unsigned long extra;
-
-               extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT);
-               pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT;
-       } else
-               pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
+       for (i = 0; i < nr_range; i++) {
+               unsigned long range, extra;
 
-       tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
+               range = mr[i].end - mr[i].start;
+               puds += (range + PUD_SIZE - 1) >> PUD_SHIFT;
 
-       if (use_pse) {
-               unsigned long extra;
+               if (mr[i].page_size_mask & (1 << PG_LEVEL_1G)) {
+                       extra = range - ((range >> PUD_SHIFT) << PUD_SHIFT);
+                       pmds += (extra + PMD_SIZE - 1) >> PMD_SHIFT;
+               } else {
+                       pmds += (range + PMD_SIZE - 1) >> PMD_SHIFT;
+               }
 
-               extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT);
+               if (mr[i].page_size_mask & (1 << PG_LEVEL_2M)) {
+                       extra = range - ((range >> PMD_SHIFT) << PMD_SHIFT);
 #ifdef CONFIG_X86_32
-               extra += PMD_SIZE;
+                       extra += PMD_SIZE;
 #endif
-               /* The first 2/4M doesn't use large pages. */
-               if (mr->start < PMD_SIZE)
-                       extra += mr->end - mr->start;
-
-               ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
-       } else
-               ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
+                       ptes += (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
+               } else {
+                       ptes += (range + PAGE_SIZE - 1) >> PAGE_SHIFT;
+               }
+       }
 
+       tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
+       tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
        tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE);
 
 #ifdef CONFIG_X86_32
@@ -86,7 +90,7 @@ static void __init find_early_table_space(struct map_range *mr, unsigned long en
        pgt_buf_top = pgt_buf_start + (tables >> PAGE_SHIFT);
 
        printk(KERN_DEBUG "kernel direct mapping tables up to %#lx @ [mem %#010lx-%#010lx]\n",
-               end - 1, pgt_buf_start << PAGE_SHIFT,
+               mr[nr_range - 1].end - 1, pgt_buf_start << PAGE_SHIFT,
                (pgt_buf_top << PAGE_SHIFT) - 1);
 }
 
@@ -267,7 +271,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
         * nodes are discovered.
         */
        if (!after_bootmem)
-               find_early_table_space(&mr[0], end, use_pse, use_gbpages);
+               find_early_table_space(mr, nr_range);
 
        for (i = 0; i < nr_range; i++)
                ret = kernel_physical_mapping_init(mr[i].start, mr[i].end,
index 2b6b4a3c8beb8727d27b1cdba22411fe0d271efb..3baff255adac6472570298d7e9ee60df75e93dfc 100644 (file)
@@ -386,7 +386,8 @@ phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end,
                 * these mappings are more intelligent.
                 */
                if (pte_val(*pte)) {
-                       pages++;
+                       if (!after_bootmem)
+                               pages++;
                        continue;
                }
 
@@ -451,6 +452,8 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
                         * attributes.
                         */
                        if (page_size_mask & (1 << PG_LEVEL_2M)) {
+                               if (!after_bootmem)
+                                       pages++;
                                last_map_addr = next;
                                continue;
                        }
@@ -526,6 +529,8 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,
                         * attributes.
                         */
                        if (page_size_mask & (1 << PG_LEVEL_1G)) {
+                               if (!after_bootmem)
+                                       pages++;
                                last_map_addr = next;
                                continue;
                        }
index 26b8a8514ee566e8a7d235a06de1037c2641adec..48768df2471af2bc9e4059fad6eb8c583f93f4d0 100644 (file)
@@ -55,7 +55,7 @@ u64 op_x86_get_ctrl(struct op_x86_model_spec const *model,
        val |= counter_config->extra;
        event &= model->event_mask ? model->event_mask : 0xFF;
        val |= event & 0xFF;
-       val |= (event & 0x0F00) << 24;
+       val |= (u64)(event & 0x0F00) << 24;
 
        return val;
 }
index aded2a91162a8af12ad104d047544afce91ff4c4..ad4439145f858314dfe518cf7cd9336c5fe9c96d 100644 (file)
@@ -70,11 +70,15 @@ EXPORT_SYMBOL(efi);
 struct efi_memory_map memmap;
 
 bool efi_64bit;
-static bool efi_native;
 
 static struct efi efi_phys __initdata;
 static efi_system_table_t efi_systab __initdata;
 
+static inline bool efi_is_native(void)
+{
+       return IS_ENABLED(CONFIG_X86_64) == efi_64bit;
+}
+
 static int __init setup_noefi(char *arg)
 {
        efi_enabled = 0;
@@ -420,7 +424,7 @@ void __init efi_reserve_boot_services(void)
        }
 }
 
-static void __init efi_unmap_memmap(void)
+void __init efi_unmap_memmap(void)
 {
        if (memmap.map) {
                early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
@@ -432,7 +436,7 @@ void __init efi_free_boot_services(void)
 {
        void *p;
 
-       if (!efi_native)
+       if (!efi_is_native())
                return;
 
        for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
@@ -684,12 +688,10 @@ void __init efi_init(void)
                return;
        }
        efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab;
-       efi_native = !efi_64bit;
 #else
        efi_phys.systab = (efi_system_table_t *)
                          (boot_params.efi_info.efi_systab |
                          ((__u64)boot_params.efi_info.efi_systab_hi<<32));
-       efi_native = efi_64bit;
 #endif
 
        if (efi_systab_init(efi_phys.systab)) {
@@ -723,7 +725,7 @@ void __init efi_init(void)
         * that doesn't match the kernel 32/64-bit mode.
         */
 
-       if (!efi_native)
+       if (!efi_is_native())
                pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
        else if (efi_runtime_init()) {
                efi_enabled = 0;
@@ -735,7 +737,7 @@ void __init efi_init(void)
                return;
        }
 #ifdef CONFIG_X86_32
-       if (efi_native) {
+       if (efi_is_native()) {
                x86_platform.get_wallclock = efi_get_time;
                x86_platform.set_wallclock = efi_set_rtc_mmss;
        }
@@ -810,6 +812,16 @@ void __iomem *efi_lookup_mapped_addr(u64 phys_addr)
        return NULL;
 }
 
+void efi_memory_uc(u64 addr, unsigned long size)
+{
+       unsigned long page_shift = 1UL << EFI_PAGE_SHIFT;
+       u64 npages;
+
+       npages = round_up(size, page_shift) / page_shift;
+       memrange_efi_to_native(&addr, &npages);
+       set_memory_uc(addr, npages);
+}
+
 /*
  * This function will switch the EFI runtime services to virtual mode.
  * Essentially, look through the EFI memmap and map every region that
@@ -823,7 +835,7 @@ void __init efi_enter_virtual_mode(void)
        efi_memory_desc_t *md, *prev_md = NULL;
        efi_status_t status;
        unsigned long size;
-       u64 end, systab, addr, npages, end_pfn;
+       u64 end, systab, end_pfn;
        void *p, *va, *new_memmap = NULL;
        int count = 0;
 
@@ -834,7 +846,7 @@ void __init efi_enter_virtual_mode(void)
         * non-native EFI
         */
 
-       if (!efi_native) {
+       if (!efi_is_native()) {
                efi_unmap_memmap();
                return;
        }
@@ -879,10 +891,14 @@ void __init efi_enter_virtual_mode(void)
                end_pfn = PFN_UP(end);
                if (end_pfn <= max_low_pfn_mapped
                    || (end_pfn > (1UL << (32 - PAGE_SHIFT))
-                       && end_pfn <= max_pfn_mapped))
+                       && end_pfn <= max_pfn_mapped)) {
                        va = __va(md->phys_addr);
-               else
-                       va = efi_ioremap(md->phys_addr, size, md->type);
+
+                       if (!(md->attribute & EFI_MEMORY_WB))
+                               efi_memory_uc((u64)(unsigned long)va, size);
+               } else
+                       va = efi_ioremap(md->phys_addr, size,
+                                        md->type, md->attribute);
 
                md->virt_addr = (u64) (unsigned long) va;
 
@@ -892,13 +908,6 @@ void __init efi_enter_virtual_mode(void)
                        continue;
                }
 
-               if (!(md->attribute & EFI_MEMORY_WB)) {
-                       addr = md->virt_addr;
-                       npages = md->num_pages;
-                       memrange_efi_to_native(&addr, &npages);
-                       set_memory_uc(addr, npages);
-               }
-
                systab = (u64) (unsigned long) efi_phys.systab;
                if (md->phys_addr <= systab && systab < end) {
                        systab += md->virt_addr - md->phys_addr;
index ac3aa54e26546ba5cb4121eba0c58ca00f06ea82..95fd505dfeb6e43dd37b0c41954f0b0db6535d1c 100644 (file)
@@ -82,7 +82,7 @@ void __init efi_call_phys_epilog(void)
 }
 
 void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,
-                                u32 type)
+                                u32 type, u64 attribute)
 {
        unsigned long last_map_pfn;
 
@@ -92,8 +92,11 @@ void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,
        last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size);
        if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size) {
                unsigned long top = last_map_pfn << PAGE_SHIFT;
-               efi_ioremap(top, size - (top - phys_addr), type);
+               efi_ioremap(top, size - (top - phys_addr), type, attribute);
        }
 
+       if (!(attribute & EFI_MEMORY_WB))
+               efi_memory_uc((u64)(unsigned long)__va(phys_addr), size);
+
        return (void __iomem *)__va(phys_addr);
 }
index e3497f240eabb869e6cda863036689e6b093899d..586d83812b67b64f96594f1eebdc859bdcb12adc 100644 (file)
@@ -81,8 +81,6 @@
 #include "smp.h"
 #include "multicalls.h"
 
-#include <xen/events.h>
-
 EXPORT_SYMBOL_GPL(hypercall_page);
 
 DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
index 6226c99729b963594a2e133290cbf8f3c6e681b8..dcf5f2dd91ec4fd91d814d46c7d6dbd6c5312a61 100644 (file)
@@ -1288,6 +1288,25 @@ unsigned long xen_read_cr2_direct(void)
        return this_cpu_read(xen_vcpu_info.arch.cr2);
 }
 
+void xen_flush_tlb_all(void)
+{
+       struct mmuext_op *op;
+       struct multicall_space mcs;
+
+       trace_xen_mmu_flush_tlb_all(0);
+
+       preempt_disable();
+
+       mcs = xen_mc_entry(sizeof(*op));
+
+       op = mcs.args;
+       op->cmd = MMUEXT_TLB_FLUSH_ALL;
+       MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
+
+       xen_mc_issue(PARAVIRT_LAZY_MMU);
+
+       preempt_enable();
+}
 static void xen_flush_tlb(void)
 {
        struct mmuext_op *op;
@@ -2518,7 +2537,7 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
        err = 0;
 out:
 
-       flush_tlb_all();
+       xen_flush_tlb_all();
 
        return err;
 }
index cdcb48adee4c6d05f65f34fb9893a55afdb4c5f1..0d1f36a22c98827ba204af46859b349ac3da91ae 100644 (file)
@@ -13,6 +13,8 @@ config XTENSA
        select GENERIC_CPU_DEVICES
        select MODULES_USE_ELF_RELA
        select GENERIC_PCI_IOMAP
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
        select ARCH_WANT_OPTIONAL_GPIOLIB
        help
          Xtensa processors are 32-bit RISC machines designed by Tensilica
index e6be5b9091c2a65509f721ed3e5f92bc7c6783bc..700c2e6f2d259d454f5f8f310b431d6b20ecbc1f 100644 (file)
@@ -62,6 +62,10 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
 static inline void iounmap(volatile void __iomem *addr)
 {
 }
+
+#define virt_to_bus     virt_to_phys
+#define bus_to_virt     phys_to_virt
+
 #endif /* CONFIG_MMU */
 
 /*
index 5c371d8d45284a1c35808d2b9e4928db03cc7652..2d630e7399ca4f94584a77cdf2a150d6c9ff7319 100644 (file)
@@ -152,6 +152,7 @@ struct thread_struct {
 
 /* Clearing a0 terminates the backtrace. */
 #define start_thread(regs, new_pc, new_sp) \
+       memset(regs, 0, sizeof(*regs)); \
        regs->pc = new_pc; \
        regs->ps = USER_PS_VALUE; \
        regs->areg[1] = new_sp; \
@@ -168,9 +169,6 @@ struct mm_struct;
 /* Free all resources held by a thread. */
 #define release_thread(thread) do { } while(0)
 
-/* Create a kernel thread without removing it from tasklists */
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 /* Copy and release all segment info associated with a VM */
 #define copy_segments(p, mm)   do { } while(0)
 #define release_segments(mm)   do { } while(0)
index c1dacca312f3906374614ae4eb0a486ab8070e8a..124aeee0d3816cadf7abe7317d168b5f3b326891 100644 (file)
@@ -10,7 +10,7 @@
 
 struct pt_regs;
 struct sigaction;
-asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*);
+asmlinkage long sys_execve(char*, char**, char**, struct pt_regs*);
 asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);
 asmlinkage long xtensa_ptrace(long, long, long, long);
 asmlinkage long xtensa_sigreturn(struct pt_regs*);
index 9ef1c31d2c8363fdae934f157abce35d1ef21e89..f4e6eaa40d1ca86946799a1f7eab6d7047a69dd5 100644 (file)
@@ -1,16 +1,9 @@
-/*
- * include/asm-xtensa/unistd.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
+#ifndef _XTENSA_UNISTD_H
+#define _XTENSA_UNISTD_H
 
+#define __ARCH_WANT_SYS_EXECVE
 #include <uapi/asm/unistd.h>
 
-
 /*
  * "Conditional" syscalls
  *
@@ -37,3 +30,5 @@
 #define __IGNORE_mmap                          /* use mmap2 */
 #define __IGNORE_vfork                         /* use clone */
 #define __IGNORE_fadvise64                     /* use fadvise64_64 */
+
+#endif /* _XTENSA_UNISTD_H */
index 479abaea5aae761a41b60ef5e1861bba3aa2e605..9f36d0e3e0aca7d8fc87257be6d48cbdea16f810 100644 (file)
@@ -1,14 +1,4 @@
-/*
- * include/asm-xtensa/unistd.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2012 Tensilica Inc.
- */
-
-#ifndef _UAPI_XTENSA_UNISTD_H
+#if !defined(_UAPI_XTENSA_UNISTD_H) || defined(__SYSCALL)
 #define _UAPI_XTENSA_UNISTD_H
 
 #ifndef __SYSCALL
@@ -272,7 +262,7 @@ __SYSCALL(115, sys_sendmmsg, 4)
 #define __NR_clone                             116
 __SYSCALL(116, xtensa_clone, 5)
 #define __NR_execve                            117
-__SYSCALL(117, xtensa_execve, 3)
+__SYSCALL(117, sys_execve, 3)
 #define __NR_exit                              118
 __SYSCALL(118, sys_exit, 1)
 #define __NR_exit_group                        119
@@ -759,4 +749,6 @@ __SYSCALL(331, sys_kcmp, 5)
 
 #define SYS_XTENSA_COUNT                  5     /* count */
 
+#undef __SYSCALL
+
 #endif /* _UAPI_XTENSA_UNISTD_H */
index 18453067c2582034e896adee07c0d474912a98d2..90bfc1dbc13dcf46992e4fb09bb7eab3cfe1bea3 100644 (file)
@@ -1832,50 +1832,6 @@ ENTRY(system_call)
        retw
 
 
-/*
- * Create a kernel thread
- *
- * int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
- * a2                    a2                 a3             a4
- */
-
-ENTRY(kernel_thread)
-       entry   a1, 16
-
-       mov     a5, a2                  # preserve fn over syscall
-       mov     a7, a3                  # preserve args over syscall
-
-       movi    a3, _CLONE_VM | _CLONE_UNTRACED
-       movi    a2, __NR_clone
-       or      a6, a4, a3              # arg0: flags
-       mov     a3, a1                  # arg1: sp
-       syscall
-
-       beq     a3, a1, 1f              # branch if parent
-       mov     a6, a7                  # args
-       callx4  a5                      # fn(args)
-
-       movi    a2, __NR_exit
-       syscall                         # return value of fn(args) still in a6
-
-1:     retw
-
-/*
- * Do a system call from kernel instead of calling sys_execve, so we end up
- * with proper pt_regs.
- *
- * int kernel_execve(const char *fname, char *const argv[], charg *const envp[])
- * a2                        a2               a3                  a4
- */
-
-ENTRY(kernel_execve)
-       entry   a1, 16
-       mov     a6, a2                  # arg0 is in a6
-       movi    a2, __NR_execve
-       syscall
-
-       retw
-
 /*
  * Task switch.
  *
@@ -1958,3 +1914,16 @@ ENTRY(ret_from_fork)
 
        j       common_exception_return
 
+/*
+ * Kernel thread creation helper
+ * On entry, set up by copy_thread: a2 = thread_fn, a3 = thread_fn arg
+ *           left from _switch_to: a6 = prev
+ */
+ENTRY(ret_from_kernel_thread)
+
+       call4   schedule_tail
+       mov     a6, a3
+       callx4  a2
+       j       common_exception_return
+
+ENDPROC(ret_from_kernel_thread)
index 1908f6642d31e0073c5884b0f90445641452cb75..09ae7bfab9a7a4a8ff2a6e2c55aadf07dda48024 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/regs.h>
 
 extern void ret_from_fork(void);
+extern void ret_from_kernel_thread(void);
 
 struct task_struct *current_set[NR_CPUS] = {&init_task, };
 
@@ -158,18 +159,30 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 /*
  * Copy thread.
  *
+ * There are two modes in which this function is called:
+ * 1) Userspace thread creation,
+ *    regs != NULL, usp_thread_fn is userspace stack pointer.
+ *    It is expected to copy parent regs (in case CLONE_VM is not set
+ *    in the clone_flags) and set up passed usp in the childregs.
+ * 2) Kernel thread creation,
+ *    regs == NULL, usp_thread_fn is the function to run in the new thread
+ *    and thread_fn_arg is its parameter.
+ *    childregs are not used for the kernel threads.
+ *
  * The stack layout for the new thread looks like this:
  *
- *     +------------------------+ <- sp in childregs (= tos)
+ *     +------------------------+
  *     |       childregs        |
  *     +------------------------+ <- thread.sp = sp in dummy-frame
  *     |      dummy-frame       |    (saved in dummy-frame spill-area)
  *     +------------------------+
  *
- * We create a dummy frame to return to ret_from_fork:
- *   a0 points to ret_from_fork (simulating a call4)
+ * We create a dummy frame to return to either ret_from_fork or
+ *   ret_from_kernel_thread:
+ *   a0 points to ret_from_fork/ret_from_kernel_thread (simulating a call4)
  *   sp points to itself (thread.sp)
- *   a2, a3 are unused.
+ *   a2, a3 are unused for userspace threads,
+ *   a2 points to thread_fn, a3 holds thread_fn arg for kernel threads.
  *
  * Note: This is a pristine frame, so we don't need any spill region on top of
  *       childregs.
@@ -185,43 +198,63 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
  * involved.  Much simpler to just not copy those live frames across.
  */
 
-int copy_thread(unsigned long clone_flags, unsigned long usp,
-               unsigned long unused,
-                struct task_struct * p, struct pt_regs * regs)
+int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
+               unsigned long thread_fn_arg,
+               struct task_struct *p, struct pt_regs *unused)
 {
-       struct pt_regs *childregs;
-       unsigned long tos;
-       int user_mode = user_mode(regs);
+       struct pt_regs *childregs = task_pt_regs(p);
 
 #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)
        struct thread_info *ti;
 #endif
 
-       /* Set up new TSS. */
-       tos = (unsigned long)task_stack_page(p) + THREAD_SIZE;
-       if (user_mode)
-               childregs = (struct pt_regs*)(tos - PT_USER_SIZE);
-       else
-               childregs = (struct pt_regs*)tos - 1;
-
-       /* This does not copy all the regs.  In a bout of brilliance or madness,
-          ARs beyond a0-a15 exist past the end of the struct. */
-       *childregs = *regs;
-
        /* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */
        *((int*)childregs - 3) = (unsigned long)childregs;
        *((int*)childregs - 4) = 0;
 
-       childregs->areg[2] = 0;
-       p->set_child_tid = p->clear_child_tid = NULL;
-       p->thread.ra = MAKE_RA_FOR_CALL((unsigned long)ret_from_fork, 0x1);
        p->thread.sp = (unsigned long)childregs;
 
-       if (user_mode(regs)) {
+       if (!(p->flags & PF_KTHREAD)) {
+               struct pt_regs *regs = current_pt_regs();
+               unsigned long usp = usp_thread_fn ?
+                       usp_thread_fn : regs->areg[1];
 
+               p->thread.ra = MAKE_RA_FOR_CALL(
+                               (unsigned long)ret_from_fork, 0x1);
+
+               /* This does not copy all the regs.
+                * In a bout of brilliance or madness,
+                * ARs beyond a0-a15 exist past the end of the struct.
+                */
+               *childregs = *regs;
                childregs->areg[1] = usp;
+               childregs->areg[2] = 0;
+
+               /* When sharing memory with the parent thread, the child
+                  usually starts on a pristine stack, so we have to reset
+                  windowbase, windowstart and wmask.
+                  (Note that such a new thread is required to always create
+                  an initial call4 frame)
+                  The exception is vfork, where the new thread continues to
+                  run on the parent's stack until it calls execve. This could
+                  be a call8 or call12, which requires a legal stack frame
+                  of the previous caller for the overflow handlers to work.
+                  (Note that it's always legal to overflow live registers).
+                  In this case, ensure to spill at least the stack pointer
+                  of that frame. */
+
                if (clone_flags & CLONE_VM) {
-                       childregs->wmask = 1;   /* can't share live windows */
+                       /* check that caller window is live and same stack */
+                       int len = childregs->wmask & ~0xf;
+                       if (regs->areg[1] == usp && len != 0) {
+                               int callinc = (regs->areg[0] >> 30) & 3;
+                               int caller_ars = XCHAL_NUM_AREGS - callinc * 4;
+                               put_user(regs->areg[caller_ars+1],
+                                        (unsigned __user*)(usp - 12));
+                       }
+                       childregs->wmask = 1;
+                       childregs->windowstart = 1;
+                       childregs->windowbase = 0;
                } else {
                        int len = childregs->wmask & ~0xf;
                        memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4],
@@ -230,11 +263,19 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 // FIXME: we need to set THREADPTR in thread_info...
                if (clone_flags & CLONE_SETTLS)
                        childregs->areg[2] = childregs->areg[6];
-
        } else {
-               /* In kernel space, we start a new thread with a new stack. */
-               childregs->wmask = 1;
-               childregs->areg[1] = tos;
+               p->thread.ra = MAKE_RA_FOR_CALL(
+                               (unsigned long)ret_from_kernel_thread, 1);
+
+               /* pass parameters to ret_from_kernel_thread:
+                * a2 = thread_fn, a3 = thread_fn arg
+                */
+               *((int *)childregs - 1) = thread_fn_arg;
+               *((int *)childregs - 2) = usp_thread_fn;
+
+               /* Childregs are only used when we're going to userspace
+                * in which case start_thread will set them up.
+                */
        }
 
 #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)
@@ -330,32 +371,5 @@ long xtensa_clone(unsigned long clone_flags, unsigned long newsp,
                   void __user *child_tid, long a5,
                   struct pt_regs *regs)
 {
-        if (!newsp)
-                newsp = regs->areg[1];
         return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
 }
-
-/*
- * xtensa_execve() executes a new program.
- */
-
-asmlinkage
-long xtensa_execve(const char __user *name,
-                  const char __user *const __user *argv,
-                   const char __user *const __user *envp,
-                   long a3, long a4, long a5,
-                   struct pt_regs *regs)
-{
-       long error;
-       struct filename *filename;
-
-       filename = getname(name);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       error = do_execve(filename->name, argv, envp, regs);
-       putname(filename);
-out:
-       return error;
-}
-
index a5c01e74d5d5590f3c5287dace8f23c10c527cd9..5702065f472a88bebc4df721dec0629208957395 100644 (file)
@@ -32,10 +32,8 @@ typedef void (*syscall_t)(void);
 syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= {
        [0 ... __NR_syscall_count - 1] = (syscall_t)&sys_ni_syscall,
 
-#undef __SYSCALL
 #define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol,
-#undef  __KERNEL_SYSCALLS__
-#include <asm/unistd.h>
+#include <uapi/asm/unistd.h>
 };
 
 asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
@@ -49,7 +47,8 @@ asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
        return (long)ret;
 }
 
-asmlinkage long xtensa_fadvise64_64(int fd, int advice, unsigned long long offset, unsigned long long len)
+asmlinkage long xtensa_fadvise64_64(int fd, int advice,
+               unsigned long long offset, unsigned long long len)
 {
        return sys_fadvise64_64(fd, offset, len, advice);
 }
index a8b9f1fd1e17f63573c74bdf8c06616c1abd7481..afe058b24e6e07c83d61f1a524b30e03340d6369 100644 (file)
@@ -43,7 +43,6 @@ EXPORT_SYMBOL(__strncpy_user);
 EXPORT_SYMBOL(clear_page);
 EXPORT_SYMBOL(copy_page);
 
-EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(empty_zero_page);
 
 /*
index 09acf1b39905ced3f08164c213a6d2aed7f29cae..a7e40a7c821427cd27f6c7019411030ea00e33e8 100644 (file)
@@ -89,7 +89,7 @@ config BLK_DEV_INTEGRITY
 
 config BLK_DEV_THROTTLING
        bool "Block layer bio throttling support"
-       depends on BLK_CGROUP=y && EXPERIMENTAL
+       depends on BLK_CGROUP=y
        default n
        ---help---
        Block layer bio throttling support. It can be used to limit
index cafcd743118969daec377f52f09e41594d188347..d0b770391ad400ad0312049c84a2b522bf985bf1 100644 (file)
@@ -285,6 +285,13 @@ static void blkg_destroy_all(struct request_queue *q)
                blkg_destroy(blkg);
                spin_unlock(&blkcg->lock);
        }
+
+       /*
+        * root blkg is destroyed.  Just clear the pointer since
+        * root_rl does not take reference on root blkg.
+        */
+       q->root_blkg = NULL;
+       q->root_rl.blkg = NULL;
 }
 
 static void blkg_rcu_free(struct rcu_head *rcu_head)
@@ -326,6 +333,9 @@ struct request_list *__blk_queue_next_rl(struct request_list *rl,
         */
        if (rl == &q->root_rl) {
                ent = &q->blkg_list;
+               /* There are no more block groups, hence no request lists */
+               if (list_empty(ent))
+                       return NULL;
        } else {
                blkg = container_of(rl, struct blkcg_gq, rl);
                ent = &blkg->q_node;
index a33870b1847bb70c6ef1937f7bef4e93bdf9c980..3c95c4d6e31afe057ebabeda36868682e8188329 100644 (file)
@@ -2868,7 +2868,8 @@ static int plug_rq_cmp(void *priv, struct list_head *a, struct list_head *b)
        struct request *rqa = container_of(a, struct request, queuelist);
        struct request *rqb = container_of(b, struct request, queuelist);
 
-       return !(rqa->q <= rqb->q);
+       return !(rqa->q < rqb->q ||
+               (rqa->q == rqb->q && blk_rq_pos(rqa) < blk_rq_pos(rqb)));
 }
 
 /*
index d1a2d74033e945237afdef3fac02aea87cdebbdd..08373086cd7e883edeec356acb102bcac46147cf 100644 (file)
@@ -159,6 +159,7 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
        if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) {
                retval = -ENOSPC;
                mutex_unlock(&acpi_dev->physical_node_lock);
+               kfree(physical_node);
                goto err;
        }
 
index e78c2a52ea46665fe3ea31a7e79ba7f5cc5c38b2..bd4e5dca3ff7e81f4ce754cbaad3856bb4948a6a 100644 (file)
@@ -409,6 +409,7 @@ static void acpi_processor_notify(struct acpi_device *device, u32 event)
                acpi_bus_generate_proc_event(device, event, 0);
                acpi_bus_generate_netlink_event(device->pnp.device_class,
                                                  dev_name(&device->dev), event, 0);
+               break;
        default:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "Unsupported event [0x%x]\n", event));
index f94d4c818fc74dc9a076e8f67fe98d7bc6620a61..0230cb6cbb3a18eda2fd323763d6594205c0ed7f 100644 (file)
@@ -1345,12 +1345,15 @@ static int
 acpi_video_bus_get_devices(struct acpi_video_bus *video,
                           struct acpi_device *device)
 {
-       int status;
+       int status = 0;
        struct acpi_device *dev;
 
-       status = acpi_video_device_enumerate(video);
-       if (status)
-               return status;
+       /*
+        * There are systems where video module known to work fine regardless
+        * of broken _DOD and ignoring returned value here doesn't cause
+        * any issues later.
+        */
+       acpi_video_device_enumerate(video);
 
        list_for_each_entry(dev, &device->children, node) {
 
index 08b4c520938463fd989bba879d791a3e418efd39..b34b5cda5ae110aeec980b6ec7c2ec608490a093 100644 (file)
@@ -236,7 +236,7 @@ config CMA_SIZE_PERCENTAGE
 
 choice
        prompt "Selected region size"
-       default CMA_SIZE_SEL_ABSOLUTE
+       default CMA_SIZE_SEL_MBYTES
 
 config CMA_SIZE_SEL_MBYTES
        bool "Use mega bytes value only"
index 560a7173f810015a9532d25395a8ad1a57366e6c..bc256b64102710039e208ec82c513e97b223a290 100644 (file)
@@ -191,9 +191,8 @@ EXPORT_SYMBOL(dma_release_from_coherent);
  * This checks whether the memory was allocated from the per-device
  * coherent memory pool and if so, maps that memory to the provided vma.
  *
- * Returns 1 if we correctly mapped the memory, or 0 if
- * dma_release_coherent() should proceed with mapping memory from
- * generic pools.
+ * Returns 1 if we correctly mapped the memory, or 0 if the caller should
+ * proceed with mapping memory from generic pools.
  */
 int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,
                           void *vaddr, size_t size, int *ret)
index 9a1469474f55addaea1ae5be1f4499187297db06..612afcc5a938f45549ed877ebd6c8ac697315fe3 100644 (file)
 #include <linux/mm.h>
 #include <linux/mutex.h>
 #include <linux/page-isolation.h>
+#include <linux/sizes.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/mm_types.h>
 #include <linux/dma-contiguous.h>
 
-#ifndef SZ_1M
-#define SZ_1M (1 << 20)
-#endif
-
 struct cma {
        unsigned long   base_pfn;
        unsigned long   count;
index 81541452887bd3ce5d868909e3fb753fb3d6b124..8945f4e489ed70a03cb272f57064a69330409a60 100644 (file)
@@ -36,68 +36,6 @@ MODULE_AUTHOR("Manuel Estrada Sainz");
 MODULE_DESCRIPTION("Multi purpose firmware loading support");
 MODULE_LICENSE("GPL");
 
-static const char *fw_path[] = {
-       "/lib/firmware/updates/" UTS_RELEASE,
-       "/lib/firmware/updates",
-       "/lib/firmware/" UTS_RELEASE,
-       "/lib/firmware"
-};
-
-/* Don't inline this: 'struct kstat' is biggish */
-static noinline long fw_file_size(struct file *file)
-{
-       struct kstat st;
-       if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st))
-               return -1;
-       if (!S_ISREG(st.mode))
-               return -1;
-       if (st.size != (long)st.size)
-               return -1;
-       return st.size;
-}
-
-static bool fw_read_file_contents(struct file *file, struct firmware *fw)
-{
-       long size;
-       char *buf;
-
-       size = fw_file_size(file);
-       if (size < 0)
-               return false;
-       buf = vmalloc(size);
-       if (!buf)
-               return false;
-       if (kernel_read(file, 0, buf, size) != size) {
-               vfree(buf);
-               return false;
-       }
-       fw->data = buf;
-       fw->size = size;
-       return true;
-}
-
-static bool fw_get_filesystem_firmware(struct firmware *fw, const char *name)
-{
-       int i;
-       bool success = false;
-       char *path = __getname();
-
-       for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
-               struct file *file;
-               snprintf(path, PATH_MAX, "%s/%s", fw_path[i], name);
-
-               file = filp_open(path, O_RDONLY, 0);
-               if (IS_ERR(file))
-                       continue;
-               success = fw_read_file_contents(file, fw);
-               fput(file);
-               if (success)
-                       break;
-       }
-       __putname(path);
-       return success;
-}
-
 /* Builtin firmware support */
 
 #ifdef CONFIG_FW_LOADER
@@ -150,6 +88,11 @@ enum {
        FW_STATUS_ABORT,
 };
 
+enum fw_buf_fmt {
+       VMALLOC_BUF,    /* used in direct loading */
+       PAGE_BUF,       /* used in loading via userspace */
+};
+
 static int loading_timeout = 60;       /* In seconds */
 
 static inline long firmware_loading_timeout(void)
@@ -173,8 +116,6 @@ struct firmware_cache {
        spinlock_t name_lock;
        struct list_head fw_names;
 
-       wait_queue_head_t wait_queue;
-       int cnt;
        struct delayed_work work;
 
        struct notifier_block   pm_notify;
@@ -187,6 +128,7 @@ struct firmware_buf {
        struct completion completion;
        struct firmware_cache *fwc;
        unsigned long status;
+       enum fw_buf_fmt fmt;
        void *data;
        size_t size;
        struct page **pages;
@@ -240,6 +182,7 @@ static struct firmware_buf *__allocate_fw_buf(const char *fw_name,
        strcpy(buf->fw_id, fw_name);
        buf->fwc = fwc;
        init_completion(&buf->completion);
+       buf->fmt = VMALLOC_BUF;
 
        pr_debug("%s: fw-%s buf=%p\n", __func__, fw_name, buf);
 
@@ -307,10 +250,14 @@ static void __fw_free_buf(struct kref *ref)
        list_del(&buf->list);
        spin_unlock(&fwc->lock);
 
-       vunmap(buf->data);
-       for (i = 0; i < buf->nr_pages; i++)
-               __free_page(buf->pages[i]);
-       kfree(buf->pages);
+
+       if (buf->fmt == PAGE_BUF) {
+               vunmap(buf->data);
+               for (i = 0; i < buf->nr_pages; i++)
+                       __free_page(buf->pages[i]);
+               kfree(buf->pages);
+       } else
+               vfree(buf->data);
        kfree(buf);
 }
 
@@ -319,6 +266,69 @@ static void fw_free_buf(struct firmware_buf *buf)
        kref_put(&buf->ref, __fw_free_buf);
 }
 
+/* direct firmware loading support */
+static const char *fw_path[] = {
+       "/lib/firmware/updates/" UTS_RELEASE,
+       "/lib/firmware/updates",
+       "/lib/firmware/" UTS_RELEASE,
+       "/lib/firmware"
+};
+
+/* Don't inline this: 'struct kstat' is biggish */
+static noinline long fw_file_size(struct file *file)
+{
+       struct kstat st;
+       if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st))
+               return -1;
+       if (!S_ISREG(st.mode))
+               return -1;
+       if (st.size != (long)st.size)
+               return -1;
+       return st.size;
+}
+
+static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
+{
+       long size;
+       char *buf;
+
+       size = fw_file_size(file);
+       if (size < 0)
+               return false;
+       buf = vmalloc(size);
+       if (!buf)
+               return false;
+       if (kernel_read(file, 0, buf, size) != size) {
+               vfree(buf);
+               return false;
+       }
+       fw_buf->data = buf;
+       fw_buf->size = size;
+       return true;
+}
+
+static bool fw_get_filesystem_firmware(struct firmware_buf *buf)
+{
+       int i;
+       bool success = false;
+       char *path = __getname();
+
+       for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
+               struct file *file;
+               snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id);
+
+               file = filp_open(path, O_RDONLY, 0);
+               if (IS_ERR(file))
+                       continue;
+               success = fw_read_file_contents(file, buf);
+               fput(file);
+               if (success)
+                       break;
+       }
+       __putname(path);
+       return success;
+}
+
 static struct firmware_priv *to_firmware_priv(struct device *dev)
 {
        return container_of(dev, struct firmware_priv, dev);
@@ -423,6 +433,21 @@ static void firmware_free_data(const struct firmware *fw)
 #ifndef PAGE_KERNEL_RO
 #define PAGE_KERNEL_RO PAGE_KERNEL
 #endif
+
+/* one pages buffer should be mapped/unmapped only once */
+static int fw_map_pages_buf(struct firmware_buf *buf)
+{
+       if (buf->fmt != PAGE_BUF)
+               return 0;
+
+       if (buf->data)
+               vunmap(buf->data);
+       buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO);
+       if (!buf->data)
+               return -ENOMEM;
+       return 0;
+}
+
 /**
  * firmware_loading_store - set value in the 'loading' control file
  * @dev: device pointer
@@ -467,6 +492,14 @@ static ssize_t firmware_loading_store(struct device *dev,
                if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) {
                        set_bit(FW_STATUS_DONE, &fw_buf->status);
                        clear_bit(FW_STATUS_LOADING, &fw_buf->status);
+
+                       /*
+                        * Several loading requests may be pending on
+                        * one same firmware buf, so let all requests
+                        * see the mapped 'buf->data' once the loading
+                        * is completed.
+                        * */
+                       fw_map_pages_buf(fw_buf);
                        complete_all(&fw_buf->completion);
                        break;
                }
@@ -670,15 +703,6 @@ exit:
        return fw_priv;
 }
 
-/* one pages buffer is mapped/unmapped only once */
-static int fw_map_pages_buf(struct firmware_buf *buf)
-{
-       buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO);
-       if (!buf->data)
-               return -ENOMEM;
-       return 0;
-}
-
 /* store the pages buffer info firmware from buf */
 static void fw_set_page_data(struct firmware_buf *buf, struct firmware *fw)
 {
@@ -778,11 +802,6 @@ _request_firmware_prepare(const struct firmware **firmware_p, const char *name,
                return NULL;
        }
 
-       if (fw_get_filesystem_firmware(firmware, name)) {
-               dev_dbg(device, "firmware: direct-loading firmware %s\n", name);
-               return NULL;
-       }
-
        ret = fw_lookup_and_allocate_buf(name, &fw_cache, &buf);
        if (!ret)
                fw_priv = fw_create_instance(firmware, name, device,
@@ -832,6 +851,21 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
        struct device *f_dev = &fw_priv->dev;
        struct firmware_buf *buf = fw_priv->buf;
        struct firmware_cache *fwc = &fw_cache;
+       int direct_load = 0;
+
+       /* try direct loading from fs first */
+       if (fw_get_filesystem_firmware(buf)) {
+               dev_dbg(f_dev->parent, "firmware: direct-loading"
+                       " firmware %s\n", buf->fw_id);
+
+               set_bit(FW_STATUS_DONE, &buf->status);
+               complete_all(&buf->completion);
+               direct_load = 1;
+               goto handle_fw;
+       }
+
+       /* fall back on userspace loading */
+       buf->fmt = PAGE_BUF;
 
        dev_set_uevent_suppress(f_dev, true);
 
@@ -870,6 +904,7 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
 
        del_timer_sync(&fw_priv->timeout);
 
+handle_fw:
        mutex_lock(&fw_lock);
        if (!buf->size || test_bit(FW_STATUS_ABORT, &buf->status))
                retval = -ENOENT;
@@ -884,9 +919,6 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
        if (!retval && f_dev->parent)
                fw_add_devm_name(f_dev->parent, buf->fw_id);
 
-       if (!retval)
-               retval = fw_map_pages_buf(buf);
-
        /*
         * After caching firmware image is started, let it piggyback
         * on request firmware.
@@ -902,6 +934,9 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
        fw_priv->buf = NULL;
        mutex_unlock(&fw_lock);
 
+       if (direct_load)
+               goto err_put_dev;
+
        device_remove_file(f_dev, &dev_attr_loading);
 err_del_bin_attr:
        device_remove_bin_file(f_dev, &firmware_attr_data);
@@ -1129,6 +1164,8 @@ int uncache_firmware(const char *fw_name)
 }
 
 #ifdef CONFIG_PM_SLEEP
+static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain);
+
 static struct fw_cache_entry *alloc_fw_cache_entry(const char *name)
 {
        struct fw_cache_entry *fce;
@@ -1142,17 +1179,27 @@ exit:
        return fce;
 }
 
-static int fw_cache_piggyback_on_request(const char *name)
+static int __fw_entry_found(const char *name)
 {
        struct firmware_cache *fwc = &fw_cache;
        struct fw_cache_entry *fce;
-       int ret = 0;
 
-       spin_lock(&fwc->name_lock);
        list_for_each_entry(fce, &fwc->fw_names, list) {
                if (!strcmp(fce->name, name))
-                       goto found;
+                       return 1;
        }
+       return 0;
+}
+
+static int fw_cache_piggyback_on_request(const char *name)
+{
+       struct firmware_cache *fwc = &fw_cache;
+       struct fw_cache_entry *fce;
+       int ret = 0;
+
+       spin_lock(&fwc->name_lock);
+       if (__fw_entry_found(name))
+               goto found;
 
        fce = alloc_fw_cache_entry(name);
        if (fce) {
@@ -1185,12 +1232,6 @@ static void __async_dev_cache_fw_image(void *fw_entry,
 
                free_fw_cache_entry(fce);
        }
-
-       spin_lock(&fwc->name_lock);
-       fwc->cnt--;
-       spin_unlock(&fwc->name_lock);
-
-       wake_up(&fwc->wait_queue);
 }
 
 /* called with dev->devres_lock held */
@@ -1229,11 +1270,19 @@ static void dev_cache_fw_image(struct device *dev, void *data)
                list_del(&fce->list);
 
                spin_lock(&fwc->name_lock);
-               fwc->cnt++;
-               list_add(&fce->list, &fwc->fw_names);
+               /* only one cache entry for one firmware */
+               if (!__fw_entry_found(fce->name)) {
+                       list_add(&fce->list, &fwc->fw_names);
+               } else {
+                       free_fw_cache_entry(fce);
+                       fce = NULL;
+               }
                spin_unlock(&fwc->name_lock);
 
-               async_schedule(__async_dev_cache_fw_image, (void *)fce);
+               if (fce)
+                       async_schedule_domain(__async_dev_cache_fw_image,
+                                             (void *)fce,
+                                             &fw_cache_domain);
        }
 }
 
@@ -1275,6 +1324,9 @@ static void device_cache_fw_images(void)
 
        pr_debug("%s\n", __func__);
 
+       /* cancel uncache work */
+       cancel_delayed_work_sync(&fwc->work);
+
        /*
         * use small loading timeout for caching devices' firmware
         * because all these firmware images have been loaded
@@ -1292,21 +1344,7 @@ static void device_cache_fw_images(void)
        mutex_unlock(&fw_lock);
 
        /* wait for completion of caching firmware for all devices */
-       spin_lock(&fwc->name_lock);
-       for (;;) {
-               prepare_to_wait(&fwc->wait_queue, &wait,
-                               TASK_UNINTERRUPTIBLE);
-               if (!fwc->cnt)
-                       break;
-
-               spin_unlock(&fwc->name_lock);
-
-               schedule();
-
-               spin_lock(&fwc->name_lock);
-       }
-       spin_unlock(&fwc->name_lock);
-       finish_wait(&fwc->wait_queue, &wait);
+       async_synchronize_full_domain(&fw_cache_domain);
 
        loading_timeout = old_timeout;
 }
@@ -1394,9 +1432,7 @@ static void __init fw_cache_init(void)
 #ifdef CONFIG_PM_SLEEP
        spin_lock_init(&fw_cache.name_lock);
        INIT_LIST_HEAD(&fw_cache.fw_names);
-       fw_cache.cnt = 0;
 
-       init_waitqueue_head(&fw_cache.wait_queue);
        INIT_DELAYED_WORK(&fw_cache.work,
                          device_uncache_fw_images_work);
 
index c22b869245d9498e7052fdc42ceacf3aaa4e332e..96b71b6536d61cef381dab119533b4a0b13f542e 100644 (file)
@@ -1862,7 +1862,7 @@ int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)
        cpuidle_drv = cpuidle_driver_ref();
        if (!cpuidle_drv) {
                ret = -ENODEV;
-               goto out;
+               goto err_drv;
        }
        if (cpuidle_drv->state_count <= state) {
                ret = -EINVAL;
@@ -1884,6 +1884,9 @@ int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)
 
  err:
        cpuidle_driver_unref();
+
+ err_drv:
+       kfree(cpu_data);
        goto out;
 }
 
index 6be390bd8bd1bc3f0fa1e3bfc38cd56f36bfa6be..f0d30543fcce0944d3e619031ea0a828a179e852 100644 (file)
@@ -3,7 +3,7 @@
 # subsystems should select the appropriate symbols.
 
 config REGMAP
-       default y if (REGMAP_I2C || REGMAP_SPI)
+       default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_MMIO || REGMAP_IRQ)
        select LZO_COMPRESS
        select LZO_DECOMPRESS
        select IRQ_DOMAIN if REGMAP_IRQ
index 80f9ab9c3aa4b7eba89b436d0dcd6a96b3623558..ac869d28d5ba42d7340122d46885c820aebdfb64 100644 (file)
@@ -120,6 +120,8 @@ int _regmap_write(struct regmap *map, unsigned int reg,
 
 struct regmap_range_node {
        struct rb_node node;
+       const char *name;
+       struct regmap *map;
 
        unsigned int range_min;
        unsigned int range_max;
index bb1ff175b9629083a4d5d6e4e0e6811de3b2f808..f4b9dd01c9819ad4e1bc789593876a1f449eb8e3 100644 (file)
@@ -56,15 +56,15 @@ static const struct file_operations regmap_name_fops = {
        .llseek = default_llseek,
 };
 
-static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
-                                   size_t count, loff_t *ppos)
+static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from,
+                                  unsigned int to, char __user *user_buf,
+                                  size_t count, loff_t *ppos)
 {
        int reg_len, val_len, tot_len;
        size_t buf_pos = 0;
        loff_t p = 0;
        ssize_t ret;
        int i;
-       struct regmap *map = file->private_data;
        char *buf;
        unsigned int val;
 
@@ -80,7 +80,7 @@ static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
        val_len = 2 * map->format.val_bytes;
        tot_len = reg_len + val_len + 3;      /* : \n */
 
-       for (i = 0; i <= map->max_register; i += map->reg_stride) {
+       for (i = from; i <= to; i += map->reg_stride) {
                if (!regmap_readable(map, i))
                        continue;
 
@@ -95,7 +95,7 @@ static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
 
                        /* Format the register */
                        snprintf(buf + buf_pos, count - buf_pos, "%.*x: ",
-                                reg_len, i);
+                                reg_len, i - from);
                        buf_pos += reg_len + 2;
 
                        /* Format the value, write all X if we can't read */
@@ -126,6 +126,15 @@ out:
        return ret;
 }
 
+static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf,
+                                   size_t count, loff_t *ppos)
+{
+       struct regmap *map = file->private_data;
+
+       return regmap_read_debugfs(map, 0, map->max_register, user_buf,
+                                  count, ppos);
+}
+
 #undef REGMAP_ALLOW_WRITE_DEBUGFS
 #ifdef REGMAP_ALLOW_WRITE_DEBUGFS
 /*
@@ -174,6 +183,22 @@ static const struct file_operations regmap_map_fops = {
        .llseek = default_llseek,
 };
 
+static ssize_t regmap_range_read_file(struct file *file, char __user *user_buf,
+                                     size_t count, loff_t *ppos)
+{
+       struct regmap_range_node *range = file->private_data;
+       struct regmap *map = range->map;
+
+       return regmap_read_debugfs(map, range->range_min, range->range_max,
+                                  user_buf, count, ppos);
+}
+
+static const struct file_operations regmap_range_fops = {
+       .open = simple_open,
+       .read = regmap_range_read_file,
+       .llseek = default_llseek,
+};
+
 static ssize_t regmap_access_read_file(struct file *file,
                                       char __user *user_buf, size_t count,
                                       loff_t *ppos)
@@ -244,6 +269,9 @@ static const struct file_operations regmap_access_fops = {
 
 void regmap_debugfs_init(struct regmap *map, const char *name)
 {
+       struct rb_node *next;
+       struct regmap_range_node *range_node;
+
        if (name) {
                map->debugfs_name = kasprintf(GFP_KERNEL, "%s-%s",
                                              dev_name(map->dev), name);
@@ -276,6 +304,18 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
                debugfs_create_bool("cache_bypass", 0400, map->debugfs,
                                    &map->cache_bypass);
        }
+
+       next = rb_first(&map->range_tree);
+       while (next) {
+               range_node = rb_entry(next, struct regmap_range_node, node);
+
+               if (range_node->name)
+                       debugfs_create_file(range_node->name, 0400,
+                                           map->debugfs, range_node,
+                                           &regmap_range_fops);
+
+               next = rb_next(&range_node->node);
+       }
 }
 
 void regmap_debugfs_exit(struct regmap *map)
index 52069d29ff12ef197c7d8a447ab27ffb7096d85e..96253cd949e98cddbf433e68913b6c4051d337fa 100644 (file)
@@ -519,20 +519,38 @@ struct regmap *regmap_init(struct device *dev,
        }
 
        map->range_tree = RB_ROOT;
-       for (i = 0; i < config->n_ranges; i++) {
+       for (i = 0; i < config->num_ranges; i++) {
                const struct regmap_range_cfg *range_cfg = &config->ranges[i];
                struct regmap_range_node *new;
 
                /* Sanity check */
-               if (range_cfg->range_max < range_cfg->range_min ||
-                   range_cfg->range_max > map->max_register ||
-                   range_cfg->selector_reg > map->max_register ||
-                   range_cfg->window_len == 0)
+               if (range_cfg->range_max < range_cfg->range_min) {
+                       dev_err(map->dev, "Invalid range %d: %d < %d\n", i,
+                               range_cfg->range_max, range_cfg->range_min);
                        goto err_range;
+               }
+
+               if (range_cfg->range_max > map->max_register) {
+                       dev_err(map->dev, "Invalid range %d: %d > %d\n", i,
+                               range_cfg->range_max, map->max_register);
+                       goto err_range;
+               }
+
+               if (range_cfg->selector_reg > map->max_register) {
+                       dev_err(map->dev,
+                               "Invalid range %d: selector out of map\n", i);
+                       goto err_range;
+               }
+
+               if (range_cfg->window_len == 0) {
+                       dev_err(map->dev, "Invalid range %d: window_len 0\n",
+                               i);
+                       goto err_range;
+               }
 
                /* Make sure, that this register range has no selector
                   or data window within its boundary */
-               for (j = 0; j < config->n_ranges; j++) {
+               for (j = 0; j < config->num_ranges; j++) {
                        unsigned sel_reg = config->ranges[j].selector_reg;
                        unsigned win_min = config->ranges[j].window_start;
                        unsigned win_max = win_min +
@@ -540,11 +558,17 @@ struct regmap *regmap_init(struct device *dev,
 
                        if (range_cfg->range_min <= sel_reg &&
                            sel_reg <= range_cfg->range_max) {
+                               dev_err(map->dev,
+                                       "Range %d: selector for %d in window\n",
+                                       i, j);
                                goto err_range;
                        }
 
                        if (!(win_max < range_cfg->range_min ||
                              win_min > range_cfg->range_max)) {
+                               dev_err(map->dev,
+                                       "Range %d: window for %d in window\n",
+                                       i, j);
                                goto err_range;
                        }
                }
@@ -555,6 +579,8 @@ struct regmap *regmap_init(struct device *dev,
                        goto err_range;
                }
 
+               new->map = map;
+               new->name = range_cfg->name;
                new->range_min = range_cfg->range_min;
                new->range_max = range_cfg->range_max;
                new->selector_reg = range_cfg->selector_reg;
@@ -564,6 +590,7 @@ struct regmap *regmap_init(struct device *dev,
                new->window_len = range_cfg->window_len;
 
                if (_regmap_range_add(map, new) == false) {
+                       dev_err(map->dev, "Failed to add range %d\n", i);
                        kfree(new);
                        goto err_range;
                }
@@ -579,7 +606,7 @@ struct regmap *regmap_init(struct device *dev,
        }
 
        ret = regcache_init(map, config);
-       if (ret < 0)
+       if (ret != 0)
                goto err_range;
 
        regmap_debugfs_init(map, config->name);
@@ -738,59 +765,57 @@ struct regmap *dev_get_regmap(struct device *dev, const char *name)
 EXPORT_SYMBOL_GPL(dev_get_regmap);
 
 static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+                              struct regmap_range_node *range,
                               unsigned int val_num)
 {
-       struct regmap_range_node *range;
        void *orig_work_buf;
        unsigned int win_offset;
        unsigned int win_page;
        bool page_chg;
        int ret;
 
-       range = _regmap_range_lookup(map, *reg);
-       if (range) {
-               win_offset = (*reg - range->range_min) % range->window_len;
-               win_page = (*reg - range->range_min) / range->window_len;
-
-               if (val_num > 1) {
-                       /* Bulk write shouldn't cross range boundary */
-                       if (*reg + val_num - 1 > range->range_max)
-                               return -EINVAL;
+       win_offset = (*reg - range->range_min) % range->window_len;
+       win_page = (*reg - range->range_min) / range->window_len;
 
-                       /* ... or single page boundary */
-                       if (val_num > range->window_len - win_offset)
-                               return -EINVAL;
-               }
+       if (val_num > 1) {
+               /* Bulk write shouldn't cross range boundary */
+               if (*reg + val_num - 1 > range->range_max)
+                       return -EINVAL;
 
-               /* It is possible to have selector register inside data window.
-                  In that case, selector register is located on every page and
-                  it needs no page switching, when accessed alone. */
-               if (val_num > 1 ||
-                   range->window_start + win_offset != range->selector_reg) {
-                       /* Use separate work_buf during page switching */
-                       orig_work_buf = map->work_buf;
-                       map->work_buf = map->selector_work_buf;
+               /* ... or single page boundary */
+               if (val_num > range->window_len - win_offset)
+                       return -EINVAL;
+       }
 
-                       ret = _regmap_update_bits(map, range->selector_reg,
-                                       range->selector_mask,
-                                       win_page << range->selector_shift,
-                                       &page_chg);
+       /* It is possible to have selector register inside data window.
+          In that case, selector register is located on every page and
+          it needs no page switching, when accessed alone. */
+       if (val_num > 1 ||
+           range->window_start + win_offset != range->selector_reg) {
+               /* Use separate work_buf during page switching */
+               orig_work_buf = map->work_buf;
+               map->work_buf = map->selector_work_buf;
 
-                       map->work_buf = orig_work_buf;
+               ret = _regmap_update_bits(map, range->selector_reg,
+                                         range->selector_mask,
+                                         win_page << range->selector_shift,
+                                         &page_chg);
 
-                       if (ret < 0)
-                               return ret;
-               }
+               map->work_buf = orig_work_buf;
 
-               *reg = range->window_start + win_offset;
+               if (ret != 0)
+                       return ret;
        }
 
+       *reg = range->window_start + win_offset;
+
        return 0;
 }
 
 static int _regmap_raw_write(struct regmap *map, unsigned int reg,
                             const void *val, size_t val_len)
 {
+       struct regmap_range_node *range;
        u8 *u8 = map->work_buf;
        void *buf;
        int ret = -ENOTSUPP;
@@ -825,9 +850,35 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
                }
        }
 
-       ret = _regmap_select_page(map, &reg, val_len / map->format.val_bytes);
-       if (ret < 0)
-               return ret;
+       range = _regmap_range_lookup(map, reg);
+       if (range) {
+               int val_num = val_len / map->format.val_bytes;
+               int win_offset = (reg - range->range_min) % range->window_len;
+               int win_residue = range->window_len - win_offset;
+
+               /* If the write goes beyond the end of the window split it */
+               while (val_num > win_residue) {
+                       dev_dbg(map->dev, "Writing window %d/%d\n",
+                               win_residue, val_len / map->format.val_bytes);
+                       ret = _regmap_raw_write(map, reg, val, win_residue *
+                                               map->format.val_bytes);
+                       if (ret != 0)
+                               return ret;
+
+                       reg += win_residue;
+                       val_num -= win_residue;
+                       val += win_residue * map->format.val_bytes;
+                       val_len -= win_residue * map->format.val_bytes;
+
+                       win_offset = (reg - range->range_min) %
+                               range->window_len;
+                       win_residue = range->window_len - win_offset;
+               }
+
+               ret = _regmap_select_page(map, &reg, range, val_num);
+               if (ret != 0)
+                       return ret;
+       }
 
        map->format.format_reg(map->work_buf, reg, map->reg_shift);
 
@@ -876,6 +927,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
 int _regmap_write(struct regmap *map, unsigned int reg,
                  unsigned int val)
 {
+       struct regmap_range_node *range;
        int ret;
        BUG_ON(!map->format.format_write && !map->format.format_val);
 
@@ -897,9 +949,12 @@ int _regmap_write(struct regmap *map, unsigned int reg,
        trace_regmap_reg_write(map->dev, reg, val);
 
        if (map->format.format_write) {
-               ret = _regmap_select_page(map, &reg, 1);
-               if (ret < 0)
-                       return ret;
+               range = _regmap_range_lookup(map, reg);
+               if (range) {
+                       ret = _regmap_select_page(map, &reg, range, 1);
+                       if (ret != 0)
+                               return ret;
+               }
 
                map->format.format_write(map, reg, val);
 
@@ -1055,12 +1110,17 @@ EXPORT_SYMBOL_GPL(regmap_bulk_write);
 static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
                            unsigned int val_len)
 {
+       struct regmap_range_node *range;
        u8 *u8 = map->work_buf;
        int ret;
 
-       ret = _regmap_select_page(map, &reg, val_len / map->format.val_bytes);
-       if (ret < 0)
-               return ret;
+       range = _regmap_range_lookup(map, reg);
+       if (range) {
+               ret = _regmap_select_page(map, &reg, range,
+                                         val_len / map->format.val_bytes);
+               if (ret != 0)
+                       return ret;
+       }
 
        map->format.format_reg(map->work_buf, reg, map->reg_shift);
 
index 432aeeedfd5e6992c28ea081e4185bf88ffeed8e..d865470bc9511a12f3c4370dd12bf22c28fc2cf0 100644 (file)
@@ -158,9 +158,10 @@ static int bcma_register_cores(struct bcma_bus *bus)
 
 static void bcma_unregister_cores(struct bcma_bus *bus)
 {
-       struct bcma_device *core;
+       struct bcma_device *core, *tmp;
 
-       list_for_each_entry(core, &bus->cores, list) {
+       list_for_each_entry_safe(core, tmp, &bus->cores, list) {
+               list_del(&core->list);
                if (core->dev_registered)
                        device_unregister(&core->dev);
        }
index f529407db93ff74dbfa8b9dad13324815467fad2..824e09c4d0d7d1bcd83a00b87e37e1ca0115d5fb 100644 (file)
@@ -131,6 +131,7 @@ config BLK_CPQ_DA
 config BLK_CPQ_CISS_DA
        tristate "Compaq Smart Array 5xxx support"
        depends on PCI
+       select CHECK_SIGNATURE
        help
          This is the driver for Compaq Smart Array 5xxx controllers.
          Everyone using these boards should say Y here.
@@ -166,8 +167,8 @@ config BLK_DEV_DAC960
          module will be called DAC960.
 
 config BLK_DEV_UMEM
-       tristate "Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)"
-       depends on PCI && EXPERIMENTAL
+       tristate "Micro Memory MM5415 Battery Backed RAM support"
+       depends on PCI
        ---help---
          Saying Y here will include support for the MM5415 family of
          battery backed (Non-volatile) RAM cards.
@@ -430,8 +431,8 @@ config CDROM_PKTCDVD_BUFFERS
          a disc is opened for writing.
 
 config CDROM_PKTCDVD_WCACHE
-       bool "Enable write caching (EXPERIMENTAL)"
-       depends on CDROM_PKTCDVD && EXPERIMENTAL
+       bool "Enable write caching"
+       depends on CDROM_PKTCDVD
        help
          If enabled, write caching will be set for the CD-R/W device. For now
          this option is dangerous unless the CD-RW media is known good, as we
@@ -508,8 +509,8 @@ config XEN_BLKDEV_BACKEND
 
 
 config VIRTIO_BLK
-       tristate "Virtio block driver (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && VIRTIO
+       tristate "Virtio block driver"
+       depends on VIRTIO
        ---help---
          This is the virtual block driver for virtio.  It can be used with
           lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M.
@@ -528,7 +529,7 @@ config BLK_DEV_HD
 
 config BLK_DEV_RBD
        tristate "Rados block device (RBD)"
-       depends on INET && EXPERIMENTAL && BLOCK
+       depends on INET && BLOCK
        select CEPH_LIB
        select LIBCRC32C
        select CRYPTO_AES
index b0f553b26d0f8d00f86f768f93aad27ebcb0529e..ca83f96756ad86b2a339971050b7378f9a9752d9 100644 (file)
@@ -5205,7 +5205,6 @@ static void cciss_shutdown(struct pci_dev *pdev)
                return;
        }
        /* write all data in the battery backed cache to disk */
-       memset(flush_buf, 0, 4);
        return_code = sendcmd_withirq(h, CCISS_CACHE_FLUSH, flush_buf,
                4, 0, CTLR_LUNID, TYPE_CMD);
        kfree(flush_buf);
index 17c675c522954cc39a210e431603aac2a3a2d946..1c49d7173966ae52754cd75776ff50fa48f30d60 100644 (file)
@@ -4109,12 +4109,19 @@ static struct platform_driver floppy_driver = {
 
 static struct platform_device floppy_device[N_DRIVE];
 
+static bool floppy_available(int drive)
+{
+       if (!(allowed_drive_mask & (1 << drive)))
+               return false;
+       if (fdc_state[FDC(drive)].version == FDC_NONE)
+               return false;
+       return true;
+}
+
 static struct kobject *floppy_find(dev_t dev, int *part, void *data)
 {
        int drive = (*part & 3) | ((*part & 0x80) >> 5);
-       if (drive >= N_DRIVE ||
-           !(allowed_drive_mask & (1 << drive)) ||
-           fdc_state[FDC(drive)].version == FDC_NONE)
+       if (drive >= N_DRIVE || !floppy_available(drive))
                return NULL;
        if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))
                return NULL;
@@ -4124,8 +4131,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
 
 static int __init do_floppy_init(void)
 {
-       int i, unit, drive;
-       int err, dr;
+       int i, unit, drive, err;
 
        set_debugt();
        interruptjiffies = resultjiffies = jiffies;
@@ -4137,34 +4143,32 @@ static int __init do_floppy_init(void)
 
        raw_cmd = NULL;
 
-       for (dr = 0; dr < N_DRIVE; dr++) {
-               disks[dr] = alloc_disk(1);
-               if (!disks[dr]) {
-                       err = -ENOMEM;
-                       goto out_put_disk;
-               }
+       floppy_wq = alloc_ordered_workqueue("floppy", 0);
+       if (!floppy_wq)
+               return -ENOMEM;
 
-               floppy_wq = alloc_ordered_workqueue("floppy", 0);
-               if (!floppy_wq) {
+       for (drive = 0; drive < N_DRIVE; drive++) {
+               disks[drive] = alloc_disk(1);
+               if (!disks[drive]) {
                        err = -ENOMEM;
                        goto out_put_disk;
                }
 
-               disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock);
-               if (!disks[dr]->queue) {
+               disks[drive]->queue = blk_init_queue(do_fd_request, &floppy_lock);
+               if (!disks[drive]->queue) {
                        err = -ENOMEM;
-                       goto out_destroy_workq;
+                       goto out_put_disk;
                }
 
-               blk_queue_max_hw_sectors(disks[dr]->queue, 64);
-               disks[dr]->major = FLOPPY_MAJOR;
-               disks[dr]->first_minor = TOMINOR(dr);
-               disks[dr]->fops = &floppy_fops;
-               sprintf(disks[dr]->disk_name, "fd%d", dr);
+               blk_queue_max_hw_sectors(disks[drive]->queue, 64);
+               disks[drive]->major = FLOPPY_MAJOR;
+               disks[drive]->first_minor = TOMINOR(drive);
+               disks[drive]->fops = &floppy_fops;
+               sprintf(disks[drive]->disk_name, "fd%d", drive);
 
-               init_timer(&motor_off_timer[dr]);
-               motor_off_timer[dr].data = dr;
-               motor_off_timer[dr].function = motor_off_callback;
+               init_timer(&motor_off_timer[drive]);
+               motor_off_timer[drive].data = drive;
+               motor_off_timer[drive].function = motor_off_callback;
        }
 
        err = register_blkdev(FLOPPY_MAJOR, "fd");
@@ -4282,9 +4286,7 @@ static int __init do_floppy_init(void)
        }
 
        for (drive = 0; drive < N_DRIVE; drive++) {
-               if (!(allowed_drive_mask & (1 << drive)))
-                       continue;
-               if (fdc_state[FDC(drive)].version == FDC_NONE)
+               if (!floppy_available(drive))
                        continue;
 
                floppy_device[drive].name = floppy_device_name;
@@ -4293,7 +4295,7 @@ static int __init do_floppy_init(void)
 
                err = platform_device_register(&floppy_device[drive]);
                if (err)
-                       goto out_release_dma;
+                       goto out_remove_drives;
 
                err = device_create_file(&floppy_device[drive].dev,
                                         &dev_attr_cmos);
@@ -4311,29 +4313,34 @@ static int __init do_floppy_init(void)
 
 out_unreg_platform_dev:
        platform_device_unregister(&floppy_device[drive]);
+out_remove_drives:
+       while (drive--) {
+               if (floppy_available(drive)) {
+                       del_gendisk(disks[drive]);
+                       device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
+                       platform_device_unregister(&floppy_device[drive]);
+               }
+       }
 out_release_dma:
        if (atomic_read(&usage_count))
                floppy_release_irq_and_dma();
 out_unreg_region:
        blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
        platform_driver_unregister(&floppy_driver);
-out_destroy_workq:
-       destroy_workqueue(floppy_wq);
 out_unreg_blkdev:
        unregister_blkdev(FLOPPY_MAJOR, "fd");
 out_put_disk:
-       while (dr--) {
-               del_timer_sync(&motor_off_timer[dr]);
-               if (disks[dr]->queue) {
-                       blk_cleanup_queue(disks[dr]->queue);
-                       /*
-                        * put_disk() is not paired with add_disk() and
-                        * will put queue reference one extra time. fix it.
-                        */
-                       disks[dr]->queue = NULL;
+       for (drive = 0; drive < N_DRIVE; drive++) {
+               if (!disks[drive])
+                       break;
+               if (disks[drive]->queue) {
+                       del_timer_sync(&motor_off_timer[drive]);
+                       blk_cleanup_queue(disks[drive]->queue);
+                       disks[drive]->queue = NULL;
                }
-               put_disk(disks[dr]);
+               put_disk(disks[drive]);
        }
+       destroy_workqueue(floppy_wq);
        return err;
 }
 
@@ -4551,8 +4558,7 @@ static void __exit floppy_module_exit(void)
        for (drive = 0; drive < N_DRIVE; drive++) {
                del_timer_sync(&motor_off_timer[drive]);
 
-               if ((allowed_drive_mask & (1 << drive)) &&
-                   fdc_state[FDC(drive)].version != FDC_NONE) {
+               if (floppy_available(drive)) {
                        del_gendisk(disks[drive]);
                        device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
                        platform_device_unregister(&floppy_device[drive]);
index e9d594fd12cbee408251c4ead03d1b71183ff7ae..54046e51160aef28e3ee733797fa453a0403a02a 100644 (file)
@@ -976,8 +976,21 @@ static int loop_clr_fd(struct loop_device *lo)
        if (lo->lo_state != Lo_bound)
                return -ENXIO;
 
-       if (lo->lo_refcnt > 1)  /* we needed one fd for the ioctl */
-               return -EBUSY;
+       /*
+        * If we've explicitly asked to tear down the loop device,
+        * and it has an elevated reference count, set it for auto-teardown when
+        * the last reference goes away. This stops $!~#$@ udev from
+        * preventing teardown because it decided that it needs to run blkid on
+        * the loopback device whenever they appear. xfstests is notorious for
+        * failing tests because blkid via udev races with a losetup
+        * <dev>/do something like mkfs/losetup -d <dev> causing the losetup -d
+        * command to fail with EBUSY.
+        */
+       if (lo->lo_refcnt > 1) {
+               lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
+               mutex_unlock(&lo->lo_ctl_mutex);
+               return 0;
+       }
 
        if (filp == NULL)
                return -EINVAL;
index f946d31d6917e00aa0637df5d21cef35ebf82845..adc6f36564cf3c9f214ca37c9b3cf8faffbe6cf8 100644 (file)
@@ -2035,8 +2035,9 @@ static unsigned int implicit_sector(unsigned char command,
        }
        return rv;
 }
-
-static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)
+static void mtip_set_timeout(struct driver_data *dd,
+                                       struct host_to_dev_fis *fis,
+                                       unsigned int *timeout, u8 erasemode)
 {
        switch (fis->command) {
        case ATA_CMD_DOWNLOAD_MICRO:
@@ -2044,7 +2045,10 @@ static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)
                break;
        case ATA_CMD_SEC_ERASE_UNIT:
        case 0xFC:
-               *timeout = 240000; /* 4 minutes */
+               if (erasemode)
+                       *timeout = ((*(dd->port->identify + 90) * 2) * 60000);
+               else
+                       *timeout = ((*(dd->port->identify + 89) * 2) * 60000);
                break;
        case ATA_CMD_STANDBYNOW1:
                *timeout = 120000;  /* 2 minutes */
@@ -2087,6 +2091,7 @@ static int exec_drive_taskfile(struct driver_data *dd,
        unsigned int transfer_size;
        unsigned long task_file_data;
        int intotal = outtotal + req_task->out_size;
+       int erasemode = 0;
 
        taskout = req_task->out_size;
        taskin = req_task->in_size;
@@ -2212,7 +2217,13 @@ static int exec_drive_taskfile(struct driver_data *dd,
                fis.lba_hi,
                fis.device);
 
-       mtip_set_timeout(&fis, &timeout);
+       /* check for erase mode support during secure erase.*/
+       if ((fis.command == ATA_CMD_SEC_ERASE_UNIT)
+                                       && (outbuf[0] & MTIP_SEC_ERASE_MODE)) {
+               erasemode = 1;
+       }
+
+       mtip_set_timeout(dd, &fis, &timeout, erasemode);
 
        /* Determine the correct transfer size.*/
        if (force_single_sector)
index 18627a1d04c59eff34f7cdd2313555b10a75b283..5f4a917bd8bbcfe88283b3509e365a0faefbb3b5 100644 (file)
@@ -33,6 +33,9 @@
 /* offset of Device Control register in PCIe extended capabilites space */
 #define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET  0x48
 
+/* check for erase mode support during secure erase */
+#define MTIP_SEC_ERASE_MODE     0x3
+
 /* # of times to retry timed out/failed IOs */
 #define MTIP_MAX_RETRIES       2
 
index 9ad3b5ec1dc1c521085db47a7928cc8cf1179701..9a54623e52d74ecc77953937bd923a9ecdb68d09 100644 (file)
@@ -158,8 +158,8 @@ struct xen_vbd {
        struct block_device     *bdev;
        /* Cached size parameter. */
        sector_t                size;
-       bool                    flush_support;
-       bool                    discard_secure;
+       unsigned int            flush_support:1;
+       unsigned int            discard_secure:1;
 };
 
 struct backend_info;
index 4f66171c668354b490f1284aec48278b8676bd84..f58434c2617cab4185b8c049804f1031f4226a6e 100644 (file)
@@ -105,11 +105,10 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
 {
        struct xen_blkif *blkif;
 
-       blkif = kmem_cache_alloc(xen_blkif_cachep, GFP_KERNEL);
+       blkif = kmem_cache_zalloc(xen_blkif_cachep, GFP_KERNEL);
        if (!blkif)
                return ERR_PTR(-ENOMEM);
 
-       memset(blkif, 0, sizeof(*blkif));
        blkif->domid = domid;
        spin_lock_init(&blkif->blk_ring_lock);
        atomic_set(&blkif->refcnt, 1);
@@ -196,7 +195,7 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif)
        }
 }
 
-void xen_blkif_free(struct xen_blkif *blkif)
+static void xen_blkif_free(struct xen_blkif *blkif)
 {
        if (!atomic_dec_and_test(&blkif->refcnt))
                BUG();
@@ -257,7 +256,7 @@ static struct attribute_group xen_vbdstat_group = {
 VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor);
 VBD_SHOW(mode, "%s\n", be->mode);
 
-int xenvbd_sysfs_addif(struct xenbus_device *dev)
+static int xenvbd_sysfs_addif(struct xenbus_device *dev)
 {
        int error;
 
@@ -281,7 +280,7 @@ fail1:      device_remove_file(&dev->dev, &dev_attr_physical_device);
        return error;
 }
 
-void xenvbd_sysfs_delif(struct xenbus_device *dev)
+static void xenvbd_sysfs_delif(struct xenbus_device *dev)
 {
        sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group);
        device_remove_file(&dev->dev, &dev_attr_mode);
index 320debbe32faf74032f5117cfaf461cbd65a63a3..9b4f0116ff21c95d73d2ad2da39d7fb40dc24ee8 100644 (file)
@@ -1456,7 +1456,7 @@ static int __devexit sonypi_remove(struct platform_device *dev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int old_camera_power;
 
 static int sonypi_suspend(struct device *dev)
index b40ee1403be9b657ffcabd5142650ddb926fb367..399831690fedc18a263636a89725ec7b9af7dadb 100644 (file)
@@ -328,6 +328,7 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
                cpufreq_update_policy(cpu);
                break;
        case CPU_DOWN_PREPARE:
+       case CPU_DOWN_PREPARE_FROZEN:
                cpufreq_stats_free_sysfs(cpu);
                break;
        case CPU_DEAD:
index 129e80bfff22e1d399fbe5320012f5721de1bcaf..e3ebb4fa2c3e5045c04f6b0b864a4499064fcbff 100644 (file)
@@ -5,7 +5,7 @@
  *  http://www.gnu.org/licenses/gpl.html
  *
  *  Maintainer:
- *  Andreas Herrmann <andreas.herrmann3@amd.com>
+ *  Andreas Herrmann <herrmann.der.user@googlemail.com>
  *
  *  Based on the powernow-k7.c module written by Dave Jones.
  *  (C) 2003 Dave Jones on behalf of SuSE Labs
@@ -1052,14 +1052,7 @@ static int powernowk8_target(struct cpufreq_policy *pol,
        struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq,
                                             .relation = relation };
 
-       /*
-        * Must run on @pol->cpu.  cpufreq core is responsible for ensuring
-        * that we're bound to the current CPU and pol->cpu stays online.
-        */
-       if (smp_processor_id() == pol->cpu)
-               return powernowk8_target_fn(&pta);
-       else
-               return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta);
+       return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta);
 }
 
 /* Driver entry point to verify the policy and range of frequencies */
index 677cd6e4e1a1c1afb387217fdc9f0f363c3149cf..d4c12180c65416043dbbf3940374ad146daad881 100644 (file)
@@ -90,6 +90,17 @@ config DW_DMAC
          Support the Synopsys DesignWare AHB DMA controller.  This
          can be integrated in chips such as the Atmel AT32ap7000.
 
+config DW_DMAC_BIG_ENDIAN_IO
+       bool "Use big endian I/O register access"
+       default y if AVR32
+       depends on DW_DMAC
+       help
+         Say yes here to use big endian I/O access when reading and writing
+         to the DMA controller registers. This is needed on some platforms,
+         like the Atmel AVR32 architecture.
+
+         If unsure, use the default setting.
+
 config AT_HDMAC
        tristate "Atmel AHB DMA support"
        depends on ARCH_AT91
index ff39fa6cd2bc443a7d96fd9d85be015f643704f5..88965597b7d08c9e2b9987957f85284cc9851f4c 100644 (file)
@@ -98,9 +98,17 @@ struct dw_dma_regs {
        u32     DW_PARAMS;
 };
 
+#ifdef CONFIG_DW_DMAC_BIG_ENDIAN_IO
+#define dma_readl_native ioread32be
+#define dma_writel_native iowrite32be
+#else
+#define dma_readl_native readl
+#define dma_writel_native writel
+#endif
+
 /* To access the registers in early stage of probe */
 #define dma_read_byaddr(addr, name) \
-       readl((addr) + offsetof(struct dw_dma_regs, name))
+       dma_readl_native((addr) + offsetof(struct dw_dma_regs, name))
 
 /* Bitfields in DW_PARAMS */
 #define DW_PARAMS_NR_CHAN      8               /* number of channels */
@@ -216,9 +224,9 @@ __dwc_regs(struct dw_dma_chan *dwc)
 }
 
 #define channel_readl(dwc, name) \
-       readl(&(__dwc_regs(dwc)->name))
+       dma_readl_native(&(__dwc_regs(dwc)->name))
 #define channel_writel(dwc, name, val) \
-       writel((val), &(__dwc_regs(dwc)->name))
+       dma_writel_native((val), &(__dwc_regs(dwc)->name))
 
 static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan)
 {
@@ -246,9 +254,9 @@ static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw)
 }
 
 #define dma_readl(dw, name) \
-       readl(&(__dw_regs(dw)->name))
+       dma_readl_native(&(__dw_regs(dw)->name))
 #define dma_writel(dw, name, val) \
-       writel((val), &(__dw_regs(dw)->name))
+       dma_writel_native((val), &(__dw_regs(dw)->name))
 
 #define channel_set_bit(dw, reg, mask) \
        dma_writel(dw, reg, ((mask) << 8) | (mask))
index f11b5b2b1a1c1e41274ed7578ba197971e209f5a..7d9554cc4976313c90604eacecf4b78227a860f7 100644 (file)
@@ -474,8 +474,10 @@ static int imxdma_xfer_desc(struct imxdma_desc *d)
                        slot = i;
                        break;
                }
-               if (slot < 0)
+               if (slot < 0) {
+                       spin_unlock_irqrestore(&imxdma->lock, flags);
                        return -EBUSY;
+               }
 
                imxdma->slots_2d[slot].xsr = d->x;
                imxdma->slots_2d[slot].ysr = d->y;
index 64385cde044b3feefcc49001edbf0e9ee647bd0d..d451caace806445428c40d3f4d5678ada4a0925d 100644 (file)
@@ -109,7 +109,7 @@ static void sirfsoc_dma_execute(struct sirfsoc_dma_chan *schan)
        sdesc = list_first_entry(&schan->queued, struct sirfsoc_dma_desc,
                node);
        /* Move the first queued descriptor to active list */
-       list_move_tail(&schan->queued, &schan->active);
+       list_move_tail(&sdesc->node, &schan->active);
 
        /* Start the DMA transfer */
        writel_relaxed(sdesc->width, sdma->base + SIRFSOC_DMA_WIDTH_0 +
@@ -428,7 +428,7 @@ static struct dma_async_tx_descriptor *sirfsoc_dma_prep_interleaved(
        unsigned long iflags;
        int ret;
 
-       if ((xt->dir != DMA_MEM_TO_DEV) || (xt->dir != DMA_DEV_TO_MEM)) {
+       if ((xt->dir != DMA_MEM_TO_DEV) && (xt->dir != DMA_DEV_TO_MEM)) {
                ret = -EINVAL;
                goto err_dir;
        }
index 5a297a26211d622b0f0ceedb0389fcbeb4223baf..cc8e7c78a23ca22972bfa570dc88d1fcf449e979 100644 (file)
@@ -170,8 +170,11 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
         * memory controller and apply to register. Search for the first
         * bandwidth entry that is greater or equal than the setting requested
         * and program that. If at last entry, turn off DRAM scrubbing.
+        *
+        * If no suitable bandwidth is found, turn off DRAM scrubbing entirely
+        * by falling back to the last element in scrubrates[].
         */
-       for (i = 0; i < ARRAY_SIZE(scrubrates); i++) {
+       for (i = 0; i < ARRAY_SIZE(scrubrates) - 1; i++) {
                /*
                 * skip scrub rates which aren't recommended
                 * (see F10 BKDG, F3x58)
@@ -181,12 +184,6 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
 
                if (scrubrates[i].bandwidth <= new_bw)
                        break;
-
-               /*
-                * if no suitable bandwidth found, turn off DRAM scrubbing
-                * entirely by falling back to the last element in the
-                * scrubrates array.
-                */
        }
 
        scrubval = scrubrates[i].scrubval;
index 725eb5aa8d8cb670d0e104d48557fb866947a20a..e87196f6d2d2db43f945e6317b3d14fe09e680f4 100644 (file)
@@ -14,6 +14,7 @@
  *
  */
 
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
@@ -161,13 +162,12 @@ static int __devinit adc_jack_probe(struct platform_device *pdev)
        err = request_any_context_irq(data->irq, adc_jack_irq_thread,
                        pdata->irq_flags, pdata->name, data);
 
-       if (err) {
+       if (err < 0) {
                dev_err(&pdev->dev, "error: irq %d\n", data->irq);
-               err = -EINVAL;
                goto err_irq;
        }
 
-       goto out;
+       return 0;
 
 err_irq:
        extcon_dev_unregister(&data->edev);
@@ -196,3 +196,7 @@ static struct platform_driver adc_jack_driver = {
 };
 
 module_platform_driver(adc_jack_driver);
+
+MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
+MODULE_DESCRIPTION("ADC Jack extcon driver");
+MODULE_LICENSE("GPL v2");
index 946a3188b2b78a4014f84e93588e8423c41501c0..d398821097f35f181c7ad554360a127de13496d5 100644 (file)
@@ -41,7 +41,7 @@
  * every single port-type of the following cable names. Please choose cable
  * names that are actually used in your extcon device.
  */
-const char *extcon_cable_name[] = {
+const char extcon_cable_name[][CABLE_NAME_MAX + 1] = {
        [EXTCON_USB]            = "USB",
        [EXTCON_USB_HOST]       = "USB-Host",
        [EXTCON_TA]             = "TA",
@@ -62,8 +62,6 @@ const char *extcon_cable_name[] = {
        [EXTCON_VIDEO_IN]       = "Video-in",
        [EXTCON_VIDEO_OUT]      = "Video-out",
        [EXTCON_MECHANICAL]     = "Mechanical",
-
-       NULL,
 };
 
 static struct class *extcon_class;
@@ -91,17 +89,13 @@ static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state)
                return 0;
 
        for (i = 0; edev->mutually_exclusive[i]; i++) {
-               int count = 0, j;
+               int weight;
                u32 correspondants = new_state & edev->mutually_exclusive[i];
-               u32 exp = 1;
-
-               for (j = 0; j < 32; j++) {
-                       if (exp & correspondants)
-                               count++;
-                       if (count > 1)
-                               return i + 1;
-                       exp <<= 1;
-               }
+
+               /* calculate the total number of bits set */
+               weight = hweight32(correspondants);
+               if (weight > 1)
+                       return i + 1;
        }
 
        return 0;
@@ -362,7 +356,7 @@ int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name)
 EXPORT_SYMBOL_GPL(extcon_get_cable_state);
 
 /**
- * extcon_get_cable_state_() - Set the status of a specific cable.
+ * extcon_set_cable_state_() - Set the status of a specific cable.
  * @edev:      the extcon device that has the cable.
  * @index:     cable index that can be retrieved by extcon_find_cable_index().
  * @cable_state:       the new cable status. The default semantics is
@@ -382,7 +376,7 @@ int extcon_set_cable_state_(struct extcon_dev *edev,
 EXPORT_SYMBOL_GPL(extcon_set_cable_state_);
 
 /**
- * extcon_get_cable_state() - Set the status of a specific cable.
+ * extcon_set_cable_state() - Set the status of a specific cable.
  * @edev:      the extcon device that has the cable.
  * @cable_name:        cable name.
  * @cable_state:       the new cable status. The default semantics is
@@ -447,6 +441,8 @@ static int _call_per_cable(struct notifier_block *nb, unsigned long val,
  *                           extcon device.
  * @obj:       an empty extcon_specific_cable_nb object to be returned.
  * @extcon_name:       the name of extcon device.
+ *                     if NULL, extcon_register_interest will register
+ *                     every cable with the target cable_name given.
  * @cable_name:                the target cable name.
  * @nb:                the notifier block to get notified.
  *
@@ -466,22 +462,44 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,
                             const char *extcon_name, const char *cable_name,
                             struct notifier_block *nb)
 {
-       if (!obj || !extcon_name || !cable_name || !nb)
+       if (!obj || !cable_name || !nb)
                return -EINVAL;
 
-       obj->edev = extcon_get_extcon_dev(extcon_name);
-       if (!obj->edev)
-               return -ENODEV;
+       if (extcon_name) {
+               obj->edev = extcon_get_extcon_dev(extcon_name);
+               if (!obj->edev)
+                       return -ENODEV;
 
-       obj->cable_index = extcon_find_cable_index(obj->edev, cable_name);
-       if (obj->cable_index < 0)
-               return -ENODEV;
+               obj->cable_index = extcon_find_cable_index(obj->edev, cable_name);
+               if (obj->cable_index < 0)
+                       return -ENODEV;
+
+               obj->user_nb = nb;
 
-       obj->user_nb = nb;
+               obj->internal_nb.notifier_call = _call_per_cable;
 
-       obj->internal_nb.notifier_call = _call_per_cable;
+               return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb);
+       } else {
+               struct class_dev_iter iter;
+               struct extcon_dev *extd;
+               struct device *dev;
+
+               if (!extcon_class)
+                       return -ENODEV;
+               class_dev_iter_init(&iter, extcon_class, NULL, NULL);
+               while ((dev = class_dev_iter_next(&iter))) {
+                       extd = (struct extcon_dev *)dev_get_drvdata(dev);
+
+                       if (extcon_find_cable_index(extd, cable_name) < 0)
+                               continue;
+
+                       class_dev_iter_exit(&iter);
+                       return extcon_register_interest(obj, extd->name,
+                                               cable_name, nb);
+               }
 
-       return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb);
+               return -ENODEV;
+       }
 }
 
 /**
@@ -551,43 +569,9 @@ static int create_extcon_class(void)
        return 0;
 }
 
-static void extcon_cleanup(struct extcon_dev *edev, bool skip)
-{
-       mutex_lock(&extcon_dev_list_lock);
-       list_del(&edev->entry);
-       mutex_unlock(&extcon_dev_list_lock);
-
-       if (!skip && get_device(edev->dev)) {
-               int index;
-
-               if (edev->mutually_exclusive && edev->max_supported) {
-                       for (index = 0; edev->mutually_exclusive[index];
-                            index++)
-                               kfree(edev->d_attrs_muex[index].attr.name);
-                       kfree(edev->d_attrs_muex);
-                       kfree(edev->attrs_muex);
-               }
-
-               for (index = 0; index < edev->max_supported; index++)
-                       kfree(edev->cables[index].attr_g.name);
-
-               if (edev->max_supported) {
-                       kfree(edev->extcon_dev_type.groups);
-                       kfree(edev->cables);
-               }
-
-               device_unregister(edev->dev);
-               put_device(edev->dev);
-       }
-
-       kfree(edev->dev);
-}
-
 static void extcon_dev_release(struct device *dev)
 {
-       struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
-
-       extcon_cleanup(edev, true);
+       kfree(dev);
 }
 
 static const char *muex_name = "mutually_exclusive";
@@ -813,7 +797,40 @@ EXPORT_SYMBOL_GPL(extcon_dev_register);
  */
 void extcon_dev_unregister(struct extcon_dev *edev)
 {
-       extcon_cleanup(edev, false);
+       int index;
+
+       mutex_lock(&extcon_dev_list_lock);
+       list_del(&edev->entry);
+       mutex_unlock(&extcon_dev_list_lock);
+
+       if (IS_ERR_OR_NULL(get_device(edev->dev))) {
+               dev_err(edev->dev, "Failed to unregister extcon_dev (%s)\n",
+                               dev_name(edev->dev));
+               return;
+       }
+
+       if (edev->mutually_exclusive && edev->max_supported) {
+               for (index = 0; edev->mutually_exclusive[index];
+                               index++)
+                       kfree(edev->d_attrs_muex[index].attr.name);
+               kfree(edev->d_attrs_muex);
+               kfree(edev->attrs_muex);
+       }
+
+       for (index = 0; index < edev->max_supported; index++)
+               kfree(edev->cables[index].attr_g.name);
+
+       if (edev->max_supported) {
+               kfree(edev->extcon_dev_type.groups);
+               kfree(edev->cables);
+       }
+
+#if defined(CONFIG_ANDROID)
+       if (switch_class)
+               class_compat_remove_link(switch_class, edev->dev, NULL);
+#endif
+       device_unregister(edev->dev);
+       put_device(edev->dev);
 }
 EXPORT_SYMBOL_GPL(extcon_dev_unregister);
 
@@ -825,6 +842,9 @@ module_init(extcon_class_init);
 
 static void __exit extcon_class_exit(void)
 {
+#if defined(CONFIG_ANDROID)
+       class_compat_unregister(switch_class);
+#endif
        class_destroy(extcon_class);
 }
 module_exit(extcon_class_exit);
index 3cc152e690b06087c8374bf35cb72106f9bfde32..71d3ab7b3d8d72c8c477250e25b8ec93ce7842e8 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <linux/extcon.h>
 #include <linux/workqueue.h>
 #include <linux/gpio.h>
 #include <linux/extcon.h>
index e21387e2da5c25d2c9fdd19dae94108f9e9455da..a17d0d91ada26865d580768b293f2bbd936e4d10 100644 (file)
@@ -239,25 +239,19 @@ const char *max77693_extcon_cable[] = {
 static int max77693_muic_set_debounce_time(struct max77693_muic_info *info,
                enum max77693_muic_adc_debounce_time time)
 {
-       int ret = 0;
-       u8 ctrl3;
+       int ret;
 
        switch (time) {
        case ADC_DEBOUNCE_TIME_5MS:
        case ADC_DEBOUNCE_TIME_10MS:
        case ADC_DEBOUNCE_TIME_25MS:
        case ADC_DEBOUNCE_TIME_38_62MS:
-               ret = max77693_read_reg(info->max77693->regmap_muic,
-                               MAX77693_MUIC_REG_CTRL3, &ctrl3);
-               ctrl3 &= ~CONTROL3_ADCDBSET_MASK;
-               ctrl3 |= (time << CONTROL3_ADCDBSET_SHIFT);
-
-               ret = max77693_write_reg(info->max77693->regmap_muic,
-                               MAX77693_MUIC_REG_CTRL3, ctrl3);
-               if (ret) {
+               ret = max77693_update_reg(info->max77693->regmap_muic,
+                                         MAX77693_MUIC_REG_CTRL3,
+                                         time << CONTROL3_ADCDBSET_SHIFT,
+                                         CONTROL3_ADCDBSET_MASK);
+               if (ret)
                        dev_err(info->dev, "failed to set ADC debounce time\n");
-                       ret = -EINVAL;
-               }
                break;
        default:
                dev_err(info->dev, "invalid ADC debounce time\n");
@@ -657,6 +651,8 @@ out:
 static int __devinit max77693_muic_probe(struct platform_device *pdev)
 {
        struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
+       struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev);
+       struct max77693_muic_platform_data *muic_pdata = pdata->muic_data;
        struct max77693_muic_info *info;
        int ret, i;
        u8 id;
@@ -727,6 +723,31 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev)
                goto err_extcon;
        }
 
+       /* Initialize MUIC register by using platform data */
+       for (i = 0 ; i < muic_pdata->num_init_data ; i++) {
+               enum max77693_irq_source irq_src = MAX77693_IRQ_GROUP_NR;
+
+               max77693_write_reg(info->max77693->regmap_muic,
+                               muic_pdata->init_data[i].addr,
+                               muic_pdata->init_data[i].data);
+
+               switch (muic_pdata->init_data[i].addr) {
+               case MAX77693_MUIC_REG_INTMASK1:
+                       irq_src = MUIC_INT1;
+                       break;
+               case MAX77693_MUIC_REG_INTMASK2:
+                       irq_src = MUIC_INT2;
+                       break;
+               case MAX77693_MUIC_REG_INTMASK3:
+                       irq_src = MUIC_INT3;
+                       break;
+               }
+
+               if (irq_src < MAX77693_IRQ_GROUP_NR)
+                       info->max77693->irq_masks_cur[irq_src]
+                               = muic_pdata->init_data[i].data;
+       }
+
        /* Check revision number of MUIC device*/
        ret = max77693_read_reg(info->max77693->regmap_muic,
                        MAX77693_MUIC_REG_ID, &id);
@@ -762,6 +783,7 @@ static int __devexit max77693_muic_remove(struct platform_device *pdev)
                free_irq(muic_irqs[i].virq, info);
        cancel_work_sync(&info->irq_work);
        extcon_dev_unregister(info->edev);
+       kfree(info->edev);
        kfree(info);
 
        return 0;
index ef9090a4271ddc00ee6d735c2c4b48051e5c09f3..77b66b0cc8f54b117280e951daf81b17d6d31c3c 100644 (file)
@@ -271,8 +271,6 @@ out:
 static int max8997_muic_handle_charger_type_detach(
                                struct max8997_muic_info *info)
 {
-       int ret = 0;
-
        switch (info->pre_charger_type) {
        case MAX8997_CHARGER_TYPE_USB:
                extcon_set_cable_state(info->edev, "USB", false);
@@ -290,11 +288,11 @@ static int max8997_muic_handle_charger_type_detach(
                extcon_set_cable_state(info->edev, "Fast-charger", false);
                break;
        default:
-               ret = -EINVAL;
+               return -EINVAL;
                break;
        }
 
-       return ret;
+       return 0;
 }
 
 static int max8997_muic_handle_charger_type(struct max8997_muic_info *info,
index ed3e55161bdc5bacbd0409a8a728f161872671c9..f05e54258ffb0a7c1b62eb54be11f2f8ed9486d8 100644 (file)
@@ -153,7 +153,7 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
        }
 
        chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers;
-       chip->buffer = devm_kzalloc(&spi->dev, chip->gpio_chip.ngpio, GFP_KERNEL);
+       chip->buffer = devm_kzalloc(&spi->dev, chip->registers, GFP_KERNEL);
        if (!chip->buffer) {
                ret = -ENOMEM;
                goto exit_destroy;
index 7a874129e5d8f3634b68ea45d5d73a2a316f8bae..cf7afb9eb61ab02c4060532dbdd39e2c2c6e9561 100644 (file)
@@ -244,6 +244,8 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
        if (ret)
                return ret;
 
+       mvebu_gpio_set(chip, pin, value);
+
        spin_lock_irqsave(&mvchip->lock, flags);
        u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
        u &= ~(1 << pin);
@@ -644,7 +646,7 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
        ct->handler = handle_edge_irq;
        ct->chip.name = mvchip->chip.label;
 
-       irq_setup_generic_chip(gc, IRQ_MSK(ngpios), IRQ_GC_INIT_MASK_CACHE,
+       irq_setup_generic_chip(gc, IRQ_MSK(ngpios), 0,
                               IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
 
        /* Setup irq domain on top of the generic chip. */
index 94cbc842fbc3a1363de61b8b7d08f2e4b56daeaf..d335af1d4d858da39b2825fd9144c01e76f877e5 100644 (file)
@@ -251,6 +251,40 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
        }
 }
 
+/**
+ * _clear_gpio_debounce - clear debounce settings for a gpio
+ * @bank: the gpio bank we're acting upon
+ * @gpio: the gpio number on this @gpio
+ *
+ * If a gpio is using debounce, then clear the debounce enable bit and if
+ * this is the only gpio in this bank using debounce, then clear the debounce
+ * time too. The debounce clock will also be disabled when calling this function
+ * if this is the only gpio in the bank using debounce.
+ */
+static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio)
+{
+       u32 gpio_bit = GPIO_BIT(bank, gpio);
+
+       if (!bank->dbck_flag)
+               return;
+
+       if (!(bank->dbck_enable_mask & gpio_bit))
+               return;
+
+       bank->dbck_enable_mask &= ~gpio_bit;
+       bank->context.debounce_en &= ~gpio_bit;
+       __raw_writel(bank->context.debounce_en,
+                    bank->base + bank->regs->debounce_en);
+
+       if (!bank->dbck_enable_mask) {
+               bank->context.debounce = 0;
+               __raw_writel(bank->context.debounce, bank->base +
+                            bank->regs->debounce);
+               clk_disable(bank->dbck);
+               bank->dbck_enabled = false;
+       }
+}
+
 static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
                                                unsigned trigger)
 {
@@ -539,6 +573,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)
        _set_gpio_irqenable(bank, gpio, 0);
        _clear_gpio_irqstatus(bank, gpio);
        _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
+       _clear_gpio_debounce(bank, gpio);
 }
 
 /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
index 031c6adf5b651542420ee819ad0810d537707222..1a3e2b9b4772f7e710c16dee60a48049a3ff5c6d 100644 (file)
@@ -116,7 +116,7 @@ static void timbgpio_irq_disable(struct irq_data *d)
        unsigned long flags;
 
        spin_lock_irqsave(&tgpio->lock, flags);
-       tgpio->last_ier &= ~(1 << offset);
+       tgpio->last_ier &= ~(1UL << offset);
        iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
        spin_unlock_irqrestore(&tgpio->lock, flags);
 }
@@ -128,7 +128,7 @@ static void timbgpio_irq_enable(struct irq_data *d)
        unsigned long flags;
 
        spin_lock_irqsave(&tgpio->lock, flags);
-       tgpio->last_ier |= 1 << offset;
+       tgpio->last_ier |= 1UL << offset;
        iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
        spin_unlock_irqrestore(&tgpio->lock, flags);
 }
index 5d6c71edc73911c7765a7530e65352fda2478845..1c8d9e3380e17276e17e8f009659954e58d05bd1 100644 (file)
@@ -623,9 +623,11 @@ static ssize_t export_store(struct class *class,
         */
 
        status = gpio_request(gpio, "sysfs");
-       if (status < 0)
+       if (status < 0) {
+               if (status == -EPROBE_DEFER)
+                       status = -ENODEV;
                goto done;
-
+       }
        status = gpio_export(gpio, true);
        if (status < 0)
                gpio_free(gpio);
@@ -1191,8 +1193,10 @@ int gpio_request(unsigned gpio, const char *label)
 
        spin_lock_irqsave(&gpio_lock, flags);
 
-       if (!gpio_is_valid(gpio))
+       if (!gpio_is_valid(gpio)) {
+               status = -EINVAL;
                goto done;
+       }
        desc = &gpio_desc[gpio];
        chip = desc->chip;
        if (chip == NULL)
index 09e11a5d921a4487b273bcdc2c479e4a26f90301..fd9d0af4d5369bb7ebac13662a3d612188c87921 100644 (file)
@@ -206,7 +206,7 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
        size_t size;
        int ret;
 
-       DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n",
+       DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n",
                        sizes->surface_width, sizes->surface_height,
                        sizes->surface_bpp);
 
@@ -220,7 +220,7 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
 
        size = mode_cmd.pitches[0] * mode_cmd.height;
        obj = drm_gem_cma_create(dev, size);
-       if (!obj)
+       if (IS_ERR(obj))
                return -ENOMEM;
 
        fbi = framebuffer_alloc(0, dev->dev);
index 441ebc1bdbef5455c6a8cc7aa34103926dd963fa..d4b20ceda3fbd8d183dc7e628683732590200f51 100644 (file)
@@ -205,8 +205,6 @@ static int drm_gem_one_name_info(int id, void *ptr, void *data)
        struct drm_gem_object *obj = ptr;
        struct seq_file *m = data;
 
-       seq_printf(m, "name %d size %zd\n", obj->name, obj->size);
-
        seq_printf(m, "%6d %8zd %7d %8d\n",
                   obj->name, obj->size,
                   atomic_read(&obj->handle_count),
index aaeb6f8d69ce3502c569dda32d2d600117fb54c5..b8a282ea87515546695bc2965bce2b9f3e4f2f2d 100644 (file)
@@ -64,7 +64,6 @@ int drm_get_platform_dev(struct platform_device *platdev,
        }
 
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               dev_set_drvdata(&platdev->dev, dev);
                ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
                if (ret)
                        goto err_g1;
index 59a26e577b57f423077d5a2c86d75364f14b6838..fc345d4ebb03acea266bfb100b4661cebf970f69 100644 (file)
@@ -1,6 +1,6 @@
 config DRM_EXYNOS
        tristate "DRM Support for Samsung SoC EXYNOS Series"
-       depends on DRM && PLAT_SAMSUNG
+       depends on DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM)
        select DRM_KMS_HELPER
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
index 18c271862ca8468a8ce0d3d4b24d8a595d29ad44..0f68a28726739dd6b795ad066edb645799cfc6d2 100644 (file)
@@ -374,6 +374,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
        exynos_connector->encoder_id = encoder->base.id;
        exynos_connector->manager = manager;
        exynos_connector->dpms = DRM_MODE_DPMS_OFF;
+       connector->dpms = DRM_MODE_DPMS_OFF;
        connector->encoder = encoder;
 
        err = drm_mode_connector_attach_encoder(connector, encoder);
index e51503fbaf2bcbf19edbdf423638a725b5703a6e..241ad1eeec64d2097a4416bd76026723d384a215 100644 (file)
  * @manager: specific encoder has its own manager to control a hardware
  *     appropriately and we can access a hardware drawing on this manager.
  * @dpms: store the encoder dpms value.
+ * @updated: indicate whether overlay data updating is needed or not.
  */
 struct exynos_drm_encoder {
        struct drm_crtc                 *old_crtc;
        struct drm_encoder              drm_encoder;
        struct exynos_drm_manager       *manager;
-       int dpms;
+       int                             dpms;
+       bool                            updated;
 };
 
 static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode)
@@ -85,7 +87,9 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
        switch (mode) {
        case DRM_MODE_DPMS_ON:
                if (manager_ops && manager_ops->apply)
-                       manager_ops->apply(manager->dev);
+                       if (!exynos_encoder->updated)
+                               manager_ops->apply(manager->dev);
+
                exynos_drm_connector_power(encoder, mode);
                exynos_encoder->dpms = mode;
                break;
@@ -94,6 +98,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
        case DRM_MODE_DPMS_OFF:
                exynos_drm_connector_power(encoder, mode);
                exynos_encoder->dpms = mode;
+               exynos_encoder->updated = false;
                break;
        default:
                DRM_ERROR("unspecified mode %d\n", mode);
@@ -205,13 +210,22 @@ static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
 
 static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
 {
-       struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+       struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
+       struct exynos_drm_manager *manager = exynos_encoder->manager;
        struct exynos_drm_manager_ops *manager_ops = manager->ops;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
        if (manager_ops && manager_ops->commit)
                manager_ops->commit(manager->dev);
+
+       /*
+        * this will avoid one issue that overlay data is updated to
+        * real hardware two times.
+        * And this variable will be used to check if the data was
+        * already updated or not by exynos_drm_encoder_dpms function.
+        */
+       exynos_encoder->updated = true;
 }
 
 static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
@@ -400,19 +414,6 @@ void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
        if (manager_ops && manager_ops->dpms)
                manager_ops->dpms(manager->dev, mode);
 
-       /*
-        * set current mode to new one so that data aren't updated into
-        * registers by drm_helper_connector_dpms two times.
-        *
-        * in case that drm_crtc_helper_set_mode() is called,
-        * overlay_ops->commit() and manager_ops->commit() callbacks
-        * can be called two times, first at drm_crtc_helper_set_mode()
-        * and second at drm_helper_connector_dpms().
-        * so with this setting, when drm_helper_connector_dpms() is called
-        * encoder->funcs->dpms() will be ignored.
-        */
-       exynos_encoder->dpms = mode;
-
        /*
         * if this condition is ok then it means that the crtc is already
         * detached from encoder and last function for detaching is properly
index 614b2e9ac462c9c402226324d9b12d38b996af14..e7fbb823fd8e5fe2fe97845a1b42a3d84efd50be 100644 (file)
@@ -1142,7 +1142,7 @@ static int __devinit mixer_probe(struct platform_device *pdev)
                const struct of_device_id *match;
                match = of_match_node(of_match_ptr(mixer_match_types),
                                                          pdev->dev.of_node);
-               drv = match->data;
+               drv = (struct mixer_drv_data *)match->data;
        } else {
                drv = (struct mixer_drv_data *)
                        platform_get_device_id(pdev)->driver_data;
index c9bfd83dde64eb6d83cf181fb6c27b3cfcf0a038..61ae104dca8c0f5b9938f092b93f7eca70a06525 100644 (file)
@@ -1505,7 +1505,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                goto put_gmch;
        }
 
-       i915_kick_out_firmware_fb(dev_priv);
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               i915_kick_out_firmware_fb(dev_priv);
 
        pci_set_master(dev->pdev);
 
index aac4e5e1a5b9b3533f36f801be7c553c2e60c8a1..6770ee6084b478475c3dde3a9bec72fff1e11a53 100644 (file)
@@ -118,6 +118,13 @@ module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600);
 MODULE_PARM_DESC(i915_enable_ppgtt,
                "Enable PPGTT (default: true)");
 
+unsigned int i915_preliminary_hw_support __read_mostly = 0;
+module_param_named(preliminary_hw_support, i915_preliminary_hw_support, int, 0600);
+MODULE_PARM_DESC(preliminary_hw_support,
+               "Enable preliminary hardware support. "
+               "Enable Haswell and ValleyView Support. "
+               "(default: false)");
+
 static struct drm_driver driver;
 extern int intel_agp_enabled;
 
@@ -826,6 +833,12 @@ i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct intel_device_info *intel_info =
                (struct intel_device_info *) ent->driver_data;
 
+       if (intel_info->is_haswell || intel_info->is_valleyview)
+               if(!i915_preliminary_hw_support) {
+                       DRM_ERROR("Preliminary hardware support disabled\n");
+                       return -ENODEV;
+               }
+
        /* Only bind to function 0 of the device. Early generations
         * used function 1 as a placeholder for multi-head. This causes
         * us confusion instead, especially on the systems where both
index b84f7861e4388cb3ccd8baa86ec3d994e4e52ceb..f511fa2f41687718494f2f1d9e2afb0c24f1fb70 100644 (file)
@@ -1217,6 +1217,7 @@ extern int i915_enable_rc6 __read_mostly;
 extern int i915_enable_fbc __read_mostly;
 extern bool i915_enable_hangcheck __read_mostly;
 extern int i915_enable_ppgtt __read_mostly;
+extern unsigned int i915_preliminary_hw_support __read_mostly;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
 extern int i915_resume(struct drm_device *dev);
index d33d02d13c9678a7dd64b1fb4c9e9c5f9682d223..107f09befe929540e9ad801ff2bbdfe97a6b651d 100644 (file)
@@ -1407,8 +1407,10 @@ out:
                return VM_FAULT_NOPAGE;
        case -ENOMEM:
                return VM_FAULT_OOM;
+       case -ENOSPC:
+               return VM_FAULT_SIGBUS;
        default:
-               WARN_ON_ONCE(ret);
+               WARN_ONCE(ret, "unhandled error in i915_gem_fault: %i\n", ret);
                return VM_FAULT_SIGBUS;
        }
 }
@@ -1822,10 +1824,11 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
                sg_set_page(sg, page, PAGE_SIZE, 0);
        }
 
+       obj->pages = st;
+
        if (i915_gem_object_needs_bit17_swizzle(obj))
                i915_gem_object_do_bit_17_swizzle(obj);
 
-       obj->pages = st;
        return 0;
 
 err_pages:
index 893f30164b7ec70a5cd2308db6db1e3e55222d6f..b726b478a4f5db604b6804ad679f7a887168705c 100644 (file)
@@ -219,20 +219,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
                intel_encoder_to_crt(to_intel_encoder(encoder));
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int dpll_md_reg;
-       u32 adpa, dpll_md;
-
-       dpll_md_reg = DPLL_MD(intel_crtc->pipe);
-
-       /*
-        * Disable separate mode multiplier used when cloning SDVO to CRT
-        * XXX this needs to be adjusted when we really are cloning
-        */
-       if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
-               dpll_md = I915_READ(dpll_md_reg);
-               I915_WRITE(dpll_md_reg,
-                          dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
-       }
+       u32 adpa;
 
        adpa = ADPA_HOTPLUG_BITS;
        if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
@@ -742,7 +729,7 @@ void intel_crt_init(struct drm_device *dev)
 
        crt->base.type = INTEL_OUTPUT_ANALOG;
        crt->base.cloneable = true;
-       if (IS_HASWELL(dev))
+       if (IS_HASWELL(dev) || IS_I830(dev))
                crt->base.crtc_mask = (1 << 0);
        else
                crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
index 682bd3729baf62369fc66d23434f058a643ffc78..461a637f1ef7d96a21ced8cd31ffd1536a7257a2 100644 (file)
@@ -7892,6 +7892,34 @@ struct intel_quirk {
        void (*hook)(struct drm_device *dev);
 };
 
+/* For systems that don't have a meaningful PCI subdevice/subvendor ID */
+struct intel_dmi_quirk {
+       void (*hook)(struct drm_device *dev);
+       const struct dmi_system_id (*dmi_id_list)[];
+};
+
+static int intel_dmi_reverse_brightness(const struct dmi_system_id *id)
+{
+       DRM_INFO("Backlight polarity reversed on %s\n", id->ident);
+       return 1;
+}
+
+static const struct intel_dmi_quirk intel_dmi_quirks[] = {
+       {
+               .dmi_id_list = &(const struct dmi_system_id[]) {
+                       {
+                               .callback = intel_dmi_reverse_brightness,
+                               .ident = "NCR Corporation",
+                               .matches = {DMI_MATCH(DMI_SYS_VENDOR, "NCR Corporation"),
+                                           DMI_MATCH(DMI_PRODUCT_NAME, ""),
+                               },
+                       },
+                       { }  /* terminating entry */
+               },
+               .hook = quirk_invert_brightness,
+       },
+};
+
 static struct intel_quirk intel_quirks[] = {
        /* HP Mini needs pipe A force quirk (LP: #322104) */
        { 0x27ae, 0x103c, 0x361a, quirk_pipea_force },
@@ -7931,6 +7959,10 @@ static void intel_init_quirks(struct drm_device *dev)
                     q->subsystem_device == PCI_ANY_ID))
                        q->hook(dev);
        }
+       for (i = 0; i < ARRAY_SIZE(intel_dmi_quirks); i++) {
+               if (dmi_check_system(*intel_dmi_quirks[i].dmi_id_list) != 0)
+                       intel_dmi_quirks[i].hook(dev);
+       }
 }
 
 /* Disable the VGA plane that we never use */
index 1b727a5c9ee5680364343be93e15203df42e2369..368ed8ef1600233b6df90f32a591b46ea8fbdf88 100644 (file)
@@ -1797,7 +1797,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                        if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
                                break;
                if (i == intel_dp->lane_count && voltage_tries == 5) {
-                       if (++loop_tries == 5) {
+                       ++loop_tries;
+                       if (loop_tries == 5) {
                                DRM_DEBUG_KMS("too many full retries, give up\n");
                                break;
                        }
@@ -1807,11 +1808,15 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                }
 
                /* Check to see if we've tried the same voltage 5 times */
-               if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) {
-                       voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
-                       voltage_tries = 0;
-               } else
+               if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
                        ++voltage_tries;
+                       if (voltage_tries == 5) {
+                               DRM_DEBUG_KMS("too many voltage retries, give up\n");
+                               break;
+                       }
+               } else
+                       voltage_tries = 0;
+               voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
 
                /* Compute new intel_dp->train_set as requested by target */
                intel_get_adjust_train(intel_dp, link_status);
index e3166df55daad03f4f5c144a5c0558aaa017fec6..edba93b3474b9540a5608f6acbd9eb75f7e53a33 100644 (file)
@@ -777,6 +777,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "D525TUD"),
                },
        },
+       {
+               .callback = intel_no_lvds_dmi_callback,
+               .ident = "Supermicro X7SPA-H",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"),
+               },
+       },
 
        { }     /* terminating entry */
 };
index 495625914e4a084f01f476d93524bed83db7ac42..d7bc817f51a024b803986e76fa492146632da66d 100644 (file)
@@ -341,9 +341,17 @@ static int intel_overlay_off(struct intel_overlay *overlay)
        intel_ring_emit(ring, flip_addr);
        intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
        /* turn overlay off */
-       intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
-       intel_ring_emit(ring, flip_addr);
-       intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+       if (IS_I830(dev)) {
+               /* Workaround: Don't disable the overlay fully, since otherwise
+                * it dies on the next OVERLAY_ON cmd. */
+               intel_ring_emit(ring, MI_NOOP);
+               intel_ring_emit(ring, MI_NOOP);
+               intel_ring_emit(ring, MI_NOOP);
+       } else {
+               intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
+               intel_ring_emit(ring, flip_addr);
+               intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+       }
        intel_ring_advance(ring);
 
        return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail);
index e019b236986128bae46c61bf49180f7ec2502a0d..e2aacd329545a1ff05a68dd4218f571c5208a2aa 100644 (file)
@@ -435,7 +435,7 @@ int intel_panel_setup_backlight(struct drm_device *dev)
        props.type = BACKLIGHT_RAW;
        props.max_brightness = _intel_panel_get_max_backlight(dev);
        if (props.max_brightness == 0) {
-               DRM_ERROR("Failed to get maximum backlight value\n");
+               DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n");
                return -ENODEV;
        }
        dev_priv->backlight =
index 0007a4d9bf6e5248effc509fd25f442b6d4e3164..79d308da29ff8e67cc064b94a31500c0d614a0ad 100644 (file)
@@ -139,6 +139,11 @@ struct intel_sdvo {
 
        /* DDC bus used by this SDVO encoder */
        uint8_t ddc_bus;
+
+       /*
+        * the sdvo flag gets lost in round trip: dtd->adjusted_mode->dtd
+        */
+       uint8_t dtd_sdvo_flags;
 };
 
 struct intel_sdvo_connector {
@@ -889,6 +894,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
 }
 #endif
 
+static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
+                                      unsigned if_index, uint8_t tx_rate,
+                                      uint8_t *data, unsigned length)
+{
+       uint8_t set_buf_index[2] = { if_index, 0 };
+       uint8_t hbuf_size, tmp[8];
+       int i;
+
+       if (!intel_sdvo_set_value(intel_sdvo,
+                                 SDVO_CMD_SET_HBUF_INDEX,
+                                 set_buf_index, 2))
+               return false;
+
+       if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO,
+                                 &hbuf_size, 1))
+               return false;
+
+       /* Buffer size is 0 based, hooray! */
+       hbuf_size++;
+
+       DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n",
+                     if_index, length, hbuf_size);
+
+       for (i = 0; i < hbuf_size; i += 8) {
+               memset(tmp, 0, 8);
+               if (i < length)
+                       memcpy(tmp, data + i, min_t(unsigned, 8, length - i));
+
+               if (!intel_sdvo_set_value(intel_sdvo,
+                                         SDVO_CMD_SET_HBUF_DATA,
+                                         tmp, 8))
+                       return false;
+       }
+
+       return intel_sdvo_set_value(intel_sdvo,
+                                   SDVO_CMD_SET_HBUF_TXRATE,
+                                   &tx_rate, 1);
+}
+
 static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
 {
        struct dip_infoframe avi_if = {
@@ -896,11 +940,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
                .ver = DIP_VERSION_AVI,
                .len = DIP_LEN_AVI,
        };
-       uint8_t tx_rate = SDVO_HBUF_TX_VSYNC;
-       uint8_t set_buf_index[2] = { 1, 0 };
        uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)];
-       uint64_t *data = (uint64_t *)sdvo_data;
-       unsigned i;
 
        intel_dip_infoframe_csum(&avi_if);
 
@@ -910,22 +950,9 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
        sdvo_data[3] = avi_if.checksum;
        memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi));
 
-       if (!intel_sdvo_set_value(intel_sdvo,
-                                 SDVO_CMD_SET_HBUF_INDEX,
-                                 set_buf_index, 2))
-               return false;
-
-       for (i = 0; i < sizeof(sdvo_data); i += 8) {
-               if (!intel_sdvo_set_value(intel_sdvo,
-                                         SDVO_CMD_SET_HBUF_DATA,
-                                         data, 8))
-                       return false;
-               data++;
-       }
-
-       return intel_sdvo_set_value(intel_sdvo,
-                                   SDVO_CMD_SET_HBUF_TXRATE,
-                                   &tx_rate, 1);
+       return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF,
+                                         SDVO_HBUF_TX_VSYNC,
+                                         sdvo_data, sizeof(sdvo_data));
 }
 
 static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo)
@@ -984,6 +1011,7 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo,
                return false;
 
        intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
+       intel_sdvo->dtd_sdvo_flags = input_dtd.part2.sdvo_flags;
 
        return true;
 }
@@ -1092,6 +1120,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
         * adjusted_mode.
         */
        intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
+       if (intel_sdvo->is_tv || intel_sdvo->is_lvds)
+               input_dtd.part2.sdvo_flags = intel_sdvo->dtd_sdvo_flags;
        if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd))
                DRM_INFO("Setting input timings on %s failed\n",
                         SDVO_NAME(intel_sdvo));
@@ -2277,10 +2307,8 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
                intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
        }
 
-       /* SDVO LVDS is cloneable because the SDVO encoder does the upscaling,
-        * as opposed to native LVDS, where we upscale with the panel-fitter
-        * (and hence only the native LVDS resolution could be cloned). */
-       intel_sdvo->base.cloneable = true;
+       /* SDVO LVDS is not cloneable because the input mode gets adjusted by the encoder */
+       intel_sdvo->base.cloneable = false;
 
        intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
        if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
index 9d030142ee43476c89cf2769f0d8c75cf1697daa..770bdd6ecd9fb96b46365bbadd97ba3011c0ef96 100644 (file)
@@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg {
 #define SDVO_CMD_SET_AUDIO_STAT                0x91
 #define SDVO_CMD_GET_AUDIO_STAT                0x92
 #define SDVO_CMD_SET_HBUF_INDEX                0x93
+  #define SDVO_HBUF_INDEX_ELD          0
+  #define SDVO_HBUF_INDEX_AVI_IF       1
 #define SDVO_CMD_GET_HBUF_INDEX                0x94
 #define SDVO_CMD_GET_HBUF_INFO         0x95
 #define SDVO_CMD_SET_HBUF_AV_SPLIT     0x96
index 1f34549aff18748758d4d72feed0eba5800734ab..70586fde69cf48018fd9786ccccacd4eef0900d4 100644 (file)
@@ -39,6 +39,11 @@ nouveau_gpuobj_destroy(struct nouveau_gpuobj *gpuobj)
                        nv_wo32(gpuobj, i, 0x00000000);
        }
 
+       if (gpuobj->node) {
+               nouveau_mm_free(&nv_gpuobj(gpuobj->parent)->heap,
+                               &gpuobj->node);
+       }
+
        if (gpuobj->heap.block_size)
                nouveau_mm_fini(&gpuobj->heap);
 
index bfddf87926dd8857a73df69cb26757836bd02f1f..a6d3cd6490f7fa97f171dff724f73430364af89f 100644 (file)
@@ -218,13 +218,16 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)
        node = kzalloc(sizeof(*node), GFP_KERNEL);
        if (!node)
                return -ENOMEM;
-       node->offset = roundup(offset, mm->block_size);
-       node->length = rounddown(offset + length, mm->block_size) - node->offset;
+
+       if (length) {
+               node->offset  = roundup(offset, mm->block_size);
+               node->length  = rounddown(offset + length, mm->block_size);
+               node->length -= node->offset;
+       }
 
        list_add_tail(&node->nl_entry, &mm->nodes);
        list_add_tail(&node->fl_entry, &mm->free);
        mm->heap_nodes++;
-       mm->heap_size += length;
        return 0;
 }
 
@@ -236,7 +239,7 @@ nouveau_mm_fini(struct nouveau_mm *mm)
        int nodes = 0;
 
        list_for_each_entry(node, &mm->nodes, nl_entry) {
-               if (nodes++ == mm->heap_nodes)
+               if (WARN_ON(nodes++ == mm->heap_nodes))
                        return -EBUSY;
        }
 
index 9ee9bf4028ca168800bc2c6fbcac96346aad9024..975137ba34a6faefb7d4121b8db2efd3464a28c6 100644 (file)
@@ -19,7 +19,6 @@ struct nouveau_mm {
 
        u32 block_size;
        int heap_nodes;
-       u32 heap_size;
 };
 
 int  nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block);
index dcb5c2befc928a716425ace89149cec8a808c2e3..70ca7d5a1aa1aaa4e4302ab599ed5398d4f666eb 100644 (file)
@@ -72,7 +72,7 @@ nouveau_bios_shadow_of(struct nouveau_bios *bios)
        }
 
        data = of_get_property(dn, "NVDA,BMP", &size);
-       if (data) {
+       if (data && size) {
                bios->size = size;
                bios->data = kmalloc(bios->size, GFP_KERNEL);
                if (bios->data)
@@ -104,6 +104,9 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios)
                goto out;
 
        bios->size = nv_rd08(bios, 0x700002) * 512;
+       if (!bios->size)
+               goto out;
+
        bios->data = kmalloc(bios->size, GFP_KERNEL);
        if (bios->data) {
                for (i = 0; i < bios->size; i++)
@@ -155,6 +158,9 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
 
        /* read entire bios image to system memory */
        bios->size = nv_rd08(bios, 0x300002) * 512;
+       if (!bios->size)
+               goto out;
+
        bios->data = kmalloc(bios->size, GFP_KERNEL);
        if (bios->data) {
                for (i = 0; i < bios->size; i++)
@@ -186,14 +192,22 @@ nouveau_bios_shadow_acpi(struct nouveau_bios *bios)
 {
        struct pci_dev *pdev = nv_device(bios)->pdev;
        int ret, cnt, i;
-       u8  data[3];
 
-       if (!nouveau_acpi_rom_supported(pdev))
+       if (!nouveau_acpi_rom_supported(pdev)) {
+               bios->data = NULL;
                return;
+       }
 
        bios->size = 0;
-       if (nouveau_acpi_get_bios_chunk(data, 0, 3) == 3)
-               bios->size = data[2] * 512;
+       bios->data = kmalloc(4096, GFP_KERNEL);
+       if (bios->data) {
+               if (nouveau_acpi_get_bios_chunk(bios->data, 0, 4096) == 4096)
+                       bios->size = bios->data[2] * 512;
+               kfree(bios->data);
+       }
+
+       if (!bios->size)
+               return;
 
        bios->data = kmalloc(bios->size, GFP_KERNEL);
        for (i = 0; bios->data && i < bios->size; i += cnt) {
@@ -229,12 +243,14 @@ nouveau_bios_shadow_pci(struct nouveau_bios *bios)
 static int
 nouveau_bios_score(struct nouveau_bios *bios, const bool writeable)
 {
-       if (!bios->data || bios->data[0] != 0x55 || bios->data[1] != 0xAA) {
+       if (bios->size < 3 || !bios->data || bios->data[0] != 0x55 ||
+                       bios->data[1] != 0xAA) {
                nv_info(bios, "... signature not found\n");
                return 0;
        }
 
-       if (nvbios_checksum(bios->data, bios->data[2] * 512)) {
+       if (nvbios_checksum(bios->data,
+                       min_t(u32, bios->data[2] * 512, bios->size))) {
                nv_info(bios, "... checksum invalid\n");
                /* if a ro image is somewhat bad, it's probably all rubbish */
                return writeable ? 2 : 1;
index 5e5f4cddae3cc7248ed527c07b94e8d0c15e97e4..f835501203e552abb29b68425cb5b0a9b37e6bec 100644 (file)
@@ -157,11 +157,10 @@ pll_map_reg(struct nouveau_bios *bios, u32 reg, u32 *type, u8 *ver, u8 *len)
        while (map->reg) {
                if (map->reg == reg && *ver >= 0x20) {
                        u16 addr = (data += hdr);
+                       *type = map->type;
                        while (cnt--) {
-                               if (nv_ro32(bios, data) == map->reg) {
-                                       *type = map->type;
+                               if (nv_ro32(bios, data) == map->reg)
                                        return data;
-                               }
                                data += *len;
                        }
                        return addr;
@@ -200,11 +199,10 @@ pll_map_type(struct nouveau_bios *bios, u8 type, u32 *reg, u8 *ver, u8 *len)
        while (map->reg) {
                if (map->type == type && *ver >= 0x20) {
                        u16 addr = (data += hdr);
+                       *reg = map->reg;
                        while (cnt--) {
-                               if (nv_ro32(bios, data) == map->reg) {
-                                       *reg = map->reg;
+                               if (nv_ro32(bios, data) == map->reg)
                                        return data;
-                               }
                                data += *len;
                        }
                        return addr;
index 42d7539e65250d239a9e7f8c65efd68855b76c90..5f570806143ad0fb35fcd67017acf07513b563e4 100644 (file)
@@ -219,13 +219,11 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                             ((priv->base.ram.size & 0x000000ff) << 32);
 
        tags = nv_rd32(priv, 0x100320);
-       if (tags) {
-               ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
-               if (ret)
-                       return ret;
+       ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
+       if (ret)
+               return ret;
 
-               nv_debug(priv, "%d compression tags\n", tags);
-       }
+       nv_debug(priv, "%d compression tags\n", tags);
 
        size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;
        switch (device->chipset) {
@@ -237,6 +235,7 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                        return ret;
 
                priv->base.ram.stolen = (u64)nv_rd32(priv, 0x100e10) << 12;
+               priv->base.ram.type = NV_MEM_TYPE_STOLEN;
                break;
        default:
                ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size,
index 3d2c88310f982553380f19a7f89d5379a89a5d01..dbfc2abf0cfe1a98379a567fa8a7a90fcd409d5f 100644 (file)
@@ -292,7 +292,7 @@ nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                case DCB_I2C_NVIO_BIT:
                        port->drive = info.drive & 0x0f;
                        if (device->card_type < NV_D0) {
-                               if (info.drive >= ARRAY_SIZE(nv50_i2c_port))
+                               if (port->drive >= ARRAY_SIZE(nv50_i2c_port))
                                        break;
                                port->drive = nv50_i2c_port[port->drive];
                                port->sense = port->drive;
index 0203e1e12caaad34f4639ec3824a33d770a5d447..49050d991e75a5c3610dfd36982113ca85c0dae3 100644 (file)
@@ -92,7 +92,8 @@ nv41_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv04_vmmgr_priv *priv;
        int ret;
 
-       if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
+       if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) ||
+           !nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
                return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass,
                                           data, size, pobject);
        }
index 0ac18d05a146389b6d87e8c7898188fda5b5c5e3..aa8131436e3dced3d3d9ef894fec6d5ff21cee2d 100644 (file)
@@ -163,7 +163,8 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv04_vmmgr_priv *priv;
        int ret;
 
-       if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
+       if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) ||
+           !nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
                return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass,
                                           data, size, pobject);
        }
index 8f98e5a8c488dba5c8e86d937aa26b5e65d78175..86124b131f4f31a2ca18e8c2416084ad6df1f585 100644 (file)
@@ -290,6 +290,7 @@ nouveau_display_create(struct drm_device *dev)
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_disp *pdisp = nouveau_disp(drm->device);
        struct nouveau_display *disp;
+       u32 pclass = dev->pdev->class >> 8;
        int ret, gen;
 
        disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL);
@@ -360,23 +361,27 @@ nouveau_display_create(struct drm_device *dev)
        drm_kms_helper_poll_init(dev);
        drm_kms_helper_poll_disable(dev);
 
-       if (nv_device(drm->device)->card_type < NV_50)
-               ret = nv04_display_create(dev);
-       else
-       if (nv_device(drm->device)->card_type < NV_D0)
-               ret = nv50_display_create(dev);
-       else
-               ret = nvd0_display_create(dev);
-       if (ret)
-               goto disp_create_err;
-
-       if (dev->mode_config.num_crtc) {
-               ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+       if (nouveau_modeset == 1 ||
+           (nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) {
+               if (nv_device(drm->device)->card_type < NV_50)
+                       ret = nv04_display_create(dev);
+               else
+               if (nv_device(drm->device)->card_type < NV_D0)
+                       ret = nv50_display_create(dev);
+               else
+                       ret = nvd0_display_create(dev);
                if (ret)
-                       goto vblank_err;
+                       goto disp_create_err;
+
+               if (dev->mode_config.num_crtc) {
+                       ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+                       if (ret)
+                               goto vblank_err;
+               }
+
+               nouveau_backlight_init(dev);
        }
 
-       nouveau_backlight_init(dev);
        return 0;
 
 vblank_err:
@@ -395,7 +400,8 @@ nouveau_display_destroy(struct drm_device *dev)
        nouveau_backlight_exit(dev);
        drm_vblank_cleanup(dev);
 
-       disp->dtor(dev);
+       if (disp->dtor)
+               disp->dtor(dev);
 
        drm_kms_helper_poll_fini(dev);
        drm_mode_config_cleanup(dev);
@@ -530,9 +536,11 @@ nouveau_page_flip_reserve(struct nouveau_bo *old_bo,
        if (ret)
                goto fail;
 
-       ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0);
-       if (ret)
-               goto fail_unreserve;
+       if (likely(old_bo != new_bo)) {
+               ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0);
+               if (ret)
+                       goto fail_unreserve;
+       }
 
        return 0;
 
@@ -551,8 +559,10 @@ nouveau_page_flip_unreserve(struct nouveau_bo *old_bo,
        nouveau_bo_fence(new_bo, fence);
        ttm_bo_unreserve(&new_bo->bo);
 
-       nouveau_bo_fence(old_bo, fence);
-       ttm_bo_unreserve(&old_bo->bo);
+       if (likely(old_bo != new_bo)) {
+               nouveau_bo_fence(old_bo, fence);
+               ttm_bo_unreserve(&old_bo->bo);
+       }
 
        nouveau_bo_unpin(old_bo);
 }
index ccae8c26ae2b34ecc25e8312ee6d57c0d14f06e3..0910125cbbc3be3cfa757f0976f3afea8cac6a21 100644 (file)
@@ -63,8 +63,9 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration");
 static int nouveau_noaccel = 0;
 module_param_named(noaccel, nouveau_noaccel, int, 0400);
 
-MODULE_PARM_DESC(modeset, "enable driver");
-static int nouveau_modeset = -1;
+MODULE_PARM_DESC(modeset, "enable driver (default: auto, "
+                         "0 = disabled, 1 = enabled, 2 = headless)");
+int nouveau_modeset = -1;
 module_param_named(modeset, nouveau_modeset, int, 0400);
 
 static struct drm_driver driver;
@@ -363,7 +364,8 @@ nouveau_drm_unload(struct drm_device *dev)
 
        nouveau_pm_fini(dev);
 
-       nouveau_display_fini(dev);
+       if (dev->mode_config.num_crtc)
+               nouveau_display_fini(dev);
        nouveau_display_destroy(dev);
 
        nouveau_irq_fini(dev);
@@ -403,13 +405,15 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
            pm_state.event == PM_EVENT_PRETHAW)
                return 0;
 
-       NV_INFO(drm, "suspending fbcon...\n");
-       nouveau_fbcon_set_suspend(dev, 1);
+       if (dev->mode_config.num_crtc) {
+               NV_INFO(drm, "suspending fbcon...\n");
+               nouveau_fbcon_set_suspend(dev, 1);
 
-       NV_INFO(drm, "suspending display...\n");
-       ret = nouveau_display_suspend(dev);
-       if (ret)
-               return ret;
+               NV_INFO(drm, "suspending display...\n");
+               ret = nouveau_display_suspend(dev);
+               if (ret)
+                       return ret;
+       }
 
        NV_INFO(drm, "evicting buffers...\n");
        ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM);
@@ -445,8 +449,10 @@ fail_client:
                nouveau_client_init(&cli->base);
        }
 
-       NV_INFO(drm, "resuming display...\n");
-       nouveau_display_resume(dev);
+       if (dev->mode_config.num_crtc) {
+               NV_INFO(drm, "resuming display...\n");
+               nouveau_display_resume(dev);
+       }
        return ret;
 }
 
@@ -486,8 +492,10 @@ nouveau_drm_resume(struct pci_dev *pdev)
        nouveau_irq_postinstall(dev);
        nouveau_pm_resume(dev);
 
-       NV_INFO(drm, "resuming display...\n");
-       nouveau_display_resume(dev);
+       if (dev->mode_config.num_crtc) {
+               NV_INFO(drm, "resuming display...\n");
+               nouveau_display_resume(dev);
+       }
        return 0;
 }
 
@@ -662,9 +670,7 @@ nouveau_drm_init(void)
 #ifdef CONFIG_VGA_CONSOLE
                if (vgacon_text_force())
                        nouveau_modeset = 0;
-               else
 #endif
-                       nouveau_modeset = 1;
        }
 
        if (!nouveau_modeset)
index 819471217546b23cb867e3e583ed856d5d810ea2..a10169927086dfea6c826dac0378ae1d2c82ffb3 100644 (file)
@@ -141,4 +141,6 @@ int nouveau_drm_resume(struct pci_dev *);
                nv_info((cli), fmt, ##args);                                   \
 } while (0)
 
+extern int nouveau_modeset;
+
 #endif
index 9ca8afdb5549777c7a2b25e64de9b63f700260bc..1d8cb506a28ae5159ebe4c9df362f3f0d92d7758 100644 (file)
@@ -61,13 +61,15 @@ nouveau_irq_handler(DRM_IRQ_ARGS)
 
        nv_subdev(pmc)->intr(nv_subdev(pmc));
 
-       if (device->card_type >= NV_D0) {
-               if (nv_rd32(device, 0x000100) & 0x04000000)
-                       nvd0_display_intr(dev);
-       } else
-       if (device->card_type >= NV_50) {
-               if (nv_rd32(device, 0x000100) & 0x04000000)
-                       nv50_display_intr(dev);
+       if (dev->mode_config.num_crtc) {
+               if (device->card_type >= NV_D0) {
+                       if (nv_rd32(device, 0x000100) & 0x04000000)
+                               nvd0_display_intr(dev);
+               } else
+               if (device->card_type >= NV_50) {
+                       if (nv_rd32(device, 0x000100) & 0x04000000)
+                               nv50_display_intr(dev);
+               }
        }
 
        return IRQ_HANDLED;
index 347a3bd78d0486f1fed24f11d8183f9382d822dd..64f7020fb605dcaff92163aa161d174ad0d77a23 100644 (file)
@@ -220,7 +220,7 @@ out:
        NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode);
 
        if (blue == 0x18) {
-               NV_INFO(drm, "Load detected on head A\n");
+               NV_DEBUG(drm, "Load detected on head A\n");
                return connector_status_connected;
        }
 
@@ -338,8 +338,8 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
 
        if (nv17_dac_sample_load(encoder) &
            NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
-               NV_INFO(drm, "Load detected on output %c\n",
-                       '@' + ffs(dcb->or));
+               NV_DEBUG(drm, "Load detected on output %c\n",
+                        '@' + ffs(dcb->or));
                return connector_status_connected;
        } else {
                return connector_status_disconnected;
@@ -413,9 +413,9 @@ static void nv04_dac_commit(struct drm_encoder *encoder)
 
        helper->dpms(encoder, DRM_MODE_DPMS_ON);
 
-       NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
-               drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
-               nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
+       NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
+                drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
+                nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 }
 
 void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable)
@@ -461,8 +461,8 @@ static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)
                return;
        nv_encoder->last_dpms = mode;
 
-       NV_INFO(drm, "Setting dpms mode %d on vga encoder (output %d)\n",
-                    mode, nv_encoder->dcb->index);
+       NV_DEBUG(drm, "Setting dpms mode %d on vga encoder (output %d)\n",
+                mode, nv_encoder->dcb->index);
 
        nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
 }
index da55d7642c8cdd325ccca35bd8a1d1b1c1bda8f5..184cdf806761c0bc0cefb52af00a8799ae8e6393 100644 (file)
@@ -476,9 +476,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
 
        helper->dpms(encoder, DRM_MODE_DPMS_ON);
 
-       NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
-               drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
-               nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
+       NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
+                drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
+                nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 }
 
 static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode)
@@ -520,8 +520,8 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode)
                return;
        nv_encoder->last_dpms = mode;
 
-       NV_INFO(drm, "Setting dpms mode %d on lvds encoder (output %d)\n",
-                    mode, nv_encoder->dcb->index);
+       NV_DEBUG(drm, "Setting dpms mode %d on lvds encoder (output %d)\n",
+                mode, nv_encoder->dcb->index);
 
        if (was_powersaving && is_powersaving_dpms(mode))
                return;
@@ -565,8 +565,8 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode)
                return;
        nv_encoder->last_dpms = mode;
 
-       NV_INFO(drm, "Setting dpms mode %d on tmds encoder (output %d)\n",
-                    mode, nv_encoder->dcb->index);
+       NV_DEBUG(drm, "Setting dpms mode %d on tmds encoder (output %d)\n",
+                mode, nv_encoder->dcb->index);
 
        nv04_dfp_update_backlight(encoder, mode);
        nv04_dfp_update_fp_control(encoder, mode);
index 099fbeda6e2e18f85b7dedbc961582516729b50a..62e826a139b3bd4b08d00a0ca46e0efc59c62d63 100644 (file)
@@ -75,8 +75,8 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode)
        struct nv04_mode_state *state = &nv04_display(dev)->mode_reg;
        uint8_t crtc1A;
 
-       NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n",
-               mode, nv_encoder->dcb->index);
+       NV_DEBUG(drm, "Setting dpms mode %d on TV encoder (output %d)\n",
+                mode, nv_encoder->dcb->index);
 
        state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK);
 
@@ -167,9 +167,8 @@ static void nv04_tv_commit(struct drm_encoder *encoder)
 
        helper->dpms(encoder, DRM_MODE_DPMS_ON);
 
-       NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
-                     drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index,
-                     '@' + ffs(nv_encoder->dcb->or));
+       NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
+                drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 }
 
 static void nv04_tv_destroy(struct drm_encoder *encoder)
index 49cbb3795a102e755337a3c2105f03caedc0f2ee..ba498f8e47a211c7bc9a8e749624be6cbd8b395b 100644 (file)
@@ -184,6 +184,7 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
        struct radeon_backlight_privdata *pdata;
        struct radeon_encoder_atom_dig *dig;
        u8 backlight_level;
+       char bl_name[16];
 
        if (!radeon_encoder->enc_priv)
                return;
@@ -203,7 +204,9 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
        memset(&props, 0, sizeof(props));
        props.max_brightness = RADEON_MAX_BL_LEVEL;
        props.type = BACKLIGHT_RAW;
-       bd = backlight_device_register("radeon_bl", &drm_connector->kdev,
+       snprintf(bl_name, sizeof(bl_name),
+                "radeon_bl%d", dev->primary->index);
+       bd = backlight_device_register(bl_name, &drm_connector->kdev,
                                       pdata, &radeon_atom_backlight_ops, &props);
        if (IS_ERR(bd)) {
                DRM_ERROR("Backlight registration failed\n");
index 573ed1bc6cf7d36ffd1a3385cc05350fd7a3d3a0..95e6318b62680652a2b600982dda4d7a39368292 100644 (file)
@@ -264,7 +264,7 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p,
        /* macro tile width & height */
        palign = (8 * surf->bankw * track->npipes) * surf->mtilea;
        halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea;
-       mtileb = (palign / 8) * (halign / 8) * tileb;;
+       mtileb = (palign / 8) * (halign / 8) * tileb;
        mtile_pr = surf->nbx / palign;
        mtile_ps = (mtile_pr * surf->nby) / halign;
        surf->layer_size = mtile_ps * mtileb * slice_pt;
@@ -2829,6 +2829,7 @@ static bool evergreen_vm_reg_valid(u32 reg)
        case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS:
                return true;
        default:
+               DRM_ERROR("Invalid register 0x%x in CS\n", reg);
                return false;
        }
 }
index 8c74c729586db21185e54465d23289a15bc4d979..81e6a568c29debcf49bb915c5d3aa19bcc88324e 100644 (file)
@@ -1538,26 +1538,31 @@ void cayman_vm_set_page(struct radeon_device *rdev, uint64_t pe,
 {
        struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index];
        uint32_t r600_flags = cayman_vm_page_flags(rdev, flags);
-       int i;
 
-       radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, 1 + count * 2));
-       radeon_ring_write(ring, pe);
-       radeon_ring_write(ring, upper_32_bits(pe) & 0xff);
-       for (i = 0; i < count; ++i) {
-               uint64_t value = 0;
-               if (flags & RADEON_VM_PAGE_SYSTEM) {
-                       value = radeon_vm_map_gart(rdev, addr);
-                       value &= 0xFFFFFFFFFFFFF000ULL;
-                       addr += incr;
-
-               } else if (flags & RADEON_VM_PAGE_VALID) {
-                       value = addr;
-                       addr += incr;
-               }
+       while (count) {
+               unsigned ndw = 1 + count * 2;
+               if (ndw > 0x3FFF)
+                       ndw = 0x3FFF;
+
+               radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, ndw));
+               radeon_ring_write(ring, pe);
+               radeon_ring_write(ring, upper_32_bits(pe) & 0xff);
+               for (; ndw > 1; ndw -= 2, --count, pe += 8) {
+                       uint64_t value = 0;
+                       if (flags & RADEON_VM_PAGE_SYSTEM) {
+                               value = radeon_vm_map_gart(rdev, addr);
+                               value &= 0xFFFFFFFFFFFFF000ULL;
+                               addr += incr;
+
+                       } else if (flags & RADEON_VM_PAGE_VALID) {
+                               value = addr;
+                               addr += incr;
+                       }
 
-               value |= r600_flags;
-               radeon_ring_write(ring, value);
-               radeon_ring_write(ring, upper_32_bits(value));
+                       value |= r600_flags;
+                       radeon_ring_write(ring, value);
+                       radeon_ring_write(ring, upper_32_bits(value));
+               }
        }
 }
 
@@ -1586,4 +1591,8 @@ void cayman_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
        /* bits 0-7 are the VM contexts0-7 */
        radeon_ring_write(ring, PACKET0(VM_INVALIDATE_REQUEST, 0));
        radeon_ring_write(ring, 1 << vm->id);
+
+       /* sync PFP to ME, otherwise we might get invalid PFP reads */
+       radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
+       radeon_ring_write(ring, 0x0);
 }
index 2423d1b5d385938f2445706abc97ab74198e1b0f..cbef6815907a13c83efff8b9e863568b1e625980 100644 (file)
 #define        PACKET3_MPEG_INDEX                              0x3A
 #define        PACKET3_WAIT_REG_MEM                            0x3C
 #define        PACKET3_MEM_WRITE                               0x3D
+#define        PACKET3_PFP_SYNC_ME                             0x42
 #define        PACKET3_SURFACE_SYNC                            0x43
 #              define PACKET3_CB0_DEST_BASE_ENA    (1 << 6)
 #              define PACKET3_CB1_DEST_BASE_ENA    (1 << 7)
index 1aa3f910b99328e9f3de367859742bb57722732b..15f5ded65e0c290e431a73d4d2c950c9fd9d2687 100644 (file)
@@ -87,7 +87,7 @@ static union acpi_object *radeon_atpx_call(acpi_handle handle, int function,
                atpx_arg_elements[1].integer.value = 0;
        }
 
-       status = acpi_evaluate_object(handle, "ATPX", &atpx_arg, &buffer);
+       status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer);
 
        /* Fail only if calling the method fails and ATPX is supported */
        if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
@@ -352,9 +352,9 @@ static int radeon_atpx_switchto(enum vga_switcheroo_client_id id)
 }
 
 /**
- * radeon_atpx_switchto - switch to the requested GPU
+ * radeon_atpx_power_state - power down/up the requested GPU
  *
- * @id: GPU to switch to
+ * @id: GPU to power down/up
  * @state: requested power state (0 = off, 1 = on)
  *
  * Execute the necessary ATPX function to power down/up the discrete GPU
@@ -373,11 +373,11 @@ static int radeon_atpx_power_state(enum vga_switcheroo_client_id id,
 }
 
 /**
- * radeon_atpx_pci_probe_handle - look up the ATRM and ATPX handles
+ * radeon_atpx_pci_probe_handle - look up the ATPX handle
  *
  * @pdev: pci device
  *
- * Look up the ATPX and ATRM handles (all asics).
+ * Look up the ATPX handles (all asics).
  * Returns true if the handles are found, false if not.
  */
 static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
index 67cfc1795ecdd4560ac720cc85b0e5a17335a507..b884c362a8c2c0770c02ecb09100d1f9440b55ab 100644 (file)
@@ -941,7 +941,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
        struct drm_mode_object *obj;
        int i;
        enum drm_connector_status ret = connector_status_disconnected;
-       bool dret = false;
+       bool dret = false, broken_edid = false;
 
        if (!force && radeon_check_hpd_status_unchanged(connector))
                return connector->status;
@@ -965,6 +965,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
                                ret = connector_status_disconnected;
                                DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector));
                                radeon_connector->ddc_bus = NULL;
+                       } else {
+                               ret = connector_status_connected;
+                               broken_edid = true; /* defer use_digital to later */
                        }
                } else {
                        radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
@@ -1047,13 +1050,24 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
 
                        encoder_funcs = encoder->helper_private;
                        if (encoder_funcs->detect) {
-                               if (ret != connector_status_connected) {
-                                       ret = encoder_funcs->detect(encoder, connector);
-                                       if (ret == connector_status_connected) {
-                                               radeon_connector->use_digital = false;
+                               if (!broken_edid) {
+                                       if (ret != connector_status_connected) {
+                                               /* deal with analog monitors without DDC */
+                                               ret = encoder_funcs->detect(encoder, connector);
+                                               if (ret == connector_status_connected) {
+                                                       radeon_connector->use_digital = false;
+                                               }
+                                               if (ret != connector_status_disconnected)
+                                                       radeon_connector->detected_by_load = true;
                                        }
-                                       if (ret != connector_status_disconnected)
-                                               radeon_connector->detected_by_load = true;
+                               } else {
+                                       enum drm_connector_status lret;
+                                       /* assume digital unless load detected otherwise */
+                                       radeon_connector->use_digital = true;
+                                       lret = encoder_funcs->detect(encoder, connector);
+                                       DRM_DEBUG_KMS("load_detect %x returned: %x\n",encoder->encoder_type,lret);
+                                       if (lret == connector_status_connected)
+                                               radeon_connector->use_digital = false;
                                }
                                break;
                        }
index bd13ca09eb626efcc2c312ef68569ffcf7655db9..e2f5f888c374cc29b2f8658a5e0ba9d91325827d 100644 (file)
@@ -355,6 +355,8 @@ int radeon_wb_init(struct radeon_device *rdev)
  */
 void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base)
 {
+       uint64_t limit = (uint64_t)radeon_vram_limit << 20;
+
        mc->vram_start = base;
        if (mc->mc_vram_size > (0xFFFFFFFF - base + 1)) {
                dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n");
@@ -368,8 +370,8 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64
                mc->mc_vram_size = mc->aper_size;
        }
        mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
-       if (radeon_vram_limit && radeon_vram_limit < mc->real_vram_size)
-               mc->real_vram_size = radeon_vram_limit;
+       if (limit && limit < mc->real_vram_size)
+               mc->real_vram_size = limit;
        dev_info(rdev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n",
                        mc->mc_vram_size >> 20, mc->vram_start,
                        mc->vram_end, mc->real_vram_size >> 20);
@@ -834,6 +836,19 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state)
                return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
 }
 
+/**
+ * radeon_check_pot_argument - check that argument is a power of two
+ *
+ * @arg: value to check
+ *
+ * Validates that a certain argument is a power of two (all asics).
+ * Returns true if argument is valid.
+ */
+static bool radeon_check_pot_argument(int arg)
+{
+       return (arg & (arg - 1)) == 0;
+}
+
 /**
  * radeon_check_arguments - validate module params
  *
@@ -845,52 +860,25 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state)
 static void radeon_check_arguments(struct radeon_device *rdev)
 {
        /* vramlimit must be a power of two */
-       switch (radeon_vram_limit) {
-       case 0:
-       case 4:
-       case 8:
-       case 16:
-       case 32:
-       case 64:
-       case 128:
-       case 256:
-       case 512:
-       case 1024:
-       case 2048:
-       case 4096:
-               break;
-       default:
+       if (!radeon_check_pot_argument(radeon_vram_limit)) {
                dev_warn(rdev->dev, "vram limit (%d) must be a power of 2\n",
                                radeon_vram_limit);
                radeon_vram_limit = 0;
-               break;
        }
-       radeon_vram_limit = radeon_vram_limit << 20;
+
        /* gtt size must be power of two and greater or equal to 32M */
-       switch (radeon_gart_size) {
-       case 4:
-       case 8:
-       case 16:
+       if (radeon_gart_size < 32) {
                dev_warn(rdev->dev, "gart size (%d) too small forcing to 512M\n",
                                radeon_gart_size);
                radeon_gart_size = 512;
-               break;
-       case 32:
-       case 64:
-       case 128:
-       case 256:
-       case 512:
-       case 1024:
-       case 2048:
-       case 4096:
-               break;
-       default:
+
+       } else if (!radeon_check_pot_argument(radeon_gart_size)) {
                dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n",
                                radeon_gart_size);
                radeon_gart_size = 512;
-               break;
        }
-       rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+       rdev->mc.gtt_size = (uint64_t)radeon_gart_size << 20;
+
        /* AGP mode can only be -1, 1, 2, 4, 8 */
        switch (radeon_agpmode) {
        case -1:
index a7677dd1ce98573121a395643b31a57480e60c76..4debd60e5aa63390f0f386ee236bfc42fe4f8cf3 100644 (file)
@@ -355,14 +355,13 @@ int radeon_gart_init(struct radeon_device *rdev)
        DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n",
                 rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages);
        /* Allocate pages table */
-       rdev->gart.pages = kzalloc(sizeof(void *) * rdev->gart.num_cpu_pages,
-                                  GFP_KERNEL);
+       rdev->gart.pages = vzalloc(sizeof(void *) * rdev->gart.num_cpu_pages);
        if (rdev->gart.pages == NULL) {
                radeon_gart_fini(rdev);
                return -ENOMEM;
        }
-       rdev->gart.pages_addr = kzalloc(sizeof(dma_addr_t) *
-                                       rdev->gart.num_cpu_pages, GFP_KERNEL);
+       rdev->gart.pages_addr = vzalloc(sizeof(dma_addr_t) *
+                                       rdev->gart.num_cpu_pages);
        if (rdev->gart.pages_addr == NULL) {
                radeon_gart_fini(rdev);
                return -ENOMEM;
@@ -388,8 +387,8 @@ void radeon_gart_fini(struct radeon_device *rdev)
                radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages);
        }
        rdev->gart.ready = false;
-       kfree(rdev->gart.pages);
-       kfree(rdev->gart.pages_addr);
+       vfree(rdev->gart.pages);
+       vfree(rdev->gart.pages_addr);
        rdev->gart.pages = NULL;
        rdev->gart.pages_addr = NULL;
 
@@ -577,7 +576,7 @@ void radeon_vm_manager_fini(struct radeon_device *rdev)
  *
  * Global and local mutex must be locked!
  */
-int radeon_vm_evict(struct radeon_device *rdev, struct radeon_vm *vm)
+static int radeon_vm_evict(struct radeon_device *rdev, struct radeon_vm *vm)
 {
        struct radeon_vm *vm_evict;
 
@@ -1036,8 +1035,7 @@ static void radeon_vm_update_ptes(struct radeon_device *rdev,
                pte = radeon_sa_bo_gpu_addr(vm->page_tables[pt_idx]);
                pte += (addr & mask) * 8;
 
-               if (((last_pte + 8 * count) != pte) ||
-                   ((count + nptes) > 1 << 11)) {
+               if ((last_pte + 8 * count) != pte) {
 
                        if (count) {
                                radeon_asic_vm_set_page(rdev, last_pte,
@@ -1148,17 +1146,17 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,
 
        if (RADEON_VM_BLOCK_SIZE > 11)
                /* reserve space for one header for every 2k dwords */
-               ndw += (nptes >> 11) * 3;
+               ndw += (nptes >> 11) * 4;
        else
                /* reserve space for one header for
                    every (1 << BLOCK_SIZE) entries */
-               ndw += (nptes >> RADEON_VM_BLOCK_SIZE) * 3;
+               ndw += (nptes >> RADEON_VM_BLOCK_SIZE) * 4;
 
        /* reserve space for pte addresses */
        ndw += nptes * 2;
 
        /* reserve space for one header for every 2k dwords */
-       ndw += (npdes >> 11) * 3;
+       ndw += (npdes >> 11) * 4;
 
        /* reserve space for pde addresses */
        ndw += npdes * 2;
index f38fbcc469358a2144791d40f910d4d900d99202..fe5c1f6b795795530075939d39c06486ce42d29d 100644 (file)
@@ -53,6 +53,7 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size,
                                struct drm_gem_object **obj)
 {
        struct radeon_bo *robj;
+       unsigned long max_size;
        int r;
 
        *obj = NULL;
@@ -60,11 +61,26 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size,
        if (alignment < PAGE_SIZE) {
                alignment = PAGE_SIZE;
        }
+
+       /* maximun bo size is the minimun btw visible vram and gtt size */
+       max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size);
+       if (size > max_size) {
+               printk(KERN_WARNING "%s:%d alloc size %dMb bigger than %ldMb limit\n",
+                      __func__, __LINE__, size >> 20, max_size >> 20);
+               return -ENOMEM;
+       }
+
+retry:
        r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, NULL, &robj);
        if (r) {
-               if (r != -ERESTARTSYS)
+               if (r != -ERESTARTSYS) {
+                       if (initial_domain == RADEON_GEM_DOMAIN_VRAM) {
+                               initial_domain |= RADEON_GEM_DOMAIN_GTT;
+                               goto retry;
+                       }
                        DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n",
                                  size, initial_domain, alignment, r);
+               }
                return r;
        }
        *obj = &robj->gem_base;
index 5677a424b58535e2bffb0422856e9385182b649c..6857cb4efb768c932f23d4645c3969fd9c792f18 100644 (file)
@@ -295,6 +295,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct radeon_device *rdev = dev->dev_private;
+       uint32_t crtc_ext_cntl = 0;
        uint32_t mask;
 
        if (radeon_crtc->crtc_id)
@@ -307,6 +308,16 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
                        RADEON_CRTC_VSYNC_DIS |
                        RADEON_CRTC_HSYNC_DIS);
 
+       /*
+        * On all dual CRTC GPUs this bit controls the CRTC of the primary DAC.
+        * Therefore it is set in the DAC DMPS function.
+        * This is different for GPU's with a single CRTC but a primary and a
+        * TV DAC: here it controls the single CRTC no matter where it is
+        * routed. Therefore we set it here.
+        */
+       if (rdev->flags & RADEON_SINGLE_CRTC)
+               crtc_ext_cntl = RADEON_CRTC_CRT_ON;
+       
        switch (mode) {
        case DRM_MODE_DPMS_ON:
                radeon_crtc->enabled = true;
@@ -317,7 +328,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
                else {
                        WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN |
                                                                         RADEON_CRTC_DISP_REQ_EN_B));
-                       WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask);
+                       WREG32_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, ~(mask | crtc_ext_cntl));
                }
                drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
                radeon_crtc_load_lut(crtc);
@@ -331,7 +342,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
                else {
                        WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN |
                                                                                    RADEON_CRTC_DISP_REQ_EN_B));
-                       WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask);
+                       WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~(mask | crtc_ext_cntl));
                }
                radeon_crtc->enabled = false;
                /* adjust pm to dpms changes AFTER disabling crtcs */
index a13ad9d707cfcccdab04d085a62d4be0ab3690df..f5ba2241dacc6cfd2bb6b55fead51a7ae2c395e8 100644 (file)
@@ -370,6 +370,7 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
        struct backlight_properties props;
        struct radeon_backlight_privdata *pdata;
        uint8_t backlight_level;
+       char bl_name[16];
 
        if (!radeon_encoder->enc_priv)
                return;
@@ -389,7 +390,9 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
        memset(&props, 0, sizeof(props));
        props.max_brightness = RADEON_MAX_BL_LEVEL;
        props.type = BACKLIGHT_RAW;
-       bd = backlight_device_register("radeon_bl", &drm_connector->kdev,
+       snprintf(bl_name, sizeof(bl_name),
+                "radeon_bl%d", dev->primary->index);
+       bd = backlight_device_register(bl_name, &drm_connector->kdev,
                                       pdata, &radeon_backlight_ops, &props);
        if (IS_ERR(bd)) {
                DRM_ERROR("Backlight registration failed\n");
@@ -534,7 +537,9 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode
                break;
        }
 
-       WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
+       /* handled in radeon_crtc_dpms() */
+       if (!(rdev->flags & RADEON_SINGLE_CRTC))
+               WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
        WREG32(RADEON_DAC_CNTL, dac_cntl);
        WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
 
@@ -659,6 +664,8 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
 
        if (ASIC_IS_R300(rdev))
                tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
+       else if (ASIC_IS_RV100(rdev))
+               tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT);
        else
                tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
 
@@ -668,6 +675,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
        tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
        WREG32(RADEON_DAC_CNTL, tmp);
 
+       tmp = dac_macro_cntl;
        tmp &= ~(RADEON_DAC_PDWN_R |
                 RADEON_DAC_PDWN_G |
                 RADEON_DAC_PDWN_B);
@@ -1089,7 +1097,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
        } else {
                if (is_tv)
                        WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
-               else
+               /* handled in radeon_crtc_dpms() */
+               else if (!(rdev->flags & RADEON_SINGLE_CRTC))
                        WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
                WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
        }
@@ -1413,13 +1422,104 @@ static bool radeon_legacy_tv_detect(struct drm_encoder *encoder,
        return found;
 }
 
+static bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder,
+                                        struct drm_connector *connector)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl;
+       uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c;
+       uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f;
+       uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp;
+       uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid;
+       bool found = false;
+       int i;
+
+       /* save the regs we need */
+       gpio_monid = RREG32(RADEON_GPIO_MONID);
+       fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
+       disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
+       crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+       disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A);
+       disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B);
+       disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C);
+       disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D);
+       disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E);
+       disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F);
+       crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP);
+       crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP);
+       crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID);
+       crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID);
+
+       tmp = RREG32(RADEON_GPIO_MONID);
+       tmp &= ~RADEON_GPIO_A_0;
+       WREG32(RADEON_GPIO_MONID, tmp);
+
+       WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON |
+                                    RADEON_FP2_PANEL_FORMAT |
+                                    R200_FP2_SOURCE_SEL_TRANS_UNIT |
+                                    RADEON_FP2_DVO_EN |
+                                    R200_FP2_DVO_RATE_SEL_SDR));
+
+       WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX |
+                                        RADEON_DISP_TRANS_MATRIX_GRAPHICS));
+
+       WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN |
+                                      RADEON_CRTC2_DISP_REQ_EN_B));
+
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0);
+
+       WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008);
+       WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800);
+       WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001);
+       WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080);
+
+       for (i = 0; i < 200; i++) {
+               tmp = RREG32(RADEON_GPIO_MONID);
+               if (tmp & RADEON_GPIO_Y_0)
+                       found = true;
+
+               if (found)
+                       break;
+
+               if (!drm_can_sleep())
+                       mdelay(1);
+               else
+                       msleep(1);
+       }
+
+       /* restore the regs we used */
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f);
+       WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp);
+       WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp);
+       WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid);
+       WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid);
+       WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+       WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
+       WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
+       WREG32(RADEON_GPIO_MONID, gpio_monid);
+
+       return found;
+}
+
 static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,
                                                             struct drm_connector *connector)
 {
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
-       uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
-       uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp;
+       uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
+       uint32_t gpiopad_a = 0, pixclks_cntl, tmp;
+       uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0;
        enum drm_connector_status found = connector_status_disconnected;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
@@ -1456,12 +1556,27 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
                return connector_status_disconnected;
        }
 
+       /* R200 uses an external DAC for secondary DAC */
+       if (rdev->family == CHIP_R200) {
+               if (radeon_legacy_ext_dac_detect(encoder, connector))
+                       found = connector_status_connected;
+               return found;
+       }
+
        /* save the regs we need */
        pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
-       gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0;
-       disp_output_cntl = ASIC_IS_R300(rdev) ? RREG32(RADEON_DISP_OUTPUT_CNTL) : 0;
-       disp_hw_debug = ASIC_IS_R300(rdev) ? 0 : RREG32(RADEON_DISP_HW_DEBUG);
-       crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+
+       if (rdev->flags & RADEON_SINGLE_CRTC) {
+               crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
+       } else {
+               if (ASIC_IS_R300(rdev)) {
+                       gpiopad_a = RREG32(RADEON_GPIOPAD_A);
+                       disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
+               } else {
+                       disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
+               }
+               crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+       }
        tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
        dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
        dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
@@ -1470,22 +1585,24 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
                               | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
        WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
 
-       if (ASIC_IS_R300(rdev))
-               WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
-
-       tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
-       tmp |= RADEON_CRTC2_CRT2_ON |
-               (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
-
-       WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
-
-       if (ASIC_IS_R300(rdev)) {
-               tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
-               tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
-               WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
+       if (rdev->flags & RADEON_SINGLE_CRTC) {
+               tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
+               WREG32(RADEON_CRTC_EXT_CNTL, tmp);
        } else {
-               tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
-               WREG32(RADEON_DISP_HW_DEBUG, tmp);
+               tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
+               tmp |= RADEON_CRTC2_CRT2_ON |
+                       (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
+               WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
+
+               if (ASIC_IS_R300(rdev)) {
+                       WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
+                       tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
+                       tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
+                       WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
+               } else {
+                       tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
+                       WREG32(RADEON_DISP_HW_DEBUG, tmp);
+               }
        }
 
        tmp = RADEON_TV_DAC_NBLANK |
@@ -1527,14 +1644,19 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
        WREG32(RADEON_DAC_CNTL2, dac_cntl2);
        WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
        WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
-       WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
 
-       if (ASIC_IS_R300(rdev)) {
-               WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
-               WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
+       if (rdev->flags & RADEON_SINGLE_CRTC) {
+               WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
        } else {
-               WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+               WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+               if (ASIC_IS_R300(rdev)) {
+                       WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
+                       WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
+               } else {
+                       WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+               }
        }
+
        WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
 
        return found;
index 8b27dd6e3144566bf9cfcb218f4697cd92dbbb95..b91118ccef867f5b59effd78d0ee93d65a932f8b 100644 (file)
@@ -105,7 +105,6 @@ int radeon_bo_create(struct radeon_device *rdev,
        struct radeon_bo *bo;
        enum ttm_bo_type type;
        unsigned long page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT;
-       unsigned long max_size = 0;
        size_t acc_size;
        int r;
 
@@ -121,18 +120,9 @@ int radeon_bo_create(struct radeon_device *rdev,
        }
        *bo_ptr = NULL;
 
-       /* maximun bo size is the minimun btw visible vram and gtt size */
-       max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size);
-       if ((page_align << PAGE_SHIFT) >= max_size) {
-               printk(KERN_WARNING "%s:%d alloc size %ldM bigger than %ldMb limit\n",
-                       __func__, __LINE__, page_align  >> (20 - PAGE_SHIFT), max_size >> 20);
-               return -ENOMEM;
-       }
-
        acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size,
                                       sizeof(struct radeon_bo));
 
-retry:
        bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);
        if (bo == NULL)
                return -ENOMEM;
@@ -154,15 +144,6 @@ retry:
                        acc_size, sg, &radeon_ttm_bo_destroy);
        up_read(&rdev->pm.mclk_lock);
        if (unlikely(r != 0)) {
-               if (r != -ERESTARTSYS) {
-                       if (domain == RADEON_GEM_DOMAIN_VRAM) {
-                               domain |= RADEON_GEM_DOMAIN_GTT;
-                               goto retry;
-                       }
-                       dev_err(rdev->dev,
-                               "object_init failed for (%lu, 0x%08X)\n",
-                               size, domain);
-               }
                return r;
        }
        *bo_ptr = bo;
index df8dd77016436373dcfcfce4e3fb3e8410a3d873..b0db712060fb3876dfc8f6b92c93acb04bee751a 100644 (file)
@@ -2808,26 +2808,31 @@ void si_vm_set_page(struct radeon_device *rdev, uint64_t pe,
 {
        struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index];
        uint32_t r600_flags = cayman_vm_page_flags(rdev, flags);
-       int i;
-       uint64_t value;
 
-       radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 2 + count * 2));
-       radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
-                                WRITE_DATA_DST_SEL(1)));
-       radeon_ring_write(ring, pe);
-       radeon_ring_write(ring, upper_32_bits(pe));
-       for (i = 0; i < count; ++i) {
-               if (flags & RADEON_VM_PAGE_SYSTEM) {
-                       value = radeon_vm_map_gart(rdev, addr);
-                       value &= 0xFFFFFFFFFFFFF000ULL;
-               } else if (flags & RADEON_VM_PAGE_VALID)
-                       value = addr;
-               else
-                       value = 0;
-               addr += incr;
-               value |= r600_flags;
-               radeon_ring_write(ring, value);
-               radeon_ring_write(ring, upper_32_bits(value));
+       while (count) {
+               unsigned ndw = 2 + count * 2;
+               if (ndw > 0x3FFE)
+                       ndw = 0x3FFE;
+
+               radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, ndw));
+               radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+                                        WRITE_DATA_DST_SEL(1)));
+               radeon_ring_write(ring, pe);
+               radeon_ring_write(ring, upper_32_bits(pe));
+               for (; ndw > 2; ndw -= 2, --count, pe += 8) {
+                       uint64_t value;
+                       if (flags & RADEON_VM_PAGE_SYSTEM) {
+                               value = radeon_vm_map_gart(rdev, addr);
+                               value &= 0xFFFFFFFFFFFFF000ULL;
+                       } else if (flags & RADEON_VM_PAGE_VALID)
+                               value = addr;
+                       else
+                               value = 0;
+                       addr += incr;
+                       value |= r600_flags;
+                       radeon_ring_write(ring, value);
+                       radeon_ring_write(ring, upper_32_bits(value));
+               }
        }
 }
 
@@ -2868,6 +2873,10 @@ void si_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
        radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2);
        radeon_ring_write(ring, 0);
        radeon_ring_write(ring, 1 << vm->id);
+
+       /* sync PFP to ME, otherwise we might get invalid PFP reads */
+       radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
+       radeon_ring_write(ring, 0x0);
 }
 
 /*
index c71d493fd0c54fc184023428bdcbfb286d2d1109..1c350fc4e449715edd5ef997e6eb791722d0f604 100644 (file)
@@ -201,6 +201,8 @@ static int shmob_drm_load(struct drm_device *dev, unsigned long flags)
                goto done;
        }
 
+       platform_set_drvdata(pdev, sdev);
+
 done:
        if (ret)
                shmob_drm_unload(dev);
@@ -299,11 +301,9 @@ static struct drm_driver shmob_drm_driver = {
 #if CONFIG_PM_SLEEP
 static int shmob_drm_pm_suspend(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct drm_device *ddev = platform_get_drvdata(pdev);
-       struct shmob_drm_device *sdev = ddev->dev_private;
+       struct shmob_drm_device *sdev = dev_get_drvdata(dev);
 
-       drm_kms_helper_poll_disable(ddev);
+       drm_kms_helper_poll_disable(sdev->ddev);
        shmob_drm_crtc_suspend(&sdev->crtc);
 
        return 0;
@@ -311,9 +311,7 @@ static int shmob_drm_pm_suspend(struct device *dev)
 
 static int shmob_drm_pm_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct drm_device *ddev = platform_get_drvdata(pdev);
-       struct shmob_drm_device *sdev = ddev->dev_private;
+       struct shmob_drm_device *sdev = dev_get_drvdata(dev);
 
        mutex_lock(&sdev->ddev->mode_config.mutex);
        shmob_drm_crtc_resume(&sdev->crtc);
index 402ab69f9f991c64d149841cc154d6ea86ae9a96..bf6e4b5a73b509a73d06873c213335158b5fff89 100644 (file)
@@ -580,6 +580,7 @@ retry:
        if (unlikely(ret != 0))
                return ret;
 
+retry_reserve:
        spin_lock(&glob->lru_lock);
 
        if (unlikely(list_empty(&bo->ddestroy))) {
@@ -587,14 +588,20 @@ retry:
                return 0;
        }
 
-       ret = ttm_bo_reserve_locked(bo, interruptible,
-                                   no_wait_reserve, false, 0);
+       ret = ttm_bo_reserve_locked(bo, false, true, false, 0);
 
-       if (unlikely(ret != 0)) {
+       if (unlikely(ret == -EBUSY)) {
                spin_unlock(&glob->lru_lock);
-               return ret;
+               if (likely(!no_wait_reserve))
+                       ret = ttm_bo_wait_unreserved(bo, interruptible);
+               if (unlikely(ret != 0))
+                       return ret;
+
+               goto retry_reserve;
        }
 
+       BUG_ON(ret != 0);
+
        /**
         * We can re-check for sync object without taking
         * the bo::lock since setting the sync object requires
@@ -811,17 +818,14 @@ retry:
                                          no_wait_reserve, no_wait_gpu);
                kref_put(&bo->list_kref, ttm_bo_release_list);
 
-               if (likely(ret == 0 || ret == -ERESTARTSYS))
-                       return ret;
-
-               goto retry;
+               return ret;
        }
 
-       ret = ttm_bo_reserve_locked(bo, false, no_wait_reserve, false, 0);
+       ret = ttm_bo_reserve_locked(bo, false, true, false, 0);
 
        if (unlikely(ret == -EBUSY)) {
                spin_unlock(&glob->lru_lock);
-               if (likely(!no_wait_gpu))
+               if (likely(!no_wait_reserve))
                        ret = ttm_bo_wait_unreserved(bo, interruptible);
 
                kref_put(&bo->list_kref, ttm_bo_release_list);
index fccd361f7b50b4e4d4bd072afac3f32869da3da7..87aa5f5d3c88657b8c55055608a65baa271c4c94 100644 (file)
@@ -104,7 +104,7 @@ udl_fb_user_fb_create(struct drm_device *dev,
 
 int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
                     const char *front, char **urb_buf_ptr,
-                    u32 byte_offset, u32 byte_width,
+                    u32 byte_offset, u32 device_byte_offset, u32 byte_width,
                     int *ident_ptr, int *sent_ptr);
 
 int udl_dumb_create(struct drm_file *file_priv,
index 69a2b16f42a60284d2d8eecb8ae1fe01fe8e2ced..d4ab3beaada027825d6182a1330b79bd75d220d4 100644 (file)
@@ -114,9 +114,10 @@ static void udlfb_dpy_deferred_io(struct fb_info *info,
        list_for_each_entry(cur, &fbdefio->pagelist, lru) {
 
                if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8),
-                                 &urb, (char *) info->fix.smem_start,
-                                 &cmd, cur->index << PAGE_SHIFT,
-                                 PAGE_SIZE, &bytes_identical, &bytes_sent))
+                                    &urb, (char *) info->fix.smem_start,
+                                    &cmd, cur->index << PAGE_SHIFT,
+                                    cur->index << PAGE_SHIFT,
+                                    PAGE_SIZE, &bytes_identical, &bytes_sent))
                        goto error;
                bytes_rendered += PAGE_SIZE;
        }
@@ -187,10 +188,11 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
        for (i = y; i < y + height ; i++) {
                const int line_offset = fb->base.pitches[0] * i;
                const int byte_offset = line_offset + (x * bpp);
-
+               const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp);
                if (udl_render_hline(dev, bpp, &urb,
                                     (char *) fb->obj->vmapping,
-                                    &cmd, byte_offset, width * bpp,
+                                    &cmd, byte_offset, dev_byte_offset,
+                                    width * bpp,
                                     &bytes_identical, &bytes_sent))
                        goto error;
        }
index dc095526ffb750124573b9c2a9e472a4bbe82101..142fee5f983f9aa36c8fff99b3ddaf4d4eba78cd 100644 (file)
@@ -213,11 +213,12 @@ static void udl_compress_hline16(
  */
 int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
                     const char *front, char **urb_buf_ptr,
-                    u32 byte_offset, u32 byte_width,
+                    u32 byte_offset, u32 device_byte_offset,
+                    u32 byte_width,
                     int *ident_ptr, int *sent_ptr)
 {
        const u8 *line_start, *line_end, *next_pixel;
-       u32 base16 = 0 + (byte_offset / bpp) * 2;
+       u32 base16 = 0 + (device_byte_offset / bpp) * 2;
        struct urb *urb = *urb_ptr;
        u8 *cmd = *urb_buf_ptr;
        u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;
index 06ebdbb6ea0207f8d92d691d15c00434f4fab21a..fd7722aecf77929eea158263af6cc1b601287408 100644 (file)
@@ -522,6 +522,12 @@ static const struct hid_device_id apple_devices[] = {
                .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
                .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
+               .driver_data = APPLE_HAS_FN },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
+               .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
+               .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
                .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
index bd3971bf31bf7bc4369911a648b02c8729a3004d..f4109fd657ff7a337761f9029969dde8ee71e3cc 100644 (file)
@@ -1532,6 +1532,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
@@ -2139,6 +2142,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
        { }
index 269b50912a4ae9207d1d04f2e014b3c950f20324..9d7a42857ea190a9b9fbc12582582b8ae97ebd2a 100644 (file)
 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI  0x0252
 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO   0x0253
 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS   0x0254
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI  0x0259
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO   0x025a
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS   0x025b
 #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI  0x0249
 #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO   0x024a
 #define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS   0x024b
index 3acdcfcc17df24f696ed7b440f6a29540456e33e..f676c01bb4710e8b786d388fbd453f27d8220a68 100644 (file)
 #define MS_RDESC               0x08
 #define MS_NOGET               0x10
 #define MS_DUPLICATE_USAGES    0x20
+#define MS_RDESC_3K            0x40
 
-/*
- * Microsoft Wireless Desktop Receiver (Model 1028) has
- * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
- */
 static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                unsigned int *rsize)
 {
        unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
 
+       /*
+        * Microsoft Wireless Desktop Receiver (Model 1028) has
+        * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
+        */
        if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 &&
                        rdesc[559] == 0x29) {
                hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");
                rdesc[557] = 0x35;
                rdesc[559] = 0x45;
        }
+       /* the same as above (s/usage/physical/) */
+       if ((quirks & MS_RDESC_3K) && *rsize == 106 &&
+                       !memcmp((char []){ 0x19, 0x00, 0x29, 0xff },
+                               &rdesc[94], 4)) {
+               rdesc[94] = 0x35;
+               rdesc[96] = 0x45;
+       }
        return rdesc;
 }
 
@@ -192,7 +200,7 @@ static const struct hid_device_id ms_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB),
                .driver_data = MS_PRESENTER },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K),
-               .driver_data = MS_ERGONOMY },
+               .driver_data = MS_ERGONOMY | MS_RDESC_3K },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0),
                .driver_data = MS_NOGET },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500),
index 3eb02b94fc87c8a3bc903474db7c3b55efd5ead5..7867d69f0efe1cd734c57e7e4627eb9aaf7a367e 100644 (file)
@@ -210,8 +210,7 @@ static struct mt_class mt_classes[] = {
        },
        { .name = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
                .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
-                       MT_QUIRK_SLOT_IS_CONTACTNUMBER,
-               .maxcontacts = 10
+                       MT_QUIRK_SLOT_IS_CONTACTNUMBER
        },
 
        { .name = MT_CLS_FLATFROG,
@@ -421,11 +420,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                         * contact max are global to the report */
                        td->last_field_index = field->index;
                        return -1;
-               }
                case HID_DG_TOUCH:
                        /* Legacy devices use TIPSWITCH and not TOUCH.
                         * Let's just ignore this field. */
                        return -1;
+               }
                /* let hid-input decide for the others */
                return 0;
 
index 406537420fffdc0b90c008dad53205bd19f2acfe..f4c3d28cd1fcc96ed76720433104aa21bd0b08a6 100644 (file)
@@ -146,14 +146,14 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
        if (ret != 0) {
                err = ret;
-               goto errorout;
+               goto error0;
        }
 
        ret = hv_ringbuffer_init(
                &newchannel->inbound, in, recv_ringbuffer_size);
        if (ret != 0) {
                err = ret;
-               goto errorout;
+               goto error0;
        }
 
 
@@ -168,7 +168,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
        if (ret != 0) {
                err = ret;
-               goto errorout;
+               goto error0;
        }
 
        /* Create and init the channel open message */
@@ -177,7 +177,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
                           GFP_KERNEL);
        if (!open_info) {
                err = -ENOMEM;
-               goto errorout;
+               goto error0;
        }
 
        init_completion(&open_info->waitevent);
@@ -193,7 +193,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
        if (userdatalen > MAX_USER_DEFINED_BYTES) {
                err = -EINVAL;
-               goto errorout;
+               goto error0;
        }
 
        if (userdatalen)
@@ -208,19 +208,18 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
                               sizeof(struct vmbus_channel_open_channel));
 
        if (ret != 0)
-               goto cleanup;
+               goto error1;
 
        t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ);
        if (t == 0) {
                err = -ETIMEDOUT;
-               goto errorout;
+               goto error1;
        }
 
 
        if (open_info->response.open_result.status)
                err = open_info->response.open_result.status;
 
-cleanup:
        spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
        list_del(&open_info->msglistentry);
        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
@@ -228,9 +227,12 @@ cleanup:
        kfree(open_info);
        return err;
 
-errorout:
-       hv_ringbuffer_cleanup(&newchannel->outbound);
-       hv_ringbuffer_cleanup(&newchannel->inbound);
+error1:
+       spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+       list_del(&open_info->msglistentry);
+       spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+error0:
        free_pages((unsigned long)out,
                get_order(send_ringbuffer_size + recv_ringbuffer_size));
        kfree(open_info);
index 68ad7d2555124a45f2d9008374d973d4b6de3b04..4f4110407387fce21c4e58cdc76dfec6093b6183 100644 (file)
@@ -2,7 +2,7 @@
  * fam15h_power.c - AMD Family 15h processor power monitoring
  *
  * Copyright (c) 2011 Advanced Micro Devices, Inc.
- * Author: Andreas Herrmann <andreas.herrmann3@amd.com>
+ * Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
  *
  *
  * This driver is free software; you can redistribute it and/or
@@ -28,7 +28,7 @@
 #include <asm/processor.h>
 
 MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor");
-MODULE_AUTHOR("Andreas Herrmann <andreas.herrmann3@amd.com>");
+MODULE_AUTHOR("Andreas Herrmann <herrmann.der.user@googlemail.com>");
 MODULE_LICENSE("GPL");
 
 /* D18F3 */
index 36509ae32083d2b3e48ec894768c504e1179577c..1381a2e3bbd4dc09dca9e74c87dd4ad2ce5ebc50 100644 (file)
@@ -630,7 +630,9 @@ static struct platform_driver gpio_fan_driver = {
        .driver = {
                .name   = "gpio-fan",
                .pm     = GPIO_FAN_PM,
+#ifdef CONFIG_OF_GPIO
                .of_match_table = of_match_ptr(of_gpio_fan_match),
+#endif
        },
 };
 
index beee6b2d361db458a1336a48bd13b5166d6d013c..1722f50f247385e0247c98e5dee91c97f18203ee 100644 (file)
@@ -8,6 +8,7 @@ obj-$(CONFIG_I2C_SMBUS)         += i2c-smbus.o
 obj-$(CONFIG_I2C_CHARDEV)      += i2c-dev.o
 obj-$(CONFIG_I2C_MUX)          += i2c-mux.o
 obj-y                          += algos/ busses/ muxes/
+obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
 
 ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG
 CFLAGS_i2c-core.o := -Wno-deprecated-declarations
index 65dd599a02620211b8db7a1ef6bfd1d8f9cdda30..e9df4612b7ebc9710db24290b159b4bd77d5d625 100644 (file)
@@ -81,7 +81,6 @@ config I2C_I801
        tristate "Intel 82801 (ICH/PCH)"
        depends on PCI
        select CHECK_SIGNATURE if X86 && DMI
-       select GPIOLIB if I2C_MUX
        help
          If you say yes to this option, support will be included for the Intel
          801 family of mainboard I2C interfaces.  Specifically, the following
index 2d33d62952c112adfb62bde5f08a342a37466c78..395b516ffa08cddbf5fdc2cbc5e2c34a558e356c 100644 (file)
@@ -85,7 +85,6 @@ obj-$(CONFIG_I2C_ACORN)               += i2c-acorn.o
 obj-$(CONFIG_I2C_ELEKTOR)      += i2c-elektor.o
 obj-$(CONFIG_I2C_PCA_ISA)      += i2c-pca-isa.o
 obj-$(CONFIG_I2C_SIBYTE)       += i2c-sibyte.o
-obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
 obj-$(CONFIG_SCx200_ACB)       += scx200_acb.o
 obj-$(CONFIG_SCx200_I2C)       += scx200_i2c.o
 
index 37793156bd936202a10362e7910d88708c4a9248..6abc00d59881c921e14ab460f8bb477995c4ea44 100644 (file)
@@ -82,7 +82,8 @@
 #include <linux/wait.h>
 #include <linux/err.h>
 
-#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
+#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
+               defined CONFIG_DMI
 #include <linux/gpio.h>
 #include <linux/i2c-mux-gpio.h>
 #include <linux/platform_device.h>
@@ -192,7 +193,8 @@ struct i801_priv {
        int len;
        u8 *data;
 
-#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
+#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
+               defined CONFIG_DMI
        const struct i801_mux_config *mux_drvdata;
        struct platform_device *mux_pdev;
 #endif
@@ -921,7 +923,8 @@ static void __init input_apanel_init(void) {}
 static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {}
 #endif /* CONFIG_X86 && CONFIG_DMI */
 
-#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
+#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
+               defined CONFIG_DMI
 static struct i801_mux_config i801_mux_config_asus_z8_d12 = {
        .gpio_chip = "gpio_ich",
        .values = { 0x02, 0x03 },
@@ -1059,7 +1062,7 @@ static unsigned int __devinit i801_get_adapter_class(struct i801_priv *priv)
 
        id = dmi_first_match(mux_dmi_table);
        if (id) {
-               /* Remove from branch classes from trunk */
+               /* Remove branch classes from trunk */
                mux_config = id->driver_data;
                for (i = 0; i < mux_config->n_values; i++)
                        class &= ~mux_config->classes[i];
index 1f58197062cfe120b8987236044afbeec5e397df..286ca191782098fe44f8a9c995b0015e2e3693ef 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Freescale MXS I2C bus driver
  *
- * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K.
+ * Copyright (C) 2011-2012 Wolfram Sang, Pengutronix e.K.
  *
  * based on a (non-working) driver which was:
  *
 
 #define DRIVER_NAME "mxs-i2c"
 
-static bool use_pioqueue;
-module_param(use_pioqueue, bool, 0);
-MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA");
-
 #define MXS_I2C_CTRL0          (0x00)
 #define MXS_I2C_CTRL0_SET      (0x04)
 
@@ -75,23 +71,6 @@ MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA");
                                 MXS_I2C_CTRL1_SLAVE_STOP_IRQ | \
                                 MXS_I2C_CTRL1_SLAVE_IRQ)
 
-#define MXS_I2C_QUEUECTRL      (0x60)
-#define MXS_I2C_QUEUECTRL_SET  (0x64)
-#define MXS_I2C_QUEUECTRL_CLR  (0x68)
-
-#define MXS_I2C_QUEUECTRL_QUEUE_RUN            0x20
-#define MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE       0x04
-
-#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)
-
-#define MXS_I2C_QUEUEDATA      (0x90)
-
-#define MXS_I2C_DATA           (0xa0)
-
 
 #define MXS_CMD_I2C_SELECT     (MXS_I2C_CTRL0_RETAIN_CLOCK |   \
                                 MXS_I2C_CTRL0_PRE_SEND_START | \
@@ -153,7 +132,6 @@ struct mxs_i2c_dev {
        const struct mxs_i2c_speed_config *speed;
 
        /* DMA support components */
-       bool                            dma_mode;
        int                             dma_channel;
        struct dma_chan                 *dmach;
        struct mxs_dma_data             dma_data;
@@ -172,99 +150,6 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
        writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);
 
        writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
-       if (i2c->dma_mode)
-               writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
-                       i2c->regs + MXS_I2C_QUEUECTRL_CLR);
-       else
-               writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
-                       i2c->regs + MXS_I2C_QUEUECTRL_SET);
-}
-
-static void mxs_i2c_pioq_setup_read(struct mxs_i2c_dev *i2c, u8 addr, int len,
-                                       int flags)
-{
-       u32 data;
-
-       writel(MXS_CMD_I2C_SELECT, i2c->regs + MXS_I2C_QUEUECMD);
-
-       data = (addr << 1) | I2C_SMBUS_READ;
-       writel(data, i2c->regs + MXS_I2C_DATA);
-
-       data = MXS_CMD_I2C_READ | MXS_I2C_CTRL0_XFER_COUNT(len) | flags;
-       writel(data, i2c->regs + MXS_I2C_QUEUECMD);
-}
-
-static void mxs_i2c_pioq_setup_write(struct mxs_i2c_dev *i2c,
-                                   u8 addr, u8 *buf, int len, int flags)
-{
-       u32 data;
-       int i, shifts_left;
-
-       data = MXS_CMD_I2C_WRITE | MXS_I2C_CTRL0_XFER_COUNT(len + 1) | flags;
-       writel(data, i2c->regs + MXS_I2C_QUEUECMD);
-
-       /*
-        * We have to copy the slave address (u8) and buffer (arbitrary number
-        * of u8) into the data register (u32). To achieve that, the u8 are put
-        * into the MSBs of 'data' which is then shifted for the next u8. When
-        * appropriate, 'data' is written to MXS_I2C_DATA. So, the first u32
-        * looks like this:
-        *
-        *  3          2          1          0
-        * 10987654|32109876|54321098|76543210
-        * --------+--------+--------+--------
-        * buffer+2|buffer+1|buffer+0|slave_addr
-        */
-
-       data = ((addr << 1) | I2C_SMBUS_WRITE) << 24;
-
-       for (i = 0; i < len; i++) {
-               data >>= 8;
-               data |= buf[i] << 24;
-               if ((i & 3) == 2)
-                       writel(data, i2c->regs + MXS_I2C_DATA);
-       }
-
-       /* Write out the remaining bytes if any */
-       shifts_left = 24 - (i & 3) * 8;
-       if (shifts_left)
-               writel(data >> shifts_left, i2c->regs + MXS_I2C_DATA);
-}
-
-/*
- * TODO: should be replaceable with a waitqueue and RD_QUEUE_IRQ (setting the
- * rd_threshold to 1). Couldn't get this to work, though.
- */
-static int mxs_i2c_wait_for_data(struct mxs_i2c_dev *i2c)
-{
-       unsigned long timeout = jiffies + msecs_to_jiffies(1000);
-
-       while (readl(i2c->regs + MXS_I2C_QUEUESTAT)
-                       & MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY) {
-                       if (time_after(jiffies, timeout))
-                               return -ETIMEDOUT;
-                       cond_resched();
-       }
-
-       return 0;
-}
-
-static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len)
-{
-       u32 uninitialized_var(data);
-       int i;
-
-       for (i = 0; i < len; i++) {
-               if ((i & 3) == 0) {
-                       if (mxs_i2c_wait_for_data(i2c))
-                               return -ETIMEDOUT;
-                       data = readl(i2c->regs + MXS_I2C_QUEUEDATA);
-               }
-               buf[i] = data & 0xff;
-               data >>= 8;
-       }
-
-       return 0;
 }
 
 static void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c)
@@ -432,39 +317,17 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
        init_completion(&i2c->cmd_complete);
        i2c->cmd_err = 0;
 
-       if (i2c->dma_mode) {
-               ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
-               if (ret)
-                       return ret;
-       } else {
-               if (msg->flags & I2C_M_RD) {
-                       mxs_i2c_pioq_setup_read(i2c, msg->addr,
-                                               msg->len, flags);
-               } else {
-                       mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf,
-                                               msg->len, flags);
-               }
-
-               writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
-                       i2c->regs + MXS_I2C_QUEUECTRL_SET);
-       }
+       ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
+       if (ret)
+               return ret;
 
        ret = wait_for_completion_timeout(&i2c->cmd_complete,
                                                msecs_to_jiffies(1000));
        if (ret == 0)
                goto timeout;
 
-       if (!i2c->dma_mode && !i2c->cmd_err && (msg->flags & I2C_M_RD)) {
-               ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len);
-               if (ret)
-                       goto timeout;
-       }
-
        if (i2c->cmd_err == -ENXIO)
                mxs_i2c_reset(i2c);
-       else
-               writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
-                               i2c->regs + MXS_I2C_QUEUECTRL_CLR);
 
        dev_dbg(i2c->dev, "Done with err=%d\n", i2c->cmd_err);
 
@@ -472,8 +335,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
 
 timeout:
        dev_dbg(i2c->dev, "Timeout!\n");
-       if (i2c->dma_mode)
-               mxs_i2c_dma_finish(i2c);
+       mxs_i2c_dma_finish(i2c);
        mxs_i2c_reset(i2c);
        return -ETIMEDOUT;
 }
@@ -502,7 +364,6 @@ 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;
@@ -515,14 +376,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
                /* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */
                i2c->cmd_err = -EIO;
 
-       if (!i2c->dma_mode) {
-               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;
@@ -555,15 +408,6 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
        struct device_node *node = dev->of_node;
        int ret;
 
-       /*
-        * The MXS I2C DMA mode is prefered and enabled by default.
-        * The PIO mode is still supported, but should be used only
-        * for debuging purposes etc.
-        */
-       i2c->dma_mode = !use_pioqueue;
-       if (!i2c->dma_mode)
-               dev_info(dev, "Using PIOQUEUE mode for I2C transfers!\n");
-
        /*
         * TODO: This is a temporary solution and should be changed
         * to use generic DMA binding later when the helpers get in.
@@ -571,8 +415,8 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
        ret = of_property_read_u32(node, "fsl,i2c-dma-channel",
                                   &i2c->dma_channel);
        if (ret) {
-               dev_warn(dev, "Failed to get DMA channel, using PIOQUEUE!\n");
-               i2c->dma_mode = 0;
+               dev_err(dev, "Failed to get DMA channel!\n");
+               return -ENODEV;
        }
 
        ret = of_property_read_u32(node, "clock-frequency", &speed);
@@ -634,15 +478,13 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
        }
 
        /* Setup the DMA */
-       if (i2c->dma_mode) {
-               dma_cap_zero(mask);
-               dma_cap_set(DMA_SLAVE, mask);
-               i2c->dma_data.chan_irq = dmairq;
-               i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
-               if (!i2c->dmach) {
-                       dev_err(dev, "Failed to request dma\n");
-                       return -ENODEV;
-               }
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+       i2c->dma_data.chan_irq = dmairq;
+       i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
+       if (!i2c->dmach) {
+               dev_err(dev, "Failed to request dma\n");
+               return -ENODEV;
        }
 
        platform_set_drvdata(pdev, i2c);
index 698d7acb0f083c10ea2028ad895e58043105f44e..02c3115a2dfa11c0aecf5a5c7e6bc24566539c8b 100644 (file)
@@ -644,7 +644,11 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
 
        pm_runtime_get_sync(&dev->adev->dev);
 
-       clk_enable(dev->clk);
+       status = clk_prepare_enable(dev->clk);
+       if (status) {
+               dev_err(&dev->adev->dev, "can't prepare_enable clock\n");
+               goto out_clk;
+       }
 
        status = init_hw(dev);
        if (status)
@@ -671,7 +675,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
        }
 
 out:
-       clk_disable(dev->clk);
+       clk_disable_unprepare(dev->clk);
+out_clk:
        pm_runtime_put_sync(&dev->adev->dev);
 
        dev->busy = false;
index f981ac4e6783104ee8586e2631fc58f788d49be6..dcea77bf6f50ff2cc1c198e7850bbbe138128238 100644 (file)
@@ -742,7 +742,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
        }
 
        ret = devm_request_irq(&pdev->dev, i2c_dev->irq,
-                       tegra_i2c_isr, 0, pdev->name, i2c_dev);
+                       tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev);
        if (ret) {
                dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
                return ret;
similarity index 75%
rename from drivers/i2c/busses/i2c-stub.c
rename to drivers/i2c/i2c-stub.c
index b1b3447942c9efd42c30ed7a9e271f00268db127..d0a9c590c3cd4708937c924afe9f6759602948f0 100644 (file)
@@ -2,7 +2,7 @@
     i2c-stub.c - I2C/SMBus chip emulator
 
     Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com>
-    Copyright (C) 2007 Jean Delvare <khali@linux-fr.org>
+    Copyright (C) 2007, 2012 Jean Delvare <khali@linux-fr.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -51,8 +51,8 @@ struct stub_chip {
 static struct stub_chip *stub_chips;
 
 /* Return negative errno on error. */
-static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
-       char read_write, u8 command, int size, union i2c_smbus_data * data)
+static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
+       char read_write, u8 command, int size, union i2c_smbus_data *data)
 {
        s32 ret;
        int i, len;
@@ -78,14 +78,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
        case I2C_SMBUS_BYTE:
                if (read_write == I2C_SMBUS_WRITE) {
                        chip->pointer = command;
-                       dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
-                                       "wrote 0x%02x.\n",
-                                       addr, command);
+                       dev_dbg(&adap->dev,
+                               "smbus byte - addr 0x%02x, wrote 0x%02x.\n",
+                               addr, command);
                } else {
                        data->byte = chip->words[chip->pointer++] & 0xff;
-                       dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
-                                       "read  0x%02x.\n",
-                                       addr, data->byte);
+                       dev_dbg(&adap->dev,
+                               "smbus byte - addr 0x%02x, read  0x%02x.\n",
+                               addr, data->byte);
                }
 
                ret = 0;
@@ -95,14 +95,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
                if (read_write == I2C_SMBUS_WRITE) {
                        chip->words[command] &= 0xff00;
                        chip->words[command] |= data->byte;
-                       dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
-                                       "wrote 0x%02x at 0x%02x.\n",
-                                       addr, data->byte, command);
+                       dev_dbg(&adap->dev,
+                               "smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\n",
+                               addr, data->byte, command);
                } else {
                        data->byte = chip->words[command] & 0xff;
-                       dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
-                                       "read  0x%02x at 0x%02x.\n",
-                                       addr, data->byte, command);
+                       dev_dbg(&adap->dev,
+                               "smbus byte data - addr 0x%02x, read  0x%02x at 0x%02x.\n",
+                               addr, data->byte, command);
                }
                chip->pointer = command + 1;
 
@@ -112,14 +112,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
        case I2C_SMBUS_WORD_DATA:
                if (read_write == I2C_SMBUS_WRITE) {
                        chip->words[command] = data->word;
-                       dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, "
-                                       "wrote 0x%04x at 0x%02x.\n",
-                                       addr, data->word, command);
+                       dev_dbg(&adap->dev,
+                               "smbus word data - addr 0x%02x, wrote 0x%04x at 0x%02x.\n",
+                               addr, data->word, command);
                } else {
                        data->word = chip->words[command];
-                       dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, "
-                                       "read  0x%04x at 0x%02x.\n",
-                                       addr, data->word, command);
+                       dev_dbg(&adap->dev,
+                               "smbus word data - addr 0x%02x, read  0x%04x at 0x%02x.\n",
+                               addr, data->word, command);
                }
 
                ret = 0;
@@ -132,17 +132,17 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
                                chip->words[command + i] &= 0xff00;
                                chip->words[command + i] |= data->block[1 + i];
                        }
-                       dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, "
-                                       "wrote %d bytes at 0x%02x.\n",
-                                       addr, len, command);
+                       dev_dbg(&adap->dev,
+                               "i2c block data - addr 0x%02x, wrote %d bytes at 0x%02x.\n",
+                               addr, len, command);
                } else {
                        for (i = 0; i < len; i++) {
                                data->block[1 + i] =
                                        chip->words[command + i] & 0xff;
                        }
-                       dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, "
-                                       "read  %d bytes at 0x%02x.\n",
-                                       addr, len, command);
+                       dev_dbg(&adap->dev,
+                               "i2c block data - addr 0x%02x, read  %d bytes at 0x%02x.\n",
+                               addr, len, command);
                }
 
                ret = 0;
@@ -179,25 +179,24 @@ static int __init i2c_stub_init(void)
        int i, ret;
 
        if (!chip_addr[0]) {
-               printk(KERN_ERR "i2c-stub: Please specify a chip address\n");
+               pr_err("i2c-stub: Please specify a chip address\n");
                return -ENODEV;
        }
 
        for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {
                if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) {
-                       printk(KERN_ERR "i2c-stub: Invalid chip address "
-                              "0x%02x\n", chip_addr[i]);
+                       pr_err("i2c-stub: Invalid chip address 0x%02x\n",
+                              chip_addr[i]);
                        return -EINVAL;
                }
 
-               printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n",
-                      chip_addr[i]);
+               pr_info("i2c-stub: Virtual chip at 0x%02x\n", chip_addr[i]);
        }
 
        /* Allocate memory for all chips at once */
        stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL);
        if (!stub_chips) {
-               printk(KERN_ERR "i2c-stub: Out of memory\n");
+               pr_err("i2c-stub: Out of memory\n");
                return -ENOMEM;
        }
 
@@ -219,4 +218,3 @@ MODULE_LICENSE("GPL");
 
 module_init(i2c_stub_init);
 module_exit(i2c_stub_exit);
-
index 6e3f143fc71d146c786a550162216be2200d0f4f..fc937aca71fbb2f7bb8a53fac55e2ae9b0cec048 100644 (file)
@@ -62,7 +62,6 @@ source "drivers/iio/frequency/Kconfig"
 source "drivers/iio/dac/Kconfig"
 source "drivers/iio/common/Kconfig"
 source "drivers/iio/gyro/Kconfig"
-source "drivers/iio/light/Kconfig"
 source "drivers/iio/magnetometer/Kconfig"
 
 endif # IIO
index f7fa3c0867b4c29026b2821cf793c352972741ce..761f2b65ac52865f4d16a99db3a1f6e7e1b61fbb 100644 (file)
@@ -18,5 +18,4 @@ obj-y += frequency/
 obj-y += dac/
 obj-y += common/
 obj-y += gyro/
-obj-y += light/
 obj-y += magnetometer/
index 57e07c61ace2e8147badfcd87e7f19fa211e4746..afd81790ab3c3e818c73b26fb6856e4f327c133a 100644 (file)
@@ -468,7 +468,7 @@ struct ib_mr *c4iw_register_phys_mem(struct ib_pd *pd,
        ret = alloc_pbl(mhp, npages);
        if (ret) {
                kfree(page_list);
-               goto err_pbl;
+               goto err;
        }
 
        ret = write_pbl(&mhp->rhp->rdev, page_list, mhp->attr.pbl_addr,
index d2fb38d43571d9f5ebba2dbc33e94ff5fc4cf737..2f215b93db6ba5a68b6d7e6fc38d21c91ff0cfa9 100644 (file)
@@ -107,7 +107,7 @@ static __be64 get_cached_alias_guid(struct mlx4_ib_dev *dev, int port, int index
 {
        if (index >= NUM_ALIAS_GUID_PER_PORT) {
                pr_err("%s: ERROR: asked for index:%d\n", __func__, index);
-               return  (__force __be64) ((u64) 0xFFFFFFFFFFFFFFFFUL);
+               return (__force __be64) -1;
        }
        return *(__be64 *)&dev->sriov.demux[port - 1].guid_cache[index];
 }
index 21a794152d15acea2a2e450258f4aaa915bce03a..0a903c129f0a19bfd0175de7aaea382dddec6d88 100644 (file)
@@ -409,38 +409,45 @@ int mlx4_ib_find_real_gid(struct ib_device *ibdev, u8 port, __be64 guid)
 }
 
 
-static int get_pkey_phys_indices(struct mlx4_ib_dev *ibdev, u8 port, u8 ph_pkey_ix,
-                                u8 *full_pk_ix, u8 *partial_pk_ix,
-                                int *is_full_member)
+static int find_slave_port_pkey_ix(struct mlx4_ib_dev *dev, int slave,
+                                  u8 port, u16 pkey, u16 *ix)
 {
-       u16 search_pkey;
-       int fm;
-       int err = 0;
-       u16 pk;
+       int i, ret;
+       u8 unassigned_pkey_ix, pkey_ix, partial_ix = 0xFF;
+       u16 slot_pkey;
 
-       err = ib_get_cached_pkey(&ibdev->ib_dev, port, ph_pkey_ix, &search_pkey);
-       if (err)
-               return err;
+       if (slave == mlx4_master_func_num(dev->dev))
+               return ib_find_cached_pkey(&dev->ib_dev, port, pkey, ix);
 
-       fm = (search_pkey & 0x8000) ? 1 : 0;
-       if (fm) {
-               *full_pk_ix = ph_pkey_ix;
-               search_pkey &= 0x7FFF;
-       } else {
-               *partial_pk_ix = ph_pkey_ix;
-               search_pkey |= 0x8000;
-       }
+       unassigned_pkey_ix = dev->dev->phys_caps.pkey_phys_table_len[port] - 1;
 
-       if (ib_find_exact_cached_pkey(&ibdev->ib_dev, port, search_pkey, &pk))
-               pk = 0xFFFF;
+       for (i = 0; i < dev->dev->caps.pkey_table_len[port]; i++) {
+               if (dev->pkeys.virt2phys_pkey[slave][port - 1][i] == unassigned_pkey_ix)
+                       continue;
 
-       if (fm)
-               *partial_pk_ix = (pk & 0xFF);
-       else
-               *full_pk_ix = (pk & 0xFF);
+               pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][i];
 
-       *is_full_member = fm;
-       return err;
+               ret = ib_get_cached_pkey(&dev->ib_dev, port, pkey_ix, &slot_pkey);
+               if (ret)
+                       continue;
+               if ((slot_pkey & 0x7FFF) == (pkey & 0x7FFF)) {
+                       if (slot_pkey & 0x8000) {
+                               *ix = (u16) pkey_ix;
+                               return 0;
+                       } else {
+                               /* take first partial pkey index found */
+                               if (partial_ix == 0xFF)
+                                       partial_ix = pkey_ix;
+                       }
+               }
+       }
+
+       if (partial_ix < 0xFF) {
+               *ix = (u16) partial_ix;
+               return 0;
+       }
+
+       return -EINVAL;
 }
 
 int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
@@ -458,10 +465,8 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
        unsigned tun_tx_ix = 0;
        int dqpn;
        int ret = 0;
-       int i;
-       int is_full_member = 0;
        u16 tun_pkey_ix;
-       u8 ph_pkey_ix, full_pk_ix = 0, partial_pk_ix = 0;
+       u16 cached_pkey;
 
        if (dest_qpt > IB_QPT_GSI)
                return -EINVAL;
@@ -481,27 +486,17 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
        else
                tun_qp = &tun_ctx->qp[1];
 
-       /* compute pkey index for slave */
-       /* get physical pkey -- virtualized Dom0 pkey to phys*/
+       /* compute P_Key index to put in tunnel header for slave */
        if (dest_qpt) {
-               ph_pkey_ix =
-                       dev->pkeys.virt2phys_pkey[mlx4_master_func_num(dev->dev)][port - 1][wc->pkey_index];
-
-               /* now, translate this to the slave pkey index */
-               ret = get_pkey_phys_indices(dev, port, ph_pkey_ix, &full_pk_ix,
-                                           &partial_pk_ix, &is_full_member);
+               u16 pkey_ix;
+               ret = ib_get_cached_pkey(&dev->ib_dev, port, wc->pkey_index, &cached_pkey);
                if (ret)
                        return -EINVAL;
 
-               for (i = 0; i < dev->dev->caps.pkey_table_len[port]; i++) {
-                       if ((dev->pkeys.virt2phys_pkey[slave][port - 1][i] == full_pk_ix) ||
-                           (is_full_member &&
-                            (dev->pkeys.virt2phys_pkey[slave][port - 1][i] == partial_pk_ix)))
-                               break;
-               }
-               if (i == dev->dev->caps.pkey_table_len[port])
+               ret = find_slave_port_pkey_ix(dev, slave, port, cached_pkey, &pkey_ix);
+               if (ret)
                        return -EINVAL;
-               tun_pkey_ix = i;
+               tun_pkey_ix = pkey_ix;
        } else
                tun_pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][0];
 
index 3c3b54c3fdd93206e60b85c421bc313d952c9655..25b2cdff00f8e4bcd76044e8916b2aa257a7276e 100644 (file)
@@ -233,7 +233,8 @@ static int send_mad_to_slave(int slave, struct mlx4_ib_demux_ctx *ctx,
 
        ib_query_ah(dev->sm_ah[ctx->port - 1], &ah_attr);
 
-       wc.pkey_index = 0;
+       if (ib_find_cached_pkey(&dev->ib_dev, ctx->port, IB_DEFAULT_PKEY_FULL, &wc.pkey_index))
+               return -EINVAL;
        wc.sl = 0;
        wc.dlid_path_bits = 0;
        wc.port_num = ctx->port;
@@ -1074,10 +1075,6 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy
        unsigned long end;
        int count;
 
-       if (ctx->flushing)
-               return;
-
-       ctx->flushing = 1;
        for (i = 0; i < MAX_VFS; ++i)
                clean_vf_mcast(ctx, i);
 
@@ -1107,9 +1104,6 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy
                force_clean_group(group);
        }
        mutex_unlock(&ctx->mcg_table_lock);
-
-       if (!destroy_wq)
-               ctx->flushing = 0;
 }
 
 struct clean_work {
@@ -1123,6 +1117,7 @@ static void mcg_clean_task(struct work_struct *work)
        struct clean_work *cw = container_of(work, struct clean_work, work);
 
        _mlx4_ib_mcg_port_cleanup(cw->ctx, cw->destroy_wq);
+       cw->ctx->flushing = 0;
        kfree(cw);
 }
 
@@ -1130,13 +1125,20 @@ void mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy_wq)
 {
        struct clean_work *work;
 
+       if (ctx->flushing)
+               return;
+
+       ctx->flushing = 1;
+
        if (destroy_wq) {
                _mlx4_ib_mcg_port_cleanup(ctx, destroy_wq);
+               ctx->flushing = 0;
                return;
        }
 
        work = kmalloc(sizeof *work, GFP_KERNEL);
        if (!work) {
+               ctx->flushing = 0;
                mcg_warn("failed allocating work for cleanup\n");
                return;
        }
index 6ae2ac47c9c806ecf5224e2eb02c49a704b40432..f0f8928b3c8a2902295ccfdf4803b43e00f3a0c9 100644 (file)
@@ -292,7 +292,6 @@ static int evdev_release(struct inode *inode, struct file *file)
        kfree(client);
 
        evdev_close_device(evdev);
-       put_device(&evdev->dev);
 
        return 0;
 }
@@ -331,7 +330,6 @@ static int evdev_open(struct inode *inode, struct file *file)
        file->private_data = client;
        nonseekable_open(inode, file);
 
-       get_device(&evdev->dev);
        return 0;
 
  err_free_client:
@@ -1001,6 +999,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
                goto err_free_evdev;
 
        cdev_init(&evdev->cdev, &evdev_fops);
+       evdev->cdev.kobj.parent = &evdev->dev.kobj;
        error = cdev_add(&evdev->cdev, evdev->dev.devt, 1);
        if (error)
                goto err_unregister_handle;
index b62b5891f3999573893c732297ecd0467a094147..f362883c94e37ce828d18938b7d25790135cf2d1 100644 (file)
@@ -243,7 +243,6 @@ static int joydev_release(struct inode *inode, struct file *file)
        kfree(client);
 
        joydev_close_device(joydev);
-       put_device(&joydev->dev);
 
        return 0;
 }
@@ -270,7 +269,6 @@ static int joydev_open(struct inode *inode, struct file *file)
        file->private_data = client;
        nonseekable_open(inode, file);
 
-       get_device(&joydev->dev);
        return 0;
 
  err_free_client:
@@ -858,6 +856,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
                goto err_free_joydev;
 
        cdev_init(&joydev->cdev, &joydev_fops);
+       joydev->cdev.kobj.parent = &joydev->dev.kobj;
        error = cdev_add(&joydev->cdev, joydev->dev.devt, 1);
        if (error)
                goto err_unregister_handle;
index b4b65af8612a3f03a79ea19422873cd777f39b76..de0874054e9faebde97690fdb23986d268cbf95d 100644 (file)
@@ -335,6 +335,7 @@ config KEYBOARD_LOCOMO
 config KEYBOARD_LPC32XX
        tristate "LPC32XX matrix key scanner support"
        depends on ARCH_LPC32XX && OF
+       select INPUT_MATRIXKMAP
        help
          Say Y here if you want to use NXP LPC32XX SoC key scanner interface,
          connected to a key matrix.
index 803ff6fe021ec001393a5a9844dd825cbcb6235d..cad9d5dd597330b2eaa523b046f33edddb3641bb 100644 (file)
@@ -368,6 +368,9 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
        unsigned int mask = 0, direct_key_num = 0;
        unsigned long kpc = 0;
 
+       /* clear pending interrupt bit */
+       keypad_readl(KPC);
+
        /* enable matrix keys with automatic scan */
        if (pdata->matrix_key_rows && pdata->matrix_key_cols) {
                kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL;
index 02ca8680ea5b8f68393cecc3925792fc74236614..6f7d99013031b66f16d2c4e25f06dd3c352a622c 100644 (file)
@@ -311,7 +311,6 @@ static void xenkbd_backend_changed(struct xenbus_device *dev,
        case XenbusStateReconfiguring:
        case XenbusStateReconfigured:
        case XenbusStateUnknown:
-       case XenbusStateClosed:
                break;
 
        case XenbusStateInitWait:
@@ -350,6 +349,10 @@ InitWait:
 
                break;
 
+       case XenbusStateClosed:
+               if (dev->state == XenbusStateClosed)
+                       break;
+               /* Missed the backend's CLOSING state -- fallthrough */
        case XenbusStateClosing:
                xenbus_frontend_closed(dev);
                break;
index 3a78f235fa3e70b8057b929a2c4e2e763141cd9f..2baff1b79a5596eb33eaaaa31577c193d80f099e 100644 (file)
 #define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI   0x0262
 #define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO    0x0263
 #define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS    0x0264
+/* MacbookPro10,2 (unibody, October 2012) */
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI  0x0259
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO   0x025a
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS   0x025b
 
 #define BCM5974_DEVICE(prod) {                                 \
        .match_flags = (USB_DEVICE_ID_MATCH_DEVICE |            \
@@ -137,6 +141,10 @@ static const struct usb_device_id bcm5974_table[] = {
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI),
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ISO),
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
+       /* MacbookPro10,2 */
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
        /* Terminating entry */
        {}
 };
@@ -379,6 +387,19 @@ static const struct bcm5974_config bcm5974_config_table[] = {
                { SN_COORD, -150, 6730 },
                { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
        },
+       {
+               USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI,
+               USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO,
+               USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS,
+               HAS_INTEGRATED_BUTTON,
+               0x84, sizeof(struct bt_data),
+               0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+               { SN_PRESSURE, 0, 300 },
+               { SN_WIDTH, 0, 2048 },
+               { SN_COORD, -4750, 5280 },
+               { SN_COORD, -150, 6730 },
+               { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
+       },
        {}
 };
 
index a1b4c37956b2ef3af055e5c66ccd7753225cabeb..8f02e3d0e712789dc2cccbb0cb52fe40fc0620db 100644 (file)
@@ -523,7 +523,6 @@ static int mousedev_release(struct inode *inode, struct file *file)
        kfree(client);
 
        mousedev_close_device(mousedev);
-       put_device(&mousedev->dev);
 
        return 0;
 }
@@ -558,7 +557,6 @@ static int mousedev_open(struct inode *inode, struct file *file)
        file->private_data = client;
        nonseekable_open(inode, file);
 
-       get_device(&mousedev->dev);
        return 0;
 
  err_free_client:
@@ -892,6 +890,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
        }
 
        cdev_init(&mousedev->cdev, &mousedev_fops);
+       mousedev->cdev.kobj.parent = &mousedev->dev.kobj;
        error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1);
        if (error)
                goto err_unregister_handle;
index 9edf9806cff9db6350e4e25677fb74177364251a..858ad446de91b338553d6577bb6d1ac886c1fbb5 100644 (file)
@@ -391,7 +391,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
                                                        features->pktlen = WACOM_PKGLEN_TPC2FG;
                                                }
 
-                                               if (features->type == MTSCREEN)
+                                               if (features->type == MTSCREEN || features->type == WACOM_24HDT)
                                                        features->pktlen = WACOM_PKGLEN_MTOUCH;
 
                                                if (features->type == BAMBOO_PT) {
@@ -402,6 +402,14 @@ static int wacom_parse_hid(struct usb_interface *intf,
                                                        features->x_max =
                                                                get_unaligned_le16(&report[i + 8]);
                                                        i += 15;
+                                               } else if (features->type == WACOM_24HDT) {
+                                                       features->x_max =
+                                                               get_unaligned_le16(&report[i + 3]);
+                                                       features->x_phy =
+                                                               get_unaligned_le16(&report[i + 8]);
+                                                       features->unit = report[i - 1];
+                                                       features->unitExpo = report[i - 3];
+                                                       i += 12;
                                                } else {
                                                        features->x_max =
                                                                get_unaligned_le16(&report[i + 3]);
@@ -434,6 +442,12 @@ static int wacom_parse_hid(struct usb_interface *intf,
                                                        features->y_phy =
                                                                get_unaligned_le16(&report[i + 6]);
                                                        i += 7;
+                                               } else if (type == WACOM_24HDT) {
+                                                       features->y_max =
+                                                               get_unaligned_le16(&report[i + 3]);
+                                                       features->y_phy =
+                                                               get_unaligned_le16(&report[i - 2]);
+                                                       i += 7;
                                                } else if (type == BAMBOO_PT) {
                                                        features->y_phy =
                                                                get_unaligned_le16(&report[i + 3]);
@@ -541,6 +555,9 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
                        /* MT Tablet PC touch */
                        return wacom_set_device_mode(intf, 3, 4, 4);
                }
+               else if (features->type == WACOM_24HDT) {
+                       return wacom_set_device_mode(intf, 18, 3, 2);
+               }
        } else if (features->device_type == BTN_TOOL_PEN) {
                if (features->type <= BAMBOO_PT && features->type != WIRELESS) {
                        return wacom_set_device_mode(intf, 2, 2, 2);
@@ -613,6 +630,30 @@ struct wacom_usbdev_data {
 static LIST_HEAD(wacom_udev_list);
 static DEFINE_MUTEX(wacom_udev_list_lock);
 
+static struct usb_device *wacom_get_sibling(struct usb_device *dev, int vendor, int product)
+{
+       int port1;
+       struct usb_device *sibling;
+
+       if (vendor == 0 && product == 0)
+               return dev;
+
+       if (dev->parent == NULL)
+               return NULL;
+
+       usb_hub_for_each_child(dev->parent, port1, sibling) {
+               struct usb_device_descriptor *d;
+               if (sibling == NULL)
+                       continue;
+
+               d = &sibling->descriptor;
+               if (d->idVendor == vendor && d->idProduct == product)
+                       return sibling;
+       }
+
+       return NULL;
+}
+
 static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev)
 {
        struct wacom_usbdev_data *data;
@@ -1257,13 +1298,19 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
        strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name));
 
        if (features->quirks & WACOM_QUIRK_MULTI_INPUT) {
+               struct usb_device *other_dev;
+
                /* Append the device type to the name */
                strlcat(wacom_wac->name,
                        features->device_type == BTN_TOOL_PEN ?
                                " Pen" : " Finger",
                        sizeof(wacom_wac->name));
 
-               error = wacom_add_shared_data(wacom_wac, dev);
+
+               other_dev = wacom_get_sibling(dev, features->oVid, features->oPid);
+               if (other_dev == NULL || wacom_get_usbdev_data(other_dev) == NULL)
+                       other_dev = dev;
+               error = wacom_add_shared_data(wacom_wac, other_dev);
                if (error)
                        goto fail3;
        }
index c3468c8dbd891865b0fd2b4a8159f499ea8df1f1..0a67031ffc131a2559d6573d5c3cf65173edd9c6 100644 (file)
@@ -806,6 +806,70 @@ static int find_slot_from_contactid(struct wacom_wac *wacom, int contactid)
        return -1;
 }
 
+static int int_dist(int x1, int y1, int x2, int y2)
+{
+       int x = x2 - x1;
+       int y = y2 - y1;
+
+       return int_sqrt(x*x + y*y);
+}
+
+static int wacom_24hdt_irq(struct wacom_wac *wacom)
+{
+       struct input_dev *input = wacom->input;
+       char *data = wacom->data;
+       int i;
+       int current_num_contacts = data[61];
+       int contacts_to_send = 0;
+
+       /*
+        * First packet resets the counter since only the first
+        * packet in series will have non-zero current_num_contacts.
+        */
+       if (current_num_contacts)
+               wacom->num_contacts_left = current_num_contacts;
+
+       /* There are at most 4 contacts per packet */
+       contacts_to_send = min(4, wacom->num_contacts_left);
+
+       for (i = 0; i < contacts_to_send; i++) {
+               int offset = (WACOM_BYTES_PER_24HDT_PACKET * i) + 1;
+               bool touch = data[offset] & 0x1 && !wacom->shared->stylus_in_proximity;
+               int id = data[offset + 1];
+               int slot = find_slot_from_contactid(wacom, id);
+
+               if (slot < 0)
+                       continue;
+               input_mt_slot(input, slot);
+               input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
+
+               if (touch) {
+                       int t_x = le16_to_cpup((__le16 *)&data[offset + 2]);
+                       int c_x = le16_to_cpup((__le16 *)&data[offset + 4]);
+                       int t_y = le16_to_cpup((__le16 *)&data[offset + 6]);
+                       int c_y = le16_to_cpup((__le16 *)&data[offset + 8]);
+                       int w = le16_to_cpup((__le16 *)&data[offset + 10]);
+                       int h = le16_to_cpup((__le16 *)&data[offset + 12]);
+
+                       input_report_abs(input, ABS_MT_POSITION_X, t_x);
+                       input_report_abs(input, ABS_MT_POSITION_Y, t_y);
+                       input_report_abs(input, ABS_MT_TOUCH_MAJOR, min(w,h));
+                       input_report_abs(input, ABS_MT_WIDTH_MAJOR, min(w, h) + int_dist(t_x, t_y, c_x, c_y));
+                       input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h));
+                       input_report_abs(input, ABS_MT_ORIENTATION, w > h);
+               }
+               wacom->slots[slot] = touch ? id : -1;
+       }
+
+       input_mt_report_pointer_emulation(input, true);
+
+       wacom->num_contacts_left -= contacts_to_send;
+       if (wacom->num_contacts_left <= 0)
+               wacom->num_contacts_left = 0;
+
+       return 1;
+}
+
 static int wacom_mt_touch(struct wacom_wac *wacom)
 {
        struct input_dev *input = wacom->input;
@@ -1255,6 +1319,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
                sync = wacom_intuos_irq(wacom_wac);
                break;
 
+       case WACOM_24HDT:
+               sync = wacom_24hdt_irq(wacom_wac);
+               break;
+
        case INTUOS5S:
        case INTUOS5:
        case INTUOS5L:
@@ -1340,7 +1408,8 @@ void wacom_setup_device_quirks(struct wacom_features *features)
 
        /* these device have multiple inputs */
        if (features->type >= WIRELESS ||
-           (features->type >= INTUOS5S && features->type <= INTUOS5L))
+           (features->type >= INTUOS5S && features->type <= INTUOS5L) ||
+           (features->oVid && features->oPid))
                features->quirks |= WACOM_QUIRK_MULTI_INPUT;
 
        /* quirk for bamboo touch with 2 low res touches */
@@ -1449,6 +1518,9 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
 
                input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
                input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
+
+               __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
                wacom_setup_cintiq(wacom_wac);
                break;
 
@@ -1575,6 +1647,15 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
                __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
                break;
 
+       case WACOM_24HDT:
+               if (features->device_type == BTN_TOOL_FINGER) {
+                       input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0);
+                       input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, features->x_max, 0, 0);
+                       input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, 0, features->y_max, 0, 0);
+                       input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
+               }
+               /* fall through */
+
        case MTSCREEN:
                if (features->device_type == BTN_TOOL_FINGER) {
                        wacom_wac->slots = kmalloc(features->touch_max *
@@ -1869,8 +1950,11 @@ static const struct wacom_features wacom_features_0xF4 =
        { "Wacom Cintiq 24HD",       WACOM_PKGLEN_INTUOS,   104480, 65600, 2047,
          63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xF8 =
-       { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS,   104480, 65600, 2047,
-         63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+       { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS,   104480, 65600, 2047, /* Pen */
+         63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 };
+static const struct wacom_features wacom_features_0xF6 =
+       { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */
+         .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10 };
 static const struct wacom_features wacom_features_0x3F =
        { "Wacom Cintiq 21UX",    WACOM_PKGLEN_INTUOS,    87200, 65600, 1023,
          63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
@@ -2113,6 +2197,7 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0x47) },
        { USB_DEVICE_WACOM(0xF4) },
        { USB_DEVICE_WACOM(0xF8) },
+       { USB_DEVICE_WACOM(0xF6) },
        { USB_DEVICE_WACOM(0xFA) },
        { USB_DEVICE_LENOVO(0x6004) },
        { }
index 96c185cc301eb95bf062440e59c49114458c0028..345f1e76975ef76ef6b251ae772a7c2b807c21ff 100644 (file)
@@ -29,6 +29,7 @@
 
 /* wacom data size per MT contact */
 #define WACOM_BYTES_PER_MT_PACKET      11
+#define WACOM_BYTES_PER_24HDT_PACKET   14
 
 /* device IDs */
 #define STYLUS_DEVICE_ID       0x02
@@ -49,6 +50,7 @@
 #define WACOM_REPORT_TPCHID            15
 #define WACOM_REPORT_TPCST             16
 #define WACOM_REPORT_TPC1FGE           18
+#define WACOM_REPORT_24HDT             1
 
 /* device quirks */
 #define WACOM_QUIRK_MULTI_INPUT                0x0001
@@ -81,6 +83,7 @@ enum {
        WACOM_MO,
        WIRELESS,
        BAMBOO_PT,
+       WACOM_24HDT,
        TABLETPC,   /* add new TPC below */
        TABLETPCE,
        TABLETPC2FG,
@@ -109,6 +112,8 @@ struct wacom_features {
        int distance_fuzz;
        unsigned quirks;
        unsigned touch_max;
+       int oVid;
+       int oPid;
 };
 
 struct wacom_shared {
index 1ba232cbc09d4e8744e1a827c3939ad7292e85a6..f7668b24c378aeed3b4ca4fc1c09d025255eccc1 100644 (file)
@@ -239,7 +239,7 @@ config TOUCHSCREEN_EETI
 
 config TOUCHSCREEN_EGALAX
        tristate "EETI eGalax multi-touch panel support"
-       depends on I2C
+       depends on I2C && OF
        help
          Say Y here to enable support for I2C connected EETI
          eGalax multi-touch panels.
index c1e3460f1195aed3953c0e09542c9718d8664421..13fa62fdfb0b4160f76484bd2aadc92151597ab8 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/bitops.h>
 #include <linux/input/mt.h>
+#include <linux/of_gpio.h>
 
 /*
  * Mouse Mode: some panel may configure the controller to mouse mode,
@@ -122,9 +123,17 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
 /* wake up controller by an falling edge of interrupt gpio.  */
 static int egalax_wake_up_device(struct i2c_client *client)
 {
-       int gpio = irq_to_gpio(client->irq);
+       struct device_node *np = client->dev.of_node;
+       int gpio;
        int ret;
 
+       if (!np)
+               return -ENODEV;
+
+       gpio = of_get_named_gpio(np, "wakeup-gpios", 0);
+       if (!gpio_is_valid(gpio))
+               return -ENODEV;
+
        ret = gpio_request(gpio, "egalax_irq");
        if (ret < 0) {
                dev_err(&client->dev,
@@ -181,7 +190,11 @@ static int __devinit egalax_ts_probe(struct i2c_client *client,
        ts->input_dev = input_dev;
 
        /* controller may be in sleep, wake it up. */
-       egalax_wake_up_device(client);
+       error = egalax_wake_up_device(client);
+       if (error) {
+               dev_err(&client->dev, "Failed to wake up the controller\n");
+               goto err_free_dev;
+       }
 
        ret = egalax_firmware_version(client);
        if (ret < 0) {
@@ -274,11 +287,17 @@ static int egalax_ts_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(egalax_ts_pm_ops, egalax_ts_suspend, egalax_ts_resume);
 
+static struct of_device_id egalax_ts_dt_ids[] = {
+       { .compatible = "eeti,egalax_ts" },
+       { /* sentinel */ }
+};
+
 static struct i2c_driver egalax_ts_driver = {
        .driver = {
                .name   = "egalax_ts",
                .owner  = THIS_MODULE,
                .pm     = &egalax_ts_pm_ops,
+               .of_match_table = of_match_ptr(egalax_ts_dt_ids),
        },
        .id_table       = egalax_ts_id,
        .probe          = egalax_ts_probe,
index 63209aaa55f01f1baf65a8a1632c8c2ce4056870..eb96f168fb9d53c68032c172faec9d2652dcfa70 100644 (file)
@@ -107,7 +107,6 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv)
        __set_bit(BTN_TOUCH, input_dev->keybit);
        input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0);
        input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0);
-       input_set_abs_params(ptsc->dev, ABS_PRESSURE, 0, 0, 0, 0);
 
        serio_set_drvdata(serio, ptsc);
 
index 18b0d99bd4d6686b3727f83896769d0a116dcf1f..81837b0710a9ba0240b1eba3c1b3f8b51d997e2f 100644 (file)
@@ -1599,21 +1599,46 @@ static void __init free_on_init_error(void)
 #endif
 }
 
+/* SB IOAPIC is always on this device in AMD systems */
+#define IOAPIC_SB_DEVID                ((0x00 << 8) | PCI_DEVFN(0x14, 0))
+
 static bool __init check_ioapic_information(void)
 {
+       bool ret, has_sb_ioapic;
        int idx;
 
-       for (idx = 0; idx < nr_ioapics; idx++) {
-               int id = mpc_ioapic_id(idx);
+       has_sb_ioapic = false;
+       ret           = false;
 
-               if (get_ioapic_devid(id) < 0) {
-                       pr_err(FW_BUG "AMD-Vi: IO-APIC[%d] not in IVRS table\n", id);
-                       pr_err("AMD-Vi: Disabling interrupt remapping due to BIOS Bug\n");
-                       return false;
+       for (idx = 0; idx < nr_ioapics; idx++) {
+               int devid, id = mpc_ioapic_id(idx);
+
+               devid = get_ioapic_devid(id);
+               if (devid < 0) {
+                       pr_err(FW_BUG "AMD-Vi: IOAPIC[%d] not in IVRS table\n", id);
+                       ret = false;
+               } else if (devid == IOAPIC_SB_DEVID) {
+                       has_sb_ioapic = true;
+                       ret           = true;
                }
        }
 
-       return true;
+       if (!has_sb_ioapic) {
+               /*
+                * We expect the SB IOAPIC to be listed in the IVRS
+                * table. The system timer is connected to the SB IOAPIC
+                * and if we don't have it in the list the system will
+                * panic at boot time.  This situation usually happens
+                * when the BIOS is buggy and provides us the wrong
+                * device id for the IOAPIC in the system.
+                */
+               pr_err(FW_BUG "AMD-Vi: No southbridge IOAPIC found in IVRS table\n");
+       }
+
+       if (!ret)
+               pr_err("AMD-Vi: Disabling interrupt remapping due to BIOS Bug(s)\n");
+
+       return ret;
 }
 
 static void __init free_dma_resources(void)
index 0b4d62e0c64573cea96dc38f237436a036aa74cf..a649f146d17bad0b62d15a1d174c57147a9a2a2f 100644 (file)
@@ -200,7 +200,7 @@ enum {
 
 #define SMMU_ADDR_TO_PFN(addr) ((addr) >> 12)
 #define SMMU_ADDR_TO_PDN(addr) ((addr) >> 22)
-#define SMMU_PDN_TO_ADDR(addr) ((pdn) << 22)
+#define SMMU_PDN_TO_ADDR(pdn)  ((pdn) << 22)
 
 #define _READABLE      (1 << SMMU_PTB_DATA_ASID_READABLE_SHIFT)
 #define _WRITABLE      (1 << SMMU_PTB_DATA_ASID_WRITABLE_SHIFT)
index 5275887089483b6b8ff8ffdc1e9fad46ac1f81fb..c44950d3eb7b48f8a81fd16db9e46ecd15343a39 100644 (file)
@@ -617,7 +617,13 @@ static void int_in_work(struct work_struct *work)
        if (rc == 0)
                /* success, resubmit interrupt read URB */
                rc = usb_submit_urb(urb, GFP_ATOMIC);
-       if (rc != 0 && rc != -ENODEV) {
+
+       switch (rc) {
+       case 0:         /* success */
+       case -ENODEV:   /* device gone */
+       case -EINVAL:   /* URB already resubmitted, or terminal badness */
+               break;
+       default:        /* failure: try to recover by resetting the device */
                dev_err(cs->dev, "clear halt failed: %s\n", get_usb_rcmsg(rc));
                rc = usb_lock_device_for_reset(ucs->udev, ucs->interface);
                if (rc == 0) {
@@ -2442,7 +2448,9 @@ static void gigaset_disconnect(struct usb_interface *interface)
 }
 
 /* gigaset_suspend
- * This function is called before the USB connection is suspended.
+ * This function is called before the USB connection is suspended
+ * or before the USB device is reset.
+ * In the latter case, message == PMSG_ON.
  */
 static int gigaset_suspend(struct usb_interface *intf, pm_message_t message)
 {
@@ -2498,7 +2506,12 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message)
        del_timer_sync(&ucs->timer_atrdy);
        del_timer_sync(&ucs->timer_cmd_in);
        del_timer_sync(&ucs->timer_int_in);
-       cancel_work_sync(&ucs->int_in_wq);
+
+       /* don't try to cancel int_in_wq from within reset as it
+        * might be the one requesting the reset
+        */
+       if (message.event != PM_EVENT_ON)
+               cancel_work_sync(&ucs->int_in_wq);
 
        gig_dbg(DEBUG_SUSPEND, "suspend complete");
        return 0;
index 45135f69509c89e83b6cc7190f1f25972ae28076..5e7dc772f5deca223ea9142d073cc66785f54b27 100644 (file)
@@ -315,8 +315,11 @@ static int run(struct mddev *mddev)
        }
        conf->nfaults = 0;
 
-       rdev_for_each(rdev, mddev)
+       rdev_for_each(rdev, mddev) {
                conf->rdev = rdev;
+               disk_stack_limits(mddev->gendisk, rdev->bdev,
+                                 rdev->data_offset << 9);
+       }
 
        md_set_array_sectors(mddev, faulty_size(mddev, 0, 0));
        mddev->private = conf;
index 8034fbd6190ce647ec2feb6a281e4bb32b406f8e..636bae0405e8167edcec328e5759b3f949dd0876 100644 (file)
@@ -2710,7 +2710,7 @@ static struct r1conf *setup_conf(struct mddev *mddev)
                    || disk_idx < 0)
                        continue;
                if (test_bit(Replacement, &rdev->flags))
-                       disk = conf->mirrors + conf->raid_disks + disk_idx;
+                       disk = conf->mirrors + mddev->raid_disks + disk_idx;
                else
                        disk = conf->mirrors + disk_idx;
 
index 906ccbd0f7dcdc6710869c5b990f9375d020d370..d1295aff41739eea048f0e43513dfba6ade4c8f1 100644 (file)
@@ -1783,7 +1783,7 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
                clear_bit(Unmerged, &rdev->flags);
        }
        md_integrity_add_rdev(rdev, mddev);
-       if (blk_queue_discard(bdev_get_queue(rdev->bdev)))
+       if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))
                queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
 
        print_conf(conf);
@@ -3613,11 +3613,14 @@ static int run(struct mddev *mddev)
                        discard_supported = true;
        }
 
-       if (discard_supported)
-               queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
-       else
-               queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
-
+       if (mddev->queue) {
+               if (discard_supported)
+                       queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,
+                                               mddev->queue);
+               else
+                       queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD,
+                                                 mddev->queue);
+       }
        /* need to check that every block has at least one working mirror */
        if (!enough(conf, -1)) {
                printk(KERN_ERR "md/raid10:%s: not enough operational mirrors.\n",
index 5bb1877810749da2581aff03c6d7d50c18b875c3..a769719e36bf534df4cc718efe4771a736da947f 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 
+#include <linux/of.h>
+
 /* Serialize access to ssc_list and user count */
 static DEFINE_SPINLOCK(user_lock);
 static LIST_HEAD(ssc_list);
@@ -29,7 +31,13 @@ struct ssc_device *ssc_request(unsigned int ssc_num)
 
        spin_lock(&user_lock);
        list_for_each_entry(ssc, &ssc_list, list) {
-               if (ssc->pdev->id == ssc_num) {
+               if (ssc->pdev->dev.of_node) {
+                       if (of_alias_get_id(ssc->pdev->dev.of_node, "ssc")
+                               == ssc_num) {
+                               ssc_valid = 1;
+                               break;
+                       }
+               } else if (ssc->pdev->id == ssc_num) {
                        ssc_valid = 1;
                        break;
                }
@@ -68,39 +76,91 @@ void ssc_free(struct ssc_device *ssc)
 }
 EXPORT_SYMBOL(ssc_free);
 
-static int __init ssc_probe(struct platform_device *pdev)
+static struct atmel_ssc_platform_data at91rm9200_config = {
+       .use_dma = 0,
+};
+
+static struct atmel_ssc_platform_data at91sam9g45_config = {
+       .use_dma = 1,
+};
+
+static const struct platform_device_id atmel_ssc_devtypes[] = {
+       {
+               .name = "at91rm9200_ssc",
+               .driver_data = (unsigned long) &at91rm9200_config,
+       }, {
+               .name = "at91sam9g45_ssc",
+               .driver_data = (unsigned long) &at91sam9g45_config,
+       }, {
+               /* sentinel */
+       }
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id atmel_ssc_dt_ids[] = {
+       {
+               .compatible = "atmel,at91rm9200-ssc",
+               .data = &at91rm9200_config,
+       }, {
+               .compatible = "atmel,at91sam9g45-ssc",
+               .data = &at91sam9g45_config,
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(of, atmel_ssc_dt_ids);
+#endif
+
+static inline const struct atmel_ssc_platform_data * __init
+       atmel_ssc_get_driver_data(struct platform_device *pdev)
+{
+       if (pdev->dev.of_node) {
+               const struct of_device_id *match;
+               match = of_match_node(atmel_ssc_dt_ids, pdev->dev.of_node);
+               if (match == NULL)
+                       return NULL;
+               return match->data;
+       }
+
+       return (struct atmel_ssc_platform_data *)
+               platform_get_device_id(pdev)->driver_data;
+}
+
+static int ssc_probe(struct platform_device *pdev)
 {
-       int retval = 0;
        struct resource *regs;
        struct ssc_device *ssc;
+       const struct atmel_ssc_platform_data *plat_dat;
 
-       ssc = kzalloc(sizeof(struct ssc_device), GFP_KERNEL);
+       ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
        if (!ssc) {
                dev_dbg(&pdev->dev, "out of memory\n");
-               retval = -ENOMEM;
-               goto out;
+               return -ENOMEM;
        }
 
+       ssc->pdev = pdev;
+
+       plat_dat = atmel_ssc_get_driver_data(pdev);
+       if (!plat_dat)
+               return -ENODEV;
+       ssc->pdata = (struct atmel_ssc_platform_data *)plat_dat;
+
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!regs) {
                dev_dbg(&pdev->dev, "no mmio resource defined\n");
-               retval = -ENXIO;
-               goto out_free;
+               return -ENXIO;
        }
 
-       ssc->clk = clk_get(&pdev->dev, "pclk");
-       if (IS_ERR(ssc->clk)) {
-               dev_dbg(&pdev->dev, "no pclk clock defined\n");
-               retval = -ENXIO;
-               goto out_free;
-       }
-
-       ssc->pdev = pdev;
-       ssc->regs = ioremap(regs->start, resource_size(regs));
+       ssc->regs = devm_request_and_ioremap(&pdev->dev, regs);
        if (!ssc->regs) {
                dev_dbg(&pdev->dev, "ioremap failed\n");
-               retval = -EINVAL;
-               goto out_clk;
+               return -EINVAL;
+       }
+
+       ssc->clk = devm_clk_get(&pdev->dev, "pclk");
+       if (IS_ERR(ssc->clk)) {
+               dev_dbg(&pdev->dev, "no pclk clock defined\n");
+               return -ENXIO;
        }
 
        /* disable all interrupts */
@@ -112,8 +172,7 @@ static int __init ssc_probe(struct platform_device *pdev)
        ssc->irq = platform_get_irq(pdev, 0);
        if (!ssc->irq) {
                dev_dbg(&pdev->dev, "could not get irq\n");
-               retval = -ENXIO;
-               goto out_unmap;
+               return -ENXIO;
        }
 
        spin_lock(&user_lock);
@@ -125,16 +184,7 @@ static int __init ssc_probe(struct platform_device *pdev)
        dev_info(&pdev->dev, "Atmel SSC device at 0x%p (irq %d)\n",
                        ssc->regs, ssc->irq);
 
-       goto out;
-
-out_unmap:
-       iounmap(ssc->regs);
-out_clk:
-       clk_put(ssc->clk);
-out_free:
-       kfree(ssc);
-out:
-       return retval;
+       return 0;
 }
 
 static int __devexit ssc_remove(struct platform_device *pdev)
@@ -142,34 +192,23 @@ static int __devexit ssc_remove(struct platform_device *pdev)
        struct ssc_device *ssc = platform_get_drvdata(pdev);
 
        spin_lock(&user_lock);
-       iounmap(ssc->regs);
-       clk_put(ssc->clk);
        list_del(&ssc->list);
-       kfree(ssc);
        spin_unlock(&user_lock);
 
        return 0;
 }
 
 static struct platform_driver ssc_driver = {
-       .remove         = __devexit_p(ssc_remove),
        .driver         = {
                .name           = "ssc",
                .owner          = THIS_MODULE,
+               .of_match_table = of_match_ptr(atmel_ssc_dt_ids),
        },
+       .id_table       = atmel_ssc_devtypes,
+       .probe          = ssc_probe,
+       .remove         = __devexit_p(ssc_remove),
 };
-
-static int __init ssc_init(void)
-{
-       return platform_driver_probe(&ssc_driver, ssc_probe);
-}
-module_init(ssc_init);
-
-static void __exit ssc_exit(void)
-{
-       platform_driver_unregister(&ssc_driver);
-}
-module_exit(ssc_exit);
+module_platform_driver(ssc_driver);
 
 MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
 MODULE_DESCRIPTION("SSC driver for Atmel AVR32 and AT91");
index dc15d248443fd833ae17199a41f28ab6712b5d5c..ef8d2a080d17f4c61b8f28aa7e07bc54ed5c0abc 100644 (file)
@@ -1060,7 +1060,7 @@ static ssize_t bonding_store_primary(struct device *d,
                goto out;
        }
 
-       sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
+       sscanf(buf, "%15s", ifname); /* IFNAMSIZ */
 
        /* check to see if we are clearing primary */
        if (!strlen(ifname) || buf[0] == '\n') {
@@ -1237,7 +1237,7 @@ static ssize_t bonding_store_active_slave(struct device *d,
                goto out;
        }
 
-       sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
+       sscanf(buf, "%15s", ifname); /* IFNAMSIZ */
 
        /* check to see if we are clearing active */
        if (!strlen(ifname) || buf[0] == '\n') {
index c78ecfca1e4582b8e57a2a42a2e14152f3640483..a412bf6d73ef6b0464f5441c85df94c3ab6b4f15 100644 (file)
 
 #define FLEXCAN_MB_CODE_MASK           (0xf0ffffff)
 
-/* FLEXCAN hardware feature flags */
+/*
+ * FLEXCAN hardware feature flags
+ *
+ * Below is some version info we got:
+ *    SOC   Version   IP-Version  Glitch-  [TR]WRN_INT
+ *                                Filter?   connected?
+ *   MX25  FlexCAN2  03.00.00.00     no         no
+ *   MX28  FlexCAN2  03.00.04.00    yes        yes
+ *   MX35  FlexCAN2  03.00.00.00     no         no
+ *   MX53  FlexCAN2  03.00.00.00    yes         no
+ *   MX6s  FlexCAN3  10.00.12.00    yes        yes
+ *
+ * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected.
+ */
 #define FLEXCAN_HAS_V10_FEATURES       BIT(1) /* For core version >= 10 */
-#define FLEXCAN_HAS_BROKEN_ERR_STATE   BIT(2) /* Broken error state handling */
+#define FLEXCAN_HAS_BROKEN_ERR_STATE   BIT(2) /* [TR]WRN_INT not connected */
 
 /* Structure of the message buffer */
 struct flexcan_mb {
@@ -205,7 +218,7 @@ static struct flexcan_devtype_data fsl_p1010_devtype_data = {
 };
 static struct flexcan_devtype_data fsl_imx28_devtype_data;
 static struct flexcan_devtype_data fsl_imx6q_devtype_data = {
-       .features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_BROKEN_ERR_STATE,
+       .features = FLEXCAN_HAS_V10_FEATURES,
 };
 
 static const struct can_bittiming_const flexcan_bittiming_const = {
index f5b82aeb2540af2646f38dce966096ac221e3eaf..6525dbcca4e3c6d4d15d0c86d92fc9350f8a09c7 100644 (file)
 
 #include "sja1000.h"
 
-MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
+MODULE_AUTHOR("Stephane Grosjean <s.grosjean@peak-system.com>");
 MODULE_DESCRIPTION("Socket-CAN driver for PEAK PCAN PCI family cards");
 MODULE_SUPPORTED_DEVICE("PEAK PCAN PCI/PCIe/PCIeC miniPCI CAN cards");
+MODULE_SUPPORTED_DEVICE("PEAK PCAN miniPCIe/cPCI PC/104+ PCI/104e CAN Cards");
 MODULE_LICENSE("GPL v2");
 
 #define DRV_NAME  "peak_pci"
@@ -64,7 +65,11 @@ struct peak_pci_chan {
 #define PEAK_PCI_DEVICE_ID     0x0001  /* for PCI/PCIe slot cards */
 #define PEAK_PCIEC_DEVICE_ID   0x0002  /* for ExpressCard slot cards */
 #define PEAK_PCIE_DEVICE_ID    0x0003  /* for nextgen PCIe slot cards */
-#define PEAK_MPCI_DEVICE_ID    0x0008  /* The miniPCI slot cards */
+#define PEAK_CPCI_DEVICE_ID    0x0004  /* for nextgen cPCI slot cards */
+#define PEAK_MPCI_DEVICE_ID    0x0005  /* for nextgen miniPCI slot cards */
+#define PEAK_PC_104P_DEVICE_ID 0x0006  /* PCAN-PC/104+ cards */
+#define PEAK_PCI_104E_DEVICE_ID        0x0007  /* PCAN-PCI/104 Express cards */
+#define PEAK_MPCIE_DEVICE_ID   0x0008  /* The miniPCIe slot cards */
 
 #define PEAK_PCI_CHAN_MAX      4
 
@@ -76,6 +81,10 @@ static DEFINE_PCI_DEVICE_TABLE(peak_pci_tbl) = {
        {PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
        {PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
        {PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+       {PEAK_PCI_VENDOR_ID, PEAK_MPCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+       {PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+       {PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+       {PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
 #ifdef CONFIG_CAN_PEAK_PCIEC
        {PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
 #endif
index e2e45ee5df33fcc75c491c78643dfe406297aabb..6dd0dd076cc527434e64569d64c8cd37d48a33df 100644 (file)
 #define LINK_20GTFD            LINK_STATUS_SPEED_AND_DUPLEX_20GTFD
 #define LINK_20GXFD            LINK_STATUS_SPEED_AND_DUPLEX_20GXFD
 
-
+#define LINK_UPDATE_MASK \
+                       (LINK_STATUS_SPEED_AND_DUPLEX_MASK | \
+                        LINK_STATUS_LINK_UP | \
+                        LINK_STATUS_PHYSICAL_LINK_FLAG | \
+                        LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | \
+                        LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | \
+                        LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | \
+                        LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK | \
+                        LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE | \
+                        LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE)
 
 #define SFP_EEPROM_CON_TYPE_ADDR               0x2
        #define SFP_EEPROM_CON_TYPE_VAL_LC      0x7
@@ -3295,6 +3304,21 @@ static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port)
               DEFAULT_PHY_DEV_ADDR);
 }
 
+static void bnx2x_xgxs_specific_func(struct bnx2x_phy *phy,
+                                    struct link_params *params,
+                                    u32 action)
+{
+       struct bnx2x *bp = params->bp;
+       switch (action) {
+       case PHY_INIT:
+               /* Set correct devad */
+               REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + params->port*0x18, 0);
+               REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18,
+                      phy->def_md_devad);
+               break;
+       }
+}
+
 static void bnx2x_xgxs_deassert(struct link_params *params)
 {
        struct bnx2x *bp = params->bp;
@@ -3309,10 +3333,8 @@ static void bnx2x_xgxs_deassert(struct link_params *params)
        REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
        udelay(500);
        REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
-
-       REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 0);
-       REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
-              params->phy[INT_PHY].def_md_devad);
+       bnx2x_xgxs_specific_func(&params->phy[INT_PHY], params,
+                                PHY_INIT);
 }
 
 static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
@@ -3545,14 +3567,11 @@ static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy,
 static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
                                        struct link_params *params,
                                        struct link_vars *vars) {
-       u16 val16 = 0, lane, i;
+       u16 lane, i, cl72_ctrl, an_adv = 0;
+       u16 ucode_ver;
        struct bnx2x *bp = params->bp;
        static struct bnx2x_reg_set reg_set[] = {
                {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7},
-               {MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0xff},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0x5555},
                {MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0x0},
                {MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415},
                {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190},
@@ -3565,12 +3584,19 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
                bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
                                 reg_set[i].val);
 
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+               MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl);
+       cl72_ctrl &= 0xf8ff;
+       cl72_ctrl |= 0x3800;
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+               MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl);
+
        /* Check adding advertisement for 1G KX */
        if (((vars->line_speed == SPEED_AUTO_NEG) &&
             (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||
            (vars->line_speed == SPEED_1000)) {
                u32 addr = MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2;
-               val16 |= (1<<5);
+               an_adv |= (1<<5);
 
                /* Enable CL37 1G Parallel Detect */
                bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, addr, 0x1);
@@ -3580,11 +3606,14 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
             (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||
            (vars->line_speed ==  SPEED_10000)) {
                /* Check adding advertisement for 10G KR */
-               val16 |= (1<<7);
+               an_adv |= (1<<7);
                /* Enable 10G Parallel Detect */
+               CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                                 MDIO_AER_BLOCK_AER_REG, 0);
+
                bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
                                 MDIO_WC_REG_PAR_DET_10G_CTRL, 1);
-
+               bnx2x_set_aer_mmd(params, phy);
                DP(NETIF_MSG_LINK, "Advertize 10G\n");
        }
 
@@ -3604,7 +3633,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
 
        /* Advertised speeds */
        bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
-                        MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16);
+                        MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, an_adv);
 
        /* Advertised and set FEC (Forward Error Correction) */
        bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
@@ -3628,9 +3657,10 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
        /* Set KR Autoneg Work-Around flag for Warpcore version older than D108
         */
        bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                       MDIO_WC_REG_UC_INFO_B1_VERSION, &val16);
-       if (val16 < 0xd108) {
-               DP(NETIF_MSG_LINK, "Enable AN KR work-around\n");
+                       MDIO_WC_REG_UC_INFO_B1_VERSION, &ucode_ver);
+       if (ucode_ver < 0xd108) {
+               DP(NETIF_MSG_LINK, "Enable AN KR work-around. WC ver:0x%x\n",
+                              ucode_ver);
                vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
        }
        bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
@@ -3651,21 +3681,16 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
                                      struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
-       u16 i;
+       u16 val16, i, lane;
        static struct bnx2x_reg_set reg_set[] = {
                /* Disable Autoneg */
                {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7},
-               {MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0},
                {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
                        0x3f00},
                {MDIO_AN_DEVAD, MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0},
                {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0},
                {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1},
                {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0xa},
-               /* Disable CL36 PCS Tx */
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0x0},
-               /* Double Wide Single Data Rate @ pll rate */
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0xFFFF},
                /* Leave cl72 training enable, needed for KR */
                {MDIO_PMA_DEVAD,
                MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150,
@@ -3676,11 +3701,24 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
                bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
                                 reg_set[i].val);
 
-       /* Leave CL72 enabled */
-       bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
-                                MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
-                                0x3800);
+       lane = bnx2x_get_warpcore_lane(phy, params);
+       /* Global registers */
+       CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                         MDIO_AER_BLOCK_AER_REG, 0);
+       /* Disable CL36 PCS Tx */
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16);
+       val16 &= ~(0x0011 << lane);
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16);
 
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16);
+       val16 |= (0x0303 << (lane << 1));
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16);
+       /* Restore AER */
+       bnx2x_set_aer_mmd(params, phy);
        /* Set speed via PMA/PMD register */
        bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
                         MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040);
@@ -4303,7 +4341,7 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
                                      struct link_params *params)
 {
        struct bnx2x *bp = params->bp;
-       u16 val16;
+       u16 val16, lane;
        bnx2x_sfp_e3_set_transmitter(params, phy, 0);
        bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
        bnx2x_set_aer_mmd(params, phy);
@@ -4340,6 +4378,30 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
                         MDIO_WC_REG_XGXSBLK1_LANECTRL2,
                         val16 & 0xff00);
 
+       lane = bnx2x_get_warpcore_lane(phy, params);
+       /* Disable CL36 PCS Tx */
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16);
+       val16 |= (0x11 << lane);
+       if (phy->flags & FLAGS_WC_DUAL_MODE)
+               val16 |= (0x22 << lane);
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16);
+
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16);
+       val16 &= ~(0x0303 << (lane << 1));
+       val16 |= (0x0101 << (lane << 1));
+       if (phy->flags & FLAGS_WC_DUAL_MODE) {
+               val16 &= ~(0x0c0c << (lane << 1));
+               val16 |= (0x0404 << (lane << 1));
+       }
+
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16);
+       /* Restore AER */
+       bnx2x_set_aer_mmd(params, phy);
+
 }
 
 static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
@@ -6296,15 +6358,7 @@ static int bnx2x_update_link_down(struct link_params *params,
        vars->mac_type = MAC_TYPE_NONE;
 
        /* Update shared memory */
-       vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK |
-                              LINK_STATUS_LINK_UP |
-                              LINK_STATUS_PHYSICAL_LINK_FLAG |
-                              LINK_STATUS_AUTO_NEGOTIATE_COMPLETE |
-                              LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK |
-                              LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK |
-                              LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK |
-                              LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE |
-                              LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE);
+       vars->link_status &= ~LINK_UPDATE_MASK;
        vars->line_speed = 0;
        bnx2x_update_mng(params, vars->link_status);
 
@@ -6452,6 +6506,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
        u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;
        u8 active_external_phy = INT_PHY;
        vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
+       vars->link_status &= ~LINK_UPDATE_MASK;
        for (phy_index = INT_PHY; phy_index < params->num_phys;
              phy_index++) {
                phy_vars[phy_index].flow_ctrl = 0;
@@ -7579,7 +7634,7 @@ static void bnx2x_warpcore_power_module(struct link_params *params,
 static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
                                                 struct link_params *params,
                                                 u16 addr, u8 byte_cnt,
-                                                u8 *o_buf)
+                                                u8 *o_buf, u8 is_init)
 {
        int rc = 0;
        u8 i, j = 0, cnt = 0;
@@ -7596,10 +7651,10 @@ static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
        /* 4 byte aligned address */
        addr32 = addr & (~0x3);
        do {
-               if (cnt == I2C_WA_PWR_ITER) {
+               if ((!is_init) && (cnt == I2C_WA_PWR_ITER)) {
                        bnx2x_warpcore_power_module(params, phy, 0);
                        /* Note that 100us are not enough here */
-                       usleep_range(1000,1000);
+                       usleep_range(1000, 2000);
                        bnx2x_warpcore_power_module(params, phy, 1);
                }
                rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt,
@@ -7719,7 +7774,7 @@ int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
        break;
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
                rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr,
-                                                          byte_cnt, o_buf);
+                                                          byte_cnt, o_buf, 0);
        break;
        }
        return rc;
@@ -7923,6 +7978,7 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
 
 {
        u8 val;
+       int rc;
        struct bnx2x *bp = params->bp;
        u16 timeout;
        /* Initialization time after hot-plug may take up to 300ms for
@@ -7930,8 +7986,14 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
         */
 
        for (timeout = 0; timeout < 60; timeout++) {
-               if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val)
-                   == 0) {
+               if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
+                       rc = bnx2x_warpcore_read_sfp_module_eeprom(phy,
+                                                                  params, 1,
+                                                                  1, &val, 1);
+               else
+                       rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1,
+                                                         &val);
+               if (rc == 0) {
                        DP(NETIF_MSG_LINK,
                           "SFP+ module initialization took %d ms\n",
                           timeout * 5);
@@ -7939,7 +8001,8 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
                }
                usleep_range(5000, 10000);
        }
-       return -EINVAL;
+       rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val);
+       return rc;
 }
 
 static void bnx2x_8727_power_module(struct bnx2x *bp,
@@ -10993,7 +11056,7 @@ static struct bnx2x_phy phy_xgxs = {
        .format_fw_ver  = (format_fw_ver_t)NULL,
        .hw_reset       = (hw_reset_t)NULL,
        .set_link_led   = (set_link_led_t)NULL,
-       .phy_specific_func = (phy_specific_func_t)NULL
+       .phy_specific_func = (phy_specific_func_t)bnx2x_xgxs_specific_func
 };
 static struct bnx2x_phy phy_warpcore = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
@@ -11465,6 +11528,11 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
                        phy->media_type = ETH_PHY_BASE_T;
                        break;
                case PORT_HW_CFG_NET_SERDES_IF_XFI:
+                       phy->supported &= (SUPPORTED_1000baseT_Full |
+                                          SUPPORTED_10000baseT_Full |
+                                          SUPPORTED_FIBRE |
+                                          SUPPORTED_Pause |
+                                          SUPPORTED_Asym_Pause);
                        phy->media_type = ETH_PHY_XFP_FIBER;
                        break;
                case PORT_HW_CFG_NET_SERDES_IF_SFI:
index d5648fc666bdf6f663505bbb433abebac08dbd48..bd1fd3d87c24d3979f01a0e9864af9866c62b9aa 100644 (file)
@@ -6794,8 +6794,9 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
 
        bnx2x_init_block(bp, BLOCK_DORQ, init_phase);
 
+       bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
+
        if (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) {
-               bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
 
                if (IS_MF(bp))
                        low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246);
@@ -11902,7 +11903,15 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
        /* disable FCOE L2 queue for E1x */
        if (CHIP_IS_E1x(bp))
                bp->flags |= NO_FCOE_FLAG;
-
+       /* disable FCOE for 57840 device, until FW supports it */
+       switch (ent->driver_data) {
+       case BCM57840_O:
+       case BCM57840_4_10:
+       case BCM57840_2_20:
+       case BCM57840_MFO:
+       case BCM57840_MF:
+               bp->flags |= NO_FCOE_FLAG;
+       }
 #endif
 
 
index a4da893ac1e15cfd02a2d071503afaa21838e51c..378988b5709a2262b98c0a790072be38b837cdf3 100644 (file)
@@ -251,6 +251,8 @@ struct adapter_params {
        unsigned char rev;                /* chip revision */
        unsigned char offload;
 
+       unsigned char bypass;
+
        unsigned int ofldq_wr_cred;
 };
 
@@ -642,6 +644,23 @@ extern int dbfifo_int_thresh;
 #define for_each_port(adapter, iter) \
        for (iter = 0; iter < (adapter)->params.nports; ++iter)
 
+static inline int is_bypass(struct adapter *adap)
+{
+       return adap->params.bypass;
+}
+
+static inline int is_bypass_device(int device)
+{
+       /* this should be set based upon device capabilities */
+       switch (device) {
+       case 0x440b:
+       case 0x440c:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
 static inline unsigned int core_ticks_per_usec(const struct adapter *adap)
 {
        return adap->params.vpd.cclk / 1000;
index 604f4f87f550c879a087fd128892d97450aa2d19..0df1284df497d8247fbf602d6578381099619d06 100644 (file)
@@ -3415,16 +3415,6 @@ static int adap_init0_config(struct adapter *adapter, int reset)
                         "mismatch: [fini] csum=%#x, computed csum=%#x\n",
                         finicsum, cfcsum);
 
-       /*
-        * If we're a pure NIC driver then disable all offloading facilities.
-        * This will allow the firmware to optimize aspects of the hardware
-        * configuration which will result in improved performance.
-        */
-       caps_cmd.ofldcaps = 0;
-       caps_cmd.iscsicaps = 0;
-       caps_cmd.rdmacaps = 0;
-       caps_cmd.fcoecaps = 0;
-
        /*
         * And now tell the firmware to use the configuration we just loaded.
         */
@@ -3513,18 +3503,6 @@ static int adap_init0_no_config(struct adapter *adapter, int reset)
        if (ret < 0)
                goto bye;
 
-#ifndef CONFIG_CHELSIO_T4_OFFLOAD
-       /*
-        * If we're a pure NIC driver then disable all offloading facilities.
-        * This will allow the firmware to optimize aspects of the hardware
-        * configuration which will result in improved performance.
-        */
-       caps_cmd.ofldcaps = 0;
-       caps_cmd.iscsicaps = 0;
-       caps_cmd.rdmacaps = 0;
-       caps_cmd.fcoecaps = 0;
-#endif
-
        if (caps_cmd.niccaps & htons(FW_CAPS_CONFIG_NIC_VM)) {
                if (!vf_acls)
                        caps_cmd.niccaps ^= htons(FW_CAPS_CONFIG_NIC_VM);
@@ -3745,6 +3723,7 @@ static int adap_init0(struct adapter *adap)
        u32 v, port_vec;
        enum dev_state state;
        u32 params[7], val[7];
+       struct fw_caps_config_cmd caps_cmd;
        int reset = 1, j;
 
        /*
@@ -3898,6 +3877,9 @@ static int adap_init0(struct adapter *adap)
                        goto bye;
        }
 
+       if (is_bypass_device(adap->pdev->device))
+               adap->params.bypass = 1;
+
        /*
         * Grab some of our basic fundamental operating parameters.
         */
@@ -3940,13 +3922,12 @@ static int adap_init0(struct adapter *adap)
                adap->tids.aftid_end = val[1];
        }
 
-#ifdef CONFIG_CHELSIO_T4_OFFLOAD
        /*
         * Get device capabilities so we can determine what resources we need
         * to manage.
         */
        memset(&caps_cmd, 0, sizeof(caps_cmd));
-       caps_cmd.op_to_write = htonl(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
+       caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
                                     FW_CMD_REQUEST | FW_CMD_READ);
        caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd));
        ret = t4_wr_mbox(adap, adap->mbox, &caps_cmd, sizeof(caps_cmd),
@@ -3991,15 +3972,6 @@ static int adap_init0(struct adapter *adap)
                adap->vres.ddp.size = val[4] - val[3] + 1;
                adap->params.ofldq_wr_cred = val[5];
 
-               params[0] = FW_PARAM_PFVF(ETHOFLD_START);
-               params[1] = FW_PARAM_PFVF(ETHOFLD_END);
-               ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2,
-                                     params, val);
-               if ((val[0] != val[1]) && (ret >= 0)) {
-                       adap->tids.uotid_base = val[0];
-                       adap->tids.nuotids = val[1] - val[0] + 1;
-               }
-
                adap->params.offload = 1;
        }
        if (caps_cmd.rdmacaps) {
@@ -4048,7 +4020,6 @@ static int adap_init0(struct adapter *adap)
        }
 #undef FW_PARAM_PFVF
 #undef FW_PARAM_DEV
-#endif /* CONFIG_CHELSIO_T4_OFFLOAD */
 
        /*
         * These are finalized by FW initialization, load their values now.
index 1b899fea1a91427bac31b171cd799fad2fc384f0..39bec73ff87c5879a9b1f6ca9ad1425d4d78c9b2 100644 (file)
@@ -102,6 +102,9 @@ struct tid_info {
        unsigned int ftid_base;
        unsigned int aftid_base;
        unsigned int aftid_end;
+       /* Server filter region */
+       unsigned int sftid_base;
+       unsigned int nsftids;
 
        spinlock_t atid_lock ____cacheline_aligned_in_smp;
        union aopen_entry *afree;
index b9db0e0405636780bf02bc598b12e79ea5f71074..2e5daee0438a55891072595400d643bd8ad1340b 100644 (file)
@@ -478,7 +478,7 @@ static int gianfar_ptp_probe(struct platform_device *dev)
                pr_err("no resource\n");
                goto no_resource;
        }
-       if (request_resource(&ioport_resource, etsects->rsrc)) {
+       if (request_resource(&iomem_resource, etsects->rsrc)) {
                pr_err("resource busy\n");
                goto no_resource;
        }
index 56b20d17d0e4c5577828040fddf8bd294868c84d..116f0e901bee2305324c4fa9035d19e6c5676b37 100644 (file)
@@ -2673,6 +2673,9 @@ static int ixgbe_get_ts_info(struct net_device *dev,
        case ixgbe_mac_X540:
        case ixgbe_mac_82599EB:
                info->so_timestamping =
+                       SOF_TIMESTAMPING_TX_SOFTWARE |
+                       SOF_TIMESTAMPING_RX_SOFTWARE |
+                       SOF_TIMESTAMPING_SOFTWARE |
                        SOF_TIMESTAMPING_TX_HARDWARE |
                        SOF_TIMESTAMPING_RX_HARDWARE |
                        SOF_TIMESTAMPING_RAW_HARDWARE;
index c10e3a6de09f042a02be933d8aa1ca928207fe6d..b35094c590ba94206be751643a7ad3a17cab9b7f 100644 (file)
@@ -143,7 +143,6 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,
                mlx4_bf_free(mdev->dev, &ring->bf);
        mlx4_qp_remove(mdev->dev, &ring->qp);
        mlx4_qp_free(mdev->dev, &ring->qp);
-       mlx4_qp_release_range(mdev->dev, ring->qpn, 1);
        mlx4_en_unmap_buffer(&ring->wqres.buf);
        mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
        kfree(ring->bounce_buf);
@@ -712,7 +711,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
        if (bounce)
                tx_desc = mlx4_en_bounce_to_desc(priv, ring, index, desc_size);
 
-       if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tag) {
+       if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tx_tag_present(skb)) {
                *(__be32 *) (&tx_desc->ctrl.vlan_tag) |= cpu_to_be32(ring->doorbell_qpn);
                op_own |= htonl((bf_index & 0xffff) << 8);
                /* Ensure new descirptor hits memory
index 51c764901ad257bce17199496d895f788a647f8b..b84a88bc44dc2a5e7391ca7bc7116344dd63a97f 100644 (file)
@@ -329,9 +329,6 @@ int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave,
        ctx = &priv->mfunc.master.slave_state[slave];
        spin_lock_irqsave(&ctx->lock, flags);
 
-       mlx4_dbg(dev, "%s: slave: %d, current state: %d new event :%d\n",
-                __func__, slave, cur_state, event);
-
        switch (cur_state) {
        case SLAVE_PORT_DOWN:
                if (MLX4_PORT_STATE_DEV_EVENT_PORT_UP == event)
@@ -366,9 +363,6 @@ int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave,
                        goto out;
        }
        ret = mlx4_get_slave_port_state(dev, slave, port);
-       mlx4_dbg(dev, "%s: slave: %d, current state: %d new event"
-                " :%d gen_event: %d\n",
-                __func__, slave, cur_state, event, *gen_event);
 
 out:
        spin_unlock_irqrestore(&ctx->lock, flags);
@@ -843,6 +837,18 @@ static void __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, struct mlx4_eq *eq)
        return priv->eq_table.uar_map[index] + 0x800 + 8 * (eq->eqn % 4);
 }
 
+static void mlx4_unmap_uar(struct mlx4_dev *dev)
+{
+       struct mlx4_priv *priv = mlx4_priv(dev);
+       int i;
+
+       for (i = 0; i < mlx4_num_eq_uar(dev); ++i)
+               if (priv->eq_table.uar_map[i]) {
+                       iounmap(priv->eq_table.uar_map[i]);
+                       priv->eq_table.uar_map[i] = NULL;
+               }
+}
+
 static int mlx4_create_eq(struct mlx4_dev *dev, int nent,
                          u8 intr, struct mlx4_eq *eq)
 {
@@ -1207,6 +1213,7 @@ err_out_unmap:
        mlx4_free_irqs(dev);
 
 err_out_bitmap:
+       mlx4_unmap_uar(dev);
        mlx4_bitmap_cleanup(&priv->eq_table.bitmap);
 
 err_out_free:
@@ -1231,10 +1238,7 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev)
        if (!mlx4_is_slave(dev))
                mlx4_unmap_clr_int(dev);
 
-       for (i = 0; i < mlx4_num_eq_uar(dev); ++i)
-               if (priv->eq_table.uar_map[i])
-                       iounmap(priv->eq_table.uar_map[i]);
-
+       mlx4_unmap_uar(dev);
        mlx4_bitmap_cleanup(&priv->eq_table.bitmap);
 
        kfree(priv->eq_table.uar_map);
index 80df2ab0177c398122725a85c82133788b711198..2aa80afd98d20038b2a174ac38a52a5eb003eaba 100644 (file)
@@ -1405,7 +1405,10 @@ unmap_bf:
        unmap_bf_area(dev);
 
 err_close:
-       mlx4_close_hca(dev);
+       if (mlx4_is_slave(dev))
+               mlx4_slave_exit(dev);
+       else
+               mlx4_CLOSE_HCA(dev, 0);
 
 err_free_icm:
        if (!mlx4_is_slave(dev))
index 926c911c0ac4b184d9d0f3fa70632b5ed84cb33b..b05705f50f0fae529e3f728471280ea4a1a1d753 100644 (file)
@@ -330,9 +330,6 @@ static void update_pkey_index(struct mlx4_dev *dev, int slave,
 
        new_index = priv->virt2phys_pkey[slave][port - 1][orig_index];
        *(u8 *)(inbox->buf + 35) = new_index;
-
-       mlx4_dbg(dev, "port = %d, orig pkey index = %d, "
-                "new pkey index = %d\n", port, orig_index, new_index);
 }
 
 static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox,
@@ -351,9 +348,6 @@ static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox,
                if (optpar & MLX4_QP_OPTPAR_ALT_ADDR_PATH)
                        qp_ctx->alt_path.mgid_index = slave & 0x7F;
        }
-
-       mlx4_dbg(dev, "slave %d, new gid index: 0x%x ",
-               slave, qp_ctx->pri_path.mgid_index);
 }
 
 static int mpt_mask(struct mlx4_dev *dev)
index 53743f7a2ca9604d6f264de3a2e3c727556a0619..af8b4142088c3d6a9114fd8c218336f54fcbcc19 100644 (file)
@@ -1524,6 +1524,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev)
                                  pldat->dma_buff_base_p);
        free_irq(ndev->irq, ndev);
        iounmap(pldat->net_base);
+       mdiobus_unregister(pldat->mii_bus);
        mdiobus_free(pldat->mii_bus);
        clk_disable(pldat->clk);
        clk_put(pldat->clk);
index b2a94d02a5217db7638164962d59b16f8def20ad..4c4fe5b1a29a5422cb272cd9ed7e26ae9ec5eee3 100644 (file)
@@ -338,26 +338,6 @@ static void pch_gbe_wait_clr_bit(void *reg, u32 bit)
                pr_err("Error: busy bit is not cleared\n");
 }
 
-/**
- * pch_gbe_wait_clr_bit_irq - Wait to clear a bit for interrupt context
- * @reg:       Pointer of register
- * @busy:      Busy bit
- */
-static int pch_gbe_wait_clr_bit_irq(void *reg, u32 bit)
-{
-       u32 tmp;
-       int ret = -1;
-       /* wait busy */
-       tmp = 20;
-       while ((ioread32(reg) & bit) && --tmp)
-               udelay(5);
-       if (!tmp)
-               pr_err("Error: busy bit is not cleared\n");
-       else
-               ret = 0;
-       return ret;
-}
-
 /**
  * pch_gbe_mac_mar_set - Set MAC address register
  * @hw:            Pointer to the HW structure
@@ -409,15 +389,20 @@ static void pch_gbe_mac_reset_hw(struct pch_gbe_hw *hw)
        return;
 }
 
-static void pch_gbe_mac_reset_rx(struct pch_gbe_hw *hw)
+static void pch_gbe_disable_mac_rx(struct pch_gbe_hw *hw)
 {
-       /* Read the MAC addresses. and store to the private data */
-       pch_gbe_mac_read_mac_addr(hw);
-       iowrite32(PCH_GBE_RX_RST, &hw->reg->RESET);
-       pch_gbe_wait_clr_bit_irq(&hw->reg->RESET, PCH_GBE_RX_RST);
-       /* Setup the MAC addresses */
-       pch_gbe_mac_mar_set(hw, hw->mac.addr, 0);
-       return;
+       u32 rctl;
+       /* Disables Receive MAC */
+       rctl = ioread32(&hw->reg->MAC_RX_EN);
+       iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN);
+}
+
+static void pch_gbe_enable_mac_rx(struct pch_gbe_hw *hw)
+{
+       u32 rctl;
+       /* Enables Receive MAC */
+       rctl = ioread32(&hw->reg->MAC_RX_EN);
+       iowrite32((rctl | PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN);
 }
 
 /**
@@ -913,7 +898,7 @@ static void pch_gbe_setup_rctl(struct pch_gbe_adapter *adapter)
 static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter)
 {
        struct pch_gbe_hw *hw = &adapter->hw;
-       u32 rdba, rdlen, rctl, rxdma;
+       u32 rdba, rdlen, rxdma;
 
        pr_debug("dma adr = 0x%08llx  size = 0x%08x\n",
                 (unsigned long long)adapter->rx_ring->dma,
@@ -921,9 +906,7 @@ static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter)
 
        pch_gbe_mac_force_mac_fc(hw);
 
-       /* Disables Receive MAC */
-       rctl = ioread32(&hw->reg->MAC_RX_EN);
-       iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN);
+       pch_gbe_disable_mac_rx(hw);
 
        /* Disables Receive DMA */
        rxdma = ioread32(&hw->reg->DMA_CTRL);
@@ -1316,38 +1299,17 @@ void pch_gbe_update_stats(struct pch_gbe_adapter *adapter)
        spin_unlock_irqrestore(&adapter->stats_lock, flags);
 }
 
-static void pch_gbe_stop_receive(struct pch_gbe_adapter *adapter)
+static void pch_gbe_disable_dma_rx(struct pch_gbe_hw *hw)
 {
-       struct pch_gbe_hw *hw = &adapter->hw;
        u32 rxdma;
-       u16 value;
-       int ret;
 
        /* Disable Receive DMA */
        rxdma = ioread32(&hw->reg->DMA_CTRL);
        rxdma &= ~PCH_GBE_RX_DMA_EN;
        iowrite32(rxdma, &hw->reg->DMA_CTRL);
-       /* Wait Rx DMA BUS is IDLE */
-       ret = pch_gbe_wait_clr_bit_irq(&hw->reg->RX_DMA_ST, PCH_GBE_IDLE_CHECK);
-       if (ret) {
-               /* Disable Bus master */
-               pci_read_config_word(adapter->pdev, PCI_COMMAND, &value);
-               value &= ~PCI_COMMAND_MASTER;
-               pci_write_config_word(adapter->pdev, PCI_COMMAND, value);
-               /* Stop Receive */
-               pch_gbe_mac_reset_rx(hw);
-               /* Enable Bus master */
-               value |= PCI_COMMAND_MASTER;
-               pci_write_config_word(adapter->pdev, PCI_COMMAND, value);
-       } else {
-               /* Stop Receive */
-               pch_gbe_mac_reset_rx(hw);
-       }
-       /* reprogram multicast address register after reset */
-       pch_gbe_set_multi(adapter->netdev);
 }
 
-static void pch_gbe_start_receive(struct pch_gbe_hw *hw)
+static void pch_gbe_enable_dma_rx(struct pch_gbe_hw *hw)
 {
        u32 rxdma;
 
@@ -1355,9 +1317,6 @@ static void pch_gbe_start_receive(struct pch_gbe_hw *hw)
        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;
 }
 
 /**
@@ -1393,7 +1352,7 @@ static irqreturn_t pch_gbe_intr(int irq, void *data)
                        int_en = ioread32(&hw->reg->INT_EN);
                        iowrite32((int_en & ~PCH_GBE_INT_RX_FIFO_ERR),
                                  &hw->reg->INT_EN);
-                       pch_gbe_stop_receive(adapter);
+                       pch_gbe_disable_dma_rx(&adapter->hw);
                        int_st |= ioread32(&hw->reg->INT_ST);
                        int_st = int_st & ioread32(&hw->reg->INT_EN);
                }
@@ -1971,12 +1930,12 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
        struct net_device *netdev = adapter->netdev;
        struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
        struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
-       int err;
+       int err = -EINVAL;
 
        /* Ensure we have a valid MAC */
        if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
                pr_err("Error: Invalid MAC address\n");
-               return -EINVAL;
+               goto out;
        }
 
        /* hardware has been reset, we need to reload some things */
@@ -1989,18 +1948,19 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
 
        err = pch_gbe_request_irq(adapter);
        if (err) {
-               pr_err("Error: can't bring device up\n");
-               return err;
+               pr_err("Error: can't bring device up - irq request failed\n");
+               goto out;
        }
        err = pch_gbe_alloc_rx_buffers_pool(adapter, rx_ring, rx_ring->count);
        if (err) {
-               pr_err("Error: can't bring device up\n");
-               return err;
+               pr_err("Error: can't bring device up - alloc rx buffers pool failed\n");
+               goto freeirq;
        }
        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);
+       pch_gbe_enable_dma_rx(&adapter->hw);
+       pch_gbe_enable_mac_rx(&adapter->hw);
 
        mod_timer(&adapter->watchdog_timer, jiffies);
 
@@ -2009,6 +1969,11 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
        netif_start_queue(adapter->netdev);
 
        return 0;
+
+freeirq:
+       pch_gbe_free_irq(adapter);
+out:
+       return err;
 }
 
 /**
@@ -2405,7 +2370,6 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget)
        int work_done = 0;
        bool poll_end_flag = false;
        bool cleaned = false;
-       u32 int_en;
 
        pr_debug("budget : %d\n", budget);
 
@@ -2422,19 +2386,13 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget)
 
        if (poll_end_flag) {
                napi_complete(napi);
-               if (adapter->rx_stop_flag) {
-                       adapter->rx_stop_flag = false;
-                       pch_gbe_start_receive(&adapter->hw);
-               }
                pch_gbe_irq_enable(adapter);
-       } else
-               if (adapter->rx_stop_flag) {
-                       adapter->rx_stop_flag = false;
-                       pch_gbe_start_receive(&adapter->hw);
-                       int_en = ioread32(&adapter->hw.reg->INT_EN);
-                       iowrite32((int_en | PCH_GBE_INT_RX_FIFO_ERR),
-                               &adapter->hw.reg->INT_EN);
-               }
+       }
+
+       if (adapter->rx_stop_flag) {
+               adapter->rx_stop_flag = false;
+               pch_gbe_enable_dma_rx(&adapter->hw);
+       }
 
        pr_debug("poll_end_flag : %d  work_done : %d  budget : %d\n",
                 poll_end_flag, work_done, budget);
index df09b1cb742fb211f639e0e6a16d658a768cf7d6..6407d0d77e810f038da14dfdf1447bae50794a8c 100644 (file)
@@ -2525,6 +2525,13 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev)
        qdev->req_q_size =
            (u32) (NUM_REQ_Q_ENTRIES * sizeof(struct ob_mac_iocb_req));
 
+       qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb);
+
+       /* The barrier is required to ensure request and response queue
+        * addr writes to the registers.
+        */
+       wmb();
+
        qdev->req_q_virt_addr =
            pci_alloc_consistent(qdev->pdev,
                                 (size_t) qdev->req_q_size,
@@ -2536,8 +2543,6 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev)
                return -ENOMEM;
        }
 
-       qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb);
-
        qdev->rsp_q_virt_addr =
            pci_alloc_consistent(qdev->pdev,
                                 (size_t) qdev->rsp_q_size,
index b26cbda5efa9b5264dd4e2bb885d35ea7e26b692..2c41894d54726e86b70ee9d4e8aba4c6200437b5 100644 (file)
@@ -5,7 +5,7 @@
 config NET_VENDOR_TI
        bool "Texas Instruments (TI) devices"
        default y
-       depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3))
+       depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3 || SOC_AM33XX))
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
index 4e2a1628484dfbc3a6fff901d976cf751bf8c151..4e9810013850ca3b4765ce002de0715d6b2c935b 100644 (file)
@@ -1334,11 +1334,11 @@ static int tso_count_edescs(struct sk_buff *skb)
 {
        struct skb_shared_info *sh = skb_shinfo(skb);
        unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-       unsigned int data_len = skb->data_len + skb->hdr_len - sh_len;
+       unsigned int data_len = skb->len - sh_len;
        unsigned int p_len = sh->gso_size;
        long f_id = -1;    /* id of the current fragment */
-       long f_size = skb->hdr_len;  /* size of the current fragment */
-       long f_used = sh_len;  /* bytes used from the current fragment */
+       long f_size = skb_headlen(skb) - sh_len;  /* current fragment size */
+       long f_used = 0;  /* bytes used from the current fragment */
        long n;            /* size of the current piece of payload */
        int num_edescs = 0;
        int segment;
@@ -1353,7 +1353,7 @@ static int tso_count_edescs(struct sk_buff *skb)
                        /* Advance as needed. */
                        while (f_used >= f_size) {
                                f_id++;
-                               f_size = sh->frags[f_id].size;
+                               f_size = skb_frag_size(&sh->frags[f_id]);
                                f_used = 0;
                        }
 
@@ -1384,13 +1384,13 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,
        struct iphdr *ih;
        struct tcphdr *th;
        unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-       unsigned int data_len = skb->data_len + skb->hdr_len - sh_len;
+       unsigned int data_len = skb->len - sh_len;
        unsigned char *data = skb->data;
        unsigned int ih_off, th_off, p_len;
        unsigned int isum_seed, tsum_seed, id, seq;
        long f_id = -1;    /* id of the current fragment */
-       long f_size = skb->hdr_len;  /* size of the current fragment */
-       long f_used = sh_len;  /* bytes used from the current fragment */
+       long f_size = skb_headlen(skb) - sh_len;  /* current fragment size */
+       long f_used = 0;  /* bytes used from the current fragment */
        long n;            /* size of the current piece of payload */
        int segment;
 
@@ -1405,7 +1405,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,
        isum_seed = ((0xFFFF - ih->check) +
                     (0xFFFF - ih->tot_len) +
                     (0xFFFF - ih->id));
-       tsum_seed = th->check + (0xFFFF ^ htons(sh_len + data_len));
+       tsum_seed = th->check + (0xFFFF ^ htons(skb->len));
        id = ntohs(ih->id);
        seq = ntohl(th->seq);
 
@@ -1444,7 +1444,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,
                        /* Advance as needed. */
                        while (f_used >= f_size) {
                                f_id++;
-                               f_size = sh->frags[f_id].size;
+                               f_size = skb_frag_size(&sh->frags[f_id]);
                                f_used = 0;
                        }
 
@@ -1478,14 +1478,14 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,
        struct tile_net_priv *priv = netdev_priv(dev);
        struct skb_shared_info *sh = skb_shinfo(skb);
        unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-       unsigned int data_len = skb->data_len + skb->hdr_len - sh_len;
+       unsigned int data_len = skb->len - sh_len;
        unsigned int p_len = sh->gso_size;
        gxio_mpipe_edesc_t edesc_head = { { 0 } };
        gxio_mpipe_edesc_t edesc_body = { { 0 } };
        long f_id = -1;    /* id of the current fragment */
-       long f_size = skb->hdr_len;  /* size of the current fragment */
-       long f_used = sh_len;  /* bytes used from the current fragment */
-       void *f_data = skb->data;
+       long f_size = skb_headlen(skb) - sh_len;  /* current fragment size */
+       long f_used = 0;  /* bytes used from the current fragment */
+       void *f_data = skb->data + sh_len;
        long n;            /* size of the current piece of payload */
        unsigned long tx_packets = 0, tx_bytes = 0;
        unsigned int csum_start;
@@ -1516,15 +1516,18 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,
 
                /* Egress the payload. */
                while (p_used < p_len) {
+                       void *va;
 
                        /* Advance as needed. */
                        while (f_used >= f_size) {
                                f_id++;
-                               f_size = sh->frags[f_id].size;
-                               f_used = 0;
+                               f_size = skb_frag_size(&sh->frags[f_id]);
                                f_data = tile_net_frag_buf(&sh->frags[f_id]);
+                               f_used = 0;
                        }
 
+                       va = f_data + f_used;
+
                        /* Use bytes from the current fragment. */
                        n = p_len - p_used;
                        if (n > f_size - f_used)
@@ -1533,7 +1536,7 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,
                        p_used += n;
 
                        /* Egress a piece of the payload. */
-                       edesc_body.va = va_to_tile_io_addr(f_data) + f_used;
+                       edesc_body.va = va_to_tile_io_addr(va);
                        edesc_body.xfer_size = n;
                        edesc_body.bound = !(p_used < p_len);
                        gxio_mpipe_equeue_put_at(equeue, edesc_body, slot);
index 983bbf4d5ef6a7437118ac2d21ba2cb66599bc8c..961f0b2939132b0b2e50a94e7610cfb72ce8faf4 100644 (file)
@@ -15,6 +15,11 @@ if PHYLIB
 
 comment "MII PHY device drivers"
 
+config AT803X_PHY
+       tristate "Drivers for Atheros AT803X PHYs"
+       ---help---
+         Currently supports the AT8030 and AT8035 model
+
 config AMD_PHY
        tristate "Drivers for the AMD PHYs"
        ---help---
index 426674debae44dfb9967e305ad571f7012010afb..9645e389a58d34fbdb0c74a737d61b33a4885b6a 100644 (file)
@@ -25,6 +25,7 @@ obj-$(CONFIG_STE10XP)         += ste10Xp.o
 obj-$(CONFIG_MICREL_PHY)       += micrel.o
 obj-$(CONFIG_MDIO_OCTEON)      += mdio-octeon.o
 obj-$(CONFIG_MICREL_KS8995MA)  += spi_ks8995.o
+obj-$(CONFIG_AT803X_PHY)       += at803x.o
 obj-$(CONFIG_AMD_PHY)          += amd.o
 obj-$(CONFIG_MDIO_BUS_MUX)     += mdio-mux.o
 obj-$(CONFIG_MDIO_BUS_MUX_GPIO)        += mdio-mux-gpio.o
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
new file mode 100644 (file)
index 0000000..45cbc10
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * drivers/net/phy/at803x.c
+ *
+ * Driver for Atheros 803x PHY
+ *
+ * Author: Matus Ujhelyi <ujhelyi.m@gmail.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/phy.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#define AT803X_INTR_ENABLE                     0x12
+#define AT803X_INTR_STATUS                     0x13
+#define AT803X_WOL_ENABLE                      0x01
+#define AT803X_DEVICE_ADDR                     0x03
+#define AT803X_LOC_MAC_ADDR_0_15_OFFSET                0x804C
+#define AT803X_LOC_MAC_ADDR_16_31_OFFSET       0x804B
+#define AT803X_LOC_MAC_ADDR_32_47_OFFSET       0x804A
+#define AT803X_MMD_ACCESS_CONTROL              0x0D
+#define AT803X_MMD_ACCESS_CONTROL_DATA         0x0E
+#define AT803X_FUNC_DATA                       0x4003
+
+MODULE_DESCRIPTION("Atheros 803x PHY driver");
+MODULE_AUTHOR("Matus Ujhelyi");
+MODULE_LICENSE("GPL");
+
+static void at803x_set_wol_mac_addr(struct phy_device *phydev)
+{
+       struct net_device *ndev = phydev->attached_dev;
+       const u8 *mac;
+       unsigned int i, offsets[] = {
+               AT803X_LOC_MAC_ADDR_32_47_OFFSET,
+               AT803X_LOC_MAC_ADDR_16_31_OFFSET,
+               AT803X_LOC_MAC_ADDR_0_15_OFFSET,
+       };
+
+       if (!ndev)
+               return;
+
+       mac = (const u8 *) ndev->dev_addr;
+
+       if (!is_valid_ether_addr(mac))
+               return;
+
+       for (i = 0; i < 3; i++) {
+               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL,
+                                 AT803X_DEVICE_ADDR);
+               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA,
+                                 offsets[i]);
+               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL,
+                                 AT803X_FUNC_DATA);
+               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA,
+                                 mac[(i * 2) + 1] | (mac[(i * 2)] << 8));
+       }
+}
+
+static int at803x_config_init(struct phy_device *phydev)
+{
+       int val;
+       u32 features;
+       int status;
+
+       features = SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_AUI |
+                  SUPPORTED_FIBRE | SUPPORTED_BNC;
+
+       val = phy_read(phydev, MII_BMSR);
+       if (val < 0)
+               return val;
+
+       if (val & BMSR_ANEGCAPABLE)
+               features |= SUPPORTED_Autoneg;
+       if (val & BMSR_100FULL)
+               features |= SUPPORTED_100baseT_Full;
+       if (val & BMSR_100HALF)
+               features |= SUPPORTED_100baseT_Half;
+       if (val & BMSR_10FULL)
+               features |= SUPPORTED_10baseT_Full;
+       if (val & BMSR_10HALF)
+               features |= SUPPORTED_10baseT_Half;
+
+       if (val & BMSR_ESTATEN) {
+               val = phy_read(phydev, MII_ESTATUS);
+               if (val < 0)
+                       return val;
+
+               if (val & ESTATUS_1000_TFULL)
+                       features |= SUPPORTED_1000baseT_Full;
+               if (val & ESTATUS_1000_THALF)
+                       features |= SUPPORTED_1000baseT_Half;
+       }
+
+       phydev->supported = features;
+       phydev->advertising = features;
+
+       /* enable WOL */
+       at803x_set_wol_mac_addr(phydev);
+       status = phy_write(phydev, AT803X_INTR_ENABLE, AT803X_WOL_ENABLE);
+       status = phy_read(phydev, AT803X_INTR_STATUS);
+
+       return 0;
+}
+
+/* ATHEROS 8035 */
+static struct phy_driver at8035_driver = {
+       .phy_id         = 0x004dd072,
+       .name           = "Atheros 8035 ethernet",
+       .phy_id_mask    = 0xffffffef,
+       .config_init    = at803x_config_init,
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_aneg    = &genphy_config_aneg,
+       .read_status    = &genphy_read_status,
+       .driver         = {
+               .owner = THIS_MODULE,
+       },
+};
+
+/* ATHEROS 8030 */
+static struct phy_driver at8030_driver = {
+       .phy_id         = 0x004dd076,
+       .name           = "Atheros 8030 ethernet",
+       .phy_id_mask    = 0xffffffef,
+       .config_init    = at803x_config_init,
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_aneg    = &genphy_config_aneg,
+       .read_status    = &genphy_read_status,
+       .driver         = {
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init atheros_init(void)
+{
+       int ret;
+
+       ret = phy_driver_register(&at8035_driver);
+       if (ret)
+               goto err1;
+
+       ret = phy_driver_register(&at8030_driver);
+       if (ret)
+               goto err2;
+
+       return 0;
+
+err2:
+       phy_driver_unregister(&at8035_driver);
+err1:
+       return ret;
+}
+
+static void __exit atheros_exit(void)
+{
+       phy_driver_unregister(&at8035_driver);
+       phy_driver_unregister(&at8030_driver);
+}
+
+module_init(atheros_init);
+module_exit(atheros_exit);
+
+static struct mdio_device_id __maybe_unused atheros_tbl[] = {
+       { 0x004dd076, 0xffffffef },
+       { 0x004dd072, 0xffffffef },
+       { }
+};
+
+MODULE_DEVICE_TABLE(mdio, atheros_tbl);
index daec9b05d168ca4f0f103f3638fcc3259e9ea304..6428fcbbdd4bf4f6967e7eb3fee32e97fceba566 100644 (file)
@@ -234,6 +234,7 @@ void free_mdio_bitbang(struct mii_bus *bus)
        struct mdiobb_ctrl *ctrl = bus->priv;
 
        module_put(ctrl->ops->owner);
+       mdiobus_unregister(bus);
        mdiobus_free(bus);
 }
 EXPORT_SYMBOL(free_mdio_bitbang);
index a03de71970499b7daaad750768318f4d08af6160..d0129827602b2867380ca4f8f774bfa104f2eef2 100644 (file)
@@ -592,6 +592,32 @@ static const struct usb_device_id  products [] = {
        .driver_info            = 0,
 },
 
+/* Novatel USB551L and MC551 - handled by qmi_wwan */
+{
+       .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 = 0,
+},
+
+/* Novatel E362 - handled by qmi_wwan */
+{
+       .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
+                | USB_DEVICE_ID_MATCH_PRODUCT
+                | USB_DEVICE_ID_MATCH_INT_INFO,
+       .idVendor               = NOVATEL_VENDOR_ID,
+       .idProduct              = 0x9010,
+       .bInterfaceClass        = USB_CLASS_COMM,
+       .bInterfaceSubClass     = USB_CDC_SUBCLASS_ETHERNET,
+       .bInterfaceProtocol     = USB_CDC_PROTO_NONE,
+       .driver_info = 0,
+},
+
 /*
  * WHITELIST!!!
  *
@@ -604,21 +630,6 @@ 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,
-}, {
        /* ZTE (Vodafone) K3805-Z */
        .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
                 | USB_DEVICE_ID_MATCH_PRODUCT
index a28a983d465e6d434a3272a36a9ab35a7b5b3eee..534d8becbbdc779219f26c3df0481cd07171bcc7 100644 (file)
@@ -62,6 +62,7 @@
 #define USB_PRODUCT_IPAD 0x129a
 #define USB_PRODUCT_IPHONE_4_VZW 0x129c
 #define USB_PRODUCT_IPHONE_4S  0x12a0
+#define USB_PRODUCT_IPHONE_5   0x12a8
 
 #define IPHETH_USBINTF_CLASS    255
 #define IPHETH_USBINTF_SUBCLASS 253
@@ -113,6 +114,10 @@ static struct usb_device_id ipheth_table[] = {
                USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S,
                IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
                IPHETH_USBINTF_PROTO) },
+       { USB_DEVICE_AND_INTERFACE_INFO(
+               USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_5,
+               IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
+               IPHETH_USBINTF_PROTO) },
        { }
 };
 MODULE_DEVICE_TABLE(usb, ipheth_table);
index 6883c371c59f5a2eb416466563cad5e1fbaa5b9a..3b566fa0f8e6277ee62f281211a0507dfdf7c227 100644 (file)
@@ -369,18 +369,73 @@ static const struct usb_device_id products[] = {
                USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff),
                .driver_info        = (unsigned long)&qmi_wwan_info,
        },
+       {       /* Novatel USB551L and MC551 */
+               USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0xb001,
+                                             USB_CLASS_COMM,
+                                             USB_CDC_SUBCLASS_ETHERNET,
+                                             USB_CDC_PROTO_NONE),
+               .driver_info        = (unsigned long)&qmi_wwan_info,
+       },
+       {       /* Novatel E362 */
+               USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0x9010,
+                                             USB_CLASS_COMM,
+                                             USB_CDC_SUBCLASS_ETHERNET,
+                                             USB_CDC_PROTO_NONE),
+               .driver_info        = (unsigned long)&qmi_wwan_info,
+       },
 
        /* 3. Combined interface devices matching on interface number */
+       {QMI_FIXED_INTF(0x19d2, 0x0002, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0012, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0017, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x0021, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0025, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0031, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0042, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0049, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0052, 4)},
        {QMI_FIXED_INTF(0x19d2, 0x0055, 1)},    /* ZTE (Vodafone) K3520-Z */
+       {QMI_FIXED_INTF(0x19d2, 0x0058, 4)},
        {QMI_FIXED_INTF(0x19d2, 0x0063, 4)},    /* ZTE (Vodafone) K3565-Z */
        {QMI_FIXED_INTF(0x19d2, 0x0104, 4)},    /* ZTE (Vodafone) K4505-Z */
+       {QMI_FIXED_INTF(0x19d2, 0x0113, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0118, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0121, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0123, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0124, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0125, 6)},
+       {QMI_FIXED_INTF(0x19d2, 0x0126, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0130, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0133, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x0141, 5)},
        {QMI_FIXED_INTF(0x19d2, 0x0157, 5)},    /* ZTE MF683 */
+       {QMI_FIXED_INTF(0x19d2, 0x0158, 3)},
        {QMI_FIXED_INTF(0x19d2, 0x0167, 4)},    /* ZTE MF820D */
+       {QMI_FIXED_INTF(0x19d2, 0x0168, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0176, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x0178, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x0191, 4)},    /* ZTE EuFi890 */
+       {QMI_FIXED_INTF(0x19d2, 0x0199, 1)},    /* ZTE MF820S */
+       {QMI_FIXED_INTF(0x19d2, 0x0200, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0257, 3)},    /* ZTE MF821 */
        {QMI_FIXED_INTF(0x19d2, 0x0326, 4)},    /* ZTE MF821D */
        {QMI_FIXED_INTF(0x19d2, 0x1008, 4)},    /* ZTE (Vodafone) K3570-Z */
        {QMI_FIXED_INTF(0x19d2, 0x1010, 4)},    /* ZTE (Vodafone) K3571-Z */
+       {QMI_FIXED_INTF(0x19d2, 0x1012, 4)},
        {QMI_FIXED_INTF(0x19d2, 0x1018, 3)},    /* ZTE (Vodafone) K5006-Z */
+       {QMI_FIXED_INTF(0x19d2, 0x1021, 2)},
+       {QMI_FIXED_INTF(0x19d2, 0x1245, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1247, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1252, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1254, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1255, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x1255, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1256, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1401, 2)},
        {QMI_FIXED_INTF(0x19d2, 0x1402, 2)},    /* ZTE MF60 */
+       {QMI_FIXED_INTF(0x19d2, 0x1424, 2)},
+       {QMI_FIXED_INTF(0x19d2, 0x1425, 2)},
+       {QMI_FIXED_INTF(0x19d2, 0x1426, 2)},    /* ZTE MF91 */
        {QMI_FIXED_INTF(0x19d2, 0x2002, 4)},    /* ZTE (Vodafone) K3765-Z */
        {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)},    /* Sierra Wireless MC7700 */
        {QMI_FIXED_INTF(0x114f, 0x68a2, 8)},    /* Sierra Wireless MC7750 */
index f9819d10b1f9d41f864dc710e6799ffed9f9d5f0..cb04f900cc461990255cd788d92437ddc1ce4afa 100644 (file)
@@ -1158,6 +1158,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
                usb_anchor_urb(urb, &dev->deferred);
                /* no use to process more packets */
                netif_stop_queue(net);
+               usb_put_urb(urb);
                spin_unlock_irqrestore(&dev->txq.lock, flags);
                netdev_dbg(dev->net, "Delaying transmission for resumption\n");
                goto deferred;
@@ -1310,6 +1311,8 @@ void usbnet_disconnect (struct usb_interface *intf)
 
        cancel_work_sync(&dev->kevent);
 
+       usb_scuttle_anchored_urbs(&dev->deferred);
+
        if (dev->driver_info->unbind)
                dev->driver_info->unbind (dev, intf);
 
index ce9d4f2c9776e08d1b543f18de8cb7100fe43a86..0ae1bcc6da730fecd4267f0076b3f3ef422ea7ce 100644 (file)
@@ -744,28 +744,43 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
 
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+               u32 buf_size;
 
-               tbi = tq->buf_info + tq->tx_ring.next2fill;
-               tbi->map_type = VMXNET3_MAP_PAGE;
-               tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
-                                                0, skb_frag_size(frag),
-                                                DMA_TO_DEVICE);
+               buf_offset = 0;
+               len = skb_frag_size(frag);
+               while (len) {
+                       tbi = tq->buf_info + tq->tx_ring.next2fill;
+                       if (len < VMXNET3_MAX_TX_BUF_SIZE) {
+                               buf_size = len;
+                               dw2 |= len;
+                       } else {
+                               buf_size = VMXNET3_MAX_TX_BUF_SIZE;
+                               /* spec says that for TxDesc.len, 0 == 2^14 */
+                       }
+                       tbi->map_type = VMXNET3_MAP_PAGE;
+                       tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
+                                                        buf_offset, buf_size,
+                                                        DMA_TO_DEVICE);
 
-               tbi->len = skb_frag_size(frag);
+                       tbi->len = buf_size;
 
-               gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
-               BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
+                       gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
+                       BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
 
-               gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
-               gdesc->dword[2] = cpu_to_le32(dw2 | skb_frag_size(frag));
-               gdesc->dword[3] = 0;
+                       gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
+                       gdesc->dword[2] = cpu_to_le32(dw2);
+                       gdesc->dword[3] = 0;
 
-               dev_dbg(&adapter->netdev->dev,
-                       "txd[%u]: 0x%llu %u %u\n",
-                       tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
-                       le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
-               vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
-               dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
+                       dev_dbg(&adapter->netdev->dev,
+                               "txd[%u]: 0x%llu %u %u\n",
+                               tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
+                               le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
+                       vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
+                       dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
+
+                       len -= buf_size;
+                       buf_offset += buf_size;
+               }
        }
 
        ctx->eop_txd = gdesc;
@@ -886,6 +901,18 @@ vmxnet3_prepare_tso(struct sk_buff *skb,
        }
 }
 
+static int txd_estimate(const struct sk_buff *skb)
+{
+       int count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + 1;
+       int i;
+
+       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+               const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+
+               count += VMXNET3_TXD_NEEDED(skb_frag_size(frag));
+       }
+       return count;
+}
 
 /*
  * Transmits a pkt thru a given tq
@@ -914,9 +941,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
        union Vmxnet3_GenericDesc tempTxDesc;
 #endif
 
-       /* conservatively estimate # of descriptors to use */
-       count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) +
-               skb_shinfo(skb)->nr_frags + 1;
+       count = txd_estimate(skb);
 
        ctx.ipv4 = (vlan_get_protocol(skb) == cpu_to_be16(ETH_P_IP));
 
index 607976c001626a75afbf590411bf6ec1bbff26c0..7b4adde93c016b7e020306220e372524da9f5deb 100644 (file)
@@ -816,7 +816,7 @@ static void vxlan_cleanup(unsigned long arg)
                                = container_of(p, struct vxlan_fdb, hlist);
                        unsigned long timeout;
 
-                       if (f->state == NUD_PERMANENT)
+                       if (f->state & NUD_PERMANENT)
                                continue;
 
                        timeout = f->used + vxlan->age_interval * HZ;
index 89bf94d4d8a1e1799715eacf684bdd6892e419c9..6f7cf49eff4d0d1dd3bd6e6b954ec5c507969a44 100644 (file)
@@ -534,107 +534,107 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
 
 static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
        /* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-       {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
-       {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
-       {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
+       {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
        {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
        {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
        {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
        {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
        {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
-       {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202},
-       {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400},
-       {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402},
-       {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404},
-       {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603},
-       {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02},
-       {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04},
-       {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20},
-       {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20},
-       {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22},
-       {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24},
-       {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640},
-       {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660},
-       {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861},
-       {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81},
-       {0x0000a54c, 0x5a08442e, 0x5a08442e, 0x47001a83, 0x47001a83},
-       {0x0000a550, 0x5e0a4431, 0x5e0a4431, 0x4a001c84, 0x4a001c84},
-       {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3},
-       {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5},
-       {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9},
-       {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb},
-       {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-       {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-       {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-       {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-       {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-       {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
-       {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
+       {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
+       {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
+       {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402},
+       {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
+       {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
+       {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
+       {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
+       {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
+       {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
+       {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
+       {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
+       {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
+       {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
+       {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861},
+       {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81},
+       {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83},
+       {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84},
+       {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3},
+       {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5},
+       {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9},
+       {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb},
+       {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
+       {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
        {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
        {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
        {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
        {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
-       {0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202},
-       {0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400},
-       {0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402},
-       {0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404},
-       {0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603},
-       {0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02},
-       {0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04},
-       {0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20},
-       {0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20},
-       {0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22},
-       {0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24},
-       {0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640},
-       {0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660},
-       {0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861},
-       {0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81},
-       {0x0000a5cc, 0x5a88442e, 0x5a88442e, 0x47801a83, 0x47801a83},
-       {0x0000a5d0, 0x5e8a4431, 0x5e8a4431, 0x4a801c84, 0x4a801c84},
-       {0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3},
-       {0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5},
-       {0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9},
-       {0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb},
-       {0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-       {0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-       {0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-       {0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-       {0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-       {0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
-       {0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
+       {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
+       {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
+       {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402},
+       {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404},
+       {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
+       {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
+       {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
+       {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
+       {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
+       {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
+       {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
+       {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
+       {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
+       {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861},
+       {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81},
+       {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83},
+       {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84},
+       {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3},
+       {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5},
+       {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9},
+       {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb},
+       {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
+       {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
        {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
        {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
-       {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
-       {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
-       {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
-       {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000},
-       {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501},
-       {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501},
-       {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03},
-       {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
-       {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04},
-       {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-       {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-       {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-       {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-       {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
-       {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
-       {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
-       {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
+       {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+       {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000},
+       {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501},
+       {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501},
+       {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03},
+       {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04},
+       {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04},
+       {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
+       {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
        {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
-       {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
-       {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
-       {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
+       {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
+       {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
+       {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
        {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
        {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-       {0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+       {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
        {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
        {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-       {0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+       {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
        {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
        {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
-       {0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
+       {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
        {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
 };
 
index 924c4616c3d990dc7f03e46ed299bdc94396d765..f5dda84176c3d4ae8277c069df06fa3bbc11922d 100644 (file)
@@ -38,6 +38,7 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
        { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */
        { USB_DEVICE(0x040D, 0x3801) }, /* VIA */
        { USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */
+       { USB_DEVICE(0x0cf3, 0xb002) }, /* Ubiquiti WifiStation */
        { USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */
 
        { USB_DEVICE(0x0cf3, 0x7015),
index 378bd70256b2c7b8ad6358b2488919198dc42950..741918a2027b56ebe0f561d5175e8a129b8a3059 100644 (file)
@@ -312,6 +312,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
        }
 
        bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
+       bf->bf_next = NULL;
        list_del(&bf->list);
 
        spin_unlock_bh(&sc->tx.txbuflock);
@@ -393,7 +394,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
        u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first;
        u32 ba[WME_BA_BMP_SIZE >> 5];
        int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
-       bool rc_update = true;
+       bool rc_update = true, isba;
        struct ieee80211_tx_rate rates[4];
        struct ath_frame_info *fi;
        int nframes;
@@ -437,13 +438,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
        tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
        tid = ATH_AN_2_TID(an, tidno);
        seq_first = tid->seq_start;
+       isba = ts->ts_flags & ATH9K_TX_BA;
 
        /*
         * The hardware occasionally sends a tx status for the wrong TID.
         * In this case, the BA status cannot be considered valid and all
         * subframes need to be retransmitted
+        *
+        * Only BlockAcks have a TID and therefore normal Acks cannot be
+        * checked
         */
-       if (tidno != ts->tid)
+       if (isba && tidno != ts->tid)
                txok = false;
 
        isaggr = bf_isaggr(bf);
@@ -1774,6 +1779,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
        list_add_tail(&bf->list, &bf_head);
        bf->bf_state.bf_type = 0;
 
+       bf->bf_next = NULL;
        bf->bf_lastbf = bf;
        ath_tx_fill_desc(sc, bf, txq, fi->framelen);
        ath_tx_txqaddbuf(sc, txq, &bf_head, false);
index 73730e94e0ac79fdbdf257f1cf969179e1c62a46..c5a99c8c81687de1b26a79bb2ad777c4d71c2029 100644 (file)
@@ -5404,6 +5404,8 @@ static void b43_bcma_remove(struct bcma_device *core)
        cancel_work_sync(&wldev->restart_work);
 
        B43_WARN_ON(!wl);
+       if (!wldev->fw.ucode.data)
+               return;                 /* NULL if firmware never loaded */
        if (wl->current_dev == wldev && wl->hw_registred) {
                b43_leds_stop(wldev);
                ieee80211_unregister_hw(wl->hw);
@@ -5478,6 +5480,8 @@ static void b43_ssb_remove(struct ssb_device *sdev)
        cancel_work_sync(&wldev->restart_work);
 
        B43_WARN_ON(!wl);
+       if (!wldev->fw.ucode.data)
+               return;                 /* NULL if firmware never loaded */
        if (wl->current_dev == wldev && wl->hw_registred) {
                b43_leds_stop(wldev);
                ieee80211_unregister_hw(wl->hw);
index a2b4b1e71017230b6d7ab262f52b45c4fa353bd7..7a6dfdc67b6cc5ed11ce8e5281cf45c5fa81818a 100644 (file)
@@ -1339,7 +1339,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
        }
 
        ret = brcmf_bus_start(dev);
-       if (ret == -ENOLINK) {
+       if (ret) {
                brcmf_dbg(ERROR, "dongle is not responding\n");
                brcmf_detach(dev);
                goto fail;
index c1abaa6db59ec97fc9da4a0419ba81ea922cfb42..a6f1e81660085766ffbd2b38ae896566f0e9eb3c 100644 (file)
@@ -3569,7 +3569,7 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
 
        if (!request || !request->n_ssids || !request->n_match_sets) {
                WL_ERR("Invalid sched scan req!! n_ssids:%d\n",
-                      request->n_ssids);
+                      request ? request->n_ssids : 0);
                return -EINVAL;
        }
 
@@ -3972,7 +3972,7 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
        u8  *iovar_ie_buf;
        u8  *curr_ie_buf;
        u8  *mgmt_ie_buf = NULL;
-       u32 mgmt_ie_buf_len = 0;
+       int mgmt_ie_buf_len;
        u32 *mgmt_ie_len = 0;
        u32 del_add_ie_buf_len = 0;
        u32 total_ie_buf_len = 0;
@@ -3982,7 +3982,7 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg,
        struct parsed_vndr_ie_info *vndrie_info;
        s32 i;
        u8 *ptr;
-       u32 remained_buf_len;
+       int remained_buf_len;
 
        WL_TRACE("bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag);
        iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
@@ -4606,12 +4606,13 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
        struct brcmf_cfg80211_profile *profile = cfg->profile;
        struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg);
        struct wiphy *wiphy = cfg_to_wiphy(cfg);
-       struct brcmf_channel_info_le channel_le;
-       struct ieee80211_channel *notify_channel;
+       struct ieee80211_channel *notify_channel = NULL;
        struct ieee80211_supported_band *band;
+       struct brcmf_bss_info_le *bi;
        u32 freq;
        s32 err = 0;
        u32 target_channel;
+       u8 *buf;
 
        WL_TRACE("Enter\n");
 
@@ -4619,11 +4620,22 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
        memcpy(profile->bssid, e->addr, ETH_ALEN);
        brcmf_update_bss_info(cfg);
 
-       brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le,
-                       sizeof(channel_le));
+       buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL);
+       if (buf == NULL) {
+               err = -ENOMEM;
+               goto done;
+       }
+
+       /* data sent to dongle has to be little endian */
+       *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX);
+       err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX);
+
+       if (err)
+               goto done;
 
-       target_channel = le32_to_cpu(channel_le.target_channel);
-       WL_CONN("Roamed to channel %d\n", target_channel);
+       bi = (struct brcmf_bss_info_le *)(buf + 4);
+       target_channel = bi->ctl_ch ? bi->ctl_ch :
+                                     CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec));
 
        if (target_channel <= CH_MAX_2G_CHANNEL)
                band = wiphy->bands[IEEE80211_BAND_2GHZ];
@@ -4633,6 +4645,8 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg,
        freq = ieee80211_channel_to_frequency(target_channel, band->band);
        notify_channel = ieee80211_get_channel(wiphy, freq);
 
+done:
+       kfree(buf);
        cfg80211_roamed(ndev, notify_channel, (u8 *)profile->bssid,
                        conn_info->req_ie, conn_info->req_ie_len,
                        conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
@@ -5186,41 +5200,6 @@ brcmf_cfg80211_event(struct net_device *ndev,
                schedule_work(&cfg->event_work);
 }
 
-static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype)
-{
-       s32 infra = 0;
-       s32 err = 0;
-
-       switch (iftype) {
-       case NL80211_IFTYPE_MONITOR:
-       case NL80211_IFTYPE_WDS:
-               WL_ERR("type (%d) : currently we do not support this mode\n",
-                      iftype);
-               err = -EINVAL;
-               return err;
-       case NL80211_IFTYPE_ADHOC:
-               infra = 0;
-               break;
-       case NL80211_IFTYPE_STATION:
-               infra = 1;
-               break;
-       case NL80211_IFTYPE_AP:
-               infra = 1;
-               break;
-       default:
-               err = -EINVAL;
-               WL_ERR("invalid type (%d)\n", iftype);
-               return err;
-       }
-       err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra);
-       if (err) {
-               WL_ERR("WLC_SET_INFRA error (%d)\n", err);
-               return err;
-       }
-
-       return 0;
-}
-
 static s32 brcmf_dongle_eventmsg(struct net_device *ndev)
 {
        /* Room for "event_msgs" + '\0' + bitvec */
@@ -5439,7 +5418,8 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
                                WL_BEACON_TIMEOUT);
        if (err)
                goto default_conf_out;
-       err = brcmf_dongle_mode(ndev, wdev->iftype);
+       err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype,
+                                         NULL, NULL);
        if (err && err != -EINPROGRESS)
                goto default_conf_out;
        err = brcmf_dongle_probecap(cfg);
index 935120fc8c9397daef4cb822b3d00176e0ca0cb8..768bf612533e04317feb756efa17563400ce6ab2 100644 (file)
@@ -10472,7 +10472,7 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv,
                } else
                        len = src->len;
 
-               dst = alloc_skb(len + sizeof(*rt_hdr), GFP_ATOMIC);
+               dst = alloc_skb(len + sizeof(*rt_hdr) + sizeof(u16)*2, GFP_ATOMIC);
                if (!dst)
                        continue;
 
index 349c205d5f62e218d3a76226b983818e92732a95..da5862064195159a7052fd92b327ce017b2d1381 100644 (file)
@@ -518,7 +518,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
         * See iwlagn_mac_channel_switch.
         */
        struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-       struct iwl6000_channel_switch_cmd cmd;
+       struct iwl6000_channel_switch_cmd *cmd;
        u32 switch_time_in_usec, ucode_switch_time;
        u16 ch;
        u32 tsf_low;
@@ -527,18 +527,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
        struct ieee80211_vif *vif = ctx->vif;
        struct iwl_host_cmd hcmd = {
                .id = REPLY_CHANNEL_SWITCH,
-               .len = { sizeof(cmd), },
+               .len = { sizeof(*cmd), },
                .flags = CMD_SYNC,
-               .data = { &cmd, },
+               .dataflags[0] = IWL_HCMD_DFL_NOCOPY,
        };
+       int err;
 
-       cmd.band = priv->band == IEEE80211_BAND_2GHZ;
+       cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+       if (!cmd)
+               return -ENOMEM;
+
+       hcmd.data[0] = cmd;
+
+       cmd->band = priv->band == IEEE80211_BAND_2GHZ;
        ch = ch_switch->channel->hw_value;
        IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
                      ctx->active.channel, ch);
-       cmd.channel = cpu_to_le16(ch);
-       cmd.rxon_flags = ctx->staging.flags;
-       cmd.rxon_filter_flags = ctx->staging.filter_flags;
+       cmd->channel = cpu_to_le16(ch);
+       cmd->rxon_flags = ctx->staging.flags;
+       cmd->rxon_filter_flags = ctx->staging.filter_flags;
        switch_count = ch_switch->count;
        tsf_low = ch_switch->timestamp & 0x0ffffffff;
        /*
@@ -554,23 +561,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
                        switch_count = 0;
        }
        if (switch_count <= 1)
-               cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
+               cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time);
        else {
                switch_time_in_usec =
                        vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
                ucode_switch_time = iwl_usecs_to_beacons(priv,
                                                         switch_time_in_usec,
                                                         beacon_interval);
-               cmd.switch_time = iwl_add_beacon_time(priv,
-                                                     priv->ucode_beacon_time,
-                                                     ucode_switch_time,
-                                                     beacon_interval);
+               cmd->switch_time = iwl_add_beacon_time(priv,
+                                                      priv->ucode_beacon_time,
+                                                      ucode_switch_time,
+                                                      beacon_interval);
        }
        IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
-                     cmd.switch_time);
-       cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
+                     cmd->switch_time);
+       cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
 
-       return iwl_dvm_send_cmd(priv, &hcmd);
+       err = iwl_dvm_send_cmd(priv, &hcmd);
+       kfree(cmd);
+       return err;
 }
 
 struct iwl_lib_ops iwl6000_lib = {
index 0679458a1bac44469ddf0d00935e7b165f66f9ed..780d3e168297fcf80c62e4345ac6d29c22007b73 100644 (file)
@@ -1825,8 +1825,6 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
                return -EBUSY;
        }
 
-       priv->scan_request = request;
-
        priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg),
                                      GFP_KERNEL);
        if (!priv->user_scan_cfg) {
@@ -1834,6 +1832,8 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
                return -ENOMEM;
        }
 
+       priv->scan_request = request;
+
        priv->user_scan_cfg->num_ssids = request->n_ssids;
        priv->user_scan_cfg->ssid_list = request->ssids;
 
@@ -1870,6 +1870,9 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
        ret = mwifiex_scan_networks(priv, priv->user_scan_cfg);
        if (ret) {
                dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
+               priv->scan_request = NULL;
+               kfree(priv->user_scan_cfg);
+               priv->user_scan_cfg = NULL;
                return ret;
        }
 
index 00b658d3b6ecfae72792b055a717aab9c41a0401..9171aaedbccdb28bf3371efcd5c7c89cecb3ab93 100644 (file)
@@ -1843,21 +1843,18 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
                                      struct cfg80211_ssid *req_ssid)
 {
        struct mwifiex_adapter *adapter = priv->adapter;
-       int ret = 0;
+       int ret;
        struct mwifiex_user_scan_cfg *scan_cfg;
 
-       if (!req_ssid)
-               return -1;
-
        if (adapter->scan_processing) {
-               dev_dbg(adapter->dev, "cmd: Scan already in process...\n");
-               return ret;
+               dev_err(adapter->dev, "cmd: Scan already in process...\n");
+               return -EBUSY;
        }
 
        if (priv->scan_block) {
-               dev_dbg(adapter->dev,
+               dev_err(adapter->dev,
                        "cmd: Scan is blocked during association...\n");
-               return ret;
+               return -EBUSY;
        }
 
        scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
index a12e84f892be1d9b13d1762a0369a7841af32645..6b2e1e431dd2fc579d1a2710b2b68ecfd47f043e 100644 (file)
@@ -1988,6 +1988,7 @@ static struct usb_driver rt2500usb_driver = {
        .disconnect     = rt2x00usb_disconnect,
        .suspend        = rt2x00usb_suspend,
        .resume         = rt2x00usb_resume,
+       .reset_resume   = rt2x00usb_resume,
        .disable_hub_initiated_lpm = 1,
 };
 
index 01dc8891070c3729c37b08cce18506ab583c4761..59474ae0aec0d14e7dfc2639c19cf65b82b3b7ea 100644 (file)
@@ -2449,7 +2449,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)
        /*
         * Check if temperature compensation is supported.
         */
-       if (tssi_bounds[4] == 0xff)
+       if (tssi_bounds[4] == 0xff || step == 0xff)
                return 0;
 
        /*
index c9e9370eb789c04ec91fd97a2a85d8d21977a144..3b8fb5a603f25244241a3219bff169962cf54733 100644 (file)
@@ -1282,6 +1282,7 @@ static struct usb_driver rt2800usb_driver = {
        .disconnect     = rt2x00usb_disconnect,
        .suspend        = rt2x00usb_suspend,
        .resume         = rt2x00usb_resume,
+       .reset_resume   = rt2x00usb_resume,
        .disable_hub_initiated_lpm = 1,
 };
 
index e5eb43b3eee74f94db85349436f0ba1e15925059..24eec66e9fd2049ae14aa709e7e2ecab0294751c 100644 (file)
@@ -2535,6 +2535,7 @@ static struct usb_driver rt73usb_driver = {
        .disconnect     = rt2x00usb_disconnect,
        .suspend        = rt2x00usb_suspend,
        .resume         = rt2x00usb_resume,
+       .reset_resume   = rt2x00usb_resume,
        .disable_hub_initiated_lpm = 1,
 };
 
index 030beb45d8b0b2b30669e945eb1ccc2e2cbd5fd7..e3ea4b346889430dfb07d604f052adb6522f18bb 100644 (file)
@@ -673,7 +673,7 @@ static int rtl_usb_start(struct ieee80211_hw *hw)
                set_hal_start(rtlhal);
 
                /* Start bulk IN */
-               _rtl_usb_receive(hw);
+               err = _rtl_usb_receive(hw);
        }
 
        return err;
index 0f1ec9e8ff14b02448877cb4f4872f45baeeccd3..2e39c04fc16bb4be31dba8800477aafed2e64441 100644 (file)
@@ -1061,8 +1061,10 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
                        seq_printf(s, "group: %s\n", gname);
                        for (i = 0; i < num_pins; i++) {
                                pname = pin_get_name(pctldev, pins[i]);
-                               if (WARN_ON(!pname))
+                               if (WARN_ON(!pname)) {
+                                       mutex_unlock(&pinctrl_mutex);
                                        return -EINVAL;
+                               }
                                seq_printf(s, "pin %d (%s)\n", pins[i], pname);
                        }
                        seq_puts(s, "\n");
index 43f474cdc11082717c881b757c6bcaf104bcbb97..baee2cc46a17a7c5c328f98c7eaa25f8f10d8fba 100644 (file)
@@ -537,8 +537,6 @@ static int pinconf_groups_show(struct seq_file *s, void *what)
        seq_puts(s, "Pin config settings per pin group\n");
        seq_puts(s, "Format: group (name): configs\n");
 
-       mutex_lock(&pinctrl_mutex);
-
        while (selector < ngroups) {
                const char *gname = pctlops->get_group_name(pctldev, selector);
 
@@ -549,8 +547,6 @@ static int pinconf_groups_show(struct seq_file *s, void *what)
                selector++;
        }
 
-       mutex_unlock(&pinctrl_mutex);
-
        return 0;
 }
 
index 01aea1c3b5fa3188a50cfe4e41ea13e48c50f56d..cf82d9ce4deeccc8c19c6104103fee84854c945a 100644 (file)
@@ -1056,7 +1056,7 @@ static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
        struct nmk_gpio_chip *nmk_chip =
                container_of(chip, struct nmk_gpio_chip, chip);
 
-       return irq_find_mapping(nmk_chip->domain, offset);
+       return irq_create_mapping(nmk_chip->domain, offset);
 }
 
 #ifdef CONFIG_DEBUG_FS
@@ -1281,7 +1281,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
        struct clk *clk;
        int secondary_irq;
        void __iomem *base;
-       int irq_start = -1;
+       int irq_start = 0;
        int irq;
        int ret;
 
@@ -1387,7 +1387,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
 
        if (!np)
                irq_start = NOMADIK_GPIO_TO_IRQ(pdata->first_gpio);
-       nmk_chip->domain = irq_domain_add_simple(NULL,
+       nmk_chip->domain = irq_domain_add_simple(np,
                                NMK_GPIO_PER_CHIP, irq_start,
                                &nmk_gpio_irq_simple_ops, nmk_chip);
        if (!nmk_chip->domain) {
index 729b686c3ad2338e2d4878ed0e1623674ba87f3f..7da0b371fd652a04ac7d55ecf89c55c915d19f8b 100644 (file)
@@ -464,7 +464,7 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx,
                *bank = g->drv_bank;
                *reg = g->drv_reg;
                *bit = g->lpmd_bit;
-               *width = 1;
+               *width = 2;
                break;
        case TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH:
                *bank = g->drv_bank;
index 0386fdf0da16441ecc874b1710e55a929d44325a..7894f14c70590058726a6c07da4286e1640058db 100644 (file)
@@ -3345,10 +3345,10 @@ static const struct tegra_function tegra30_functions[] = {
        FUNCTION(vi_alt3),
 };
 
-#define MUXCTL_REG_A   0x3000
-#define PINGROUP_REG_A 0x868
+#define DRV_PINGROUP_REG_A     0x868   /* bank 0 */
+#define PINGROUP_REG_A         0x3000  /* bank 1 */
 
-#define PINGROUP_REG_Y(r) ((r) - MUXCTL_REG_A)
+#define PINGROUP_REG_Y(r) ((r) - PINGROUP_REG_A)
 #define PINGROUP_REG_N(r) -1
 
 #define PINGROUP(pg_name, f0, f1, f2, f3, f_safe, r, od, ior)  \
@@ -3364,25 +3364,25 @@ static const struct tegra_function tegra30_functions[] = {
                },                                              \
                .func_safe = TEGRA_MUX_ ## f_safe,              \
                .mux_reg = PINGROUP_REG_Y(r),                   \
-               .mux_bank = 0,                                  \
+               .mux_bank = 1,                                  \
                .mux_bit = 0,                                   \
                .pupd_reg = PINGROUP_REG_Y(r),                  \
-               .pupd_bank = 0,                                 \
+               .pupd_bank = 1,                                 \
                .pupd_bit = 2,                                  \
                .tri_reg = PINGROUP_REG_Y(r),                   \
-               .tri_bank = 0,                                  \
+               .tri_bank = 1,                                  \
                .tri_bit = 4,                                   \
                .einput_reg = PINGROUP_REG_Y(r),                \
-               .einput_bank = 0,                               \
+               .einput_bank = 1,                               \
                .einput_bit = 5,                                \
                .odrain_reg = PINGROUP_REG_##od(r),             \
-               .odrain_bank = 0,                               \
+               .odrain_bank = 1,                               \
                .odrain_bit = 6,                                \
                .lock_reg = PINGROUP_REG_Y(r),                  \
-               .lock_bank = 0,                                 \
+               .lock_bank = 1,                                 \
                .lock_bit = 7,                                  \
                .ioreset_reg = PINGROUP_REG_##ior(r),           \
-               .ioreset_bank = 0,                              \
+               .ioreset_bank = 1,                              \
                .ioreset_bit = 8,                               \
                .drv_reg = -1,                                  \
        }
@@ -3401,8 +3401,8 @@ static const struct tegra_function tegra30_functions[] = {
                .odrain_reg = -1,                               \
                .lock_reg = -1,                                 \
                .ioreset_reg = -1,                              \
-               .drv_reg = ((r) - PINGROUP_REG_A),              \
-               .drv_bank = 1,                                  \
+               .drv_reg = ((r) - DRV_PINGROUP_REG_A),          \
+               .drv_bank = 0,                                  \
                .hsm_bit = hsm_b,                               \
                .schmitt_bit = schmitt_b,                       \
                .lpmd_bit = lpmd_b,                             \
index 891cd6c61d0ae76112ccc0f6b6da3876d21569ad..4eed51044c5dd331f576fc1b1b71655e5f932366 100644 (file)
@@ -392,6 +392,8 @@ static int dryice_rtc_probe(struct platform_device *pdev)
        if (imxdi->ioaddr == NULL)
                return -ENOMEM;
 
+       spin_lock_init(&imxdi->irq_lock);
+
        imxdi->irq = platform_get_irq(pdev, 0);
        if (imxdi->irq < 0)
                return imxdi->irq;
index b4d572f65f079d93650cebd8ff5f7bb39bcb75d2..fd00afd8b850da2abaa916ba485dccd748939319 100644 (file)
@@ -377,7 +377,11 @@ static int css_evaluate_new_subchannel(struct subchannel_id schid, int slow)
                /* Will be done on the slow path. */
                return -EAGAIN;
        }
-       if (stsch_err(schid, &schib) || !css_sch_is_valid(&schib)) {
+       if (stsch_err(schid, &schib)) {
+               /* Subchannel is not provided. */
+               return -ENXIO;
+       }
+       if (!css_sch_is_valid(&schib)) {
                /* Unusable - ignore. */
                return 0;
        }
@@ -536,6 +540,7 @@ static int slow_eval_unknown_fn(struct subchannel_id schid, void *data)
                case -ENOMEM:
                case -EIO:
                        /* These should abort looping */
+                       idset_sch_del_subseq(slow_subchannel_set, schid);
                        break;
                default:
                        rc = 0;
index e6d5f8c49524d05f78f6548a2937b1747bd7ffe6..199bc6791177491bea28b360845911a282b259b5 100644 (file)
@@ -1,9 +1,10 @@
 /*
- *    Copyright IBM Corp. 2007
+ *    Copyright IBM Corp. 2007, 2012
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
 
 #include <linux/vmalloc.h>
+#include <linux/bitmap.h>
 #include <linux/bitops.h>
 #include "idset.h"
 #include "css.h"
@@ -89,6 +90,14 @@ void idset_sch_del(struct idset *set, struct subchannel_id schid)
        idset_del(set, schid.ssid, schid.sch_no);
 }
 
+/* Clear ids starting from @schid up to end of subchannel set. */
+void idset_sch_del_subseq(struct idset *set, struct subchannel_id schid)
+{
+       int pos = schid.ssid * set->num_id + schid.sch_no;
+
+       bitmap_clear(set->bitmap, pos, set->num_id - schid.sch_no);
+}
+
 int idset_sch_contains(struct idset *set, struct subchannel_id schid)
 {
        return idset_contains(set, schid.ssid, schid.sch_no);
@@ -111,20 +120,13 @@ int idset_sch_get_first(struct idset *set, struct subchannel_id *schid)
 
 int idset_is_empty(struct idset *set)
 {
-       int bitnum;
-
-       bitnum = find_first_bit(set->bitmap, set->num_ssid * set->num_id);
-       if (bitnum >= set->num_ssid * set->num_id)
-               return 1;
-       return 0;
+       return bitmap_empty(set->bitmap, set->num_ssid * set->num_id);
 }
 
 void idset_add_set(struct idset *to, struct idset *from)
 {
-       unsigned long i, len;
+       int len = min(__BITOPS_WORDS(to->num_ssid * to->num_id),
+                     __BITOPS_WORDS(from->num_ssid * from->num_id));
 
-       len = min(__BITOPS_WORDS(to->num_ssid * to->num_id),
-                 __BITOPS_WORDS(from->num_ssid * from->num_id));
-       for (i = 0; i < len ; i++)
-               to->bitmap[i] |= from->bitmap[i];
+       bitmap_or(to->bitmap, to->bitmap, from->bitmap, len);
 }
index 3d943f03591e1b2180cc6fdd9c92e54c99a0d0e4..06d3bc01bb0934a52198349da2657e8787c46c13 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    Copyright IBM Corp. 2007
+ *    Copyright IBM Corp. 2007, 2012
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
 
@@ -17,6 +17,7 @@ void idset_fill(struct idset *set);
 struct idset *idset_sch_new(void);
 void idset_sch_add(struct idset *set, struct subchannel_id id);
 void idset_sch_del(struct idset *set, struct subchannel_id id);
+void idset_sch_del_subseq(struct idset *set, struct subchannel_id schid);
 int idset_sch_contains(struct idset *set, struct subchannel_id id);
 int idset_sch_get_first(struct idset *set, struct subchannel_id *id);
 int idset_is_empty(struct idset *set);
index bd4708a422cd78b09fd8594ded593af775343398..20fd974f903afd5d4ae15c95db2549d49db52849 100644 (file)
@@ -149,6 +149,7 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)
 int
 qla24xx_disable_vp(scsi_qla_host_t *vha)
 {
+       unsigned long flags;
        int ret;
 
        ret = qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL);
@@ -156,7 +157,9 @@ qla24xx_disable_vp(scsi_qla_host_t *vha)
        atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
 
        /* Remove port id from vp target map */
+       spin_lock_irqsave(&vha->hw->vport_slock, flags);
        qlt_update_vp_map(vha, RESET_AL_PA);
+       spin_unlock_irqrestore(&vha->hw->vport_slock, flags);
 
        qla2x00_mark_vp_devices_dead(vha);
        atomic_set(&vha->vp_state, VP_FAILED);
index 0e09d8f433d1683e61ba61074d7c67b71919d970..62aa5584f64478d286e373414dd8b119315a5204 100644 (file)
@@ -557,6 +557,7 @@ static bool qlt_check_fcport_exist(struct scsi_qla_host *vha,
        int pmap_len;
        fc_port_t *fcport;
        int global_resets;
+       unsigned long flags;
 
 retry:
        global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count);
@@ -625,10 +626,10 @@ retry:
            sess->s_id.b.area, sess->loop_id, fcport->d_id.b.domain,
            fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id);
 
-       sess->s_id = fcport->d_id;
-       sess->loop_id = fcport->loop_id;
-       sess->conf_compl_supported = !!(fcport->flags &
-           FCF_CONF_COMP_SUPPORTED);
+       spin_lock_irqsave(&ha->hardware_lock, flags);
+       ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
+                               (fcport->flags & FCF_CONF_COMP_SUPPORTED));
+       spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        res = true;
 
@@ -740,10 +741,9 @@ static struct qla_tgt_sess *qlt_create_sess(
                                qlt_undelete_sess(sess);
 
                        kref_get(&sess->se_sess->sess_kref);
-                       sess->s_id = fcport->d_id;
-                       sess->loop_id = fcport->loop_id;
-                       sess->conf_compl_supported = !!(fcport->flags &
-                           FCF_CONF_COMP_SUPPORTED);
+                       ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
+                                               (fcport->flags & FCF_CONF_COMP_SUPPORTED));
+
                        if (sess->local && !local)
                                sess->local = 0;
                        spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -796,8 +796,7 @@ static struct qla_tgt_sess *qlt_create_sess(
         */
        kref_get(&sess->se_sess->sess_kref);
 
-       sess->conf_compl_supported = !!(fcport->flags &
-           FCF_CONF_COMP_SUPPORTED);
+       sess->conf_compl_supported = (fcport->flags & FCF_CONF_COMP_SUPPORTED);
        BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name));
        memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name));
 
@@ -869,10 +868,8 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
                        ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007,
                            "Reappeared sess %p\n", sess);
                }
-               sess->s_id = fcport->d_id;
-               sess->loop_id = fcport->loop_id;
-               sess->conf_compl_supported = !!(fcport->flags &
-                   FCF_CONF_COMP_SUPPORTED);
+               ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
+                                       (fcport->flags & FCF_CONF_COMP_SUPPORTED));
        }
 
        if (sess && sess->local) {
index 170af1571214095fe82db73fa52f520c16a8197b..bad749561ec2ae4fe57e3ea28763ec627f0b18f1 100644 (file)
@@ -648,6 +648,7 @@ struct qla_tgt_func_tmpl {
 
        int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *,
                                        void *, uint8_t *, uint16_t);
+       void (*update_sess)(struct qla_tgt_sess *, port_id_t, uint16_t, bool);
        struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *,
                                                const uint16_t);
        struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *,
index 2358c16c4c8ea8a0cdb85c33c2c97a5b4e65c400..3d74f2f39ae18954ac825f4599b689d770f494cf 100644 (file)
@@ -237,7 +237,7 @@ static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg)
                                struct tcm_qla2xxx_tpg, se_tpg);
        struct tcm_qla2xxx_lport *lport = tpg->lport;
 
-       return &lport->lport_name[0];
+       return lport->lport_naa_name;
 }
 
 static char *tcm_qla2xxx_npiv_get_fabric_wwn(struct se_portal_group *se_tpg)
@@ -1457,6 +1457,78 @@ static int tcm_qla2xxx_check_initiator_node_acl(
        return 0;
 }
 
+static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
+                                   uint16_t loop_id, bool conf_compl_supported)
+{
+       struct qla_tgt *tgt = sess->tgt;
+       struct qla_hw_data *ha = tgt->ha;
+       struct tcm_qla2xxx_lport *lport = ha->tgt.target_lport_ptr;
+       struct se_node_acl *se_nacl = sess->se_sess->se_node_acl;
+       struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl,
+                       struct tcm_qla2xxx_nacl, se_node_acl);
+       u32 key;
+
+
+       if (sess->loop_id != loop_id || sess->s_id.b24 != s_id.b24)
+               pr_info("Updating session %p from port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x loop_id %d -> %d s_id %x:%x:%x -> %x:%x:%x\n",
+                       sess,
+                       sess->port_name[0], sess->port_name[1],
+                       sess->port_name[2], sess->port_name[3],
+                       sess->port_name[4], sess->port_name[5],
+                       sess->port_name[6], sess->port_name[7],
+                       sess->loop_id, loop_id,
+                       sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa,
+                       s_id.b.domain, s_id.b.area, s_id.b.al_pa);
+
+       if (sess->loop_id != loop_id) {
+               /*
+                * Because we can shuffle loop IDs around and we
+                * update different sessions non-atomically, we might
+                * have overwritten this session's old loop ID
+                * already, and we might end up overwriting some other
+                * session that will be updated later.  So we have to
+                * be extra careful and we can't warn about those things...
+                */
+               if (lport->lport_loopid_map[sess->loop_id].se_nacl == se_nacl)
+                       lport->lport_loopid_map[sess->loop_id].se_nacl = NULL;
+
+               lport->lport_loopid_map[loop_id].se_nacl = se_nacl;
+
+               sess->loop_id = loop_id;
+       }
+
+       if (sess->s_id.b24 != s_id.b24) {
+               key = (((u32) sess->s_id.b.domain << 16) |
+                      ((u32) sess->s_id.b.area   <<  8) |
+                      ((u32) sess->s_id.b.al_pa));
+
+               if (btree_lookup32(&lport->lport_fcport_map, key))
+                       WARN(btree_remove32(&lport->lport_fcport_map, key) != se_nacl,
+                            "Found wrong se_nacl when updating s_id %x:%x:%x\n",
+                            sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa);
+               else
+                       WARN(1, "No lport_fcport_map entry for s_id %x:%x:%x\n",
+                            sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa);
+
+               key = (((u32) s_id.b.domain << 16) |
+                      ((u32) s_id.b.area   <<  8) |
+                      ((u32) s_id.b.al_pa));
+
+               if (btree_lookup32(&lport->lport_fcport_map, key)) {
+                       WARN(1, "Already have lport_fcport_map entry for s_id %x:%x:%x\n",
+                            s_id.b.domain, s_id.b.area, s_id.b.al_pa);
+                       btree_update32(&lport->lport_fcport_map, key, se_nacl);
+               } else {
+                       btree_insert32(&lport->lport_fcport_map, key, se_nacl, GFP_ATOMIC);
+               }
+
+               sess->s_id = s_id;
+               nacl->nport_id = key;
+       }
+
+       sess->conf_compl_supported = conf_compl_supported;
+}
+
 /*
  * Calls into tcm_qla2xxx used by qla2xxx LLD I/O path.
  */
@@ -1467,6 +1539,7 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
        .free_cmd               = tcm_qla2xxx_free_cmd,
        .free_mcmd              = tcm_qla2xxx_free_mcmd,
        .free_session           = tcm_qla2xxx_free_session,
+       .update_sess            = tcm_qla2xxx_update_sess,
        .check_initiator_node_acl = tcm_qla2xxx_check_initiator_node_acl,
        .find_sess_by_s_id      = tcm_qla2xxx_find_sess_by_s_id,
        .find_sess_by_loop_id   = tcm_qla2xxx_find_sess_by_loop_id,
@@ -1534,6 +1607,7 @@ static struct se_wwn *tcm_qla2xxx_make_lport(
        lport->lport_wwpn = wwpn;
        tcm_qla2xxx_format_wwn(&lport->lport_name[0], TCM_QLA2XXX_NAMELEN,
                                wwpn);
+       sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) wwpn);
 
        ret = tcm_qla2xxx_init_lport(lport);
        if (ret != 0)
@@ -1601,6 +1675,7 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport(
        lport->lport_npiv_wwnn = npiv_wwnn;
        tcm_qla2xxx_npiv_format_wwn(&lport->lport_npiv_name[0],
                        TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn);
+       sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) npiv_wwpn);
 
 /* FIXME: tcm_qla2xxx_npiv_make_lport */
        ret = -ENOSYS;
index 8254981033524466bc372ac4bbd067aa5d19cc5b..9ba075fe9781f0148dca9aa73b6525e554a91154 100644 (file)
@@ -61,6 +61,8 @@ struct tcm_qla2xxx_lport {
        u64 lport_npiv_wwnn;
        /* ASCII formatted WWPN for FC Target Lport */
        char lport_name[TCM_QLA2XXX_NAMELEN];
+       /* ASCII formatted naa WWPN for VPD page 83 etc */
+       char lport_naa_name[TCM_QLA2XXX_NAMELEN];
        /* ASCII formatted WWPN+WWNN for NPIV FC Target Lport */
        char lport_npiv_name[TCM_QLA2XXX_NPIV_NAMELEN];
        /* map for fc_port pointers in 24-bit FC Port ID space */
index edf1360ab09e5be8311b7338a28d75ce8bbb46a3..86dd04d6bc873dfa30f0bab1148bd863aac818fc 100644 (file)
@@ -323,6 +323,7 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs,
        if (!ret) {
                dev_err(ssp->dev, "DMA transfer timeout\n");
                ret = -ETIMEDOUT;
+               dmaengine_terminate_all(ssp->dmach);
                goto err_vmalloc;
        }
 
@@ -480,7 +481,7 @@ static int mxs_spi_transfer_one(struct spi_master *master,
                first = last = 0;
        }
 
-       m->status = 0;
+       m->status = status;
        spi_finalize_current_message(master);
 
        return status;
index 919464102d33afb2d493ace07c81c80403d1d51d..a1db91a99b89a670cb7979c5fd758c90796aa2a9 100644 (file)
@@ -2186,8 +2186,6 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
        printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",
               adev->res.start, pl022->virtbase);
 
-       pm_runtime_resume(dev);
-
        pl022->clk = devm_clk_get(&adev->dev, NULL);
        if (IS_ERR(pl022->clk)) {
                status = PTR_ERR(pl022->clk);
@@ -2292,7 +2290,6 @@ pl022_remove(struct amba_device *adev)
 
        clk_disable(pl022->clk);
        clk_unprepare(pl022->clk);
-       pm_runtime_disable(&adev->dev);
        amba_release_regions(adev);
        tasklet_disable(&pl022->pump_transfers);
        spi_unregister_master(pl022->master);
index 4894bde4bbffea3f65d7ff30db4277c92ab79587..30faf6d4ab9135c84ecd8f359626ddd75e896b60 100644 (file)
@@ -147,8 +147,6 @@ struct rspi_data {
        unsigned char spsr;
 
        /* for dmaengine */
-       struct sh_dmae_slave dma_tx;
-       struct sh_dmae_slave dma_rx;
        struct dma_chan *chan_tx;
        struct dma_chan *chan_rx;
        int irq;
@@ -663,20 +661,16 @@ static irqreturn_t rspi_irq(int irq, void *_sr)
        return ret;
 }
 
-static bool rspi_filter(struct dma_chan *chan, void *filter_param)
-{
-       chan->private = filter_param;
-       return true;
-}
-
-static void __devinit rspi_request_dma(struct rspi_data *rspi,
-                                      struct platform_device *pdev)
+static int __devinit rspi_request_dma(struct rspi_data *rspi,
+                                     struct platform_device *pdev)
 {
        struct rspi_plat_data *rspi_pd = pdev->dev.platform_data;
        dma_cap_mask_t mask;
+       struct dma_slave_config cfg;
+       int ret;
 
        if (!rspi_pd)
-               return;
+               return 0;       /* The driver assumes no error. */
 
        rspi->dma_width_16bit = rspi_pd->dma_width_16bit;
 
@@ -684,21 +678,35 @@ static void __devinit rspi_request_dma(struct rspi_data *rspi,
        if (rspi_pd->dma_rx_id && rspi_pd->dma_tx_id) {
                dma_cap_zero(mask);
                dma_cap_set(DMA_SLAVE, mask);
-               rspi->dma_rx.slave_id = rspi_pd->dma_rx_id;
-               rspi->chan_rx = dma_request_channel(mask, rspi_filter,
-                                                   &rspi->dma_rx);
-               if (rspi->chan_rx)
-                       dev_info(&pdev->dev, "Use DMA when rx.\n");
+               rspi->chan_rx = dma_request_channel(mask, shdma_chan_filter,
+                                                   (void *)rspi_pd->dma_rx_id);
+               if (rspi->chan_rx) {
+                       cfg.slave_id = rspi_pd->dma_rx_id;
+                       cfg.direction = DMA_DEV_TO_MEM;
+                       ret = dmaengine_slave_config(rspi->chan_rx, &cfg);
+                       if (!ret)
+                               dev_info(&pdev->dev, "Use DMA when rx.\n");
+                       else
+                               return ret;
+               }
        }
        if (rspi_pd->dma_tx_id) {
                dma_cap_zero(mask);
                dma_cap_set(DMA_SLAVE, mask);
-               rspi->dma_tx.slave_id = rspi_pd->dma_tx_id;
-               rspi->chan_tx = dma_request_channel(mask, rspi_filter,
-                                                   &rspi->dma_tx);
-               if (rspi->chan_tx)
-                       dev_info(&pdev->dev, "Use DMA when tx\n");
+               rspi->chan_tx = dma_request_channel(mask, shdma_chan_filter,
+                                                   (void *)rspi_pd->dma_tx_id);
+               if (rspi->chan_tx) {
+                       cfg.slave_id = rspi_pd->dma_tx_id;
+                       cfg.direction = DMA_MEM_TO_DEV;
+                       ret = dmaengine_slave_config(rspi->chan_tx, &cfg);
+                       if (!ret)
+                               dev_info(&pdev->dev, "Use DMA when tx\n");
+                       else
+                               return ret;
+               }
        }
+
+       return 0;
 }
 
 static void __devexit rspi_release_dma(struct rspi_data *rspi)
@@ -788,7 +796,11 @@ static int __devinit rspi_probe(struct platform_device *pdev)
        }
 
        rspi->irq = irq;
-       rspi_request_dma(rspi, pdev);
+       ret = rspi_request_dma(rspi, pdev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "rspi_request_dma failed.\n");
+               goto error4;
+       }
 
        ret = spi_register_master(master);
        if (ret < 0) {
index 7b0ba92e7e46730d1d5c72137c9f1b2b9ddc3201..5d4610babd8a6a48e4d5ac161a04db7322ad2892 100644 (file)
@@ -567,7 +567,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
                page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
 
                BUG_ON(*page);
-               *page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+               *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
                if (*page == NULL) {
                        pr_err("binder: %d: binder_alloc_buf failed "
                               "for page at %p\n", proc->pid, page_addr);
@@ -2419,14 +2419,38 @@ static void binder_release_work(struct list_head *list)
                        struct binder_transaction *t;
 
                        t = container_of(w, struct binder_transaction, work);
-                       if (t->buffer->target_node && !(t->flags & TF_ONE_WAY))
+                       if (t->buffer->target_node &&
+                           !(t->flags & TF_ONE_WAY)) {
                                binder_send_failed_reply(t, BR_DEAD_REPLY);
+                       } else {
+                               binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+                                       "binder: undelivered transaction %d\n",
+                                       t->debug_id);
+                               t->buffer->transaction = NULL;
+                               kfree(t);
+                               binder_stats_deleted(BINDER_STAT_TRANSACTION);
+                       }
                } break;
                case BINDER_WORK_TRANSACTION_COMPLETE: {
+                       binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+                               "binder: undelivered TRANSACTION_COMPLETE\n");
                        kfree(w);
                        binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
                } break;
+               case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
+               case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
+                       struct binder_ref_death *death;
+
+                       death = container_of(w, struct binder_ref_death, work);
+                       binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+                               "binder: undelivered death notification, %p\n",
+                               death->cookie);
+                       kfree(death);
+                       binder_stats_deleted(BINDER_STAT_DEATH);
+               } break;
                default:
+                       pr_err("binder: unexpected work type, %d, not freed\n",
+                              w->type);
                        break;
                }
        }
@@ -2899,6 +2923,7 @@ static void binder_deferred_release(struct binder_proc *proc)
                nodes++;
                rb_erase(&node->rb_node, &proc->nodes);
                list_del_init(&node->work.entry);
+               binder_release_work(&node->async_todo);
                if (hlist_empty(&node->refs)) {
                        kfree(node);
                        binder_stats_deleted(BINDER_STAT_NODE);
@@ -2937,6 +2962,7 @@ static void binder_deferred_release(struct binder_proc *proc)
                binder_delete_ref(ref);
        }
        binder_release_work(&proc->todo);
+       binder_release_work(&proc->delivered_death);
        buffers = 0;
 
        while ((n = rb_first(&proc->allocated_buffers))) {
index 7dff3c01dc29ef3286d5559065a1c2c9e52819d5..d00aff6671df961c475f41bb3bb3141b41d5f83f 100644 (file)
@@ -289,6 +289,8 @@ static void pci_8255_detach(struct comedi_device *dev)
        struct comedi_subdevice *s;
        int i;
 
+       if (!board || !devpriv)
+               return;
        if (dev->subdevices) {
                for (i = 0; i < board->n_8255; i++) {
                        s = &dev->subdevices[i];
index 08f305210a695d57e1ef2c8181ec3d47b2f62c53..29eb52d11d2f7b3ef6b2a7f1372e3b99f95862fc 100644 (file)
@@ -1410,6 +1410,8 @@ static void dio200_detach(struct comedi_device *dev)
        const struct dio200_layout_struct *layout;
        unsigned n;
 
+       if (!thisboard)
+               return;
        if (dev->irq)
                free_irq(dev->irq, dev);
        if (dev->subdevices) {
index eacb5e4735d7df0a3ccf7e794bb0744ab936f71a..4e4f3c15df87e9db99528806b15ba48c54a558c2 100644 (file)
@@ -573,9 +573,10 @@ static int __devinit pc236_attach_pci(struct comedi_device *dev,
 static void pc236_detach(struct comedi_device *dev)
 {
        const struct pc236_board *thisboard = comedi_board(dev);
-       struct pc236_private *devpriv = dev->private;
 
-       if (devpriv)
+       if (!thisboard)
+               return;
+       if (dev->iobase)
                pc236_intr_disable(dev);
        if (dev->irq)
                free_irq(dev->irq, dev);
index 60830ccfb903f48fc9720490040d59bc113f0c5c..d0a4c441228b405d4459f70cb264b13717c26161 100644 (file)
@@ -323,6 +323,8 @@ static void pc263_detach(struct comedi_device *dev)
 {
        const struct pc263_board *thisboard = comedi_board(dev);
 
+       if (!thisboard)
+               return;
        if (is_isa_board(thisboard)) {
                if (dev->iobase)
                        release_region(dev->iobase, PC263_IO_SIZE);
index 5fd21fa6c1c76d25f910c41ca26ecec86b8894e8..c304528cfb1341293255f097620c1d1f8877c7fe 100644 (file)
@@ -846,6 +846,8 @@ static void __maybe_unused das08_detach(struct comedi_device *dev)
 {
        const struct das08_board_struct *thisboard = comedi_board(dev);
 
+       if (!thisboard)
+               return;
        das08_common_detach(dev);
        if (is_isa_board(thisboard)) {
                if (dev->iobase)
index 2ba0ade45c6484b940b1ed9559a4bd85f96e5a84..68d7c6a5db7dac901fd2f208f923106930c3553f 100644 (file)
@@ -95,7 +95,7 @@ static int daq700_dio_insn_bits(struct comedi_device *dev,
        }
 
        data[1] = s->state & 0xff;
-       data[1] |= inb(dev->iobase + DIO_R);
+       data[1] |= inb(dev->iobase + DIO_R) << 8;
 
        return insn->n;
 }
index 28b91a6c378908ba2f30b01b88a11d819b3dd9f7..b5a19a0863fbb8ba3e7fe2842f66b0611992b054 100644 (file)
@@ -772,6 +772,8 @@ void labpc_common_detach(struct comedi_device *dev)
 {
        struct comedi_subdevice *s;
 
+       if (!thisboard)
+               return;
        if (dev->subdevices) {
                s = &dev->subdevices[2];
                subdev_8255_cleanup(dev, s);
index 8e37d6e04277663d7b7d135a5dd653f050a16785..b12ca68cd9e4f286191349ba148aabcf3b9d6e56 100644 (file)
@@ -310,30 +310,32 @@ static int adis16201_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 1220;
-                       else
-                               *val2 = 610;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 220000; /* 1.22 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 610000; /* 0.610 mV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = -470000;
+                       *val = -470; /* 0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
-                       *val2 = 462500;
-                       return IIO_VAL_INT_PLUS_MICRO;
+                       *val2 = IIO_G_TO_M_S_2(462400); /* 0.4624 mg */
+                       return IIO_VAL_INT_PLUS_NANO;
                case IIO_INCLI:
                        *val = 0;
-                       *val2 = 100000;
+                       *val2 = 100000; /* 0.1 degree */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
                break;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / -470 - 1278; /* 25 C = 1278 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                switch (chan->type) {
index 002fa9dfc3756ee5052c9039dd7bb2af48473168..e7b3441115aee59861571a40ebecaaf45a4160e7 100644 (file)
@@ -316,25 +316,27 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 1220;
-                       else
-                               *val2 = 610;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 220000; /* 1.22 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 610000; /* 0.61 mV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = -470000;
+                       *val = -470; /* -0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_INCLI:
                        *val = 0;
-                       *val2 = 25000;
+                       *val2 = 25000; /* 0.025 degree */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / -470 - 1278; /* 25 C = 1278 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                bits = 14;
index 05bdb7c2c8e3f100953c8b0fde872ae367f26c45..c6234c2f46aabdac362921e903fcdfa955f4a8a8 100644 (file)
@@ -317,26 +317,28 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 1220;
-                       else
-                               *val2 = 610;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 220000; /* 1.22 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 610000; /* 0.61 mV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = -470000;
+                       *val = -470; /* 0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
                        switch (chan->channel2) {
                        case IIO_MOD_X:
                        case IIO_MOD_ROOT_SUM_SQUARED_X_Y:
-                               *val2 = 17125;
+                               *val2 = IIO_G_TO_M_S_2(17125); /* 17.125 mg */
                                break;
                        case IIO_MOD_Y:
                        case IIO_MOD_Z:
-                               *val2 = 8407;
+                               *val2 = IIO_G_TO_M_S_2(8407); /* 8.407 mg */
                                break;
                        }
                        return IIO_VAL_INT_PLUS_MICRO;
@@ -345,7 +347,7 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
                }
                break;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / -470 - 1278; /* 25 C = 1278 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
        case IIO_CHAN_INFO_PEAK:
index b7333bfe0b2f1312a51548a731e73f2f41bd36ba..7ee974b45d7d3a3eb354ef073a1094c9183f26c3 100644 (file)
@@ -343,28 +343,29 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
                case IIO_VOLTAGE:
                        *val = 0;
                        if (chan->channel == 0)
-                               *val2 = 305180;
+                               *val2 = 305180; /* 0.30518 mV */
                        else
-                               *val2 = 610500;
+                               *val2 = 610500; /* 0.6105 mV */
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = -470000;
+                       *val = -470; /* -0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
-                       *val2 = 2394;
-                       return IIO_VAL_INT_PLUS_MICRO;
+                       *val2 = IIO_G_TO_M_S_2(244140); /* 0.244140 mg */
+                       return IIO_VAL_INT_PLUS_NANO;
                case IIO_INCLI:
+               case IIO_ROT:
                        *val = 0;
-                       *val2 = 436;
+                       *val2 = 25000; /* 0.025 degree */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
                break;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / -470 - 0x4FE; /* 25 C = 0x4FE */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                switch (chan->type) {
@@ -491,6 +492,7 @@ static const struct iio_chan_spec adis16209_channels[] = {
                .modified = 1,
                .channel2 = IIO_MOD_X,
                .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+               IIO_CHAN_INFO_SCALE_SHARED_BIT,
                .address = rot,
                .scan_index = ADIS16209_SCAN_ROT,
                .scan_type = {
index c755089c711715802ce6e90818a35bae41941acb..eaadd9df3f78360c111b54b05ac3b93a96ba7cb7 100644 (file)
@@ -486,7 +486,7 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,
                break;
        case IIO_CHAN_INFO_OFFSET:
                if (chan->type == IIO_TEMP) {
-                       *val = 25;
+                       *val = 25000 / -470 - 1278; /* 25 C = 1278 */
                        return IIO_VAL_INT;
                }
                addrind = 1;
@@ -495,19 +495,22 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,
                addrind = 2;
                break;
        case IIO_CHAN_INFO_SCALE:
-               *val = 0;
                switch (chan->type) {
                case IIO_TEMP:
-                       *val2 = -470000;
+                       *val = -470; /* -0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
-                       *val2 = 1887042;
+                       *val2 = IIO_G_TO_M_S_2(19073); /* 19.073 g */
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_VOLTAGE:
-                       if (chan->channel == 0)
-                               *val2 = 0012221;
-                       else /* Should really be dependent on VDD */
-                               *val2 = 305;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 220700; /* 1.2207 mV */
+                       } else {
+                               /* Should really be dependent on VDD */
+                               *val2 = 305180; /* 305.18 uV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
index 0fc26a49d681abbb4ece13156771e429db9aee2f..35e093973d5cb9028992682344f3dc9bba23be96 100644 (file)
@@ -373,30 +373,31 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 4880;
-                       else
+                       if (chan->channel == 0) {
+                               *val = 4;
+                               *val2 = 880000; /* 4.88 mV */
+                               return IIO_VAL_INT_PLUS_MICRO;
+                       } else {
                                return -EINVAL;
-                       return IIO_VAL_INT_PLUS_MICRO;
+                       }
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = 244000;
+                       *val = 244; /* 0.244 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
-                       *val2 = 504062;
+                       *val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
                break;
        case IIO_CHAN_INFO_PEAK_SCALE:
-               *val = 6;
-               *val2 = 629295;
+               *val = 0;
+               *val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */
                return IIO_VAL_INT_PLUS_MICRO;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / 244 - 0x133; /* 25 C = 0x133 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                bits = 10;
index 9571c03aa4cc976346d17bcb27f41d4dc4319060..aa964a2d829016e25b918ede1418d25152a9a425 100644 (file)
@@ -498,28 +498,33 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
                switch (chan->type) {
                case IIO_ANGL_VEL:
                        *val = 0;
-                       if (spi_get_device_id(st->us)->driver_data)
-                               *val2 = 320;
-                       else
-                               *val2 = 1278;
+                       if (spi_get_device_id(st->us)->driver_data) {
+                               /* 0.01832 degree / sec */
+                               *val2 = IIO_DEGREE_TO_RAD(18320);
+                       } else {
+                               /* 0.07326 degree / sec */
+                               *val2 = IIO_DEGREE_TO_RAD(73260);
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 18315;
-                       else
-                               *val2 = 610500;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 831500; /* 1.8315 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 610500; /* 610.5 uV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = 145300;
+                       *val = 145;
+                       *val2 = 300000; /* 0.1453 C */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
                break;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 250000 / 1453; /* 25 C = 0x00 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                switch (chan->type) {
index d59d7ac856a9db8bb3c0bff7ccf1811d97917539..77c601da184603c6391cecc1b10d887cb38ffb70 100644 (file)
@@ -139,6 +139,8 @@ struct adis16400_chip_info {
        const long flags;
        unsigned int gyro_scale_micro;
        unsigned int accel_scale_micro;
+       int temp_scale_nano;
+       int temp_offset;
        unsigned long default_scan_mask;
 };
 
index b302c9ba271260e2f31476e51420af68fbbd28db..3144a7b1e1c4f6cd03f0b55780aa473603afa51e 100644 (file)
@@ -553,10 +553,13 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_VOLTAGE:
                        *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 2418;
-                       else
-                               *val2 = 806;
+                       if (chan->channel == 0) {
+                               *val = 2;
+                               *val2 = 418000; /* 2.418 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 805800; /* 805.8 uV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
@@ -564,11 +567,11 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_MAGN:
                        *val = 0;
-                       *val2 = 500;
+                       *val2 = 500; /* 0.5 mgauss */
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = 140000;
+                       *val = st->variant->temp_scale_nano / 1000000;
+                       *val2 = (st->variant->temp_scale_nano % 1000000);
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
@@ -586,9 +589,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_OFFSET:
                /* currently only temperature */
-               *val = 198;
-               *val2 = 160000;
-               return IIO_VAL_INT_PLUS_MICRO;
+               *val = st->variant->temp_offset;
+               return IIO_VAL_INT;
        case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
                mutex_lock(&indio_dev->mlock);
                /* Need both the number of taps and the sampling frequency */
@@ -1035,7 +1037,7 @@ static const struct iio_chan_spec adis16334_channels[] = {
                .indexed = 1,
                .channel = 0,
                .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+               IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
                IIO_CHAN_INFO_SCALE_SHARED_BIT,
                .address = temp0,
                .scan_index = ADIS16400_SCAN_TEMP,
@@ -1058,8 +1060,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
        [ADIS16300] = {
                .channels = adis16300_channels,
                .num_channels = ARRAY_SIZE(adis16300_channels),
-               .gyro_scale_micro = 873,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
                .accel_scale_micro = 5884,
+               .temp_scale_nano = 140000000, /* 0.14 C */
+               .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
                .default_scan_mask = (1 << ADIS16400_SCAN_SUPPLY) |
                (1 << ADIS16400_SCAN_GYRO_X) | (1 << ADIS16400_SCAN_ACC_X) |
                (1 << ADIS16400_SCAN_ACC_Y) | (1 << ADIS16400_SCAN_ACC_Z) |
@@ -1070,8 +1074,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
        [ADIS16334] = {
                .channels = adis16334_channels,
                .num_channels = ARRAY_SIZE(adis16334_channels),
-               .gyro_scale_micro = 873,
-               .accel_scale_micro = 981,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
+               .temp_scale_nano = 67850000, /* 0.06785 C */
+               .temp_offset = 25000000 / 67850, /* 25 C = 0x00 */
                .default_scan_mask = (1 << ADIS16400_SCAN_GYRO_X) |
                (1 << ADIS16400_SCAN_GYRO_Y) | (1 << ADIS16400_SCAN_GYRO_Z) |
                (1 << ADIS16400_SCAN_ACC_X) | (1 << ADIS16400_SCAN_ACC_Y) |
@@ -1080,8 +1086,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
        [ADIS16350] = {
                .channels = adis16350_channels,
                .num_channels = ARRAY_SIZE(adis16350_channels),
-               .gyro_scale_micro = 872664,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(73260), /* 0.07326 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(2522), /* 0.002522 g */
+               .temp_scale_nano = 145300000, /* 0.1453 C */
+               .temp_offset = 25000000 / 145300, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
                .flags = ADIS16400_NO_BURST,
        },
@@ -1090,8 +1098,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16350_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x3FE8,
-               .gyro_scale_micro = 1279,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
+               .temp_scale_nano = 136000000, /* 0.136 C */
+               .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
        },
        [ADIS16362] = {
@@ -1099,8 +1109,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16350_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x3FEA,
-               .gyro_scale_micro = 1279,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(333), /* 0.333 mg */
+               .temp_scale_nano = 136000000, /* 0.136 C */
+               .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
        },
        [ADIS16364] = {
@@ -1108,8 +1120,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16350_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x3FEC,
-               .gyro_scale_micro = 1279,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
+               .temp_scale_nano = 136000000, /* 0.136 C */
+               .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
        },
        [ADIS16365] = {
@@ -1117,8 +1131,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16350_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x3FED,
-               .gyro_scale_micro = 1279,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
+               .temp_scale_nano = 136000000, /* 0.136 C */
+               .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
        },
        [ADIS16400] = {
@@ -1126,9 +1142,11 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16400_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x4015,
-               .gyro_scale_micro = 873,
-               .accel_scale_micro = 32656,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
                .default_scan_mask = 0xFFF,
+               .temp_scale_nano = 140000000, /* 0.14 C */
+               .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
        }
 };
 
index bb8aa70281cd9da9aa55edf89850b08f1b848a2c..46d6657280b8490799f818123166827771d22615 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/slab.h>
 #include "tpci200.h"
 
 static u16 tpci200_status_timeout[] = {
index 3434e6ec01426677ff576de960ffbf65440af8d6..66e2c2f8a239964c22f3fe18dbd8d6a644b95013 100644 (file)
@@ -246,7 +246,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj)
         * DSS, GPU, etc. are not cache coherent:
         */
        if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) {
-               addrs = kmalloc(npages * sizeof(addrs), GFP_KERNEL);
+               addrs = kmalloc(npages * sizeof(*addrs), GFP_KERNEL);
                if (!addrs) {
                        ret = -ENOMEM;
                        goto free_pages;
@@ -257,7 +257,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj)
                                        0, PAGE_SIZE, DMA_BIDIRECTIONAL);
                }
        } else {
-               addrs = kzalloc(npages * sizeof(addrs), GFP_KERNEL);
+               addrs = kzalloc(npages * sizeof(*addrs), GFP_KERNEL);
                if (!addrs) {
                        ret = -ENOMEM;
                        goto free_pages;
index 843c54101438fa1aa30aafe564016d45aa3ba10d..3abf6619dace58319beee2be2fba640d02f059d2 100644 (file)
@@ -18,6 +18,7 @@ config ZCACHE2
 config RAMSTER
        bool "Cross-machine RAM capacity sharing, aka peer-to-peer tmem"
        depends on CONFIGFS_FS=y && SYSFS=y && !HIGHMEM && ZCACHE2=y
+       depends on NET
        # must ensure struct page is 8-byte aligned
        select HAVE_ALIGNED_STRUCT_PAGE if !64_BIT
        default n
index 066a3ceec65e92fccb725401e41e410e52d7ee1a..f619fb3c56d298334a615eb1b34203ccd1e5f5d3 100644 (file)
@@ -126,7 +126,8 @@ static int mem_map_vmalloc(struct bridge_dev_context *dev_context,
                                  u32 ul_num_bytes,
                                  struct hw_mmu_map_attrs_t *hw_attrs);
 
-bool wait_for_start(struct bridge_dev_context *dev_context, u32 dw_sync_addr);
+bool wait_for_start(struct bridge_dev_context *dev_context,
+                       void __iomem *sync_addr);
 
 /*  ----------------------------------- Globals */
 
@@ -363,10 +364,11 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
 {
        int status = 0;
        struct bridge_dev_context *dev_context = dev_ctxt;
-       u32 dw_sync_addr = 0;
+       void __iomem *sync_addr;
        u32 ul_shm_base;        /* Gpp Phys SM base addr(byte) */
        u32 ul_shm_base_virt;   /* Dsp Virt SM base addr */
        u32 ul_tlb_base_virt;   /* Base of MMU TLB entry */
+       u32 shm_sync_pa;
        /* Offset of shm_base_virt from tlb_base_virt */
        u32 ul_shm_offset_virt;
        s32 entry_ndx;
@@ -397,15 +399,22 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
        /* Kernel logical address */
        ul_shm_base = dev_context->atlb_entry[0].gpp_va + ul_shm_offset_virt;
 
+       /* SHM physical sync address */
+       shm_sync_pa = dev_context->atlb_entry[0].gpp_pa + ul_shm_offset_virt +
+                       SHMSYNCOFFSET;
+
        /* 2nd wd is used as sync field */
-       dw_sync_addr = ul_shm_base + SHMSYNCOFFSET;
+       sync_addr = ioremap(shm_sync_pa, SZ_32);
+       if (!sync_addr)
+               return -ENOMEM;
+
        /* Write a signature into the shm base + offset; this will
         * get cleared when the DSP program starts. */
        if ((ul_shm_base_virt == 0) || (ul_shm_base == 0)) {
                pr_err("%s: Illegal SM base\n", __func__);
                status = -EPERM;
        } else
-               __raw_writel(0xffffffff, dw_sync_addr);
+               __raw_writel(0xffffffff, sync_addr);
 
        if (!status) {
                resources = dev_context->resources;
@@ -419,8 +428,10 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
                         * function is made available.
                         */
                        void __iomem *ctrl = ioremap(0x48002000, SZ_4K);
-                       if (!ctrl)
+                       if (!ctrl) {
+                               iounmap(sync_addr);
                                return -ENOMEM;
+                       }
 
                        (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK,
                                        OMAP3430_RST1_IVA2_MASK, OMAP3430_IVA2_MOD,
@@ -588,15 +599,15 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
                (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK, 0,
                                        OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
 
-               dev_dbg(bridge, "Waiting for Sync @ 0x%x\n", dw_sync_addr);
+               dev_dbg(bridge, "Waiting for Sync @ 0x%x\n", *(u32 *)sync_addr);
                dev_dbg(bridge, "DSP c_int00 Address =  0x%x\n", dsp_addr);
                if (dsp_debug)
-                       while (__raw_readw(dw_sync_addr))
+                       while (__raw_readw(sync_addr))
                                ;
 
                /* Wait for DSP to clear word in shared memory */
                /* Read the Location */
-               if (!wait_for_start(dev_context, dw_sync_addr))
+               if (!wait_for_start(dev_context, sync_addr))
                        status = -ETIMEDOUT;
 
                dev_get_symbol(dev_context->dev_obj, "_WDT_enable", &wdt_en);
@@ -612,7 +623,7 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
                        /* Write the synchronization bit to indicate the
                         * completion of OPP table update to DSP
                         */
-                       __raw_writel(0XCAFECAFE, dw_sync_addr);
+                       __raw_writel(0XCAFECAFE, sync_addr);
 
                        /* update board state */
                        dev_context->brd_state = BRD_RUNNING;
@@ -621,6 +632,9 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
                        dev_context->brd_state = BRD_UNKNOWN;
                }
        }
+
+       iounmap(sync_addr);
+
        return status;
 }
 
@@ -1796,12 +1810,13 @@ static int mem_map_vmalloc(struct bridge_dev_context *dev_context,
  *  ======== wait_for_start ========
  *      Wait for the singal from DSP that it has started, or time out.
  */
-bool wait_for_start(struct bridge_dev_context *dev_context, u32 dw_sync_addr)
+bool wait_for_start(struct bridge_dev_context *dev_context,
+                       void __iomem *sync_addr)
 {
        u16 timeout = TIHELEN_ACKTIMEOUT;
 
        /*  Wait for response from board */
-       while (__raw_readw(dw_sync_addr) && --timeout)
+       while (__raw_readw(sync_addr) && --timeout)
                udelay(10);
 
        /*  If timed out: return false */
index 71cb822936499fb23b82f19053337a5159307c87..50244a474178610b6f0271b88dbb6479e21e03ac 100644 (file)
@@ -47,38 +47,13 @@ enum hw_mmu_page_size_t {
        HW_MMU_SUPERSECTION
 };
 
-/*
- * FUNCTION          : mmu_flush_entry
- *
- * INPUTS:
- *
- *       Identifier      : base_address
- *       Type          : const u32
- *       Description     : Base Address of instance of MMU module
- *
- * RETURNS:
- *
- *       Type          : hw_status
- *       Description     : 0            -- No errors occurred
- *                      RET_BAD_NULL_PARAM     -- A Pointer
- *                                             Parameter was set to NULL
- *
- * PURPOSE:          : Flush the TLB entry pointed by the
- *                     lock counter register
- *                     even if this entry is set protected
- *
- * METHOD:            : Check the Input parameter and Flush a
- *                      single entry in the TLB.
- */
-static hw_status mmu_flush_entry(const void __iomem *base_address);
-
 /*
  * FUNCTION          : mmu_set_cam_entry
  *
  * INPUTS:
  *
  *       Identifier      : base_address
- *       TypE          : const u32
+ *       Type           : void __iomem *
  *       Description     : Base Address of instance of MMU module
  *
  *       Identifier      : page_sz
@@ -112,7 +87,7 @@ static hw_status mmu_flush_entry(const void __iomem *base_address);
  *
  * METHOD:             : Check the Input parameters and set the CAM entry.
  */
-static hw_status mmu_set_cam_entry(const void __iomem *base_address,
+static hw_status mmu_set_cam_entry(void __iomem *base_address,
                                   const u32 page_sz,
                                   const u32 preserved_bit,
                                   const u32 valid_bit,
@@ -124,7 +99,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address,
  * INPUTS:
  *
  *       Identifier      : base_address
- *       Type          : const u32
+ *       Type           : void __iomem *
  *       Description     : Base Address of instance of MMU module
  *
  *       Identifier      : physical_addr
@@ -157,7 +132,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address,
  *
  * METHOD:            : Check the Input parameters and set the RAM entry.
  */
-static hw_status mmu_set_ram_entry(const void __iomem *base_address,
+static hw_status mmu_set_ram_entry(void __iomem *base_address,
                                   const u32 physical_addr,
                                   enum hw_endianism_t endianism,
                                   enum hw_element_size_t element_size,
@@ -165,7 +140,7 @@ static hw_status mmu_set_ram_entry(const void __iomem *base_address,
 
 /* HW FUNCTIONS */
 
-hw_status hw_mmu_enable(const void __iomem *base_address)
+hw_status hw_mmu_enable(void __iomem *base_address)
 {
        hw_status status = 0;
 
@@ -174,7 +149,7 @@ hw_status hw_mmu_enable(const void __iomem *base_address)
        return status;
 }
 
-hw_status hw_mmu_disable(const void __iomem *base_address)
+hw_status hw_mmu_disable(void __iomem *base_address)
 {
        hw_status status = 0;
 
@@ -183,7 +158,7 @@ hw_status hw_mmu_disable(const void __iomem *base_address)
        return status;
 }
 
-hw_status hw_mmu_num_locked_set(const void __iomem *base_address,
+hw_status hw_mmu_num_locked_set(void __iomem *base_address,
                                u32 num_locked_entries)
 {
        hw_status status = 0;
@@ -193,7 +168,7 @@ hw_status hw_mmu_num_locked_set(const void __iomem *base_address,
        return status;
 }
 
-hw_status hw_mmu_victim_num_set(const void __iomem *base_address,
+hw_status hw_mmu_victim_num_set(void __iomem *base_address,
                                u32 victim_entry_num)
 {
        hw_status status = 0;
@@ -203,7 +178,7 @@ hw_status hw_mmu_victim_num_set(const void __iomem *base_address,
        return status;
 }
 
-hw_status hw_mmu_event_ack(const void __iomem *base_address, u32 irq_mask)
+hw_status hw_mmu_event_ack(void __iomem *base_address, u32 irq_mask)
 {
        hw_status status = 0;
 
@@ -212,7 +187,7 @@ hw_status hw_mmu_event_ack(const void __iomem *base_address, u32 irq_mask)
        return status;
 }
 
-hw_status hw_mmu_event_disable(const void __iomem *base_address, u32 irq_mask)
+hw_status hw_mmu_event_disable(void __iomem *base_address, u32 irq_mask)
 {
        hw_status status = 0;
        u32 irq_reg;
@@ -224,7 +199,7 @@ hw_status hw_mmu_event_disable(const void __iomem *base_address, u32 irq_mask)
        return status;
 }
 
-hw_status hw_mmu_event_enable(const void __iomem *base_address, u32 irq_mask)
+hw_status hw_mmu_event_enable(void __iomem *base_address, u32 irq_mask)
 {
        hw_status status = 0;
        u32 irq_reg;
@@ -236,7 +211,7 @@ hw_status hw_mmu_event_enable(const void __iomem *base_address, u32 irq_mask)
        return status;
 }
 
-hw_status hw_mmu_event_status(const void __iomem *base_address, u32 *irq_mask)
+hw_status hw_mmu_event_status(void __iomem *base_address, u32 *irq_mask)
 {
        hw_status status = 0;
 
@@ -245,7 +220,7 @@ hw_status hw_mmu_event_status(const void __iomem *base_address, u32 *irq_mask)
        return status;
 }
 
-hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, u32 *addr)
+hw_status hw_mmu_fault_addr_read(void __iomem *base_address, u32 *addr)
 {
        hw_status status = 0;
 
@@ -255,7 +230,7 @@ hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, u32 *addr)
        return status;
 }
 
-hw_status hw_mmu_ttb_set(const void __iomem *base_address, u32 ttb_phys_addr)
+hw_status hw_mmu_ttb_set(void __iomem *base_address, u32 ttb_phys_addr)
 {
        hw_status status = 0;
        u32 load_ttb;
@@ -267,7 +242,7 @@ hw_status hw_mmu_ttb_set(const void __iomem *base_address, u32 ttb_phys_addr)
        return status;
 }
 
-hw_status hw_mmu_twl_enable(const void __iomem *base_address)
+hw_status hw_mmu_twl_enable(void __iomem *base_address)
 {
        hw_status status = 0;
 
@@ -276,7 +251,7 @@ hw_status hw_mmu_twl_enable(const void __iomem *base_address)
        return status;
 }
 
-hw_status hw_mmu_twl_disable(const void __iomem *base_address)
+hw_status hw_mmu_twl_disable(void __iomem *base_address)
 {
        hw_status status = 0;
 
@@ -285,45 +260,7 @@ hw_status hw_mmu_twl_disable(const void __iomem *base_address)
        return status;
 }
 
-hw_status hw_mmu_tlb_flush(const void __iomem *base_address, u32 virtual_addr,
-                          u32 page_sz)
-{
-       hw_status status = 0;
-       u32 virtual_addr_tag;
-       enum hw_mmu_page_size_t pg_size_bits;
-
-       switch (page_sz) {
-       case HW_PAGE_SIZE4KB:
-               pg_size_bits = HW_MMU_SMALL_PAGE;
-               break;
-
-       case HW_PAGE_SIZE64KB:
-               pg_size_bits = HW_MMU_LARGE_PAGE;
-               break;
-
-       case HW_PAGE_SIZE1MB:
-               pg_size_bits = HW_MMU_SECTION;
-               break;
-
-       case HW_PAGE_SIZE16MB:
-               pg_size_bits = HW_MMU_SUPERSECTION;
-               break;
-
-       default:
-               return -EINVAL;
-       }
-
-       /* Generate the 20-bit tag from virtual address */
-       virtual_addr_tag = ((virtual_addr & MMU_ADDR_MASK) >> 12);
-
-       mmu_set_cam_entry(base_address, pg_size_bits, 0, 0, virtual_addr_tag);
-
-       mmu_flush_entry(base_address);
-
-       return status;
-}
-
-hw_status hw_mmu_tlb_add(const void __iomem *base_address,
+hw_status hw_mmu_tlb_add(void __iomem *base_address,
                         u32 physical_addr,
                         u32 virtual_addr,
                         u32 page_sz,
@@ -503,20 +440,8 @@ hw_status hw_mmu_pte_clear(const u32 pg_tbl_va, u32 virtual_addr, u32 page_size)
        return status;
 }
 
-/* mmu_flush_entry */
-static hw_status mmu_flush_entry(const void __iomem *base_address)
-{
-       hw_status status = 0;
-       u32 flush_entry_data = 0x1;
-
-       /* write values to register */
-       MMUMMU_FLUSH_ENTRY_WRITE_REGISTER32(base_address, flush_entry_data);
-
-       return status;
-}
-
 /* mmu_set_cam_entry */
-static hw_status mmu_set_cam_entry(const void __iomem *base_address,
+static hw_status mmu_set_cam_entry(void __iomem *base_address,
                                   const u32 page_sz,
                                   const u32 preserved_bit,
                                   const u32 valid_bit,
@@ -536,7 +461,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address,
 }
 
 /* mmu_set_ram_entry */
-static hw_status mmu_set_ram_entry(const void __iomem *base_address,
+static hw_status mmu_set_ram_entry(void __iomem *base_address,
                                   const u32 physical_addr,
                                   enum hw_endianism_t endianism,
                                   enum hw_element_size_t element_size,
@@ -556,7 +481,7 @@ static hw_status mmu_set_ram_entry(const void __iomem *base_address,
 
 }
 
-void hw_mmu_tlb_flush_all(const void __iomem *base)
+void hw_mmu_tlb_flush_all(void __iomem *base)
 {
        __raw_writel(1, base + MMU_GFLUSH);
 }
index 1458a2c6027b7e1fc3cac1c160b837e10b29c6b3..1c50bb36edfee4e4ba918b6d86ee5f18cee78624 100644 (file)
@@ -42,44 +42,41 @@ struct hw_mmu_map_attrs_t {
        bool donotlockmpupage;
 };
 
-extern hw_status hw_mmu_enable(const void __iomem *base_address);
+extern hw_status hw_mmu_enable(void __iomem *base_address);
 
-extern hw_status hw_mmu_disable(const void __iomem *base_address);
+extern hw_status hw_mmu_disable(void __iomem *base_address);
 
-extern hw_status hw_mmu_num_locked_set(const void __iomem *base_address,
+extern hw_status hw_mmu_num_locked_set(void __iomem *base_address,
                                       u32 num_locked_entries);
 
-extern hw_status hw_mmu_victim_num_set(const void __iomem *base_address,
+extern hw_status hw_mmu_victim_num_set(void __iomem *base_address,
                                       u32 victim_entry_num);
 
 /* For MMU faults */
-extern hw_status hw_mmu_event_ack(const void __iomem *base_address,
+extern hw_status hw_mmu_event_ack(void __iomem *base_address,
                                  u32 irq_mask);
 
-extern hw_status hw_mmu_event_disable(const void __iomem *base_address,
+extern hw_status hw_mmu_event_disable(void __iomem *base_address,
                                      u32 irq_mask);
 
-extern hw_status hw_mmu_event_enable(const void __iomem *base_address,
+extern hw_status hw_mmu_event_enable(void __iomem *base_address,
                                     u32 irq_mask);
 
-extern hw_status hw_mmu_event_status(const void __iomem *base_address,
+extern hw_status hw_mmu_event_status(void __iomem *base_address,
                                     u32 *irq_mask);
 
-extern hw_status hw_mmu_fault_addr_read(const void __iomem *base_address,
+extern hw_status hw_mmu_fault_addr_read(void __iomem *base_address,
                                        u32 *addr);
 
 /* Set the TT base address */
-extern hw_status hw_mmu_ttb_set(const void __iomem *base_address,
+extern hw_status hw_mmu_ttb_set(void __iomem *base_address,
                                u32 ttb_phys_addr);
 
-extern hw_status hw_mmu_twl_enable(const void __iomem *base_address);
+extern hw_status hw_mmu_twl_enable(void __iomem *base_address);
 
-extern hw_status hw_mmu_twl_disable(const void __iomem *base_address);
+extern hw_status hw_mmu_twl_disable(void __iomem *base_address);
 
-extern hw_status hw_mmu_tlb_flush(const void __iomem *base_address,
-                                 u32 virtual_addr, u32 page_sz);
-
-extern hw_status hw_mmu_tlb_add(const void __iomem *base_address,
+extern hw_status hw_mmu_tlb_add(void __iomem *base_address,
                                u32 physical_addr,
                                u32 virtual_addr,
                                u32 page_sz,
@@ -97,7 +94,7 @@ extern hw_status hw_mmu_pte_set(const u32 pg_tbl_va,
 extern hw_status hw_mmu_pte_clear(const u32 pg_tbl_va,
                                  u32 virtual_addr, u32 page_size);
 
-void hw_mmu_tlb_flush_all(const void __iomem *base);
+void hw_mmu_tlb_flush_all(void __iomem *base);
 
 static inline u32 hw_mmu_pte_addr_l1(u32 l1_base, u32 va)
 {
index 60a278136bdf58f14718fb43913d292a51b01397..b32c75673ab441c5795b456d25d272ffdaf79866 100644 (file)
@@ -53,8 +53,8 @@ struct cfg_hostres {
        u32 chnl_buf_size;
        u32 num_chnls;
        void __iomem *per_base;
-       u32 per_pm_base;
-       u32 core_pm_base;
+       void __iomem *per_pm_base;
+       void __iomem *core_pm_base;
        void __iomem *dmmu_base;
 };
 
index ed00d3da3205a0074333fb0a4dfd778ca6417280..5e2f4d82d925fbf76b628299347c4f83a86321a3 100644 (file)
@@ -47,8 +47,8 @@
 #include <asm/cacheflush.h>
 #include <linux/dma-mapping.h>
 
-/* TODO -- Remove, once BP defines them */
-#define INT_DSP_MMU_IRQ        28
+/* TODO -- Remove, once omap-iommu is used */
+#define INT_DSP_MMU_IRQ        (28 + NR_IRQS)
 
 #define PRCM_VDD1 1
 
index 6795205b01553e07b671c63a1c49519b092c6e7f..db1da28cecba84d4800363df964647e85b8177c9 100644 (file)
@@ -667,10 +667,10 @@ int drv_request_bridge_res_dsp(void **phost_resources)
                                                         OMAP_DSP_MEM3_SIZE);
                host_res->per_base = ioremap(OMAP_PER_CM_BASE,
                                                OMAP_PER_CM_SIZE);
-               host_res->per_pm_base = (u32) ioremap(OMAP_PER_PRM_BASE,
-                                                        OMAP_PER_PRM_SIZE);
-               host_res->core_pm_base = (u32) ioremap(OMAP_CORE_PRM_BASE,
-                                                         OMAP_CORE_PRM_SIZE);
+               host_res->per_pm_base = ioremap(OMAP_PER_PRM_BASE,
+                                               OMAP_PER_PRM_SIZE);
+               host_res->core_pm_base = ioremap(OMAP_CORE_PRM_BASE,
+                                                       OMAP_CORE_PRM_SIZE);
                host_res->dmmu_base = ioremap(OMAP_DMMU_BASE,
                                                 OMAP_DMMU_SIZE);
 
index c2fc6137c7708372ff4cde1d8f9f6375fe3086a8..294e9b40f51666396c2a56c3d92036951e04382d 100644 (file)
@@ -304,8 +304,7 @@ int node_allocate(struct proc_object *hprocessor,
        u32 pul_value;
        u32 dynext_base;
        u32 off_set = 0;
-       u32 ul_stack_seg_addr, ul_stack_seg_val;
-       u32 ul_gpp_mem_base;
+       u32 ul_stack_seg_val;
        struct cfg_hostres *host_res;
        struct bridge_dev_context *pbridge_context;
        u32 mapped_addr = 0;
@@ -581,6 +580,9 @@ func_cont:
                if (strcmp((char *)
                           pnode->dcd_props.obj_data.node_obj.ndb_props.
                           stack_seg_name, STACKSEGLABEL) == 0) {
+                       void __iomem *stack_seg;
+                       u32 stack_seg_pa;
+
                        status =
                            hnode_mgr->nldr_fxns.
                            get_fxn_addr(pnode->nldr_node_obj, "DYNEXT_BEG",
@@ -608,14 +610,21 @@ func_cont:
                                goto func_end;
                        }
 
-                       ul_gpp_mem_base = (u32) host_res->mem_base[1];
                        off_set = pul_value - dynext_base;
-                       ul_stack_seg_addr = ul_gpp_mem_base + off_set;
-                       ul_stack_seg_val = readl(ul_stack_seg_addr);
+                       stack_seg_pa = host_res->mem_phys[1] + off_set;
+                       stack_seg = ioremap(stack_seg_pa, SZ_32);
+                       if (!stack_seg) {
+                               status = -ENOMEM;
+                               goto func_end;
+                       }
+
+                       ul_stack_seg_val = readl(stack_seg);
+
+                       iounmap(stack_seg);
 
                        dev_dbg(bridge, "%s: StackSegVal = 0x%x, StackSegAddr ="
                                " 0x%x\n", __func__, ul_stack_seg_val,
-                               ul_stack_seg_addr);
+                               host_res->mem_base[1] + off_set);
 
                        pnode->create_args.asa.task_arg_obj.stack_seg =
                            ul_stack_seg_val;
index 653b074035f7b165d04d1587d428097ecfac780a..6edefde23722b436641166f5b678291d6648c6b2 100644 (file)
@@ -223,8 +223,13 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
        cmem = zs_map_object(zram->mem_pool, zram->table[index].handle,
                                ZS_MM_RO);
 
-       ret = lzo1x_decompress_safe(cmem, zram->table[index].size,
+       if (zram->table[index].size == PAGE_SIZE) {
+               memcpy(uncmem, cmem, PAGE_SIZE);
+               ret = LZO_E_OK;
+       } else {
+               ret = lzo1x_decompress_safe(cmem, zram->table[index].size,
                                    uncmem, &clen);
+       }
 
        if (is_partial_io(bvec)) {
                memcpy(user_mem + bvec->bv_offset, uncmem + offset,
@@ -342,8 +347,11 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
                goto out;
        }
 
-       if (unlikely(clen > max_zpage_size))
+       if (unlikely(clen > max_zpage_size)) {
                zram_stat_inc(&zram->stats.bad_compress);
+               src = uncmem;
+               clen = PAGE_SIZE;
+       }
 
        handle = zs_malloc(zram->mem_pool, clen);
        if (!handle) {
index d6ce2182e67207d41932fec75914b9d2c7f44479..035c2c762537c63e9bf62210b5476f7aef5c687a 100644 (file)
@@ -3719,7 +3719,9 @@ restart:
                 */
                iscsit_thread_check_cpumask(conn, current, 1);
 
-               schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT);
+               wait_event_interruptible(conn->queues_wq,
+                                        !iscsit_conn_all_queues_empty(conn) ||
+                                        ts->status == ISCSI_THREAD_SET_RESET);
 
                if ((ts->status == ISCSI_THREAD_SET_RESET) ||
                     signal_pending(current))
index 2ba9f9b9435c8684e59d0c65b6a18a6586ec5490..21048dbf7d13cc7ac116be38bb13a9ac6300c2a0 100644 (file)
@@ -486,6 +486,7 @@ struct iscsi_tmr_req {
 };
 
 struct iscsi_conn {
+       wait_queue_head_t       queues_wq;
        /* Authentication Successful for this connection */
        u8                      auth_complete;
        /* State connection is currently in */
index cdc8a10939c3d8d00912a6d9b5d735930d4e60ab..f8dbec05d5e56736fdc9238f997fcc8b18209021 100644 (file)
@@ -41,6 +41,7 @@
 
 static int iscsi_login_init_conn(struct iscsi_conn *conn)
 {
+       init_waitqueue_head(&conn->queues_wq);
        INIT_LIST_HEAD(&conn->conn_list);
        INIT_LIST_HEAD(&conn->conn_cmd_list);
        INIT_LIST_HEAD(&conn->immed_queue_list);
index afd98ccd40ae564f8013155bf6a4d99f857f339a..1a91195ab619a9ebbfa503cf7851c3cb8ca02b49 100644 (file)
@@ -488,7 +488,7 @@ void iscsit_add_cmd_to_immediate_queue(
        atomic_set(&conn->check_immediate_queue, 1);
        spin_unlock_bh(&conn->immed_queue_lock);
 
-       wake_up_process(conn->thread_set->tx_thread);
+       wake_up(&conn->queues_wq);
 }
 
 struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *conn)
@@ -562,7 +562,7 @@ void iscsit_add_cmd_to_response_queue(
        atomic_inc(&cmd->response_queue_count);
        spin_unlock_bh(&conn->response_queue_lock);
 
-       wake_up_process(conn->thread_set->tx_thread);
+       wake_up(&conn->queues_wq);
 }
 
 struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *conn)
@@ -616,6 +616,24 @@ static void iscsit_remove_cmd_from_response_queue(
        }
 }
 
+bool iscsit_conn_all_queues_empty(struct iscsi_conn *conn)
+{
+       bool empty;
+
+       spin_lock_bh(&conn->immed_queue_lock);
+       empty = list_empty(&conn->immed_queue_list);
+       spin_unlock_bh(&conn->immed_queue_lock);
+
+       if (!empty)
+               return empty;
+
+       spin_lock_bh(&conn->response_queue_lock);
+       empty = list_empty(&conn->response_queue_list);
+       spin_unlock_bh(&conn->response_queue_lock);
+
+       return empty;
+}
+
 void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn)
 {
        struct iscsi_queue_req *qr, *qr_tmp;
index 44054bd35437af3b21fbdc5422171d7d8032f76c..894d0f8379246f63166666b36259fbe0315d8dd4 100644 (file)
@@ -25,6 +25,7 @@ extern struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_
 extern void iscsit_add_cmd_to_response_queue(struct iscsi_cmd *, struct iscsi_conn *, u8);
 extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *);
 extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_conn *);
+extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *);
 extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *);
 extern void iscsit_release_cmd(struct iscsi_cmd *);
 extern void iscsit_free_cmd(struct iscsi_cmd *);
index 015f5be27bf6f00dab299b20b295ef71df4af3e2..c123327499a3572f5e950f6483ea20d99096ebab 100644 (file)
@@ -3206,7 +3206,8 @@ static int __init target_core_init_configfs(void)
        if (ret < 0)
                goto out;
 
-       if (core_dev_setup_virtual_lun0() < 0)
+       ret = core_dev_setup_virtual_lun0();
+       if (ret < 0)
                goto out;
 
        return 0;
index 8d774da16320707cb81f525f511188ff202c57ae..9abef9f8eb760a88e7073802ceec77197421bf97 100644 (file)
@@ -850,20 +850,20 @@ int se_dev_check_shutdown(struct se_device *dev)
 
 static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size)
 {
-       u32 tmp, aligned_max_sectors;
+       u32 aligned_max_sectors;
+       u32 alignment;
        /*
         * Limit max_sectors to a PAGE_SIZE aligned value for modern
         * transport_allocate_data_tasks() operation.
         */
-       tmp = rounddown((max_sectors * block_size), PAGE_SIZE);
-       aligned_max_sectors = (tmp / block_size);
-       if (max_sectors != aligned_max_sectors) {
-               printk(KERN_INFO "Rounding down aligned max_sectors from %u"
-                               " to %u\n", max_sectors, aligned_max_sectors);
-               return aligned_max_sectors;
-       }
+       alignment = max(1ul, PAGE_SIZE / block_size);
+       aligned_max_sectors = rounddown(max_sectors, alignment);
+
+       if (max_sectors != aligned_max_sectors)
+               pr_info("Rounding down aligned max_sectors from %u to %u\n",
+                       max_sectors, aligned_max_sectors);
 
-       return max_sectors;
+       return aligned_max_sectors;
 }
 
 void se_dev_set_default_attribs(
index 868f8aa04f13d318b1c752d08887703f7a72de21..a6e27d967c7b7b4abc53dd194927252ed2cde897 100644 (file)
@@ -135,6 +135,12 @@ static int sbc_emulate_verify(struct se_cmd *cmd)
        return 0;
 }
 
+static int sbc_emulate_noop(struct se_cmd *cmd)
+{
+       target_complete_cmd(cmd, GOOD);
+       return 0;
+}
+
 static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors)
 {
        return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors;
@@ -531,6 +537,18 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
                size = 0;
                cmd->execute_cmd = sbc_emulate_verify;
                break;
+       case REZERO_UNIT:
+       case SEEK_6:
+       case SEEK_10:
+               /*
+                * There are still clients out there which use these old SCSI-2
+                * commands. This mainly happens when running VMs with legacy
+                * guest systems, connected via SCSI command pass-through to
+                * iSCSI targets. Make them happy and return status GOOD.
+                */
+               size = 0;
+               cmd->execute_cmd = sbc_emulate_noop;
+               break;
        default:
                ret = spc_parse_cdb(cmd, &size);
                if (ret)
index 9229bd9ad61b3db7cd4d182ab3d5315f24785a5f..6fd434d3d7e477ab7d49660d20e02b0d638b8e3a 100644 (file)
@@ -605,6 +605,8 @@ static int spc_emulate_inquiry(struct se_cmd *cmd)
        unsigned char buf[SE_INQUIRY_BUF];
        int p, ret;
 
+       memset(buf, 0, SE_INQUIRY_BUF);
+
        if (dev == tpg->tpg_virt_lun0.lun_se_dev)
                buf[0] = 0x3f; /* Not connected */
        else
index 1c59a3c23b2c1b37ee8a3c54d62b8c66ea6f9e87..be75c4331a9222a5ca4d0b015ebdbe5a983c20ae 100644 (file)
@@ -140,15 +140,15 @@ void core_tmr_abort_task(
                printk("ABORT_TASK: Found referenced %s task_tag: %u\n",
                        se_cmd->se_tfo->get_fabric_name(), ref_tag);
 
-               spin_lock_irq(&se_cmd->t_state_lock);
+               spin_lock(&se_cmd->t_state_lock);
                if (se_cmd->transport_state & CMD_T_COMPLETE) {
                        printk("ABORT_TASK: ref_tag: %u already complete, skipping\n", ref_tag);
-                       spin_unlock_irq(&se_cmd->t_state_lock);
+                       spin_unlock(&se_cmd->t_state_lock);
                        spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
                        goto out;
                }
                se_cmd->transport_state |= CMD_T_ABORTED;
-               spin_unlock_irq(&se_cmd->t_state_lock);
+               spin_unlock(&se_cmd->t_state_lock);
 
                list_del_init(&se_cmd->se_cmd_list);
                kref_get(&se_cmd->cmd_kref);
index c33baff86aa699deacd04bd873e3c31fa5569cf5..9097155e9ebe7100c0bc1a4ac13b7c508a84ac8a 100644 (file)
@@ -1616,7 +1616,6 @@ static void target_complete_tmr_failure(struct work_struct *work)
 
        se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;
        se_cmd->se_tfo->queue_tm_rsp(se_cmd);
-       transport_generic_free_cmd(se_cmd, 0);
 }
 
 /**
index fd03e8581afc2a8e86ed354c03c06e84a1b604cc..6dd29e4ce36b1cd4841b94b6f1c1bd6251040972 100644 (file)
@@ -815,7 +815,7 @@ static struct platform_device_id exynos_tmu_driver_ids[] = {
        },
        { },
 };
-MODULE_DEVICE_TABLE(platform, exynos4_tmu_driver_ids);
+MODULE_DEVICE_TABLE(platform, exynos_tmu_driver_ids);
 
 static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(
                        struct platform_device *pdev)
index d4452716aaab1a7dbec7e3df53ec0abbed43aabd..f7a1b574a304e8808cb0cfda0d7e91ef6272bd50 100644 (file)
@@ -210,7 +210,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
                goto error_free_priv;
        }
 
-       zone = thermal_zone_device_register("rcar_thermal", 0, priv,
+       zone = thermal_zone_device_register("rcar_thermal", 0, 0, priv,
                                            &rcar_thermal_zone_ops, 0, 0);
        if (IS_ERR(zone)) {
                dev_err(&pdev->dev, "thermal zone device is NULL\n");
index 6ede6fd92b4cd00e939dca479e0f3e3a0a0d923e..6d3d26a607b9fd26bc03cff7d50f62ccbf8a589b 100644 (file)
@@ -671,19 +671,19 @@ serial_omap_configure_xonxoff
 
        /*
         * IXON Flag:
-        * Flow control for OMAP.TX
-        * OMAP.RX should listen for XON/XOFF
+        * Enable XON/XOFF flow control on output.
+        * Transmit XON1, XOFF1
         */
        if (termios->c_iflag & IXON)
-               up->efr |= OMAP_UART_SW_RX;
+               up->efr |= OMAP_UART_SW_TX;
 
        /*
         * IXOFF Flag:
-        * Flow control for OMAP.RX
-        * OMAP.TX should send XON/XOFF
+        * Enable XON/XOFF flow control on input.
+        * Receiver compares XON1, XOFF1.
         */
        if (termios->c_iflag & IXOFF)
-               up->efr |= OMAP_UART_SW_TX;
+               up->efr |= OMAP_UART_SW_RX;
 
        serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
index 64854d76f52901f39bf658a17790d4b512853a81..1af04bdeaf0c1884487ed830bcee7dd32ee720b6 100644 (file)
@@ -739,13 +739,16 @@ static void hub_tt_work(struct work_struct *work)
        int                     limit = 100;
 
        spin_lock_irqsave (&hub->tt.lock, flags);
-       while (--limit && !list_empty (&hub->tt.clear_list)) {
+       while (!list_empty(&hub->tt.clear_list)) {
                struct list_head        *next;
                struct usb_tt_clear     *clear;
                struct usb_device       *hdev = hub->hdev;
                const struct hc_driver  *drv;
                int                     status;
 
+               if (!hub->quiescing && --limit < 0)
+                       break;
+
                next = hub->tt.clear_list.next;
                clear = list_entry (next, struct usb_tt_clear, clear_list);
                list_del (&clear->clear_list);
@@ -1210,7 +1213,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
        if (hub->has_indicators)
                cancel_delayed_work_sync(&hub->leds);
        if (hub->tt.hub)
-               cancel_work_sync(&hub->tt.clear_work);
+               flush_work(&hub->tt.clear_work);
 }
 
 /* caller has locked the hub device */
index 43ac7482fa9184dbd4748d42d6a6008e21f330ef..c009263a47e3250951fc1b16cab143ba0934eb86 100644 (file)
@@ -2069,8 +2069,10 @@ static irqreturn_t net2272_irq(int irq, void *_dev)
 #if defined(PLX_PCI_RDK2)
        /* see if PCI int for us by checking irqstat */
        intcsr = readl(dev->rdk2.fpga_base_addr + RDK2_IRQSTAT);
-       if (!intcsr & (1 << NET2272_PCI_IRQ))
+       if (!intcsr & (1 << NET2272_PCI_IRQ)) {
+               spin_unlock(&dev->lock);
                return IRQ_NONE;
+       }
        /* check dma interrupts */
 #endif
        /* Platform/devcice interrupt handler */
index 966d1484ee79a2db8c5e78e135c5e0760814d183..39f9e4a9a2d3f086470c6cac459ca0ab4a4fec78 100644 (file)
@@ -545,7 +545,14 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = {
                /*  Pegatron Lucid (Ordissimo AIRIS) */
                .matches = {
                        DMI_MATCH(DMI_BOARD_NAME, "M11JB"),
-                       DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"),
+               },
+       },
+       {
+               /*  Pegatron Lucid (Ordissimo) */
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_NAME, "Ordissimo"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"),
                },
        },
        { }
index 4b436f5a41711bc1a7747f3c7b187ff547c7acbd..5f3a7c74aa8d39404212d342f6236fe1ea48d514 100644 (file)
@@ -544,7 +544,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci,
        int i;
        /* Fields are 32 bits wide, DMA addresses are in bytes */
        int field_size = 32 / 8;
-       struct xhci_slot_ctx *slot_ctx;
        dma_addr_t dma = ctx->dma;
        int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
 
@@ -570,7 +569,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci,
                        dbg_rsvd64(xhci, (u64 *)ctrl_ctx, dma);
        }
 
-       slot_ctx = xhci_get_slot_ctx(xhci, ctx);
        xhci_dbg_slot_ctx(xhci, ctx);
        xhci_dbg_ep_ctx(xhci, ctx, last_ep);
 }
index aa90ad4d4fd53b2f70288641dcd13942355ca875..a686cf4905bb80ae3e4c7b206c05d7cd2b960920 100644 (file)
@@ -151,9 +151,8 @@ static void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
                if (portsc & PORT_DEV_REMOVE)
                        port_removable |= 1 << (i + 1);
        }
-       memset(&desc->u.ss.DeviceRemovable,
-                       (__force __u16) cpu_to_le16(port_removable),
-                       sizeof(__u16));
+
+       desc->u.ss.DeviceRemovable = cpu_to_le16(port_removable);
 }
 
 static void xhci_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
@@ -809,11 +808,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        temp = xhci_readl(xhci, port_array[wIndex]);
                        xhci_dbg(xhci, "set port power, actual port %d status  = 0x%x\n", wIndex, temp);
 
+                       spin_unlock_irqrestore(&xhci->lock, flags);
                        temp = usb_acpi_power_manageable(hcd->self.root_hub,
                                        wIndex);
                        if (temp)
                                usb_acpi_set_power_state(hcd->self.root_hub,
                                                wIndex, true);
+                       spin_lock_irqsave(&xhci->lock, flags);
                        break;
                case USB_PORT_FEAT_RESET:
                        temp = (temp | PORT_RESET);
@@ -917,11 +918,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        xhci_writel(xhci, temp & ~PORT_POWER,
                                port_array[wIndex]);
 
+                       spin_unlock_irqrestore(&xhci->lock, flags);
                        temp = usb_acpi_power_manageable(hcd->self.root_hub,
                                        wIndex);
                        if (temp)
                                usb_acpi_set_power_state(hcd->self.root_hub,
                                                wIndex, false);
+                       spin_lock_irqsave(&xhci->lock, flags);
                        break;
                default:
                        goto error;
index c6ebb176dc4fb33d1307b9068ea7d27728356637..4e1a8946b8d167c1f36be62b3bc63265f7271815 100644 (file)
@@ -1228,6 +1228,17 @@ static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd)
        cur_seg = find_trb_seg(xhci->cmd_ring->first_seg,
                        xhci->cmd_ring->dequeue, &cycle_state);
 
+       if (!cur_seg) {
+               xhci_warn(xhci, "Command ring mismatch, dequeue = %p %llx (dma)\n",
+                               xhci->cmd_ring->dequeue,
+                               (unsigned long long)
+                               xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
+                                       xhci->cmd_ring->dequeue));
+               xhci_debug_ring(xhci, xhci->cmd_ring);
+               xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
+               return;
+       }
+
        /* find the command trb matched by cd from command ring */
        for (cmd_trb = xhci->cmd_ring->dequeue;
                        cmd_trb != xhci->cmd_ring->enqueue;
index 7d462bf20092cee0d35adad12d42ea1d2a28e595..c9e419f29b7454225516cb8629ddff80af5187d9 100644 (file)
@@ -1627,7 +1627,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
        struct xhci_hcd *xhci;
        struct xhci_container_ctx *in_ctx, *out_ctx;
        unsigned int ep_index;
-       struct xhci_ep_ctx *ep_ctx;
        struct xhci_slot_ctx *slot_ctx;
        struct xhci_input_control_ctx *ctrl_ctx;
        u32 added_ctxs;
@@ -1663,7 +1662,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
        out_ctx = virt_dev->out_ctx;
        ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
        ep_index = xhci_get_endpoint_index(&ep->desc);
-       ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
 
        /* If this endpoint is already in use, and the upper layers are trying
         * to add it again without dropping it, reject the addition.
@@ -1817,6 +1815,8 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
        case COMP_EBADSLT:
                dev_warn(&udev->dev, "WARN: slot not enabled for"
                                "evaluate context command.\n");
+               ret = -EINVAL;
+               break;
        case COMP_CTX_STATE:
                dev_warn(&udev->dev, "WARN: invalid context state for "
                                "evaluate context command.\n");
@@ -4021,7 +4021,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
 static unsigned long long xhci_service_interval_to_ns(
                struct usb_endpoint_descriptor *desc)
 {
-       return (1 << (desc->bInterval - 1)) * 125 * 1000;
+       return (1ULL << (desc->bInterval - 1)) * 125 * 1000;
 }
 
 static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev,
@@ -4142,7 +4142,7 @@ static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev,
                        (xhci_service_interval_to_ns(desc) > timeout_ns))
                timeout_ns = xhci_service_interval_to_ns(desc);
 
-       u2_del_ns = udev->bos->ss_cap->bU2DevExitLat * 1000;
+       u2_del_ns = le16_to_cpu(udev->bos->ss_cap->bU2DevExitLat) * 1000ULL;
        if (u2_del_ns > timeout_ns)
                timeout_ns = u2_del_ns;
 
index 4223d761223d3440a243a87150d4283537e89a4b..6589268a651517da44f99cd7391e2ca35f84f12a 100644 (file)
@@ -158,3 +158,4 @@ int ezusb_fx2_ihex_firmware_download(struct usb_device *dev,
 }
 EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download);
 
+MODULE_LICENSE("GPL");
index 444346e1e10d768086b1e10487f6b6428c892897..ff5f112053d28f114e4d90844b7aa2172f3856d4 100644 (file)
@@ -458,11 +458,11 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
        struct platform_device  *musb;
        struct resource *res;
        struct resource resources[2];
-       char res_name[10];
+       char res_name[11];
        int ret, musbid;
 
        /* get memory resource */
-       sprintf(res_name, "musb%d", id);
+       snprintf(res_name, sizeof(res_name), "musb%d", id);
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
        if (!res) {
                dev_err(dev, "%s get mem resource failed\n", res_name);
@@ -473,7 +473,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
        resources[0] = *res;
 
        /* get irq resource */
-       sprintf(res_name, "musb%d-irq", id);
+       snprintf(res_name, sizeof(res_name), "musb%d-irq", id);
        res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);
        if (!res) {
                dev_err(dev, "%s get irq resource failed\n", res_name);
@@ -530,7 +530,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
 
                of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);
                of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);
-               sprintf(res_name, "port%d-mode", id);
+               snprintf(res_name, sizeof(res_name), "port%d-mode", id);
                of_property_read_u32(np, res_name, (u32 *)&pdata->mode);
                of_property_read_u32(np, "power", (u32 *)&pdata->power);
                config->multipoint = of_property_read_bool(np, "multipoint");
index 143c4e9e1be45cc24c0a612d38e590a5ad136be9..c021b202c0f3fe05894d3a94075c55bea8dd1a66 100644 (file)
@@ -795,6 +795,7 @@ static void xfer_work(struct work_struct *work)
        dev_dbg(dev, "  %s %d (%d/ %d)\n",
                fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero);
 
+       usbhs_pipe_enable(pipe);
        usbhsf_dma_start(pipe, fifo);
        dma_async_issue_pending(chan);
 }
index 9b69a132329474052486e0483649b6c64a746a4f..069cd765400cbf51f649564d5ed8490d90cd8259 100644 (file)
@@ -334,6 +334,11 @@ static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv,
        struct device *dev = usbhs_priv_to_dev(priv);
        unsigned long flags;
 
+       if (unlikely(!uep)) {
+               dev_err(dev, "no uep\n");
+               return;
+       }
+
        /********************  spin lock ********************/
        usbhs_lock(priv, flags);
 
index e9c7046ae355a9da6746c83b669b8605c38fec96..d255f66e708e80ee78d72bc052bef4e71ba578e2 100644 (file)
@@ -242,13 +242,11 @@ out:      kfree(buffer);
        return r;
 }
 
-/* allocate private data */
-static int ch341_attach(struct usb_serial *serial)
+static int ch341_port_probe(struct usb_serial_port *port)
 {
        struct ch341_private *priv;
        int r;
 
-       /* private data */
        priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
@@ -258,17 +256,27 @@ static int ch341_attach(struct usb_serial *serial)
        priv->baud_rate = DEFAULT_BAUD_RATE;
        priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
 
-       r = ch341_configure(serial->dev, priv);
+       r = ch341_configure(port->serial->dev, priv);
        if (r < 0)
                goto error;
 
-       usb_set_serial_port_data(serial->port[0], priv);
+       usb_set_serial_port_data(port, priv);
        return 0;
 
 error: kfree(priv);
        return r;
 }
 
+static int ch341_port_remove(struct usb_serial_port *port)
+{
+       struct ch341_private *priv;
+
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
+}
+
 static int ch341_carrier_raised(struct usb_serial_port *port)
 {
        struct ch341_private *priv = usb_get_serial_port_data(port);
@@ -304,7 +312,7 @@ static void ch341_close(struct usb_serial_port *port)
 static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
-       struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]);
+       struct ch341_private *priv = usb_get_serial_port_data(port);
        int r;
 
        priv->baud_rate = DEFAULT_BAUD_RATE;
@@ -608,7 +616,8 @@ static struct usb_serial_driver ch341_device = {
        .tiocmget          = ch341_tiocmget,
        .tiocmset          = ch341_tiocmset,
        .read_int_callback = ch341_read_int_callback,
-       .attach            = ch341_attach,
+       .port_probe        = ch341_port_probe,
+       .port_remove       = ch341_port_remove,
        .reset_resume      = ch341_reset_resume,
 };
 
index c86f68c6b0785942e16315ebf34443a0f94b2161..b50fa1c6d885be8df8d5675edbedc6637fb9c33f 100644 (file)
@@ -244,6 +244,8 @@ static int digi_startup_device(struct usb_serial *serial);
 static int digi_startup(struct usb_serial *serial);
 static void digi_disconnect(struct usb_serial *serial);
 static void digi_release(struct usb_serial *serial);
+static int digi_port_probe(struct usb_serial_port *port);
+static int digi_port_remove(struct usb_serial_port *port);
 static void digi_read_bulk_callback(struct urb *urb);
 static int digi_read_inb_callback(struct urb *urb);
 static int digi_read_oob_callback(struct urb *urb);
@@ -294,6 +296,8 @@ static struct usb_serial_driver digi_acceleport_2_device = {
        .attach =                       digi_startup,
        .disconnect =                   digi_disconnect,
        .release =                      digi_release,
+       .port_probe =                   digi_port_probe,
+       .port_remove =                  digi_port_remove,
 };
 
 static struct usb_serial_driver digi_acceleport_4_device = {
@@ -320,6 +324,8 @@ static struct usb_serial_driver digi_acceleport_4_device = {
        .attach =                       digi_startup,
        .disconnect =                   digi_disconnect,
        .release =                      digi_release,
+       .port_probe =                   digi_port_probe,
+       .port_remove =                  digi_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -1240,59 +1246,50 @@ static int digi_startup_device(struct usb_serial *serial)
        return ret;
 }
 
-
-static int digi_startup(struct usb_serial *serial)
+static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
 {
-
-       int i;
        struct digi_port *priv;
-       struct digi_serial *serial_priv;
 
-       /* allocate the private data structures for all ports */
-       /* number of regular ports + 1 for the out-of-band port */
-       for (i = 0; i < serial->type->num_ports + 1; i++) {
-               /* allocate port private structure */
-               priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL);
-               if (priv == NULL) {
-                       while (--i >= 0)
-                               kfree(usb_get_serial_port_data(serial->port[i]));
-                       return 1;                       /* error */
-               }
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
 
-               /* initialize port private structure */
-               spin_lock_init(&priv->dp_port_lock);
-               priv->dp_port_num = i;
-               priv->dp_out_buf_len = 0;
-               priv->dp_write_urb_in_use = 0;
-               priv->dp_modem_signals = 0;
-               init_waitqueue_head(&priv->dp_modem_change_wait);
-               priv->dp_transmit_idle = 0;
-               init_waitqueue_head(&priv->dp_transmit_idle_wait);
-               priv->dp_throttled = 0;
-               priv->dp_throttle_restart = 0;
-               init_waitqueue_head(&priv->dp_flush_wait);
-               init_waitqueue_head(&priv->dp_close_wait);
-               INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
-               priv->dp_port = serial->port[i];
-               /* initialize write wait queue for this port */
-               init_waitqueue_head(&serial->port[i]->write_wait);
-
-               usb_set_serial_port_data(serial->port[i], priv);
-       }
+       spin_lock_init(&priv->dp_port_lock);
+       priv->dp_port_num = port_num;
+       init_waitqueue_head(&priv->dp_modem_change_wait);
+       init_waitqueue_head(&priv->dp_transmit_idle_wait);
+       init_waitqueue_head(&priv->dp_flush_wait);
+       init_waitqueue_head(&priv->dp_close_wait);
+       INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
+       priv->dp_port = port;
 
-       /* allocate serial private structure */
-       serial_priv = kmalloc(sizeof(struct digi_serial), GFP_KERNEL);
-       if (serial_priv == NULL) {
-               for (i = 0; i < serial->type->num_ports + 1; i++)
-                       kfree(usb_get_serial_port_data(serial->port[i]));
-               return 1;                       /* error */
-       }
+       init_waitqueue_head(&port->write_wait);
+
+       usb_set_serial_port_data(port, priv);
+
+       return 0;
+}
+
+static int digi_startup(struct usb_serial *serial)
+{
+       struct digi_serial *serial_priv;
+       int ret;
+
+       serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
+       if (!serial_priv)
+               return -ENOMEM;
 
-       /* initialize serial private structure */
        spin_lock_init(&serial_priv->ds_serial_lock);
        serial_priv->ds_oob_port_num = serial->type->num_ports;
        serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num];
-       serial_priv->ds_device_started = 0;
+
+       ret = digi_port_init(serial_priv->ds_oob_port,
+                                               serial_priv->ds_oob_port_num);
+       if (ret) {
+               kfree(serial_priv);
+               return ret;
+       }
+
        usb_set_serial_data(serial, serial_priv);
 
        return 0;
@@ -1313,15 +1310,35 @@ static void digi_disconnect(struct usb_serial *serial)
 
 static void digi_release(struct usb_serial *serial)
 {
-       int i;
+       struct digi_serial *serial_priv;
+       struct digi_port *priv;
+
+       serial_priv = usb_get_serial_data(serial);
+
+       priv = usb_get_serial_port_data(serial_priv->ds_oob_port);
+       kfree(priv);
 
-       /* free the private data structures for all ports */
-       /* number of regular ports + 1 for the out-of-band port */
-       for (i = 0; i < serial->type->num_ports + 1; i++)
-               kfree(usb_get_serial_port_data(serial->port[i]));
-       kfree(usb_get_serial_data(serial));
+       kfree(serial_priv);
 }
 
+static int digi_port_probe(struct usb_serial_port *port)
+{
+       unsigned port_num;
+
+       port_num = port->number - port->serial->minor;
+
+       return digi_port_init(port, port_num);
+}
+
+static int digi_port_remove(struct usb_serial_port *port)
+{
+       struct digi_port *priv;
+
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
+}
 
 static void digi_read_bulk_callback(struct urb *urb)
 {
index 20a132ec39e201c4190027a4f2d6750654d553cd..4264821a3b34fb653d28dafe2171e6b9239ca8e5 100644 (file)
@@ -203,8 +203,7 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port)
        return 0;
 }
 
-/* fake probe - only to allocate data structures */
-static int ipw_probe(struct usb_serial *serial, const struct usb_device_id *id)
+static int ipw_attach(struct usb_serial *serial)
 {
        struct usb_wwan_intf_private *data;
 
@@ -303,9 +302,9 @@ static struct usb_serial_driver ipw_device = {
        .num_ports =            1,
        .open =                 ipw_open,
        .close =                ipw_close,
-       .probe =                ipw_probe,
-       .attach =               usb_wwan_startup,
+       .attach =               ipw_attach,
        .release =              ipw_release,
+       .port_probe =           usb_wwan_port_probe,
        .port_remove =          usb_wwan_port_remove,
        .dtr_rts =              ipw_dtr_rts,
        .write =                usb_wwan_write,
index 29c943d737d0db508b70cda61ce6770d3a335f43..7179b0c5f8148e183219b2a71c34d6d7bf7494a6 100644 (file)
@@ -1374,13 +1374,9 @@ static struct callbacks {
           data in device_details */
 static void keyspan_setup_urbs(struct usb_serial *serial)
 {
-       int                             i, j;
        struct keyspan_serial_private   *s_priv;
        const struct keyspan_device_details     *d_details;
-       struct usb_serial_port          *port;
-       struct keyspan_port_private     *p_priv;
        struct callbacks                *cback;
-       int                             endp;
 
        s_priv = usb_get_serial_data(serial);
        d_details = s_priv->device_details;
@@ -1404,45 +1400,6 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
                (serial, d_details->glocont_endpoint, USB_DIR_OUT,
                 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
                 cback->glocont_callback);
-
-       /* Setup endpoints for each port specific thing */
-       for (i = 0; i < d_details->num_ports; i++) {
-               port = serial->port[i];
-               p_priv = usb_get_serial_port_data(port);
-
-               /* Do indat endpoints first, once for each flip */
-               endp = d_details->indat_endpoints[i];
-               for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) {
-                       p_priv->in_urbs[j] = keyspan_setup_urb
-                               (serial, endp, USB_DIR_IN, port,
-                                p_priv->in_buffer[j], 64,
-                                cback->indat_callback);
-               }
-               for (; j < 2; ++j)
-                       p_priv->in_urbs[j] = NULL;
-
-               /* outdat endpoints also have flip */
-               endp = d_details->outdat_endpoints[i];
-               for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) {
-                       p_priv->out_urbs[j] = keyspan_setup_urb
-                               (serial, endp, USB_DIR_OUT, port,
-                                p_priv->out_buffer[j], 64,
-                                cback->outdat_callback);
-               }
-               for (; j < 2; ++j)
-                       p_priv->out_urbs[j] = NULL;
-
-               /* inack endpoint */
-               p_priv->inack_urb = keyspan_setup_urb
-                       (serial, d_details->inack_endpoints[i], USB_DIR_IN,
-                        port, p_priv->inack_buffer, 1, cback->inack_callback);
-
-               /* outcont endpoint */
-               p_priv->outcont_urb = keyspan_setup_urb
-                       (serial, d_details->outcont_endpoints[i], USB_DIR_OUT,
-                        port, p_priv->outcont_buffer, 64,
-                        cback->outcont_callback);
-       }
 }
 
 /* usa19 function doesn't require prescaler */
@@ -2407,9 +2364,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
 static int keyspan_startup(struct usb_serial *serial)
 {
        int                             i, err;
-       struct usb_serial_port          *port;
        struct keyspan_serial_private   *s_priv;
-       struct keyspan_port_private     *p_priv;
        const struct keyspan_device_details     *d_details;
 
        for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
@@ -2432,19 +2387,6 @@ static int keyspan_startup(struct usb_serial *serial)
        s_priv->device_details = d_details;
        usb_set_serial_data(serial, s_priv);
 
-       /* Now setup per port private data */
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               p_priv = kzalloc(sizeof(struct keyspan_port_private),
-                                                               GFP_KERNEL);
-               if (!p_priv) {
-                       dev_dbg(&port->dev, "%s - kmalloc for keyspan_port_private (%d) failed!.\n", __func__, i);
-                       return 1;
-               }
-               p_priv->device_details = d_details;
-               usb_set_serial_port_data(port, p_priv);
-       }
-
        keyspan_setup_urbs(serial);
 
        if (s_priv->instat_urb != NULL) {
@@ -2463,59 +2405,112 @@ static int keyspan_startup(struct usb_serial *serial)
 
 static void keyspan_disconnect(struct usb_serial *serial)
 {
-       int                             i, j;
-       struct usb_serial_port          *port;
-       struct keyspan_serial_private   *s_priv;
-       struct keyspan_port_private     *p_priv;
+       struct keyspan_serial_private *s_priv;
 
        s_priv = usb_get_serial_data(serial);
 
-       /* Stop reading/writing urbs */
        stop_urb(s_priv->instat_urb);
        stop_urb(s_priv->glocont_urb);
        stop_urb(s_priv->indat_urb);
-       for (i = 0; i < serial->num_ports; ++i) {
-               port = serial->port[i];
-               p_priv = usb_get_serial_port_data(port);
-               stop_urb(p_priv->inack_urb);
-               stop_urb(p_priv->outcont_urb);
-               for (j = 0; j < 2; j++) {
-                       stop_urb(p_priv->in_urbs[j]);
-                       stop_urb(p_priv->out_urbs[j]);
-               }
-       }
+}
+
+static void keyspan_release(struct usb_serial *serial)
+{
+       struct keyspan_serial_private *s_priv;
+
+       s_priv = usb_get_serial_data(serial);
 
-       /* Now free them */
        usb_free_urb(s_priv->instat_urb);
        usb_free_urb(s_priv->indat_urb);
        usb_free_urb(s_priv->glocont_urb);
-       for (i = 0; i < serial->num_ports; ++i) {
-               port = serial->port[i];
-               p_priv = usb_get_serial_port_data(port);
-               usb_free_urb(p_priv->inack_urb);
-               usb_free_urb(p_priv->outcont_urb);
-               for (j = 0; j < 2; j++) {
-                       usb_free_urb(p_priv->in_urbs[j]);
-                       usb_free_urb(p_priv->out_urbs[j]);
-               }
-       }
+
+       kfree(s_priv);
 }
 
-static void keyspan_release(struct usb_serial *serial)
+static int keyspan_port_probe(struct usb_serial_port *port)
 {
-       int                             i;
-       struct usb_serial_port          *port;
-       struct keyspan_serial_private   *s_priv;
+       struct usb_serial *serial = port->serial;
+       struct keyspan_port_private *s_priv;
+       struct keyspan_port_private *p_priv;
+       const struct keyspan_device_details *d_details;
+       struct callbacks *cback;
+       int endp;
+       int port_num;
+       int i;
 
        s_priv = usb_get_serial_data(serial);
+       d_details = s_priv->device_details;
 
-       kfree(s_priv);
+       p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
+       if (!p_priv)
+               return -ENOMEM;
 
-       /* Now free per port private data */
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               kfree(usb_get_serial_port_data(port));
+       s_priv = usb_get_serial_data(port->serial);
+       p_priv->device_details = d_details;
+
+       /* Setup values for the various callback routines */
+       cback = &keyspan_callbacks[d_details->msg_format];
+
+       port_num = port->number - port->serial->minor;
+
+       /* Do indat endpoints first, once for each flip */
+       endp = d_details->indat_endpoints[port_num];
+       for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
+               p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
+                                               USB_DIR_IN, port,
+                                               p_priv->in_buffer[i], 64,
+                                               cback->indat_callback);
+       }
+       /* outdat endpoints also have flip */
+       endp = d_details->outdat_endpoints[port_num];
+       for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
+               p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
+                                               USB_DIR_OUT, port,
+                                               p_priv->out_buffer[i], 64,
+                                               cback->outdat_callback);
+       }
+       /* inack endpoint */
+       p_priv->inack_urb = keyspan_setup_urb(serial,
+                                       d_details->inack_endpoints[port_num],
+                                       USB_DIR_IN, port,
+                                       p_priv->inack_buffer, 1,
+                                       cback->inack_callback);
+       /* outcont endpoint */
+       p_priv->outcont_urb = keyspan_setup_urb(serial,
+                                       d_details->outcont_endpoints[port_num],
+                                       USB_DIR_OUT, port,
+                                       p_priv->outcont_buffer, 64,
+                                        cback->outcont_callback);
+
+       usb_set_serial_port_data(port, p_priv);
+
+       return 0;
+}
+
+static int keyspan_port_remove(struct usb_serial_port *port)
+{
+       struct keyspan_port_private *p_priv;
+       int i;
+
+       p_priv = usb_get_serial_port_data(port);
+
+       stop_urb(p_priv->inack_urb);
+       stop_urb(p_priv->outcont_urb);
+       for (i = 0; i < 2; i++) {
+               stop_urb(p_priv->in_urbs[i]);
+               stop_urb(p_priv->out_urbs[i]);
+       }
+
+       usb_free_urb(p_priv->inack_urb);
+       usb_free_urb(p_priv->outcont_urb);
+       for (i = 0; i < 2; i++) {
+               usb_free_urb(p_priv->in_urbs[i]);
+               usb_free_urb(p_priv->out_urbs[i]);
        }
+
+       kfree(p_priv);
+
+       return 0;
 }
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
index 0a8a40b5711e8d288a222aef5c86573c1a674cc1..0273dda303a4672f348175b6787b03c356a62b72 100644 (file)
@@ -42,6 +42,8 @@ static void keyspan_dtr_rts           (struct usb_serial_port *port, int on);
 static int  keyspan_startup            (struct usb_serial *serial);
 static void keyspan_disconnect         (struct usb_serial *serial);
 static void keyspan_release            (struct usb_serial *serial);
+static int keyspan_port_probe(struct usb_serial_port *port);
+static int keyspan_port_remove(struct usb_serial_port *port);
 static int  keyspan_write_room         (struct tty_struct *tty);
 
 static int  keyspan_write              (struct tty_struct *tty,
@@ -567,6 +569,8 @@ static struct usb_serial_driver keyspan_1port_device = {
        .attach                 = keyspan_startup,
        .disconnect             = keyspan_disconnect,
        .release                = keyspan_release,
+       .port_probe             = keyspan_port_probe,
+       .port_remove            = keyspan_port_remove,
 };
 
 static struct usb_serial_driver keyspan_2port_device = {
@@ -589,6 +593,8 @@ static struct usb_serial_driver keyspan_2port_device = {
        .attach                 = keyspan_startup,
        .disconnect             = keyspan_disconnect,
        .release                = keyspan_release,
+       .port_probe             = keyspan_port_probe,
+       .port_remove            = keyspan_port_remove,
 };
 
 static struct usb_serial_driver keyspan_4port_device = {
@@ -611,6 +617,8 @@ static struct usb_serial_driver keyspan_4port_device = {
        .attach                 = keyspan_startup,
        .disconnect             = keyspan_disconnect,
        .release                = keyspan_release,
+       .port_probe             = keyspan_port_probe,
+       .port_remove            = keyspan_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
index f3947712e1375db3ee407a5efa20a1acad3d3c9d..8a2081004107977dc929d586ffda41fdf34abf06 100644 (file)
@@ -49,7 +49,8 @@
  * Function prototypes
  */
 static int  mct_u232_startup(struct usb_serial *serial);
-static void mct_u232_release(struct usb_serial *serial);
+static int  mct_u232_port_probe(struct usb_serial_port *port);
+static int  mct_u232_port_remove(struct usb_serial_port *remove);
 static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void mct_u232_close(struct usb_serial_port *port);
 static void mct_u232_dtr_rts(struct usb_serial_port *port, int on);
@@ -99,7 +100,8 @@ static struct usb_serial_driver mct_u232_device = {
        .tiocmget =          mct_u232_tiocmget,
        .tiocmset =          mct_u232_tiocmset,
        .attach =            mct_u232_startup,
-       .release =           mct_u232_release,
+       .port_probe =        mct_u232_port_probe,
+       .port_remove =       mct_u232_port_remove,
        .ioctl =             mct_u232_ioctl,
        .get_icount =        mct_u232_get_icount,
 };
@@ -388,18 +390,8 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port,
 
 static int mct_u232_startup(struct usb_serial *serial)
 {
-       struct mct_u232_private *priv;
        struct usb_serial_port *port, *rport;
 
-       priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-       spin_lock_init(&priv->lock);
-       init_waitqueue_head(&priv->msr_wait);
-       usb_set_serial_port_data(serial->port[0], priv);
-
-       init_waitqueue_head(&serial->port[0]->write_wait);
-
        /* Puh, that's dirty */
        port = serial->port[0];
        rport = serial->port[1];
@@ -412,18 +404,31 @@ static int mct_u232_startup(struct usb_serial *serial)
        return 0;
 } /* mct_u232_startup */
 
+static int mct_u232_port_probe(struct usb_serial_port *port)
+{
+       struct mct_u232_private *priv;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       spin_lock_init(&priv->lock);
+       init_waitqueue_head(&priv->msr_wait);
+
+       usb_set_serial_port_data(port, priv);
 
-static void mct_u232_release(struct usb_serial *serial)
+       return 0;
+}
+
+static int mct_u232_port_remove(struct usb_serial_port *port)
 {
        struct mct_u232_private *priv;
-       int i;
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               /* My special items, the standard routines free my urbs */
-               priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(priv);
-       }
-} /* mct_u232_release */
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
+}
 
 static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
@@ -515,12 +520,14 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
 
 static void mct_u232_close(struct usb_serial_port *port)
 {
-       if (port->serial->dev) {
-               /* shutdown our urbs */
-               usb_kill_urb(port->write_urb);
-               usb_kill_urb(port->read_urb);
-               usb_kill_urb(port->interrupt_in_urb);
-       }
+       /*
+        * Must kill the read urb as it is actually an interrupt urb, which
+        * generic close thus fails to kill.
+        */
+       usb_kill_urb(port->read_urb);
+       usb_kill_urb(port->interrupt_in_urb);
+
+       usb_serial_generic_close(port);
 } /* mct_u232_close */
 
 
index 0b257ddffbdbd903da48db51746bee3da9ebe4d6..6f29c74eb76925098a9cab841142c955c6d3a725 100644 (file)
@@ -179,16 +179,13 @@ static void metrousb_cleanup(struct usb_serial_port *port)
 {
        dev_dbg(&port->dev, "%s\n", __func__);
 
-       if (port->serial->dev) {
-               /* Shutdown any interrupt in urbs. */
-               if (port->interrupt_in_urb) {
-                       usb_unlink_urb(port->interrupt_in_urb);
-                       usb_kill_urb(port->interrupt_in_urb);
-               }
-
-               /* Send deactivate cmd to device */
+       usb_unlink_urb(port->interrupt_in_urb);
+       usb_kill_urb(port->interrupt_in_urb);
+
+       mutex_lock(&port->serial->disc_mutex);
+       if (!port->serial->disconnected)
                metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port);
-       }
+       mutex_unlock(&port->serial->disc_mutex);
 }
 
 static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
@@ -271,51 +268,27 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr
        return retval;
 }
 
-static void metrousb_shutdown(struct usb_serial *serial)
+static int metrousb_port_probe(struct usb_serial_port *port)
 {
-       int i = 0;
+       struct metrousb_private *metro_priv;
 
-       dev_dbg(&serial->dev->dev, "%s\n", __func__);
+       metro_priv = kzalloc(sizeof(*metro_priv), GFP_KERNEL);
+       if (!metro_priv)
+               return -ENOMEM;
 
-       /* Stop reading and writing on all ports. */
-       for (i = 0; i < serial->num_ports; ++i) {
-               /* Close any open urbs. */
-               metrousb_cleanup(serial->port[i]);
+       spin_lock_init(&metro_priv->lock);
 
-               /* Free memory. */
-               kfree(usb_get_serial_port_data(serial->port[i]));
-               usb_set_serial_port_data(serial->port[i], NULL);
+       usb_set_serial_port_data(port, metro_priv);
 
-               dev_dbg(&serial->dev->dev, "%s - freed port number=%d\n",
-                       __func__, serial->port[i]->number);
-       }
+       return 0;
 }
 
-static int metrousb_startup(struct usb_serial *serial)
+static int metrousb_port_remove(struct usb_serial_port *port)
 {
        struct metrousb_private *metro_priv;
-       struct usb_serial_port *port;
-       int i = 0;
 
-       dev_dbg(&serial->dev->dev, "%s\n", __func__);
-
-       /* Loop through the serial ports setting up the private structures.
-        * Currently we only use one port. */
-       for (i = 0; i < serial->num_ports; ++i) {
-               port = serial->port[i];
-
-               /* Declare memory. */
-               metro_priv = kzalloc(sizeof(struct metrousb_private), GFP_KERNEL);
-               if (!metro_priv)
-                       return -ENOMEM;
-
-               /* Initialize memory. */
-               spin_lock_init(&metro_priv->lock);
-               usb_set_serial_port_data(port, metro_priv);
-
-               dev_dbg(&serial->dev->dev, "%s - port number=%d\n ",
-                       __func__, port->number);
-       }
+       metro_priv = usb_get_serial_port_data(port);
+       kfree(metro_priv);
 
        return 0;
 }
@@ -414,8 +387,8 @@ static struct usb_serial_driver metrousb_device = {
        .close                  = metrousb_cleanup,
        .read_int_callback      = metrousb_read_int_callback,
        .write_int_callback     = metrousb_write_int_callback,
-       .attach                 = metrousb_startup,
-       .release                = metrousb_shutdown,
+       .port_probe             = metrousb_port_probe,
+       .port_remove            = metrousb_port_remove,
        .throttle               = metrousb_throttle,
        .unthrottle             = metrousb_unthrottle,
        .tiocmget               = metrousb_tiocmget,
index 1bf1ad0666667a9c31284c658814b651d91d2c66..75267421aad85636d480b732a507a176e874814f 100644 (file)
@@ -1966,9 +1966,7 @@ static int mos7720_ioctl(struct tty_struct *tty,
 
 static int mos7720_startup(struct usb_serial *serial)
 {
-       struct moschip_port *mos7720_port;
        struct usb_device *dev;
-       int i;
        char data;
        u16 product;
        int ret_val;
@@ -1999,29 +1997,6 @@ static int mos7720_startup(struct usb_serial *serial)
                serial->port[1]->interrupt_in_buffer = NULL;
        }
 
-
-       /* set up serial port private structures */
-       for (i = 0; i < serial->num_ports; ++i) {
-               mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
-               if (mos7720_port == NULL) {
-                       dev_err(&dev->dev, "%s - Out of memory\n", __func__);
-                       return -ENOMEM;
-               }
-
-               /* Initialize all port interrupt end point to port 0 int
-                * endpoint.  Our device has only one interrupt endpoint
-                * common to all ports */
-               serial->port[i]->interrupt_in_endpointAddress =
-                               serial->port[0]->interrupt_in_endpointAddress;
-
-               mos7720_port->port = serial->port[i];
-               usb_set_serial_port_data(serial->port[i], mos7720_port);
-
-               dev_dbg(&dev->dev, "port number is %d\n", serial->port[i]->number);
-               dev_dbg(&dev->dev, "serial number is %d\n", serial->minor);
-       }
-
-
        /* setting configuration feature to one */
        usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
                        (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ);
@@ -2049,8 +2024,6 @@ static int mos7720_startup(struct usb_serial *serial)
 
 static void mos7720_release(struct usb_serial *serial)
 {
-       int i;
-
 #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
        /* close the parallel port */
 
@@ -2089,9 +2062,36 @@ static void mos7720_release(struct usb_serial *serial)
                kref_put(&mos_parport->ref_count, destroy_mos_parport);
        }
 #endif
-       /* free private structure allocated for serial port */
-       for (i = 0; i < serial->num_ports; ++i)
-               kfree(usb_get_serial_port_data(serial->port[i]));
+}
+
+static int mos7720_port_probe(struct usb_serial_port *port)
+{
+       struct moschip_port *mos7720_port;
+
+       mos7720_port = kzalloc(sizeof(*mos7720_port), GFP_KERNEL);
+       if (!mos7720_port)
+               return -ENOMEM;
+
+       /* Initialize all port interrupt end point to port 0 int endpoint.
+        * Our device has only one interrupt endpoint common to all ports.
+        */
+       port->interrupt_in_endpointAddress =
+               port->serial->port[0]->interrupt_in_endpointAddress;
+       mos7720_port->port = port;
+
+       usb_set_serial_port_data(port, mos7720_port);
+
+       return 0;
+}
+
+static int mos7720_port_remove(struct usb_serial_port *port)
+{
+       struct moschip_port *mos7720_port;
+
+       mos7720_port = usb_get_serial_port_data(port);
+       kfree(mos7720_port);
+
+       return 0;
 }
 
 static struct usb_serial_driver moschip7720_2port_driver = {
@@ -2109,6 +2109,8 @@ static struct usb_serial_driver moschip7720_2port_driver = {
        .probe                  = mos77xx_probe,
        .attach                 = mos7720_startup,
        .release                = mos7720_release,
+       .port_probe             = mos7720_port_probe,
+       .port_remove            = mos7720_port_remove,
        .ioctl                  = mos7720_ioctl,
        .tiocmget               = mos7720_tiocmget,
        .tiocmset               = mos7720_tiocmset,
index d6d4eeca8c68390ef4555e455cbfea66c68038b9..1cf3375ec1afb12fbea2314a63539ced2c36b221 100644 (file)
@@ -218,12 +218,10 @@ struct moschip_port {
        int port_num;           /*Actual port number in the device(1,2,etc) */
        struct urb *write_urb;  /* write URB for this port */
        struct urb *read_urb;   /* read URB for this port */
-       struct urb *int_urb;
        __u8 shadowLCR;         /* last LCR value received */
        __u8 shadowMCR;         /* last MCR value received */
        char open;
        char open_ports;
-       char zombie;
        wait_queue_head_t wait_chase;   /* for handling sleeping while waiting for chase to finish */
        wait_queue_head_t delta_msr_wait;       /* for handling sleeping while waiting for msr change to happen */
        int delta_msr_cond;
@@ -478,7 +476,6 @@ static void mos7840_control_callback(struct urb *urb)
        struct moschip_port *mos7840_port;
        struct device *dev = &urb->dev->dev;
        __u8 regval = 0x0;
-       int result = 0;
        int status = urb->status;
 
        mos7840_port = urb->context;
@@ -495,7 +492,7 @@ static void mos7840_control_callback(struct urb *urb)
                return;
        default:
                dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status);
-               goto exit;
+               return;
        }
 
        dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length);
@@ -508,16 +505,6 @@ static void mos7840_control_callback(struct urb *urb)
                mos7840_handle_new_msr(mos7840_port, regval);
        else if (mos7840_port->MsrLsr == 1)
                mos7840_handle_new_lsr(mos7840_port, regval);
-
-exit:
-       spin_lock(&mos7840_port->pool_lock);
-       if (!mos7840_port->zombie)
-               result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC);
-       spin_unlock(&mos7840_port->pool_lock);
-       if (result) {
-               dev_err(dev, "%s - Error %d submitting interrupt urb\n",
-                       __func__, result);
-       }
 }
 
 static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
@@ -686,14 +673,7 @@ static void mos7840_interrupt_callback(struct urb *urb)
                                        wreg = MODEM_STATUS_REGISTER;
                                        break;
                                }
-                               spin_lock(&mos7840_port->pool_lock);
-                               if (!mos7840_port->zombie) {
-                                       rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
-                               } else {
-                                       spin_unlock(&mos7840_port->pool_lock);
-                                       return;
-                               }
-                               spin_unlock(&mos7840_port->pool_lock);
+                               rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
                        }
                }
        }
@@ -2347,309 +2327,249 @@ static int mos7840_calc_num_ports(struct usb_serial *serial)
        return mos7840_num_ports;
 }
 
-/****************************************************************************
- * mos7840_startup
- ****************************************************************************/
-
-static int mos7840_startup(struct usb_serial *serial)
+static int mos7840_port_probe(struct usb_serial_port *port)
 {
+       struct usb_serial *serial = port->serial;
        struct moschip_port *mos7840_port;
-       struct usb_device *dev;
-       int i, status;
+       int status;
+       int pnum;
        __u16 Data;
 
-       dev = serial->dev;
-
        /* we set up the pointers to the endpoints in the mos7840_open *
         * function, as the structures aren't created yet.             */
 
-       /* set up port private structures */
-       for (i = 0; i < serial->num_ports; ++i) {
-               dev_dbg(&dev->dev, "mos7840_startup: configuring port %d............\n", i);
-               mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
-               if (mos7840_port == NULL) {
-                       dev_err(&dev->dev, "%s - Out of memory\n", __func__);
-                       status = -ENOMEM;
-                       i--; /* don't follow NULL pointer cleaning up */
-                       goto error;
-               }
-
-               /* Initialize all port interrupt end point to port 0 int
-                * endpoint. Our device has only one interrupt end point
-                * common to all port */
-
-               mos7840_port->port = serial->port[i];
-               mos7840_set_port_private(serial->port[i], mos7840_port);
-               spin_lock_init(&mos7840_port->pool_lock);
-
-               /* minor is not initialised until later by
-                * usb-serial.c:get_free_serial() and cannot therefore be used
-                * to index device instances */
-               mos7840_port->port_num = i + 1;
-               dev_dbg(&dev->dev, "serial->port[i]->number = %d\n", serial->port[i]->number);
-               dev_dbg(&dev->dev, "serial->port[i]->serial->minor = %d\n", serial->port[i]->serial->minor);
-               dev_dbg(&dev->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num);
-               dev_dbg(&dev->dev, "serial->minor = %d\n", serial->minor);
-
-               if (mos7840_port->port_num == 1) {
-                       mos7840_port->SpRegOffset = 0x0;
-                       mos7840_port->ControlRegOffset = 0x1;
-                       mos7840_port->DcrRegOffset = 0x4;
-               } else if ((mos7840_port->port_num == 2)
-                          && (serial->num_ports == 4)) {
-                       mos7840_port->SpRegOffset = 0x8;
-                       mos7840_port->ControlRegOffset = 0x9;
-                       mos7840_port->DcrRegOffset = 0x16;
-               } else if ((mos7840_port->port_num == 2)
-                          && (serial->num_ports == 2)) {
-                       mos7840_port->SpRegOffset = 0xa;
-                       mos7840_port->ControlRegOffset = 0xb;
-                       mos7840_port->DcrRegOffset = 0x19;
-               } else if ((mos7840_port->port_num == 3)
-                          && (serial->num_ports == 4)) {
-                       mos7840_port->SpRegOffset = 0xa;
-                       mos7840_port->ControlRegOffset = 0xb;
-                       mos7840_port->DcrRegOffset = 0x19;
-               } else if ((mos7840_port->port_num == 4)
-                          && (serial->num_ports == 4)) {
-                       mos7840_port->SpRegOffset = 0xc;
-                       mos7840_port->ControlRegOffset = 0xd;
-                       mos7840_port->DcrRegOffset = 0x1c;
-               }
-               mos7840_dump_serial_port(serial->port[i], mos7840_port);
-               mos7840_set_port_private(serial->port[i], mos7840_port);
+       pnum = port->number - serial->minor;
 
-               /* enable rx_disable bit in control register */
-               status = mos7840_get_reg_sync(serial->port[i],
-                                mos7840_port->ControlRegOffset, &Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Reading ControlReg failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "ControlReg Reading success val is %x, status%d\n", Data, status);
-               Data |= 0x08;   /* setting driver done bit */
-               Data |= 0x04;   /* sp1_bit to have cts change reflect in
-                                  modem status reg */
-
-               /* Data |= 0x20; //rx_disable bit */
-               status = mos7840_set_reg_sync(serial->port[i],
-                                        mos7840_port->ControlRegOffset, Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "ControlReg Writing success(rx_disable) status%d\n", status);
+       dev_dbg(&port->dev, "mos7840_startup: configuring port %d\n", pnum);
+       mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
+       if (mos7840_port == NULL) {
+               dev_err(&port->dev, "%s - Out of memory\n", __func__);
+               return -ENOMEM;
+       }
 
-               /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2
-                  and 0x24 in DCR3 */
-               Data = 0x01;
-               status = mos7840_set_reg_sync(serial->port[i],
-                        (__u16) (mos7840_port->DcrRegOffset + 0), Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing DCR0 failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "DCR0 Writing success status%d\n", status);
+       /* Initialize all port interrupt end point to port 0 int
+        * endpoint. Our device has only one interrupt end point
+        * common to all port */
+
+       mos7840_port->port = port;
+       mos7840_set_port_private(port, mos7840_port);
+       spin_lock_init(&mos7840_port->pool_lock);
+
+       /* minor is not initialised until later by
+        * usb-serial.c:get_free_serial() and cannot therefore be used
+        * to index device instances */
+       mos7840_port->port_num = pnum + 1;
+       dev_dbg(&port->dev, "port->number = %d\n", port->number);
+       dev_dbg(&port->dev, "port->serial->minor = %d\n", port->serial->minor);
+       dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num);
+       dev_dbg(&port->dev, "serial->minor = %d\n", serial->minor);
+
+       if (mos7840_port->port_num == 1) {
+               mos7840_port->SpRegOffset = 0x0;
+               mos7840_port->ControlRegOffset = 0x1;
+               mos7840_port->DcrRegOffset = 0x4;
+       } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 4)) {
+               mos7840_port->SpRegOffset = 0x8;
+               mos7840_port->ControlRegOffset = 0x9;
+               mos7840_port->DcrRegOffset = 0x16;
+       } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 2)) {
+               mos7840_port->SpRegOffset = 0xa;
+               mos7840_port->ControlRegOffset = 0xb;
+               mos7840_port->DcrRegOffset = 0x19;
+       } else if ((mos7840_port->port_num == 3) && (serial->num_ports == 4)) {
+               mos7840_port->SpRegOffset = 0xa;
+               mos7840_port->ControlRegOffset = 0xb;
+               mos7840_port->DcrRegOffset = 0x19;
+       } else if ((mos7840_port->port_num == 4) && (serial->num_ports == 4)) {
+               mos7840_port->SpRegOffset = 0xc;
+               mos7840_port->ControlRegOffset = 0xd;
+               mos7840_port->DcrRegOffset = 0x1c;
+       }
+       mos7840_dump_serial_port(port, mos7840_port);
+       mos7840_set_port_private(port, mos7840_port);
+
+       /* enable rx_disable bit in control register */
+       status = mos7840_get_reg_sync(port,
+                       mos7840_port->ControlRegOffset, &Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Reading ControlReg failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "ControlReg Reading success val is %x, status%d\n", Data, status);
+       Data |= 0x08;   /* setting driver done bit */
+       Data |= 0x04;   /* sp1_bit to have cts change reflect in
+                          modem status reg */
 
-               Data = 0x05;
-               status = mos7840_set_reg_sync(serial->port[i],
-                        (__u16) (mos7840_port->DcrRegOffset + 1), Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing DCR1 failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "DCR1 Writing success status%d\n", status);
+       /* Data |= 0x20; //rx_disable bit */
+       status = mos7840_set_reg_sync(port,
+                       mos7840_port->ControlRegOffset, Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "ControlReg Writing success(rx_disable) status%d\n", status);
 
-               Data = 0x24;
-               status = mos7840_set_reg_sync(serial->port[i],
-                        (__u16) (mos7840_port->DcrRegOffset + 2), Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing DCR2 failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "DCR2 Writing success status%d\n", status);
+       /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2
+          and 0x24 in DCR3 */
+       Data = 0x01;
+       status = mos7840_set_reg_sync(port,
+                       (__u16) (mos7840_port->DcrRegOffset + 0), Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing DCR0 failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "DCR0 Writing success status%d\n", status);
 
-               /* write values in clkstart0x0 and clkmulti 0x20 */
-               Data = 0x0;
-               status = mos7840_set_reg_sync(serial->port[i],
-                                        CLK_START_VALUE_REGISTER, Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status);
+       Data = 0x05;
+       status = mos7840_set_reg_sync(port,
+                       (__u16) (mos7840_port->DcrRegOffset + 1), Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing DCR1 failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "DCR1 Writing success status%d\n", status);
 
-               Data = 0x20;
-               status = mos7840_set_reg_sync(serial->port[i],
-                                       CLK_MULTI_REGISTER, Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status);
-                       goto error;
-               } else
-                       dev_dbg(&dev->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status);
+       Data = 0x24;
+       status = mos7840_set_reg_sync(port,
+                       (__u16) (mos7840_port->DcrRegOffset + 2), Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing DCR2 failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "DCR2 Writing success status%d\n", status);
 
-               /* write value 0x0 to scratchpad register */
-               Data = 0x00;
-               status = mos7840_set_uart_reg(serial->port[i],
-                                               SCRATCH_PAD_REGISTER, Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status);
+       /* write values in clkstart0x0 and clkmulti 0x20 */
+       Data = 0x0;
+       status = mos7840_set_reg_sync(port, CLK_START_VALUE_REGISTER, Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status);
 
-               /* Zero Length flag register */
-               if ((mos7840_port->port_num != 1)
-                   && (serial->num_ports == 2)) {
+       Data = 0x20;
+       status = mos7840_set_reg_sync(port, CLK_MULTI_REGISTER, Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status);
+               goto error;
+       } else
+               dev_dbg(&port->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status);
 
-                       Data = 0xff;
-                       status = mos7840_set_reg_sync(serial->port[i],
-                                     (__u16) (ZLP_REG1 +
-                                     ((__u16)mos7840_port->port_num)), Data);
-                       dev_dbg(&dev->dev, "ZLIP offset %x\n",
+       /* write value 0x0 to scratchpad register */
+       Data = 0x00;
+       status = mos7840_set_uart_reg(port, SCRATCH_PAD_REGISTER, Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status);
+
+       /* Zero Length flag register */
+       if ((mos7840_port->port_num != 1) && (serial->num_ports == 2)) {
+               Data = 0xff;
+               status = mos7840_set_reg_sync(port,
+                               (__u16) (ZLP_REG1 +
+                                       ((__u16)mos7840_port->port_num)), Data);
+               dev_dbg(&port->dev, "ZLIP offset %x\n",
                                (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num)));
-                       if (status < 0) {
-                               dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 2, status);
-                               break;
-                       } else
-                               dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 2, status);
-               } else {
-                       Data = 0xff;
-                       status = mos7840_set_reg_sync(serial->port[i],
-                             (__u16) (ZLP_REG1 +
-                             ((__u16)mos7840_port->port_num) - 0x1), Data);
-                       dev_dbg(&dev->dev, "ZLIP offset %x\n",
+               if (status < 0) {
+                       dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 2, status);
+                       goto out;
+               } else
+                       dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 2, status);
+       } else {
+               Data = 0xff;
+               status = mos7840_set_reg_sync(port,
+                               (__u16) (ZLP_REG1 +
+                                       ((__u16)mos7840_port->port_num) - 0x1), Data);
+               dev_dbg(&port->dev, "ZLIP offset %x\n",
                                (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1));
-                       if (status < 0) {
-                               dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 1, status);
-                               break;
-                       } else
-                               dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 1, status);
+               if (status < 0) {
+                       dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 1, status);
+                       goto out;
+               } else
+                       dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 1, status);
 
-               }
-               mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL);
-               mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
-               mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest),
-                                                               GFP_KERNEL);
-               if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf ||
-                                                       !mos7840_port->dr) {
-                       status = -ENOMEM;
-                       goto error;
-               }
+       }
+       mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL);
+       mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
+       mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest),
+                       GFP_KERNEL);
+       if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf ||
+                       !mos7840_port->dr) {
+               status = -ENOMEM;
+               goto error;
+       }
 
-               mos7840_port->has_led = false;
+       mos7840_port->has_led = false;
 
-               /* Initialize LED timers */
-               if (device_type == MOSCHIP_DEVICE_ID_7810) {
-                       mos7840_port->has_led = true;
+       /* Initialize LED timers */
+       if (device_type == MOSCHIP_DEVICE_ID_7810) {
+               mos7840_port->has_led = true;
 
-                       init_timer(&mos7840_port->led_timer1);
-                       mos7840_port->led_timer1.function = mos7840_led_off;
-                       mos7840_port->led_timer1.expires =
-                                       jiffies + msecs_to_jiffies(LED_ON_MS);
-                       mos7840_port->led_timer1.data =
-                                               (unsigned long)mos7840_port;
+               init_timer(&mos7840_port->led_timer1);
+               mos7840_port->led_timer1.function = mos7840_led_off;
+               mos7840_port->led_timer1.expires =
+                       jiffies + msecs_to_jiffies(LED_ON_MS);
+               mos7840_port->led_timer1.data = (unsigned long)mos7840_port;
 
-                       init_timer(&mos7840_port->led_timer2);
-                       mos7840_port->led_timer2.function =
-                                               mos7840_led_flag_off;
-                       mos7840_port->led_timer2.expires =
-                                       jiffies + msecs_to_jiffies(LED_OFF_MS);
-                       mos7840_port->led_timer2.data =
-                                               (unsigned long)mos7840_port;
+               init_timer(&mos7840_port->led_timer2);
+               mos7840_port->led_timer2.function = mos7840_led_flag_off;
+               mos7840_port->led_timer2.expires =
+                       jiffies + msecs_to_jiffies(LED_OFF_MS);
+               mos7840_port->led_timer2.data = (unsigned long)mos7840_port;
 
-                       mos7840_port->led_flag = false;
+               mos7840_port->led_flag = false;
 
-                       /* Turn off LED */
-                       mos7840_set_led_sync(serial->port[i],
-                                               MODEM_CONTROL_REGISTER, 0x0300);
-               }
+               /* Turn off LED */
+               mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300);
        }
+out:
+       if (pnum == serial->num_ports - 1) {
+               /* Zero Length flag enable */
+               Data = 0x0f;
+               status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
+               if (status < 0) {
+                       dev_dbg(&port->dev, "Writing ZLP_REG5 failed status-0x%x\n", status);
+                       goto error;
+               } else
+                       dev_dbg(&port->dev, "ZLP_REG5 Writing success status%d\n", status);
 
-       /* Zero Length flag enable */
-       Data = 0x0f;
-       status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
-       if (status < 0) {
-               dev_dbg(&dev->dev, "Writing ZLP_REG5 failed status-0x%x\n", status);
-               goto error;
-       } else
-               dev_dbg(&dev->dev, "ZLP_REG5 Writing success status%d\n", status);
-
-       /* setting configuration feature to one */
-       usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-                       (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, MOS_WDR_TIMEOUT);
+               /* setting configuration feature to one */
+               usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                               0x03, 0x00, 0x01, 0x00, NULL, 0x00,
+                               MOS_WDR_TIMEOUT);
+       }
        return 0;
 error:
-       for (/* nothing */; i >= 0; i--) {
-               mos7840_port = mos7840_get_port_private(serial->port[i]);
+       kfree(mos7840_port->dr);
+       kfree(mos7840_port->ctrl_buf);
+       usb_free_urb(mos7840_port->control_urb);
+       kfree(mos7840_port);
 
-               kfree(mos7840_port->dr);
-               kfree(mos7840_port->ctrl_buf);
-               usb_free_urb(mos7840_port->control_urb);
-               kfree(mos7840_port);
-               serial->port[i] = NULL;
-       }
        return status;
 }
 
-/****************************************************************************
- * mos7840_disconnect
- *     This function is called whenever the device is removed from the usb bus.
- ****************************************************************************/
-
-static void mos7840_disconnect(struct usb_serial *serial)
+static int mos7840_port_remove(struct usb_serial_port *port)
 {
-       int i;
-       unsigned long flags;
        struct moschip_port *mos7840_port;
 
-       /* check for the ports to be closed,close the ports and disconnect */
+       mos7840_port = mos7840_get_port_private(port);
 
-       /* free private structure allocated for serial port  *
-        * stop reads and writes on all ports                */
+       if (mos7840_port->has_led) {
+               /* Turn off LED */
+               mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300);
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               mos7840_port = mos7840_get_port_private(serial->port[i]);
-               if (mos7840_port) {
-                       spin_lock_irqsave(&mos7840_port->pool_lock, flags);
-                       mos7840_port->zombie = 1;
-                       spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
-                       usb_kill_urb(mos7840_port->control_urb);
-               }
+               del_timer_sync(&mos7840_port->led_timer1);
+               del_timer_sync(&mos7840_port->led_timer2);
        }
-}
-
-/****************************************************************************
- * mos7840_release
- *     This function is called when the usb_serial structure is freed.
- ****************************************************************************/
-
-static void mos7840_release(struct usb_serial *serial)
-{
-       int i;
-       struct moschip_port *mos7840_port;
-
-       /* check for the ports to be closed,close the ports and disconnect */
+       usb_kill_urb(mos7840_port->control_urb);
+       usb_free_urb(mos7840_port->control_urb);
+       kfree(mos7840_port->ctrl_buf);
+       kfree(mos7840_port->dr);
+       kfree(mos7840_port);
 
-       /* free private structure allocated for serial port  *
-        * stop reads and writes on all ports                */
-
-       for (i = 0; i < serial->num_ports; ++i) {
-               mos7840_port = mos7840_get_port_private(serial->port[i]);
-               if (mos7840_port) {
-                       if (mos7840_port->has_led) {
-                               /* Turn off LED */
-                               mos7840_set_led_sync(mos7840_port->port,
-                                               MODEM_CONTROL_REGISTER, 0x0300);
-
-                               del_timer_sync(&mos7840_port->led_timer1);
-                               del_timer_sync(&mos7840_port->led_timer2);
-                       }
-                       kfree(mos7840_port->ctrl_buf);
-                       kfree(mos7840_port->dr);
-                       kfree(mos7840_port);
-               }
-       }
+       return 0;
 }
 
 static struct usb_serial_driver moschip7840_4port_device = {
@@ -2677,9 +2597,8 @@ static struct usb_serial_driver moschip7840_4port_device = {
        .tiocmget = mos7840_tiocmget,
        .tiocmset = mos7840_tiocmset,
        .get_icount = mos7840_get_icount,
-       .attach = mos7840_startup,
-       .disconnect = mos7840_disconnect,
-       .release = mos7840_release,
+       .port_probe = mos7840_port_probe,
+       .port_remove = mos7840_port_remove,
        .read_bulk_callback = mos7840_bulk_in_callback,
        .read_int_callback = mos7840_interrupt_callback,
 };
index 6def58b79382f97511929b2c3fc8e386c71ffa51..9ab73d2957746d49292357382f7a081faa25cd55 100644 (file)
@@ -44,8 +44,8 @@ static int  omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
                                const unsigned char *buf, int count);
 static int  omninet_write_room(struct tty_struct *tty);
 static void omninet_disconnect(struct usb_serial *serial);
-static void omninet_release(struct usb_serial *serial);
-static int omninet_attach(struct usb_serial *serial);
+static int omninet_port_probe(struct usb_serial_port *port);
+static int omninet_port_remove(struct usb_serial_port *port);
 
 static const struct usb_device_id id_table[] = {
        { USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) },
@@ -62,7 +62,8 @@ static struct usb_serial_driver zyxel_omninet_device = {
        .description =          "ZyXEL - omni.net lcd plus usb",
        .id_table =             id_table,
        .num_ports =            1,
-       .attach =               omninet_attach,
+       .port_probe =           omninet_port_probe,
+       .port_remove =          omninet_port_remove,
        .open =                 omninet_open,
        .close =                omninet_close,
        .write =                omninet_write,
@@ -70,7 +71,6 @@ static struct usb_serial_driver zyxel_omninet_device = {
        .read_bulk_callback =   omninet_read_bulk_callback,
        .write_bulk_callback =  omninet_write_bulk_callback,
        .disconnect =           omninet_disconnect,
-       .release =              omninet_release,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -112,18 +112,26 @@ struct omninet_data {
        __u8    od_outseq;      /* Sequence number for bulk_out URBs */
 };
 
-static int omninet_attach(struct usb_serial *serial)
+static int omninet_port_probe(struct usb_serial_port *port)
 {
        struct omninet_data *od;
-       struct usb_serial_port *port = serial->port[0];
 
        od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL);
-       if (!od) {
-               dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n",
-                       __func__, sizeof(struct omninet_data));
+       if (!od)
                return -ENOMEM;
-       }
+
        usb_set_serial_port_data(port, od);
+
+       return 0;
+}
+
+static int omninet_port_remove(struct usb_serial_port *port)
+{
+       struct omninet_data *od;
+
+       od = usb_get_serial_port_data(port);
+       kfree(od);
+
        return 0;
 }
 
@@ -279,14 +287,6 @@ static void omninet_disconnect(struct usb_serial *serial)
        usb_kill_urb(wport->write_urb);
 }
 
-
-static void omninet_release(struct usb_serial *serial)
-{
-       struct usb_serial_port *port = serial->port[0];
-
-       kfree(usb_get_serial_port_data(port));
-}
-
 module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
index 41b1647306eb0970f55993f0099307af50739349..6aba731d4864457acba4e644b463a5c2f725dfc7 100644 (file)
@@ -155,7 +155,11 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
 {
        struct usb_serial *serial = port->serial;
        int retval;
-       u8 buffer[2];
+       u8 *buffer;
+
+       buffer = kzalloc(1, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
 
        buffer[0] = val;
        /* Send the message to the vendor control endpoint
@@ -164,6 +168,7 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
                                requesttype,
                                USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
                                0, 0, buffer, 1, 0);
+       kfree(buffer);
 
        return retval;
 }
@@ -281,7 +286,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
        if (!dr) {
                dev_err(&port->dev, "out of memory\n");
                count = -ENOMEM;
-               goto error;
+               goto error_no_dr;
        }
 
        dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT;
@@ -311,6 +316,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
 
        return count;
 error:
+       kfree(dr);
+error_no_dr:
        usb_free_urb(urb);
 error_no_urb:
        kfree(buffer);
index 54d4148d01d120a6d5c2085eb3d884328405a109..5dee7d61241e2269d6453a0c5693af3a354e8a0e 100644 (file)
@@ -47,6 +47,7 @@
 /* Function prototypes */
 static int  option_probe(struct usb_serial *serial,
                        const struct usb_device_id *id);
+static int option_attach(struct usb_serial *serial);
 static void option_release(struct usb_serial *serial);
 static int option_send_setup(struct usb_serial_port *port);
 static void option_instat_callback(struct urb *urb);
@@ -1288,8 +1289,9 @@ static struct usb_serial_driver option_1port_device = {
        .tiocmget          = usb_wwan_tiocmget,
        .tiocmset          = usb_wwan_tiocmset,
        .ioctl             = usb_wwan_ioctl,
-       .attach            = usb_wwan_startup,
+       .attach            = option_attach,
        .release           = option_release,
+       .port_probe        = usb_wwan_port_probe,
        .port_remove       = usb_wwan_port_remove,
        .read_int_callback = option_instat_callback,
 #ifdef CONFIG_PM
@@ -1335,8 +1337,6 @@ static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason,
 static int option_probe(struct usb_serial *serial,
                        const struct usb_device_id *id)
 {
-       struct usb_wwan_intf_private *data;
-       struct option_private *priv;
        struct usb_interface_descriptor *iface_desc =
                                &serial->interface->cur_altsetting->desc;
        struct usb_device_descriptor *dev_desc = &serial->dev->descriptor;
@@ -1374,6 +1374,19 @@ static int option_probe(struct usb_serial *serial,
                iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
                return -ENODEV;
 
+       /* Store device id so we can use it during attach. */
+       usb_set_serial_data(serial, (void *)id);
+
+       return 0;
+}
+
+static int option_attach(struct usb_serial *serial)
+{
+       struct usb_interface_descriptor *iface_desc;
+       const struct usb_device_id *id;
+       struct usb_wwan_intf_private *data;
+       struct option_private *priv;
+
        data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
@@ -1384,6 +1397,10 @@ static int option_probe(struct usb_serial *serial,
                return -ENOMEM;
        }
 
+       /* Retrieve device id stored at probe. */
+       id = usb_get_serial_data(serial);
+       iface_desc = &serial->interface->cur_altsetting->desc;
+
        priv->bInterfaceNumber = iface_desc->bInterfaceNumber;
        data->private = priv;
 
index c3ddb65c05f295158ee6ac4022cbca367bf11f21..aa148c21ea40e82a6f49b58b855ed2278f53cf3a 100644 (file)
@@ -138,7 +138,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
 
 static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
 {
-       struct usb_wwan_intf_private *data;
        struct usb_host_interface *intf = serial->interface->cur_altsetting;
        struct device *dev = &serial->dev->dev;
        int retval = -ENODEV;
@@ -154,13 +153,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
        ifnum = intf->desc.bInterfaceNumber;
        dev_dbg(dev, "This Interface = %d\n", ifnum);
 
-       data = kzalloc(sizeof(struct usb_wwan_intf_private),
-                                        GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       spin_lock_init(&data->susp_lock);
-
        if (nintf == 1) {
                /* QDL mode */
                /* Gobi 2000 has a single altsetting, older ones have two */
@@ -253,20 +245,28 @@ done:
                }
        }
 
-       /* Set serial->private if not returning error */
-       if (retval == 0)
-               usb_set_serial_data(serial, data);
-       else
-               kfree(data);
-
        return retval;
 }
 
+static int qc_attach(struct usb_serial *serial)
+{
+       struct usb_wwan_intf_private *data;
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       spin_lock_init(&data->susp_lock);
+
+       usb_set_serial_data(serial, data);
+
+       return 0;
+}
+
 static void qc_release(struct usb_serial *serial)
 {
        struct usb_wwan_intf_private *priv = usb_get_serial_data(serial);
 
-       /* Free the private data allocated in qcprobe */
        usb_set_serial_data(serial, NULL);
        kfree(priv);
 }
@@ -285,8 +285,9 @@ static struct usb_serial_driver qcdevice = {
        .write               = usb_wwan_write,
        .write_room          = usb_wwan_write_room,
        .chars_in_buffer     = usb_wwan_chars_in_buffer,
-       .attach              = usb_wwan_startup,
+       .attach              = qc_attach,
        .release             = qc_release,
+       .port_probe          = usb_wwan_port_probe,
        .port_remove         = usb_wwan_port_remove,
 #ifdef CONFIG_PM
        .suspend             = usb_wwan_suspend,
index 2cdfdcc90b378b68402fc016cb0f1b4344b10ef3..ffcfc962ab10b5a4043cd900f8ca6e90094ff417 100644 (file)
@@ -143,12 +143,12 @@ static void qt2_read_bulk_callback(struct urb *urb);
 
 static void qt2_release(struct usb_serial *serial)
 {
-       int i;
+       struct qt2_serial_private *serial_priv;
 
-       kfree(usb_get_serial_data(serial));
+       serial_priv = usb_get_serial_data(serial);
 
-       for (i = 0; i < serial->num_ports; i++)
-               kfree(usb_get_serial_port_data(serial->port[i]));
+       usb_free_urb(serial_priv->read_urb);
+       kfree(serial_priv);
 }
 
 static inline int calc_baud_divisor(int baudrate)
@@ -423,11 +423,16 @@ static void qt2_close(struct usb_serial_port *port)
        port_priv->is_open = false;
 
        spin_lock_irqsave(&port_priv->urb_lock, flags);
-       if (port_priv->write_urb->status == -EINPROGRESS)
-               usb_kill_urb(port_priv->write_urb);
+       usb_kill_urb(port_priv->write_urb);
        port_priv->urb_in_use = false;
        spin_unlock_irqrestore(&port_priv->urb_lock, flags);
 
+       mutex_lock(&port->serial->disc_mutex);
+       if (port->serial->disconnected) {
+               mutex_unlock(&port->serial->disc_mutex);
+               return;
+       }
+
        /* flush the port transmit buffer */
        i = usb_control_msg(serial->dev,
                            usb_rcvctrlpipe(serial->dev, 0),
@@ -459,26 +464,14 @@ static void qt2_close(struct usb_serial_port *port)
                dev_err(&port->dev, "%s - close port failed %i\n",
                        __func__, i);
 
+       mutex_unlock(&port->serial->disc_mutex);
 }
 
 static void qt2_disconnect(struct usb_serial *serial)
 {
        struct qt2_serial_private *serial_priv = usb_get_serial_data(serial);
-       struct qt2_port_private *port_priv;
-       int i;
-
-       if (serial_priv->read_urb->status == -EINPROGRESS)
-               usb_kill_urb(serial_priv->read_urb);
-
-       usb_free_urb(serial_priv->read_urb);
 
-       for (i = 0; i < serial->num_ports; i++) {
-               port_priv = usb_get_serial_port_data(serial->port[i]);
-
-               if (port_priv->write_urb->status == -EINPROGRESS)
-                       usb_kill_urb(port_priv->write_urb);
-               usb_free_urb(port_priv->write_urb);
-       }
+       usb_kill_urb(serial_priv->read_urb);
 }
 
 static int get_serial_info(struct usb_serial_port *port,
@@ -773,11 +766,9 @@ static void qt2_read_bulk_callback(struct urb *urb)
 
 static int qt2_setup_urbs(struct usb_serial *serial)
 {
-       struct usb_serial_port *port;
        struct usb_serial_port *port0;
        struct qt2_serial_private *serial_priv;
-       struct qt2_port_private *port_priv;
-       int pcount, status;
+       int status;
 
        port0 = serial->port[0];
 
@@ -795,46 +786,21 @@ static int qt2_setup_urbs(struct usb_serial *serial)
                          sizeof(serial_priv->read_buffer),
                          qt2_read_bulk_callback, serial);
 
-       /* setup write_urb for each port */
-       for (pcount = 0; pcount < serial->num_ports; pcount++) {
-
-               port = serial->port[pcount];
-               port_priv = usb_get_serial_port_data(port);
-
-               port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL);
-               if (!port_priv->write_urb) {
-                       dev_err(&serial->dev->dev,
-                               "failed to alloc write_urb for port %i\n",
-                               pcount);
-                       return -ENOMEM;
-               }
-
-               usb_fill_bulk_urb(port_priv->write_urb,
-                                 serial->dev,
-                                 usb_sndbulkpipe(serial->dev,
-                                                 port0->
-                                                 bulk_out_endpointAddress),
-                                 port_priv->write_buffer,
-                                 sizeof(port_priv->write_buffer),
-                                 qt2_write_bulk_callback, port);
-       }
-
        status = usb_submit_urb(serial_priv->read_urb, GFP_KERNEL);
        if (status != 0) {
                dev_err(&serial->dev->dev,
                        "%s - submit read urb failed %i\n", __func__, status);
+               usb_free_urb(serial_priv->read_urb);
                return status;
        }
 
        return 0;
-
 }
 
 static int qt2_attach(struct usb_serial *serial)
 {
        struct qt2_serial_private *serial_priv;
-       struct qt2_port_private *port_priv;
-       int status, pcount;
+       int status;
 
        /* power on unit */
        status = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
@@ -854,26 +820,6 @@ static int qt2_attach(struct usb_serial *serial)
 
        usb_set_serial_data(serial, serial_priv);
 
-       for (pcount = 0; pcount < serial->num_ports; pcount++) {
-               port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
-               if (!port_priv) {
-                       dev_err(&serial->dev->dev,
-                               "%s- kmalloc(%Zd) failed.\n", __func__,
-                               sizeof(*port_priv));
-                       pcount--;
-                       status = -ENOMEM;
-                       goto attach_failed;
-               }
-
-               spin_lock_init(&port_priv->lock);
-               spin_lock_init(&port_priv->urb_lock);
-               init_waitqueue_head(&port_priv->delta_msr_wait);
-
-               port_priv->port = serial->port[pcount];
-
-               usb_set_serial_port_data(serial->port[pcount], port_priv);
-       }
-
        status = qt2_setup_urbs(serial);
        if (status != 0)
                goto attach_failed;
@@ -881,14 +827,53 @@ static int qt2_attach(struct usb_serial *serial)
        return 0;
 
 attach_failed:
-       for (/* empty */; pcount >= 0; pcount--) {
-               port_priv = usb_get_serial_port_data(serial->port[pcount]);
-               kfree(port_priv);
-       }
        kfree(serial_priv);
        return status;
 }
 
+static int qt2_port_probe(struct usb_serial_port *port)
+{
+       struct usb_serial *serial = port->serial;
+       struct qt2_port_private *port_priv;
+       u8 bEndpointAddress;
+
+       port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
+       if (!port_priv)
+               return -ENOMEM;
+
+       spin_lock_init(&port_priv->lock);
+       spin_lock_init(&port_priv->urb_lock);
+       init_waitqueue_head(&port_priv->delta_msr_wait);
+       port_priv->port = port;
+
+       port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!port_priv->write_urb) {
+               kfree(port_priv);
+               return -ENOMEM;
+       }
+       bEndpointAddress = serial->port[0]->bulk_out_endpointAddress;
+       usb_fill_bulk_urb(port_priv->write_urb, serial->dev,
+                               usb_sndbulkpipe(serial->dev, bEndpointAddress),
+                               port_priv->write_buffer,
+                               sizeof(port_priv->write_buffer),
+                               qt2_write_bulk_callback, port);
+
+       usb_set_serial_port_data(port, port_priv);
+
+       return 0;
+}
+
+static int qt2_port_remove(struct usb_serial_port *port)
+{
+       struct qt2_port_private *port_priv;
+
+       port_priv = usb_get_serial_port_data(port);
+       usb_free_urb(port_priv->write_urb);
+       kfree(port_priv);
+
+       return 0;
+}
+
 static int qt2_tiocmget(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
@@ -1127,6 +1112,8 @@ static struct usb_serial_driver qt2_device = {
        .attach              = qt2_attach,
        .release             = qt2_release,
        .disconnect          = qt2_disconnect,
+       .port_probe          = qt2_port_probe,
+       .port_remove         = qt2_port_remove,
        .dtr_rts             = qt2_dtr_rts,
        .break_ctl           = qt2_break_ctl,
        .tiocmget            = qt2_tiocmget,
index 01d882cf3775a2523662e4ab40f917a91eac5099..270860f6bb2aee0a97f2091c7c33041332cccc1e 100644 (file)
@@ -161,7 +161,6 @@ static int sierra_probe(struct usb_serial *serial,
 {
        int result = 0;
        struct usb_device *udev;
-       struct sierra_intf_private *data;
        u8 ifnum;
 
        udev = serial->dev;
@@ -188,11 +187,6 @@ static int sierra_probe(struct usb_serial *serial,
                return -ENODEV;
        }
 
-       data = serial->private = kzalloc(sizeof(struct sierra_intf_private), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-       spin_lock_init(&data->susp_lock);
-
        return result;
 }
 
@@ -884,11 +878,15 @@ static void sierra_dtr_rts(struct usb_serial_port *port, int on)
 
 static int sierra_startup(struct usb_serial *serial)
 {
-       struct usb_serial_port *port;
-       struct sierra_port_private *portdata;
-       struct sierra_iface_info *himemoryp = NULL;
-       int i;
-       u8 ifnum;
+       struct sierra_intf_private *intfdata;
+
+       intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL);
+       if (!intfdata)
+               return -ENOMEM;
+
+       spin_lock_init(&intfdata->susp_lock);
+
+       usb_set_serial_data(serial, intfdata);
 
        /* Set Device mode to D0 */
        sierra_set_power_state(serial->dev, 0x0000);
@@ -897,68 +895,71 @@ static int sierra_startup(struct usb_serial *serial)
        if (nmea)
                sierra_vsc_set_nmea(serial->dev, 1);
 
-       /* Now setup per port private data */
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
-               if (!portdata) {
-                       dev_dbg(&port->dev, "%s: kmalloc for "
-                               "sierra_port_private (%d) failed!\n",
-                               __func__, i);
-                       return -ENOMEM;
-               }
-               spin_lock_init(&portdata->lock);
-               init_usb_anchor(&portdata->active);
-               init_usb_anchor(&portdata->delayed);
-               ifnum = i;
-               /* Assume low memory requirements */
-               portdata->num_out_urbs = N_OUT_URB;
-               portdata->num_in_urbs  = N_IN_URB;
-
-               /* Determine actual memory requirements */
-               if (serial->num_ports == 1) {
-                       /* Get interface number for composite device */
-                       ifnum = sierra_calc_interface(serial);
-                       himemoryp =
-                           (struct sierra_iface_info *)&typeB_interface_list;
-                       if (is_himemory(ifnum, himemoryp)) {
-                               portdata->num_out_urbs = N_OUT_URB_HM;
-                               portdata->num_in_urbs  = N_IN_URB_HM;
-                       }
-               }
-               else {
-                       himemoryp =
-                           (struct sierra_iface_info *)&typeA_interface_list;
-                       if (is_himemory(i, himemoryp)) {
-                               portdata->num_out_urbs = N_OUT_URB_HM;
-                               portdata->num_in_urbs  = N_IN_URB_HM;
-                       }
-               }
-               dev_dbg(&serial->dev->dev,
-                       "Memory usage (urbs) interface #%d, in=%d, out=%d\n",
-                       ifnum,portdata->num_in_urbs, portdata->num_out_urbs );
-               /* Set the port private data pointer */
-               usb_set_serial_port_data(port, portdata);
-       }
-
        return 0;
 }
 
 static void sierra_release(struct usb_serial *serial)
 {
-       int i;
-       struct usb_serial_port *port;
+       struct sierra_intf_private *intfdata;
+
+       intfdata = usb_get_serial_data(serial);
+       kfree(intfdata);
+}
+
+static int sierra_port_probe(struct usb_serial_port *port)
+{
+       struct usb_serial *serial = port->serial;
        struct sierra_port_private *portdata;
+       const struct sierra_iface_info *himemoryp;
+       u8 ifnum;
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               port = serial->port[i];
-               if (!port)
-                       continue;
-               portdata = usb_get_serial_port_data(port);
-               if (!portdata)
-                       continue;
-               kfree(portdata);
+       portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
+       if (!portdata)
+               return -ENOMEM;
+
+       spin_lock_init(&portdata->lock);
+       init_usb_anchor(&portdata->active);
+       init_usb_anchor(&portdata->delayed);
+
+       /* Assume low memory requirements */
+       portdata->num_out_urbs = N_OUT_URB;
+       portdata->num_in_urbs  = N_IN_URB;
+
+       /* Determine actual memory requirements */
+       if (serial->num_ports == 1) {
+               /* Get interface number for composite device */
+               ifnum = sierra_calc_interface(serial);
+               himemoryp = &typeB_interface_list;
+       } else {
+               /* This is really the usb-serial port number of the interface
+                * rather than the interface number.
+                */
+               ifnum = port->number - serial->minor;
+               himemoryp = &typeA_interface_list;
        }
+
+       if (is_himemory(ifnum, himemoryp)) {
+               portdata->num_out_urbs = N_OUT_URB_HM;
+               portdata->num_in_urbs  = N_IN_URB_HM;
+       }
+
+       dev_dbg(&port->dev,
+                       "Memory usage (urbs) interface #%d, in=%d, out=%d\n",
+                       ifnum, portdata->num_in_urbs, portdata->num_out_urbs);
+
+       usb_set_serial_port_data(port, portdata);
+
+       return 0;
+}
+
+static int sierra_port_remove(struct usb_serial_port *port)
+{
+       struct sierra_port_private *portdata;
+
+       portdata = usb_get_serial_port_data(port);
+       kfree(portdata);
+
+       return 0;
 }
 
 #ifdef CONFIG_PM
@@ -1062,6 +1063,8 @@ static struct usb_serial_driver sierra_device = {
        .tiocmset          = sierra_tiocmset,
        .attach            = sierra_startup,
        .release           = sierra_release,
+       .port_probe        = sierra_port_probe,
+       .port_remove       = sierra_port_remove,
        .suspend           = sierra_suspend,
        .resume            = sierra_resume,
        .read_int_callback = sierra_instat_callback,
index 1f034d2397c6c6ea3888e79aa6cd2ddb6d73202b..684739b8efd05b15a5646585d94417f3aa20a53d 100644 (file)
@@ -8,7 +8,7 @@
 extern void usb_wwan_dtr_rts(struct usb_serial_port *port, int on);
 extern int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port);
 extern void usb_wwan_close(struct usb_serial_port *port);
-extern int usb_wwan_startup(struct usb_serial *serial);
+extern int usb_wwan_port_probe(struct usb_serial_port *port);
 extern int usb_wwan_port_remove(struct usb_serial_port *port);
 extern int usb_wwan_write_room(struct tty_struct *tty);
 extern void usb_wwan_set_termios(struct tty_struct *tty,
index e42aa398ed37a3e8f774c2cbbdbaed8ae72e6eb3..61a73ad1a1877c4558444a34884e236a8352e0d9 100644 (file)
@@ -447,10 +447,12 @@ void usb_wwan_close(struct usb_serial_port *port)
 EXPORT_SYMBOL(usb_wwan_close);
 
 /* Helper functions used by usb_wwan_setup_urbs */
-static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint,
+static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
+                                     int endpoint,
                                      int dir, void *ctx, char *buf, int len,
                                      void (*callback) (struct urb *))
 {
+       struct usb_serial *serial = port->serial;
        struct urb *urb;
 
        if (endpoint == -1)
@@ -472,101 +474,75 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint,
        return urb;
 }
 
-/* Setup urbs */
-static void usb_wwan_setup_urbs(struct usb_serial *serial)
+int usb_wwan_port_probe(struct usb_serial_port *port)
 {
-       int i, j;
-       struct usb_serial_port *port;
        struct usb_wwan_port_private *portdata;
+       struct urb *urb;
+       u8 *buffer;
+       int err;
+       int i;
 
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               portdata = usb_get_serial_port_data(port);
+       portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
+       if (!portdata)
+               return -ENOMEM;
 
-               /* Do indat endpoints first */
-               for (j = 0; j < N_IN_URB; ++j) {
-                       portdata->in_urbs[j] = usb_wwan_setup_urb(serial,
-                                                                 port->
-                                                                 bulk_in_endpointAddress,
-                                                                 USB_DIR_IN,
-                                                                 port,
-                                                                 portdata->
-                                                                 in_buffer[j],
-                                                                 IN_BUFLEN,
-                                                                 usb_wwan_indat_callback);
-               }
+       init_usb_anchor(&portdata->delayed);
 
-               /* outdat endpoints */
-               for (j = 0; j < N_OUT_URB; ++j) {
-                       portdata->out_urbs[j] = usb_wwan_setup_urb(serial,
-                                                                  port->
-                                                                  bulk_out_endpointAddress,
-                                                                  USB_DIR_OUT,
-                                                                  port,
-                                                                  portdata->
-                                                                  out_buffer
-                                                                  [j],
-                                                                  OUT_BUFLEN,
-                                                                  usb_wwan_outdat_callback);
-               }
+       for (i = 0; i < N_IN_URB; i++) {
+               buffer = (u8 *)__get_free_page(GFP_KERNEL);
+               if (!buffer)
+                       goto bail_out_error;
+               portdata->in_buffer[i] = buffer;
+
+               urb = usb_wwan_setup_urb(port, port->bulk_in_endpointAddress,
+                                               USB_DIR_IN, port,
+                                               buffer, IN_BUFLEN,
+                                               usb_wwan_indat_callback);
+               portdata->in_urbs[i] = urb;
        }
-}
-
-int usb_wwan_startup(struct usb_serial *serial)
-{
-       int i, j, err;
-       struct usb_serial_port *port;
-       struct usb_wwan_port_private *portdata;
-       u8 *buffer;
 
-       /* Now setup per port private data */
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
-               if (!portdata) {
-                       dev_dbg(&port->dev, "%s: kmalloc for usb_wwan_port_private (%d) failed!.\n",
-                               __func__, i);
-                       return 1;
-               }
-               init_usb_anchor(&portdata->delayed);
+       for (i = 0; i < N_OUT_URB; i++) {
+               if (port->bulk_out_endpointAddress == -1)
+                       continue;
 
-               for (j = 0; j < N_IN_URB; j++) {
-                       buffer = (u8 *) __get_free_page(GFP_KERNEL);
-                       if (!buffer)
-                               goto bail_out_error;
-                       portdata->in_buffer[j] = buffer;
-               }
+               buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
+               if (!buffer)
+                       goto bail_out_error2;
+               portdata->out_buffer[i] = buffer;
 
-               for (j = 0; j < N_OUT_URB; j++) {
-                       buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
-                       if (!buffer)
-                               goto bail_out_error2;
-                       portdata->out_buffer[j] = buffer;
-               }
+               urb = usb_wwan_setup_urb(port, port->bulk_out_endpointAddress,
+                                               USB_DIR_OUT, port,
+                                               buffer, OUT_BUFLEN,
+                                               usb_wwan_outdat_callback);
+               portdata->out_urbs[i] = urb;
+       }
 
-               usb_set_serial_port_data(port, portdata);
+       usb_set_serial_port_data(port, portdata);
 
-               if (!port->interrupt_in_urb)
-                       continue;
+       if (port->interrupt_in_urb) {
                err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
                if (err)
                        dev_dbg(&port->dev, "%s: submit irq_in urb failed %d\n",
                                __func__, err);
        }
-       usb_wwan_setup_urbs(serial);
+
        return 0;
 
 bail_out_error2:
-       for (j = 0; j < N_OUT_URB; j++)
-               kfree(portdata->out_buffer[j]);
+       for (i = 0; i < N_OUT_URB; i++) {
+               usb_free_urb(portdata->out_urbs[i]);
+               kfree(portdata->out_buffer[i]);
+       }
 bail_out_error:
-       for (j = 0; j < N_IN_URB; j++)
-               if (portdata->in_buffer[j])
-                       free_page((unsigned long)portdata->in_buffer[j]);
+       for (i = 0; i < N_IN_URB; i++) {
+               usb_free_urb(portdata->in_urbs[i]);
+               free_page((unsigned long)portdata->in_buffer[i]);
+       }
        kfree(portdata);
-       return 1;
+
+       return -ENOMEM;
 }
-EXPORT_SYMBOL(usb_wwan_startup);
+EXPORT_SYMBOL_GPL(usb_wwan_port_probe);
 
 int usb_wwan_port_remove(struct usb_serial_port *port)
 {
index 346c7efc20b06d42899616cb8bb0766007cde82e..b9fca3586d741003a50ffb435be7de74020c48e8 100644 (file)
@@ -83,6 +83,8 @@ static int  whiteheat_firmware_attach(struct usb_serial *serial);
 /* function prototypes for the Connect Tech WhiteHEAT serial converter */
 static int  whiteheat_attach(struct usb_serial *serial);
 static void whiteheat_release(struct usb_serial *serial);
+static int  whiteheat_port_probe(struct usb_serial_port *port);
+static int  whiteheat_port_remove(struct usb_serial_port *port);
 static int  whiteheat_open(struct tty_struct *tty,
                        struct usb_serial_port *port);
 static void whiteheat_close(struct usb_serial_port *port);
@@ -117,6 +119,8 @@ static struct usb_serial_driver whiteheat_device = {
        .num_ports =            4,
        .attach =               whiteheat_attach,
        .release =              whiteheat_release,
+       .port_probe =           whiteheat_port_probe,
+       .port_remove =          whiteheat_port_remove,
        .open =                 whiteheat_open,
        .close =                whiteheat_close,
        .ioctl =                whiteheat_ioctl,
@@ -218,15 +222,12 @@ static int whiteheat_attach(struct usb_serial *serial)
 {
        struct usb_serial_port *command_port;
        struct whiteheat_command_private *command_info;
-       struct usb_serial_port *port;
-       struct whiteheat_private *info;
        struct whiteheat_hw_info *hw_info;
        int pipe;
        int ret;
        int alen;
        __u8 *command;
        __u8 *result;
-       int i;
 
        command_port = serial->port[COMMAND_PORT];
 
@@ -285,22 +286,6 @@ static int whiteheat_attach(struct usb_serial *serial)
                 serial->type->description,
                 hw_info->sw_major_rev, hw_info->sw_minor_rev);
 
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-
-               info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
-               if (info == NULL) {
-                       dev_err(&port->dev,
-                               "%s: Out of memory for port structures\n",
-                               serial->type->description);
-                       goto no_private;
-               }
-
-               info->mcr = 0;
-
-               usb_set_serial_port_data(port, info);
-       }
-
        command_info = kmalloc(sizeof(struct whiteheat_command_private),
                                                                GFP_KERNEL);
        if (command_info == NULL) {
@@ -333,16 +318,10 @@ no_firmware:
                "%s: please contact support@connecttech.com\n",
                serial->type->description);
        kfree(result);
+       kfree(command);
        return -ENODEV;
 
 no_command_private:
-       for (i = serial->num_ports - 1; i >= 0; i--) {
-               port = serial->port[i];
-               info = usb_get_serial_port_data(port);
-               kfree(info);
-no_private:
-               ;
-       }
        kfree(result);
 no_result_buffer:
        kfree(command);
@@ -350,21 +329,36 @@ no_command_buffer:
        return -ENOMEM;
 }
 
-
 static void whiteheat_release(struct usb_serial *serial)
 {
        struct usb_serial_port *command_port;
-       struct whiteheat_private *info;
-       int i;
 
        /* free up our private data for our command port */
        command_port = serial->port[COMMAND_PORT];
        kfree(usb_get_serial_port_data(command_port));
+}
 
-       for (i = 0; i < serial->num_ports; i++) {
-               info = usb_get_serial_port_data(serial->port[i]);
-               kfree(info);
-       }
+static int whiteheat_port_probe(struct usb_serial_port *port)
+{
+       struct whiteheat_private *info;
+
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       usb_set_serial_port_data(port, info);
+
+       return 0;
+}
+
+static int whiteheat_port_remove(struct usb_serial_port *port)
+{
+       struct whiteheat_private *info;
+
+       info = usb_get_serial_port_data(port);
+       kfree(info);
+
+       return 0;
 }
 
 static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port)
index 779cd954abcbd26d1fc935650d102dc524b8ca5a..d305a5aa3a5d7683a5bcd1c2e60c4a0262f35f65 100644 (file)
@@ -1004,6 +1004,12 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999,
                USB_SC_8070, USB_PR_CB, NULL,
                US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ),
 
+/* Submitted by Oleksandr Chumachenko <ledest@gmail.com> */
+UNUSUAL_DEV( 0x07cf, 0x1167, 0x0100, 0x0100,
+               "Casio",
+               "EX-N1 DigitalCamera",
+               USB_SC_8070, USB_PR_DEVICE, NULL, 0),
+
 /* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/
 UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
                "Samsung",
index 072cbbadbc3683ef75fd6ff2420e40463b8f722e..7f93f34b7f913e188aa31fbe82372f409817e9dd 100644 (file)
@@ -379,7 +379,8 @@ static void handle_rx(struct vhost_net *net)
                .hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE
        };
        size_t total_len = 0;
-       int err, headcount, mergeable;
+       int err, mergeable;
+       s16 headcount;
        size_t vhost_hlen, sock_hlen;
        size_t vhost_len, sock_len;
        /* TODO: check that we are running from vhost_worker? */
index c101697a4ba708e06b2ea102ba6000d97eaa0ed8..765a945f8ea12ef2e1a9fc80c428a885f9806320 100644 (file)
@@ -60,7 +60,8 @@ config LCD_LTV350QV
          The LTV350QV panel is present on all ATSTK1000 boards.
 
 config LCD_ILI9320
-       tristate
+       tristate "ILI Technology ILI9320 controller support"
+       depends on SPI
        help
          If you have a panel based on the ILI9320 controller chip
          then say y to include a power driver for it.
index b7f5173ff9e94214ed40c3c40f4444324e128888..917bb5681684d31490e1b228b60db57cc0d53a7b 100644 (file)
@@ -641,7 +641,6 @@ static void xenfb_backend_changed(struct xenbus_device *dev,
        case XenbusStateReconfiguring:
        case XenbusStateReconfigured:
        case XenbusStateUnknown:
-       case XenbusStateClosed:
                break;
 
        case XenbusStateInitWait:
@@ -670,6 +669,10 @@ InitWait:
                info->feature_resize = val;
                break;
 
+       case XenbusStateClosed:
+               if (dev->state == XenbusStateClosed)
+                       break;
+               /* Missed the backend's CLOSING state -- fallthrough */
        case XenbusStateClosing:
                xenbus_frontend_closed(dev);
                break;
index d4dffcd528730330a0d4cff238dcf0b56e3f318b..126d8ce591ce5fc7e69348f746e91e60b04bc4ee 100644 (file)
@@ -3,6 +3,7 @@ menu "Xen driver support"
 
 config XEN_BALLOON
        bool "Xen memory balloon driver"
+       depends on !ARM
        default y
        help
          The balloon driver allows the Xen domain to request more memory from
@@ -145,6 +146,7 @@ config SWIOTLB_XEN
 
 config XEN_TMEM
        bool
+       depends on !ARM
        default y if (CLEANCACHE || FRONTSWAP)
        help
          Shim to interface in-kernel Transcendent Memory hooks
index 31ab82fda38a264cd045c4b52c117eb375f8e80e..d6886d90ccfd53eed62773a755ee282e9553a55f 100644 (file)
@@ -55,7 +55,6 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/tlb.h>
-#include <asm/e820.h>
 
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
@@ -88,7 +87,7 @@ struct balloon_stats balloon_stats;
 EXPORT_SYMBOL_GPL(balloon_stats);
 
 /* We increase/decrease in batches which fit in a page */
-static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)];
+static xen_pfn_t frame_list[PAGE_SIZE / sizeof(unsigned long)];
 
 #ifdef CONFIG_HIGHMEM
 #define inc_totalhigh_pages() (totalhigh_pages++)
index 42569c77ccc8886d38b924a457489819d0dd53c4..f3ccc80a455f54c0abd15c1018f2fc79c7a0332a 100644 (file)
@@ -8,7 +8,9 @@
 
 static int xen_dbgp_op(struct usb_hcd *hcd, int op)
 {
+#ifdef CONFIG_PCI
        const struct device *ctrlr = hcd_to_bus(hcd)->controller;
+#endif
        struct physdev_dbgp_op dbgp;
 
        if (!xen_initial_domain())
index 59e10a1286d53ff73aa3e0a6c91a5aed9033de9e..912ac81b6dbff5e2b9f48c2b2662083bf00ce476 100644 (file)
@@ -115,7 +115,9 @@ struct irq_info {
 #define PIRQ_SHAREABLE (1 << 1)
 
 static int *evtchn_to_irq;
+#ifdef CONFIG_X86
 static unsigned long *pirq_eoi_map;
+#endif
 static bool (*pirq_needs_eoi)(unsigned irq);
 
 static DEFINE_PER_CPU(unsigned long [NR_EVENT_CHANNELS/BITS_PER_LONG],
@@ -277,10 +279,12 @@ static unsigned int cpu_from_evtchn(unsigned int evtchn)
        return ret;
 }
 
+#ifdef CONFIG_X86
 static bool pirq_check_eoi_map(unsigned irq)
 {
        return test_bit(pirq_from_irq(irq), pirq_eoi_map);
 }
+#endif
 
 static bool pirq_needs_eoi_flag(unsigned irq)
 {
index 610bfc6be17708594783d231d608c14651625376..2e22df2f7a3f8b57fe44ce8842b825602a012658 100644 (file)
@@ -105,6 +105,21 @@ static void gntdev_print_maps(struct gntdev_priv *priv,
 #endif
 }
 
+static void gntdev_free_map(struct grant_map *map)
+{
+       if (map == NULL)
+               return;
+
+       if (map->pages)
+               free_xenballooned_pages(map->count, map->pages);
+       kfree(map->pages);
+       kfree(map->grants);
+       kfree(map->map_ops);
+       kfree(map->unmap_ops);
+       kfree(map->kmap_ops);
+       kfree(map);
+}
+
 static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
 {
        struct grant_map *add;
@@ -142,12 +157,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
        return add;
 
 err:
-       kfree(add->pages);
-       kfree(add->grants);
-       kfree(add->map_ops);
-       kfree(add->unmap_ops);
-       kfree(add->kmap_ops);
-       kfree(add);
+       gntdev_free_map(add);
        return NULL;
 }
 
@@ -198,17 +208,9 @@ static void gntdev_put_map(struct grant_map *map)
                evtchn_put(map->notify.event);
        }
 
-       if (map->pages) {
-               if (!use_ptemod)
-                       unmap_grant_pages(map, 0, map->count);
-
-               free_xenballooned_pages(map->count, map->pages);
-       }
-       kfree(map->pages);
-       kfree(map->grants);
-       kfree(map->map_ops);
-       kfree(map->unmap_ops);
-       kfree(map);
+       if (map->pages && !use_ptemod)
+               unmap_grant_pages(map, 0, map->count);
+       gntdev_free_map(map);
 }
 
 /* ------------------------------------------------------------------ */
index b2b0a375b3484b162b0c2ebc6cd09d5584f8ec60..b91f14e831648e68093a02f804f82e4113325360 100644 (file)
@@ -84,7 +84,7 @@ struct gnttab_ops {
         * nr_gframes is the number of frames to map grant table. Returning
         * GNTST_okay means success and negative value means failure.
         */
-       int (*map_frames)(unsigned long *frames, unsigned int nr_gframes);
+       int (*map_frames)(xen_pfn_t *frames, unsigned int nr_gframes);
        /*
         * Release a list of frames which are mapped in map_frames for grant
         * entry status.
@@ -960,7 +960,7 @@ static unsigned nr_status_frames(unsigned nr_grant_frames)
        return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP;
 }
 
-static int gnttab_map_frames_v1(unsigned long *frames, unsigned int nr_gframes)
+static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes)
 {
        int rc;
 
@@ -977,7 +977,7 @@ static void gnttab_unmap_frames_v1(void)
        arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames);
 }
 
-static int gnttab_map_frames_v2(unsigned long *frames, unsigned int nr_gframes)
+static int gnttab_map_frames_v2(xen_pfn_t *frames, unsigned int nr_gframes)
 {
        uint64_t *sframes;
        unsigned int nr_sframes;
@@ -1029,7 +1029,7 @@ static void gnttab_unmap_frames_v2(void)
 static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
 {
        struct gnttab_setup_table setup;
-       unsigned long *frames;
+       xen_pfn_t *frames;
        unsigned int nr_gframes = end_idx + 1;
        int rc;
 
index 5e5ad7e2885832f64f2131aa43aead50548cae0a..96453f8a85c5543f506ecc128f22e91b3d2dbdbb 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/kobject.h>
+#include <linux/err.h>
 
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
@@ -284,7 +285,8 @@ static ssize_t virtual_start_show(struct hyp_sysfs_attr *attr, char *buffer)
                ret = HYPERVISOR_xen_version(XENVER_platform_parameters,
                                             parms);
                if (!ret)
-                       ret = sprintf(buffer, "%lx\n", parms->virt_start);
+                       ret = sprintf(buffer, "%"PRI_xen_ulong"\n",
+                                     parms->virt_start);
                kfree(parms);
        }
 
index 46d140baebd8770463b9d37399f5149220920532..0f478ac483cd418e1a8a0b84fdb1b35651ce6404 100644 (file)
@@ -89,9 +89,15 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
 
        mutex_lock(&vpci_dev->lock);
 
-       /* Keep multi-function devices together on the virtual PCI bus */
-       for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
-               if (!list_empty(&vpci_dev->dev_list[slot])) {
+       /*
+        * Keep multi-function devices together on the virtual PCI bus, except
+        * virtual functions.
+        */
+       if (!dev->is_virtfn) {
+               for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+                       if (list_empty(&vpci_dev->dev_list[slot]))
+                               continue;
+
                        t = list_entry(list_first(&vpci_dev->dev_list[slot]),
                                       struct pci_dev_entry, list);
 
@@ -116,7 +122,7 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
                               pci_name(dev), slot);
                        list_add_tail(&dev_entry->list,
                                      &vpci_dev->dev_list[slot]);
-                       func = PCI_FUNC(dev->devfn);
+                       func = dev->is_virtfn ? 0 : PCI_FUNC(dev->devfn);
                        goto unlock;
                }
        }
index 89f76252a16f20e2638ee578faf4e3cbb4a316c6..ac727028e658f75778fa916ca94e91c5d80e0737 100644 (file)
@@ -458,7 +458,7 @@ static ssize_t xenbus_file_write(struct file *filp,
                goto out;
 
        /* Can't write a xenbus message larger we can buffer */
-       if ((len + u->len) > sizeof(u->u.buffer)) {
+       if (len > sizeof(u->u.buffer) - u->len) {
                /* On error, dump existing buffer */
                u->len = 0;
                rc = -EINVAL;
index f5dda83ad7a55048256f29ab79756c092450c08f..acedeabe589c94eaecd5ab5d478f7e7b3bfbe4af 100644 (file)
@@ -627,6 +627,7 @@ static struct xenbus_watch *find_watch(const char *token)
  */
 static bool xen_strict_xenbus_quirk(void)
 {
+#ifdef CONFIG_X86
        uint32_t eax, ebx, ecx, edx, base;
 
        base = xen_cpuid_base();
@@ -634,6 +635,7 @@ static bool xen_strict_xenbus_quirk(void)
 
        if ((eax >> 16) < 4)
                return true;
+#endif
        return false;
 
 }
index 9298c65ad9c74bb1c4adde9ef9ffa07b397ca63f..b96fc6ce485595f0179bc909c807ae197258e671 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -75,6 +75,7 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)
        unsigned int sz = sizeof(struct bio) + extra_size;
        struct kmem_cache *slab = NULL;
        struct bio_slab *bslab, *new_bio_slabs;
+       unsigned int new_bio_slab_max;
        unsigned int i, entry = -1;
 
        mutex_lock(&bio_slab_lock);
@@ -97,12 +98,13 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)
                goto out_unlock;
 
        if (bio_slab_nr == bio_slab_max && entry == -1) {
-               bio_slab_max <<= 1;
+               new_bio_slab_max = bio_slab_max << 1;
                new_bio_slabs = krealloc(bio_slabs,
-                                        bio_slab_max * sizeof(struct bio_slab),
+                                        new_bio_slab_max * sizeof(struct bio_slab),
                                         GFP_KERNEL);
                if (!new_bio_slabs)
                        goto out_unlock;
+               bio_slab_max = new_bio_slab_max;
                bio_slabs = new_bio_slabs;
        }
        if (entry == -1)
index b3c1d3dae77d06fcde3fa3ecf36b2af9e2b25d85..1a1e5e3b1eafc7f00454cb2d544b8761161d015e 100644 (file)
@@ -1661,6 +1661,39 @@ static int blkdev_mmap(struct file *file, struct vm_area_struct *vma)
        return ret;
 }
 
+static ssize_t blkdev_splice_read(struct file *file, loff_t *ppos,
+                                 struct pipe_inode_info *pipe, size_t len,
+                                 unsigned int flags)
+{
+       ssize_t ret;
+       struct block_device *bdev = I_BDEV(file->f_mapping->host);
+
+       percpu_down_read(&bdev->bd_block_size_semaphore);
+
+       ret = generic_file_splice_read(file, ppos, pipe, len, flags);
+
+       percpu_up_read(&bdev->bd_block_size_semaphore);
+
+       return ret;
+}
+
+static ssize_t blkdev_splice_write(struct pipe_inode_info *pipe,
+                                  struct file *file, loff_t *ppos, size_t len,
+                                  unsigned int flags)
+{
+       ssize_t ret;
+       struct block_device *bdev = I_BDEV(file->f_mapping->host);
+
+       percpu_down_read(&bdev->bd_block_size_semaphore);
+
+       ret = generic_file_splice_write(pipe, file, ppos, len, flags);
+
+       percpu_up_read(&bdev->bd_block_size_semaphore);
+
+       return ret;
+}
+
+
 /*
  * Try to release a page associated with block device when the system
  * is under memory pressure.
@@ -1699,8 +1732,8 @@ const struct file_operations def_blk_fops = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = compat_blkdev_ioctl,
 #endif
-       .splice_read    = generic_file_splice_read,
-       .splice_write   = generic_file_splice_write,
+       .splice_read    = blkdev_splice_read,
+       .splice_write   = blkdev_splice_write,
 };
 
 int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
index f3187938e081c7dcbf842d424f5de6ed06d3f93f..208d8aa5b07e488f1f39cb0877ff46bb5d08d5a6 100644 (file)
@@ -283,9 +283,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
                goto out;
        }
 
-       rcu_read_lock();
-       root_level = btrfs_header_level(root->node);
-       rcu_read_unlock();
+       root_level = btrfs_old_root_level(root, time_seq);
 
        if (root_level + 1 == level)
                goto out;
@@ -1177,16 +1175,15 @@ int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid,
        return ret;
 }
 
-static char *ref_to_path(struct btrfs_root *fs_root,
-                        struct btrfs_path *path,
-                        u32 name_len, unsigned long name_off,
-                        struct extent_buffer *eb_in, u64 parent,
-                        char *dest, u32 size)
+char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
+                       u32 name_len, unsigned long name_off,
+                       struct extent_buffer *eb_in, u64 parent,
+                       char *dest, u32 size)
 {
        int slot;
        u64 next_inum;
        int ret;
-       s64 bytes_left = size - 1;
+       s64 bytes_left = ((s64)size) - 1;
        struct extent_buffer *eb = eb_in;
        struct btrfs_key found_key;
        int leave_spinning = path->leave_spinning;
@@ -1266,10 +1263,10 @@ char *btrfs_iref_to_path(struct btrfs_root *fs_root,
                         struct extent_buffer *eb_in, u64 parent,
                         char *dest, u32 size)
 {
-       return ref_to_path(fs_root, path,
-                          btrfs_inode_ref_name_len(eb_in, iref),
-                          (unsigned long)(iref + 1),
-                          eb_in, parent, dest, size);
+       return btrfs_ref_to_path(fs_root, path,
+                                btrfs_inode_ref_name_len(eb_in, iref),
+                                (unsigned long)(iref + 1),
+                                eb_in, parent, dest, size);
 }
 
 /*
@@ -1715,9 +1712,8 @@ static int inode_to_path(u64 inum, u32 name_len, unsigned long name_off,
                                        ipath->fspath->bytes_left - s_ptr : 0;
 
        fspath_min = (char *)ipath->fspath->val + (i + 1) * s_ptr;
-       fspath = ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len,
-                            name_off, eb, inum, fspath_min,
-                            bytes_left);
+       fspath = btrfs_ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len,
+                                  name_off, eb, inum, fspath_min, bytes_left);
        if (IS_ERR(fspath))
                return PTR_ERR(fspath);
 
index e75533043a5ffbab21ff133877c352b743ef6592..d61feca79455bda94308c9ab3608b23409a84c73 100644 (file)
@@ -62,6 +62,10 @@ int btrfs_find_all_roots(struct btrfs_trans_handle *trans,
 char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
                         struct btrfs_inode_ref *iref, struct extent_buffer *eb,
                         u64 parent, char *dest, u32 size);
+char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
+                       u32 name_len, unsigned long name_off,
+                       struct extent_buffer *eb_in, u64 parent,
+                       char *dest, u32 size);
 
 struct btrfs_data_container *init_data_container(u32 total_bytes);
 struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root,
index b334362110003165a72b63433b192f2b481c3b01..cdfb4c49a806ad4ba0ebe83b5569a4121a10a220 100644 (file)
@@ -596,6 +596,11 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info,
        if (tree_mod_dont_log(fs_info, eb))
                return 0;
 
+       /*
+        * When we override something during the move, we log these removals.
+        * This can only happen when we move towards the beginning of the
+        * buffer, i.e. dst_slot < src_slot.
+        */
        for (i = 0; i + dst_slot < src_slot && i < nr_items; i++) {
                ret = tree_mod_log_insert_key_locked(fs_info, eb, i + dst_slot,
                                              MOD_LOG_KEY_REMOVE_WHILE_MOVING);
@@ -647,8 +652,6 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info,
        if (tree_mod_dont_log(fs_info, NULL))
                return 0;
 
-       __tree_mod_log_free_eb(fs_info, old_root);
-
        ret = tree_mod_alloc(fs_info, flags, &tm);
        if (ret < 0)
                goto out;
@@ -926,12 +929,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
                        ret = btrfs_dec_ref(trans, root, buf, 1, 1);
                        BUG_ON(ret); /* -ENOMEM */
                }
-               /*
-                * don't log freeing in case we're freeing the root node, this
-                * is done by tree_mod_log_set_root_pointer later
-                */
-               if (buf != root->node && btrfs_header_level(buf) != 0)
-                       tree_mod_log_free_eb(root->fs_info, buf);
+               tree_mod_log_free_eb(root->fs_info, buf);
                clean_tree_block(trans, root, buf);
                *last_ref = 1;
        }
@@ -1225,6 +1223,8 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb,
        free_extent_buffer(eb);
 
        __tree_mod_log_rewind(eb_rewin, time_seq, tm);
+       WARN_ON(btrfs_header_nritems(eb_rewin) >
+               BTRFS_NODEPTRS_PER_BLOCK(fs_info->fs_root));
 
        return eb_rewin;
 }
@@ -1241,9 +1241,11 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
 {
        struct tree_mod_elem *tm;
        struct extent_buffer *eb;
+       struct extent_buffer *old;
        struct tree_mod_root *old_root = NULL;
        u64 old_generation = 0;
        u64 logical;
+       u32 blocksize;
 
        eb = btrfs_read_lock_root_node(root);
        tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq);
@@ -1259,14 +1261,32 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
        }
 
        tm = tree_mod_log_search(root->fs_info, logical, time_seq);
-       if (old_root)
+       if (old_root && tm && tm->op != MOD_LOG_KEY_REMOVE_WHILE_FREEING) {
+               btrfs_tree_read_unlock(root->node);
+               free_extent_buffer(root->node);
+               blocksize = btrfs_level_size(root, old_root->level);
+               old = read_tree_block(root, logical, blocksize, 0);
+               if (!old) {
+                       pr_warn("btrfs: failed to read tree block %llu from get_old_root\n",
+                               logical);
+                       WARN_ON(1);
+               } else {
+                       eb = btrfs_clone_extent_buffer(old);
+                       free_extent_buffer(old);
+               }
+       } else if (old_root) {
+               btrfs_tree_read_unlock(root->node);
+               free_extent_buffer(root->node);
                eb = alloc_dummy_extent_buffer(logical, root->nodesize);
-       else
+       } else {
                eb = btrfs_clone_extent_buffer(root->node);
-       btrfs_tree_read_unlock(root->node);
-       free_extent_buffer(root->node);
+               btrfs_tree_read_unlock(root->node);
+               free_extent_buffer(root->node);
+       }
+
        if (!eb)
                return NULL;
+       extent_buffer_get(eb);
        btrfs_tree_read_lock(eb);
        if (old_root) {
                btrfs_set_header_bytenr(eb, eb->start);
@@ -1279,11 +1299,28 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
                __tree_mod_log_rewind(eb, time_seq, tm);
        else
                WARN_ON(btrfs_header_level(eb) != 0);
-       extent_buffer_get(eb);
+       WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root));
 
        return eb;
 }
 
+int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq)
+{
+       struct tree_mod_elem *tm;
+       int level;
+
+       tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq);
+       if (tm && tm->op == MOD_LOG_ROOT_REPLACE) {
+               level = tm->old_root.level;
+       } else {
+               rcu_read_lock();
+               level = btrfs_header_level(root->node);
+               rcu_read_unlock();
+       }
+
+       return level;
+}
+
 static inline int should_cow_block(struct btrfs_trans_handle *trans,
                                   struct btrfs_root *root,
                                   struct extent_buffer *buf)
@@ -1725,6 +1762,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
                        goto enospc;
                }
 
+               tree_mod_log_free_eb(root->fs_info, root->node);
                tree_mod_log_set_root_pointer(root, child);
                rcu_assign_pointer(root->node, child);
 
@@ -2970,8 +3008,10 @@ static int push_node_left(struct btrfs_trans_handle *trans,
                           push_items * sizeof(struct btrfs_key_ptr));
 
        if (push_items < src_nritems) {
-               tree_mod_log_eb_move(root->fs_info, src, 0, push_items,
-                                    src_nritems - push_items);
+               /*
+                * don't call tree_mod_log_eb_move here, key removal was already
+                * fully logged by tree_mod_log_eb_copy above.
+                */
                memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0),
                                      btrfs_node_key_ptr_offset(push_items),
                                      (src_nritems - push_items) *
index 926c9ffc66d93324d155481c4ecba13d27fa3fec..c72ead869507412ac9939c0748a482035baaf2aa 100644 (file)
@@ -3120,6 +3120,7 @@ static inline u64 btrfs_inc_tree_mod_seq(struct btrfs_fs_info *fs_info)
 {
        return atomic_inc_return(&fs_info->tree_mod_seq);
 }
+int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq);
 
 /* root-item.c */
 int btrfs_find_root_ref(struct btrfs_root *tree_root,
@@ -3338,6 +3339,8 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
 int btrfs_update_inode(struct btrfs_trans_handle *trans,
                              struct btrfs_root *root,
                              struct inode *inode);
+int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
+                               struct btrfs_root *root, struct inode *inode);
 int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode);
 int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode);
 int btrfs_orphan_cleanup(struct btrfs_root *root);
index 8036d3a848530daed167453ebfb68eb8a83950f3..472873a94d969a86967e832eac2d452f274f11f9 100644 (file)
@@ -4110,8 +4110,8 @@ struct extent_buffer *alloc_dummy_extent_buffer(u64 start, unsigned long len)
 
        return eb;
 err:
-       for (i--; i >= 0; i--)
-               __free_page(eb->pages[i]);
+       for (; i > 0; i--)
+               __free_page(eb->pages[i - 1]);
        __free_extent_buffer(eb);
        return NULL;
 }
index 85a1e5053fe63a9d8df6682da38198883e00bb22..95542a1b3dfc99632219310f0108788789247fc9 100644 (file)
@@ -94,8 +94,6 @@ static noinline int cow_file_range(struct inode *inode,
                                   struct page *locked_page,
                                   u64 start, u64 end, int *page_started,
                                   unsigned long *nr_written, int unlock);
-static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
-                               struct btrfs_root *root, struct inode *inode);
 
 static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
                                     struct inode *inode,  struct inode *dir,
@@ -2746,8 +2744,9 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
        return btrfs_update_inode_item(trans, root, inode);
 }
 
-static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
-                               struct btrfs_root *root, struct inode *inode)
+noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
+                                        struct btrfs_root *root,
+                                        struct inode *inode)
 {
        int ret;
 
index 61168805f175b3c50ffef99b87e97fdeb2643ebd..8fcf9a59c28d08c5c8a6c65e34844e321ca2b66c 100644 (file)
@@ -343,7 +343,8 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)
                return -EOPNOTSUPP;
        if (copy_from_user(&range, arg, sizeof(range)))
                return -EFAULT;
-       if (range.start > total_bytes)
+       if (range.start > total_bytes ||
+           range.len < fs_info->sb->s_blocksize)
                return -EINVAL;
 
        range.len = min(range.len, total_bytes - range.start);
@@ -570,7 +571,8 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
                ret = btrfs_commit_transaction(trans,
                                               root->fs_info->extent_root);
        }
-       BUG_ON(ret);
+       if (ret)
+               goto fail;
 
        ret = pending_snapshot->error;
        if (ret)
index 5039686df6ae8e801ed8985eb5e821a226e18855..fe9d02c45f8e521f87b44d6deff3e5f8d99aa3a9 100644 (file)
@@ -790,8 +790,10 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,
        }
 
        path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
+       if (!path) {
+               ret = -ENOMEM;
+               goto out_free_root;
+       }
 
        key.objectid = 0;
        key.type = BTRFS_QGROUP_STATUS_KEY;
@@ -800,7 +802,7 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,
        ret = btrfs_insert_empty_item(trans, quota_root, path, &key,
                                      sizeof(*ptr));
        if (ret)
-               goto out;
+               goto out_free_path;
 
        leaf = path->nodes[0];
        ptr = btrfs_item_ptr(leaf, path->slots[0],
@@ -818,8 +820,15 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,
        fs_info->quota_root = quota_root;
        fs_info->pending_quota_state = 1;
        spin_unlock(&fs_info->qgroup_lock);
-out:
+out_free_path:
        btrfs_free_path(path);
+out_free_root:
+       if (ret) {
+               free_extent_buffer(quota_root->node);
+               free_extent_buffer(quota_root->commit_root);
+               kfree(quota_root);
+       }
+out:
        return ret;
 }
 
index c7beb543a4a89300f1e586492b767ea8f9bef683..e78b297b0b00cc990e8eb7a3f1f34619638e5ef4 100644 (file)
@@ -745,31 +745,36 @@ typedef int (*iterate_inode_ref_t)(int num, u64 dir, int index,
                                   void *ctx);
 
 /*
- * Helper function to iterate the entries in ONE btrfs_inode_ref.
+ * Helper function to iterate the entries in ONE btrfs_inode_ref or
+ * btrfs_inode_extref.
  * The iterate callback may return a non zero value to stop iteration. This can
  * be a negative value for error codes or 1 to simply stop it.
  *
- * path must point to the INODE_REF when called.
+ * path must point to the INODE_REF or INODE_EXTREF when called.
  */
 static int iterate_inode_ref(struct send_ctx *sctx,
                             struct btrfs_root *root, struct btrfs_path *path,
                             struct btrfs_key *found_key, int resolve,
                             iterate_inode_ref_t iterate, void *ctx)
 {
-       struct extent_buffer *eb;
+       struct extent_buffer *eb = path->nodes[0];
        struct btrfs_item *item;
        struct btrfs_inode_ref *iref;
+       struct btrfs_inode_extref *extref;
        struct btrfs_path *tmp_path;
        struct fs_path *p;
-       u32 cur;
-       u32 len;
+       u32 cur = 0;
        u32 total;
-       int slot;
+       int slot = path->slots[0];
        u32 name_len;
        char *start;
        int ret = 0;
-       int num;
+       int num = 0;
        int index;
+       u64 dir;
+       unsigned long name_off;
+       unsigned long elem_size;
+       unsigned long ptr;
 
        p = fs_path_alloc_reversed(sctx);
        if (!p)
@@ -781,24 +786,40 @@ static int iterate_inode_ref(struct send_ctx *sctx,
                return -ENOMEM;
        }
 
-       eb = path->nodes[0];
-       slot = path->slots[0];
-       item = btrfs_item_nr(eb, slot);
-       iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref);
-       cur = 0;
-       len = 0;
-       total = btrfs_item_size(eb, item);
 
-       num = 0;
+       if (found_key->type == BTRFS_INODE_REF_KEY) {
+               ptr = (unsigned long)btrfs_item_ptr(eb, slot,
+                                                   struct btrfs_inode_ref);
+               item = btrfs_item_nr(eb, slot);
+               total = btrfs_item_size(eb, item);
+               elem_size = sizeof(*iref);
+       } else {
+               ptr = btrfs_item_ptr_offset(eb, slot);
+               total = btrfs_item_size_nr(eb, slot);
+               elem_size = sizeof(*extref);
+       }
+
        while (cur < total) {
                fs_path_reset(p);
 
-               name_len = btrfs_inode_ref_name_len(eb, iref);
-               index = btrfs_inode_ref_index(eb, iref);
+               if (found_key->type == BTRFS_INODE_REF_KEY) {
+                       iref = (struct btrfs_inode_ref *)(ptr + cur);
+                       name_len = btrfs_inode_ref_name_len(eb, iref);
+                       name_off = (unsigned long)(iref + 1);
+                       index = btrfs_inode_ref_index(eb, iref);
+                       dir = found_key->offset;
+               } else {
+                       extref = (struct btrfs_inode_extref *)(ptr + cur);
+                       name_len = btrfs_inode_extref_name_len(eb, extref);
+                       name_off = (unsigned long)&extref->name;
+                       index = btrfs_inode_extref_index(eb, extref);
+                       dir = btrfs_inode_extref_parent(eb, extref);
+               }
+
                if (resolve) {
-                       start = btrfs_iref_to_path(root, tmp_path, iref, eb,
-                                               found_key->offset, p->buf,
-                                               p->buf_len);
+                       start = btrfs_ref_to_path(root, tmp_path, name_len,
+                                                 name_off, eb, dir,
+                                                 p->buf, p->buf_len);
                        if (IS_ERR(start)) {
                                ret = PTR_ERR(start);
                                goto out;
@@ -809,9 +830,10 @@ static int iterate_inode_ref(struct send_ctx *sctx,
                                                p->buf_len + p->buf - start);
                                if (ret < 0)
                                        goto out;
-                               start = btrfs_iref_to_path(root, tmp_path, iref,
-                                               eb, found_key->offset, p->buf,
-                                               p->buf_len);
+                               start = btrfs_ref_to_path(root, tmp_path,
+                                                         name_len, name_off,
+                                                         eb, dir,
+                                                         p->buf, p->buf_len);
                                if (IS_ERR(start)) {
                                        ret = PTR_ERR(start);
                                        goto out;
@@ -820,21 +842,16 @@ static int iterate_inode_ref(struct send_ctx *sctx,
                        }
                        p->start = start;
                } else {
-                       ret = fs_path_add_from_extent_buffer(p, eb,
-                                       (unsigned long)(iref + 1), name_len);
+                       ret = fs_path_add_from_extent_buffer(p, eb, name_off,
+                                                            name_len);
                        if (ret < 0)
                                goto out;
                }
 
-
-               len = sizeof(*iref) + name_len;
-               iref = (struct btrfs_inode_ref *)((char *)iref + len);
-               cur += len;
-
-               ret = iterate(num, found_key->offset, index, p, ctx);
+               cur += elem_size + name_len;
+               ret = iterate(num, dir, index, p, ctx);
                if (ret)
                        goto out;
-
                num++;
        }
 
@@ -998,7 +1015,8 @@ static int get_inode_path(struct send_ctx *sctx, struct btrfs_root *root,
        }
        btrfs_item_key_to_cpu(p->nodes[0], &found_key, p->slots[0]);
        if (found_key.objectid != ino ||
-               found_key.type != BTRFS_INODE_REF_KEY) {
+           (found_key.type != BTRFS_INODE_REF_KEY &&
+            found_key.type != BTRFS_INODE_EXTREF_KEY)) {
                ret = -ENOENT;
                goto out;
        }
@@ -1551,8 +1569,8 @@ static int get_first_ref(struct send_ctx *sctx,
        struct btrfs_key key;
        struct btrfs_key found_key;
        struct btrfs_path *path;
-       struct btrfs_inode_ref *iref;
        int len;
+       u64 parent_dir;
 
        path = alloc_path_for_send();
        if (!path)
@@ -1568,27 +1586,41 @@ static int get_first_ref(struct send_ctx *sctx,
        if (!ret)
                btrfs_item_key_to_cpu(path->nodes[0], &found_key,
                                path->slots[0]);
-       if (ret || found_key.objectid != key.objectid ||
-           found_key.type != key.type) {
+       if (ret || found_key.objectid != ino ||
+           (found_key.type != BTRFS_INODE_REF_KEY &&
+            found_key.type != BTRFS_INODE_EXTREF_KEY)) {
                ret = -ENOENT;
                goto out;
        }
 
-       iref = btrfs_item_ptr(path->nodes[0], path->slots[0],
-                       struct btrfs_inode_ref);
-       len = btrfs_inode_ref_name_len(path->nodes[0], iref);
-       ret = fs_path_add_from_extent_buffer(name, path->nodes[0],
-                       (unsigned long)(iref + 1), len);
+       if (key.type == BTRFS_INODE_REF_KEY) {
+               struct btrfs_inode_ref *iref;
+               iref = btrfs_item_ptr(path->nodes[0], path->slots[0],
+                                     struct btrfs_inode_ref);
+               len = btrfs_inode_ref_name_len(path->nodes[0], iref);
+               ret = fs_path_add_from_extent_buffer(name, path->nodes[0],
+                                                    (unsigned long)(iref + 1),
+                                                    len);
+               parent_dir = found_key.offset;
+       } else {
+               struct btrfs_inode_extref *extref;
+               extref = btrfs_item_ptr(path->nodes[0], path->slots[0],
+                                       struct btrfs_inode_extref);
+               len = btrfs_inode_extref_name_len(path->nodes[0], extref);
+               ret = fs_path_add_from_extent_buffer(name, path->nodes[0],
+                                       (unsigned long)&extref->name, len);
+               parent_dir = btrfs_inode_extref_parent(path->nodes[0], extref);
+       }
        if (ret < 0)
                goto out;
        btrfs_release_path(path);
 
-       ret = get_inode_info(root, found_key.offset, NULL, dir_gen, NULL, NULL,
+       ret = get_inode_info(root, parent_dir, NULL, dir_gen, NULL, NULL,
                        NULL, NULL);
        if (ret < 0)
                goto out;
 
-       *dir = found_key.offset;
+       *dir = parent_dir;
 
 out:
        btrfs_free_path(path);
@@ -2430,7 +2462,8 @@ verbose_printk("btrfs: send_create_inode %llu\n", ino);
                TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH_LINK, p);
        } else if (S_ISCHR(mode) || S_ISBLK(mode) ||
                   S_ISFIFO(mode) || S_ISSOCK(mode)) {
-               TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, rdev);
+               TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, new_encode_dev(rdev));
+               TLV_PUT_U64(sctx, BTRFS_SEND_A_MODE, mode);
        }
 
        ret = send_cmd(sctx);
@@ -3226,7 +3259,8 @@ static int process_all_refs(struct send_ctx *sctx,
                btrfs_item_key_to_cpu(eb, &found_key, slot);
 
                if (found_key.objectid != key.objectid ||
-                   found_key.type != key.type)
+                   (found_key.type != BTRFS_INODE_REF_KEY &&
+                    found_key.type != BTRFS_INODE_EXTREF_KEY))
                        break;
 
                ret = iterate_inode_ref(sctx, root, path, &found_key, 0, cb,
@@ -3987,7 +4021,7 @@ static int process_recorded_refs_if_needed(struct send_ctx *sctx, int at_end)
        if (sctx->cur_ino == 0)
                goto out;
        if (!at_end && sctx->cur_ino == sctx->cmp_key->objectid &&
-           sctx->cmp_key->type <= BTRFS_INODE_REF_KEY)
+           sctx->cmp_key->type <= BTRFS_INODE_EXTREF_KEY)
                goto out;
        if (list_empty(&sctx->new_refs) && list_empty(&sctx->deleted_refs))
                goto out;
@@ -4033,22 +4067,21 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end)
        if (ret < 0)
                goto out;
 
-       if (!S_ISLNK(sctx->cur_inode_mode)) {
-               if (!sctx->parent_root || sctx->cur_inode_new) {
+       if (!sctx->parent_root || sctx->cur_inode_new) {
+               need_chown = 1;
+               if (!S_ISLNK(sctx->cur_inode_mode))
                        need_chmod = 1;
-                       need_chown = 1;
-               } else {
-                       ret = get_inode_info(sctx->parent_root, sctx->cur_ino,
-                                       NULL, NULL, &right_mode, &right_uid,
-                                       &right_gid, NULL);
-                       if (ret < 0)
-                               goto out;
+       } else {
+               ret = get_inode_info(sctx->parent_root, sctx->cur_ino,
+                               NULL, NULL, &right_mode, &right_uid,
+                               &right_gid, NULL);
+               if (ret < 0)
+                       goto out;
 
-                       if (left_uid != right_uid || left_gid != right_gid)
-                               need_chown = 1;
-                       if (left_mode != right_mode)
-                               need_chmod = 1;
-               }
+               if (left_uid != right_uid || left_gid != right_gid)
+                       need_chown = 1;
+               if (!S_ISLNK(sctx->cur_inode_mode) && left_mode != right_mode)
+                       need_chmod = 1;
        }
 
        if (S_ISREG(sctx->cur_inode_mode)) {
@@ -4335,7 +4368,8 @@ static int changed_cb(struct btrfs_root *left_root,
 
        if (key->type == BTRFS_INODE_ITEM_KEY)
                ret = changed_inode(sctx, result);
-       else if (key->type == BTRFS_INODE_REF_KEY)
+       else if (key->type == BTRFS_INODE_REF_KEY ||
+                key->type == BTRFS_INODE_EXTREF_KEY)
                ret = changed_ref(sctx, result);
        else if (key->type == BTRFS_XATTR_ITEM_KEY)
                ret = changed_xattr(sctx, result);
index 77db875b511638b7ff94854c6b1482942da2b3fb..04bbfb1052ebfee9db25427d5542e795cac351cd 100644 (file)
@@ -1200,7 +1200,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        btrfs_i_size_write(parent_inode, parent_inode->i_size +
                                         dentry->d_name.len * 2);
        parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME;
-       ret = btrfs_update_inode(trans, parent_root, parent_inode);
+       ret = btrfs_update_inode_fallback(trans, parent_root, parent_inode);
        if (ret)
                btrfs_abort_transaction(trans, root, ret);
 fail:
index 029b903a4ae3797322e05090790b86c9e8596c43..0f5ebb72a5ea01693b339d66e3f928de9b783f78 100644 (file)
@@ -1819,6 +1819,13 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
                                    "Failed to relocate sys chunks after "
                                    "device initialization. This can be fixed "
                                    "using the \"btrfs balance\" command.");
+               trans = btrfs_attach_transaction(root);
+               if (IS_ERR(trans)) {
+                       if (PTR_ERR(trans) == -ENOENT)
+                               return 0;
+                       return PTR_ERR(trans);
+               }
+               ret = btrfs_commit_transaction(trans, root);
        }
 
        return ret;
index 02ce90972d81ca6e8b60ed580931c676c441fc2c..9349bb37a2fe68df93651e6afeb384468157edd2 100644 (file)
@@ -90,6 +90,8 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,
                *max_len = handle_length;
                type = 255;
        }
+       if (dentry)
+               dput(dentry);
        return type;
 }
 
index 3f152b92a94ad2824876fd99c9fbfdd05098d0cf..afc2bb6917806e85ee916d8b2c25cb2183890055 100644 (file)
@@ -471,9 +471,19 @@ static int exact_lock(dev_t dev, void *data)
  */
 int cdev_add(struct cdev *p, dev_t dev, unsigned count)
 {
+       int error;
+
        p->dev = dev;
        p->count = count;
-       return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
+
+       error = kobj_map(cdev_map, dev, count, NULL,
+                        exact_match, exact_lock, p);
+       if (error)
+               return error;
+
+       kobject_get(p->kobj.parent);
+
+       return 0;
 }
 
 static void cdev_unmap(dev_t dev, unsigned count)
@@ -498,14 +508,20 @@ void cdev_del(struct cdev *p)
 static void cdev_default_release(struct kobject *kobj)
 {
        struct cdev *p = container_of(kobj, struct cdev, kobj);
+       struct kobject *parent = kobj->parent;
+
        cdev_purge(p);
+       kobject_put(parent);
 }
 
 static void cdev_dynamic_release(struct kobject *kobj)
 {
        struct cdev *p = container_of(kobj, struct cdev, kobj);
+       struct kobject *parent = kobj->parent;
+
        cdev_purge(p);
        kfree(p);
+       kobject_put(parent);
 }
 
 static struct kobj_type ktype_cdev_default = {
index f5054025f9da7c154b067db092cc44f8b953f835..4c6285fff598e1faf9bb471f8b3b5593db74b355 100644 (file)
@@ -210,6 +210,8 @@ static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd,
 
        err  = get_user(palp, &up->palette);
        err |= get_user(length, &up->length);
+       if (err)
+               return -EFAULT;
 
        up_native = compat_alloc_user_space(sizeof(struct video_spu_palette));
        err  = put_user(compat_ptr(palp), &up_native->palette);
index 8b9011b67041ddcd57dbcc42e77fa7d0d8b05f7e..0039055b1fc6533c636ca98dd2b9ad73b52d5de6 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1083,7 +1083,8 @@ int flush_old_exec(struct linux_binprm * bprm)
        bprm->mm = NULL;                /* We're using it now */
 
        set_fs(USER_DS);
-       current->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD);
+       current->flags &=
+               ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD | PF_NOFREEZE);
        flush_thread();
        current->personality &= ~bprm->per_clear;
 
index 1b5089067d018d581c68242f39fcf522a8fee55d..cf1821784a16bff41349319400940c7e4218fa5a 100644 (file)
@@ -174,8 +174,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
                ext4_free_inodes_set(sb, gdp, 0);
                ext4_itable_unused_set(sb, gdp, 0);
                memset(bh->b_data, 0xff, sb->s_blocksize);
-               ext4_block_bitmap_csum_set(sb, block_group, gdp, bh,
-                                          EXT4_BLOCKS_PER_GROUP(sb) / 8);
+               ext4_block_bitmap_csum_set(sb, block_group, gdp, bh);
                return;
        }
        memset(bh->b_data, 0, sb->s_blocksize);
@@ -212,8 +211,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
         */
        ext4_mark_bitmap_end(num_clusters_in_group(sb, block_group),
                             sb->s_blocksize * 8, bh->b_data);
-       ext4_block_bitmap_csum_set(sb, block_group, gdp, bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, block_group, gdp, bh);
        ext4_group_desc_csum_set(sb, block_group, gdp);
 }
 
@@ -350,7 +348,7 @@ void ext4_validate_block_bitmap(struct super_block *sb,
                return;
        }
        if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group,
-                       desc, bh, EXT4_BLOCKS_PER_GROUP(sb) / 8))) {
+                       desc, bh))) {
                ext4_unlock_group(sb, block_group);
                ext4_error(sb, "bg %u: bad block bitmap checksum", block_group);
                return;
index 5c2d1813ebe919188d53dac74de8b512a7f02965..3285aa5a706af3f97c6a182a12304c7478177d9d 100644 (file)
@@ -58,11 +58,12 @@ void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
 
 int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
                                  struct ext4_group_desc *gdp,
-                                 struct buffer_head *bh, int sz)
+                                 struct buffer_head *bh)
 {
        __u32 hi;
        __u32 provided, calculated;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
+       int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8;
 
        if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
                                        EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
@@ -84,8 +85,9 @@ int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
 
 void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
                                struct ext4_group_desc *gdp,
-                               struct buffer_head *bh, int sz)
+                               struct buffer_head *bh)
 {
+       int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8;
        __u32 csum;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
 
index 3ab2539b7b2eb477222a3dbb7dd8b51cea3cca84..3c20de1d59d0d44586199ade586864758e2ce204 100644 (file)
@@ -1882,10 +1882,10 @@ int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
                                  struct buffer_head *bh, int sz);
 void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
                                struct ext4_group_desc *gdp,
-                               struct buffer_head *bh, int sz);
+                               struct buffer_head *bh);
 int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
                                  struct ext4_group_desc *gdp,
-                                 struct buffer_head *bh, int sz);
+                                 struct buffer_head *bh);
 
 /* balloc.c */
 extern void ext4_validate_block_bitmap(struct super_block *sb,
@@ -2063,8 +2063,7 @@ extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count);
 extern int ext4_calculate_overhead(struct super_block *sb);
 extern int ext4_superblock_csum_verify(struct super_block *sb,
                                       struct ext4_super_block *es);
-extern void ext4_superblock_csum_set(struct super_block *sb,
-                                    struct ext4_super_block *es);
+extern void ext4_superblock_csum_set(struct super_block *sb);
 extern void *ext4_kvmalloc(size_t size, gfp_t flags);
 extern void *ext4_kvzalloc(size_t size, gfp_t flags);
 extern void ext4_kvfree(void *ptr);
index bfa65b49d4243d75a5c73456fc2ee4e3698537f4..b4323ba846b52ad09fe0740699ea2d82ff92ba65 100644 (file)
@@ -143,17 +143,13 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line,
        struct buffer_head *bh = EXT4_SB(sb)->s_sbh;
        int err = 0;
 
+       ext4_superblock_csum_set(sb);
        if (ext4_handle_valid(handle)) {
-               ext4_superblock_csum_set(sb,
-                               (struct ext4_super_block *)bh->b_data);
                err = jbd2_journal_dirty_metadata(handle, bh);
                if (err)
                        ext4_journal_abort_handle(where, line, __func__,
                                                  bh, handle, err);
-       } else {
-               ext4_superblock_csum_set(sb,
-                               (struct ext4_super_block *)bh->b_data);
+       } else
                mark_buffer_dirty(bh);
-       }
        return err;
 }
index 1c94cca35ed1a12ce42ce39bddea7c9dd23111cf..7011ac967208e941272f09a07e3292d72ef576f9 100644 (file)
@@ -52,6 +52,9 @@
 #define EXT4_EXT_MARK_UNINIT1  0x2  /* mark first half uninitialized */
 #define EXT4_EXT_MARK_UNINIT2  0x4  /* mark second half uninitialized */
 
+#define EXT4_EXT_DATA_VALID1   0x8  /* first half contains valid data */
+#define EXT4_EXT_DATA_VALID2   0x10 /* second half contains valid data */
+
 static __le32 ext4_extent_block_csum(struct inode *inode,
                                     struct ext4_extent_header *eh)
 {
@@ -2914,6 +2917,9 @@ static int ext4_split_extent_at(handle_t *handle,
        unsigned int ee_len, depth;
        int err = 0;
 
+       BUG_ON((split_flag & (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)) ==
+              (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2));
+
        ext_debug("ext4_split_extents_at: inode %lu, logical"
                "block %llu\n", inode->i_ino, (unsigned long long)split);
 
@@ -2972,7 +2978,14 @@ static int ext4_split_extent_at(handle_t *handle,
 
        err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
        if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) {
-               err = ext4_ext_zeroout(inode, &orig_ex);
+               if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
+                       if (split_flag & EXT4_EXT_DATA_VALID1)
+                               err = ext4_ext_zeroout(inode, ex2);
+                       else
+                               err = ext4_ext_zeroout(inode, ex);
+               } else
+                       err = ext4_ext_zeroout(inode, &orig_ex);
+
                if (err)
                        goto fix_extent_len;
                /* update the extent length and mark as initialized */
@@ -3025,12 +3038,13 @@ static int ext4_split_extent(handle_t *handle,
        uninitialized = ext4_ext_is_uninitialized(ex);
 
        if (map->m_lblk + map->m_len < ee_block + ee_len) {
-               split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ?
-                             EXT4_EXT_MAY_ZEROOUT : 0;
+               split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT;
                flags1 = flags | EXT4_GET_BLOCKS_PRE_IO;
                if (uninitialized)
                        split_flag1 |= EXT4_EXT_MARK_UNINIT1 |
                                       EXT4_EXT_MARK_UNINIT2;
+               if (split_flag & EXT4_EXT_DATA_VALID2)
+                       split_flag1 |= EXT4_EXT_DATA_VALID1;
                err = ext4_split_extent_at(handle, inode, path,
                                map->m_lblk + map->m_len, split_flag1, flags1);
                if (err)
@@ -3043,8 +3057,8 @@ static int ext4_split_extent(handle_t *handle,
                return PTR_ERR(path);
 
        if (map->m_lblk >= ee_block) {
-               split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ?
-                             EXT4_EXT_MAY_ZEROOUT : 0;
+               split_flag1 = split_flag & (EXT4_EXT_MAY_ZEROOUT |
+                                           EXT4_EXT_DATA_VALID2);
                if (uninitialized)
                        split_flag1 |= EXT4_EXT_MARK_UNINIT1;
                if (split_flag & EXT4_EXT_MARK_UNINIT2)
@@ -3323,26 +3337,47 @@ static int ext4_split_unwritten_extents(handle_t *handle,
 
        split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0;
        split_flag |= EXT4_EXT_MARK_UNINIT2;
-
+       if (flags & EXT4_GET_BLOCKS_CONVERT)
+               split_flag |= EXT4_EXT_DATA_VALID2;
        flags |= EXT4_GET_BLOCKS_PRE_IO;
        return ext4_split_extent(handle, inode, path, map, split_flag, flags);
 }
 
 static int ext4_convert_unwritten_extents_endio(handle_t *handle,
-                                             struct inode *inode,
-                                             struct ext4_ext_path *path)
+                                               struct inode *inode,
+                                               struct ext4_map_blocks *map,
+                                               struct ext4_ext_path *path)
 {
        struct ext4_extent *ex;
+       ext4_lblk_t ee_block;
+       unsigned int ee_len;
        int depth;
        int err = 0;
 
        depth = ext_depth(inode);
        ex = path[depth].p_ext;
+       ee_block = le32_to_cpu(ex->ee_block);
+       ee_len = ext4_ext_get_actual_len(ex);
 
        ext_debug("ext4_convert_unwritten_extents_endio: inode %lu, logical"
                "block %llu, max_blocks %u\n", inode->i_ino,
-               (unsigned long long)le32_to_cpu(ex->ee_block),
-               ext4_ext_get_actual_len(ex));
+                 (unsigned long long)ee_block, ee_len);
+
+       /* If extent is larger than requested then split is required */
+       if (ee_block != map->m_lblk || ee_len > map->m_len) {
+               err = ext4_split_unwritten_extents(handle, inode, map, path,
+                                                  EXT4_GET_BLOCKS_CONVERT);
+               if (err < 0)
+                       goto out;
+               ext4_ext_drop_refs(path);
+               path = ext4_ext_find_extent(inode, map->m_lblk, path);
+               if (IS_ERR(path)) {
+                       err = PTR_ERR(path);
+                       goto out;
+               }
+               depth = ext_depth(inode);
+               ex = path[depth].p_ext;
+       }
 
        err = ext4_ext_get_access(handle, inode, path + depth);
        if (err)
@@ -3652,7 +3687,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
        }
        /* IO end_io complete, convert the filled extent to written */
        if ((flags & EXT4_GET_BLOCKS_CONVERT)) {
-               ret = ext4_convert_unwritten_extents_endio(handle, inode,
+               ret = ext4_convert_unwritten_extents_endio(handle, inode, map,
                                                        path);
                if (ret >= 0) {
                        ext4_update_inode_fsync_trans(handle, inode, 1);
@@ -4428,6 +4463,9 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
         */
        if (len <= EXT_UNINIT_MAX_LEN << blkbits)
                flags |= EXT4_GET_BLOCKS_NO_NORMALIZE;
+
+       /* Prevent race condition between unwritten */
+       ext4_flush_unwritten_io(inode);
 retry:
        while (ret >= 0 && ret < max_blocks) {
                map.m_lblk = map.m_lblk + ret;
index fa36372f3fdf827ed2557a3ecf5ccceab9e2cfe1..3a100e7a62a8343d31912a423330e11ea40e2e2a 100644 (file)
@@ -725,6 +725,10 @@ repeat_in_this_group:
                                   "inode=%lu", ino + 1);
                        continue;
                }
+               BUFFER_TRACE(inode_bitmap_bh, "get_write_access");
+               err = ext4_journal_get_write_access(handle, inode_bitmap_bh);
+               if (err)
+                       goto fail;
                ext4_lock_group(sb, group);
                ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data);
                ext4_unlock_group(sb, group);
@@ -738,6 +742,11 @@ repeat_in_this_group:
        goto out;
 
 got:
+       BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata");
+       err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh);
+       if (err)
+               goto fail;
+
        /* We may have to initialize the block bitmap if it isn't already */
        if (ext4_has_group_desc_csum(sb) &&
            gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
@@ -762,9 +771,7 @@ got:
                        ext4_free_group_clusters_set(sb, gdp,
                                ext4_free_clusters_after_init(sb, group, gdp));
                        ext4_block_bitmap_csum_set(sb, group, gdp,
-                                                  block_bitmap_bh,
-                                                  EXT4_BLOCKS_PER_GROUP(sb) /
-                                                  8);
+                                                  block_bitmap_bh);
                        ext4_group_desc_csum_set(sb, group, gdp);
                }
                ext4_unlock_group(sb, group);
@@ -773,11 +780,6 @@ got:
                        goto fail;
        }
 
-       BUFFER_TRACE(inode_bitmap_bh, "get_write_access");
-       err = ext4_journal_get_write_access(handle, inode_bitmap_bh);
-       if (err)
-               goto fail;
-
        BUFFER_TRACE(group_desc_bh, "get_write_access");
        err = ext4_journal_get_write_access(handle, group_desc_bh);
        if (err)
@@ -825,11 +827,6 @@ got:
        }
        ext4_unlock_group(sb, group);
 
-       BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata");
-       err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh);
-       if (err)
-               goto fail;
-
        BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata");
        err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh);
        if (err)
index f8b27bf80acaf45a3b9ce9aa872d2bed48b2f27d..526e55358606c83a548657449907cd94eed3c155 100644 (file)
@@ -2805,8 +2805,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
        }
        len = ext4_free_group_clusters(sb, gdp) - ac->ac_b_ex.fe_len;
        ext4_free_group_clusters_set(sb, gdp, len);
-       ext4_block_bitmap_csum_set(sb, ac->ac_b_ex.fe_group, gdp, bitmap_bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, ac->ac_b_ex.fe_group, gdp, bitmap_bh);
        ext4_group_desc_csum_set(sb, ac->ac_b_ex.fe_group, gdp);
 
        ext4_unlock_group(sb, ac->ac_b_ex.fe_group);
@@ -4666,8 +4665,7 @@ do_more:
 
        ret = ext4_free_group_clusters(sb, gdp) + count_clusters;
        ext4_free_group_clusters_set(sb, gdp, ret);
-       ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh);
        ext4_group_desc_csum_set(sb, block_group, gdp);
        ext4_unlock_group(sb, block_group);
        percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters);
@@ -4811,8 +4809,7 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
        mb_free_blocks(NULL, &e4b, bit, count);
        blk_free_count = blocks_freed + ext4_free_group_clusters(sb, desc);
        ext4_free_group_clusters_set(sb, desc, blk_free_count);
-       ext4_block_bitmap_csum_set(sb, block_group, desc, bitmap_bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, block_group, desc, bitmap_bh);
        ext4_group_desc_csum_set(sb, block_group, desc);
        ext4_unlock_group(sb, block_group);
        percpu_counter_add(&sbi->s_freeclusters_counter,
@@ -4993,8 +4990,9 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
        minlen = EXT4_NUM_B2C(EXT4_SB(sb),
                              range->minlen >> sb->s_blocksize_bits);
 
-       if (unlikely(minlen > EXT4_CLUSTERS_PER_GROUP(sb)) ||
-           unlikely(start >= max_blks))
+       if (minlen > EXT4_CLUSTERS_PER_GROUP(sb) ||
+           start >= max_blks ||
+           range->len < sb->s_blocksize)
                return -EINVAL;
        if (end >= max_blks)
                end = max_blks - 1;
index 7a75e1086961eedb674b8c2bf1bb84e657f4dfa2..47bf06a2765ddcbbd37eb84e693680278ea96fb9 100644 (file)
@@ -1212,8 +1212,7 @@ static int ext4_set_bitmap_checksums(struct super_block *sb,
        bh = ext4_get_bitmap(sb, group_data->block_bitmap);
        if (!bh)
                return -EIO;
-       ext4_block_bitmap_csum_set(sb, group, gdp, bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, group, gdp, bh);
        brelse(bh);
 
        return 0;
index 7265a0367476a87f0355b17c22b2488f65ec9a5f..80928f716850924cb34e7a591367cadf115fb95a 100644 (file)
@@ -143,9 +143,10 @@ int ext4_superblock_csum_verify(struct super_block *sb,
        return es->s_checksum == ext4_superblock_csum(sb, es);
 }
 
-void ext4_superblock_csum_set(struct super_block *sb,
-                             struct ext4_super_block *es)
+void ext4_superblock_csum_set(struct super_block *sb)
 {
+       struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+
        if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
                EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
                return;
@@ -1963,7 +1964,7 @@ static int ext4_fill_flex_info(struct super_block *sb)
                sbi->s_log_groups_per_flex = 0;
                return 1;
        }
-       groups_per_flex = 1 << sbi->s_log_groups_per_flex;
+       groups_per_flex = 1U << sbi->s_log_groups_per_flex;
 
        err = ext4_alloc_flex_bg_array(sb, sbi->s_groups_count);
        if (err)
@@ -4381,7 +4382,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
                cpu_to_le32(percpu_counter_sum_positive(
                                &EXT4_SB(sb)->s_freeinodes_counter));
        BUFFER_TRACE(sbh, "marking dirty");
-       ext4_superblock_csum_set(sb, es);
+       ext4_superblock_csum_set(sb);
        mark_buffer_dirty(sbh);
        if (sync) {
                error = sync_dirty_buffer(sbh);
index d3b5fa80b71b76a973919a6b9cfa2ebb34096adf..708d997a77485989d53583084a3e1b99354fb407 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -900,7 +900,7 @@ int replace_fd(unsigned fd, struct file *file, unsigned flags)
                return __close_fd(files, fd);
 
        if (fd >= rlimit(RLIMIT_NOFILE))
-               return -EMFILE;
+               return -EBADF;
 
        spin_lock(&files->file_lock);
        err = expand_files(files, fd);
@@ -926,7 +926,7 @@ SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags)
                return -EINVAL;
 
        if (newfd >= rlimit(RLIMIT_NOFILE))
-               return -EMFILE;
+               return -EBADF;
 
        spin_lock(&files->file_lock);
        err = expand_files(files, newfd);
index 9947563e41750223035daa3aeeaba785a9baf82c..dfcd5030455933bcfbc795c251bc3f0b6fa8e36a 100644 (file)
@@ -83,7 +83,7 @@ int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range)
        struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap;
        struct super_block *sb = ipbmap->i_sb;
        int agno, agno_end;
-       s64 start, end, minlen;
+       u64 start, end, minlen;
        u64 trimmed = 0;
 
        /**
@@ -93,15 +93,19 @@ int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range)
         * minlen:      minimum extent length in Bytes
         */
        start = range->start >> sb->s_blocksize_bits;
-       if (start < 0)
-               start = 0;
        end = start + (range->len >> sb->s_blocksize_bits) - 1;
-       if (end >= bmp->db_mapsize)
-               end = bmp->db_mapsize - 1;
        minlen = range->minlen >> sb->s_blocksize_bits;
-       if (minlen <= 0)
+       if (minlen == 0)
                minlen = 1;
 
+       if (minlen > bmp->db_agsize ||
+           start >= bmp->db_mapsize ||
+           range->len < sb->s_blocksize)
+               return -EINVAL;
+
+       if (end >= bmp->db_mapsize)
+               end = bmp->db_mapsize - 1;
+
        /**
         * we trim all ag's within the range
         */
index e4fb3ba5a58a3d50eb11a0f9533ca58ae5150283..3d7e09bcc0e9efad7418803737e385c76d22a776 100644 (file)
@@ -85,29 +85,38 @@ static struct rpc_clnt *nsm_create(struct net *net)
        return rpc_create(&args);
 }
 
+static struct rpc_clnt *nsm_client_set(struct lockd_net *ln,
+               struct rpc_clnt *clnt)
+{
+       spin_lock(&ln->nsm_clnt_lock);
+       if (ln->nsm_users == 0) {
+               if (clnt == NULL)
+                       goto out;
+               ln->nsm_clnt = clnt;
+       }
+       clnt = ln->nsm_clnt;
+       ln->nsm_users++;
+out:
+       spin_unlock(&ln->nsm_clnt_lock);
+       return clnt;
+}
+
 static struct rpc_clnt *nsm_client_get(struct net *net)
 {
-       static DEFINE_MUTEX(nsm_create_mutex);
-       struct rpc_clnt *clnt;
+       struct rpc_clnt *clnt, *new;
        struct lockd_net *ln = net_generic(net, lockd_net_id);
 
-       spin_lock(&ln->nsm_clnt_lock);
-       if (ln->nsm_users) {
-               ln->nsm_users++;
-               clnt = ln->nsm_clnt;
-               spin_unlock(&ln->nsm_clnt_lock);
+       clnt = nsm_client_set(ln, NULL);
+       if (clnt != NULL)
                goto out;
-       }
-       spin_unlock(&ln->nsm_clnt_lock);
 
-       mutex_lock(&nsm_create_mutex);
-       clnt = nsm_create(net);
-       if (!IS_ERR(clnt)) {
-               ln->nsm_clnt = clnt;
-               smp_wmb();
-               ln->nsm_users = 1;
-       }
-       mutex_unlock(&nsm_create_mutex);
+       clnt = new = nsm_create(net);
+       if (IS_ERR(clnt))
+               goto out;
+
+       clnt = nsm_client_set(ln, new);
+       if (clnt != new)
+               rpc_shutdown_client(new);
 out:
        return clnt;
 }
@@ -115,18 +124,16 @@ out:
 static void nsm_client_put(struct net *net)
 {
        struct lockd_net *ln = net_generic(net, lockd_net_id);
-       struct rpc_clnt *clnt = ln->nsm_clnt;
-       int shutdown = 0;
+       struct rpc_clnt *clnt = NULL;
 
        spin_lock(&ln->nsm_clnt_lock);
-       if (ln->nsm_users) {
-               if (--ln->nsm_users)
-                       ln->nsm_clnt = NULL;
-               shutdown = !ln->nsm_users;
+       ln->nsm_users--;
+       if (ln->nsm_users == 0) {
+               clnt = ln->nsm_clnt;
+               ln->nsm_clnt = NULL;
        }
        spin_unlock(&ln->nsm_clnt_lock);
-
-       if (shutdown)
+       if (clnt != NULL)
                rpc_shutdown_client(clnt);
 }
 
index d1895f30815670de8abd8a6c921443035c21a364..937f9d50c84bdead7516057fead3d5a702ead4b9 100644 (file)
@@ -705,8 +705,8 @@ static inline void put_link(struct nameidata *nd, struct path *link, void *cooki
        path_put(link);
 }
 
-int sysctl_protected_symlinks __read_mostly = 1;
-int sysctl_protected_hardlinks __read_mostly = 1;
+int sysctl_protected_symlinks __read_mostly = 0;
+int sysctl_protected_hardlinks __read_mostly = 0;
 
 /**
  * may_follow_link - Check symlink following for unsafe situations
index 9a521fb3986955aab3f32e755bdef94e9c313aa2..5088b57b078a729d09ced36b3e491c01cba9cf4c 100644 (file)
@@ -241,7 +241,7 @@ static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt,
                svc_exit_thread(cb_info->rqst);
                cb_info->rqst = NULL;
                cb_info->task = NULL;
-               return PTR_ERR(cb_info->task);
+               return ret;
        }
        dprintk("nfs_callback_up: service started\n");
        return 0;
index 31c26c4dcc238110de0fa7374f1a2ab51a1541cd..ca4b11ec87a292e92e5d9496f8ac194d97a5bf9f 100644 (file)
@@ -217,7 +217,7 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)
 {
        char buf1[NFS_DNS_HOSTNAME_MAXLEN+1];
        struct nfs_dns_ent key, *item;
-       unsigned long ttl;
+       unsigned int ttl;
        ssize_t len;
        int ret = -EINVAL;
 
@@ -240,7 +240,8 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)
        key.namelen = len;
        memset(&key.h, 0, sizeof(key.h));
 
-       ttl = get_expiry(&buf);
+       if (get_uint(&buf, &ttl) < 0)
+               goto out;
        if (ttl == 0)
                goto out;
        key.h.expiry_time = ttl + seconds_since_boot();
index 5c7325c5c5e66b23beacd6fb7485fda5a640dcd9..6fa01aea24889cae08385e5bfe0aab16c742adc8 100644 (file)
@@ -685,7 +685,10 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
        if (ctx->cred != NULL)
                put_rpccred(ctx->cred);
        dput(ctx->dentry);
-       nfs_sb_deactive(sb);
+       if (is_sync)
+               nfs_sb_deactive(sb);
+       else
+               nfs_sb_deactive_async(sb);
        kfree(ctx->mdsthreshold);
        kfree(ctx);
 }
index 59b133c5d652df5d2397b1e24e22f390fed459fc..05521cadac2e9821292c8c4eeefa037f5ef0a726 100644 (file)
@@ -351,10 +351,12 @@ extern int __init register_nfs_fs(void);
 extern void __exit unregister_nfs_fs(void);
 extern void nfs_sb_active(struct super_block *sb);
 extern void nfs_sb_deactive(struct super_block *sb);
+extern void nfs_sb_deactive_async(struct super_block *sb);
 
 /* namespace.c */
+#define NFS_PATH_CANONICAL 1
 extern char *nfs_path(char **p, struct dentry *dentry,
-                     char *buffer, ssize_t buflen);
+                     char *buffer, ssize_t buflen, unsigned flags);
 extern struct vfsmount *nfs_d_automount(struct path *path);
 struct vfsmount *nfs_submount(struct nfs_server *, struct dentry *,
                              struct nfs_fh *, struct nfs_fattr *);
@@ -498,7 +500,7 @@ static inline char *nfs_devname(struct dentry *dentry,
                                char *buffer, ssize_t buflen)
 {
        char *dummy;
-       return nfs_path(&dummy, dentry, buffer, buflen);
+       return nfs_path(&dummy, dentry, buffer, buflen, NFS_PATH_CANONICAL);
 }
 
 /*
index 8e65c7f1f87c526707959c0e691e36532406d1fa..015f71f8f62c271ebcd6c6ec3949aeff446ce420 100644 (file)
@@ -181,7 +181,7 @@ int nfs_mount(struct nfs_mount_request *info)
        else
                msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT];
 
-       status = rpc_call_sync(mnt_clnt, &msg, 0);
+       status = rpc_call_sync(mnt_clnt, &msg, RPC_TASK_SOFT|RPC_TASK_TIMEOUT);
        rpc_shutdown_client(mnt_clnt);
 
        if (status < 0)
index 655925373b9161c6a6c64ad157002d10cf8064e2..dd057bc6b65b28d3822229e0c0d5d0777b7955b9 100644 (file)
@@ -33,6 +33,7 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;
  * @dentry - pointer to dentry
  * @buffer - result buffer
  * @buflen - length of buffer
+ * @flags - options (see below)
  *
  * Helper function for constructing the server pathname
  * by arbitrary hashed dentry.
@@ -40,8 +41,14 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;
  * This is mainly for use in figuring out the path on the
  * server side when automounting on top of an existing partition
  * and in generating /proc/mounts and friends.
+ *
+ * Supported flags:
+ * NFS_PATH_CANONICAL: ensure there is exactly one slash after
+ *                    the original device (export) name
+ *                    (if unset, the original name is returned verbatim)
  */
-char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen)
+char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen,
+              unsigned flags)
 {
        char *end;
        int namelen;
@@ -74,7 +81,7 @@ rename_retry:
                rcu_read_unlock();
                goto rename_retry;
        }
-       if (*end != '/') {
+       if ((flags & NFS_PATH_CANONICAL) && *end != '/') {
                if (--buflen < 0) {
                        spin_unlock(&dentry->d_lock);
                        rcu_read_unlock();
@@ -91,9 +98,11 @@ rename_retry:
                return end;
        }
        namelen = strlen(base);
-       /* Strip off excess slashes in base string */
-       while (namelen > 0 && base[namelen - 1] == '/')
-               namelen--;
+       if (flags & NFS_PATH_CANONICAL) {
+               /* Strip off excess slashes in base string */
+               while (namelen > 0 && base[namelen - 1] == '/')
+                       namelen--;
+       }
        buflen -= namelen;
        if (buflen < 0) {
                spin_unlock(&dentry->d_lock);
index 52d8472120663de91855690fa0996cdf03e4a8a4..2e45fd9c02a38cc9d7b3ee0ee87150fa3a8e7ea8 100644 (file)
@@ -122,12 +122,21 @@ static void filelayout_reset_read(struct nfs_read_data *data)
        }
 }
 
+static void filelayout_fenceme(struct inode *inode, struct pnfs_layout_hdr *lo)
+{
+       if (!test_and_clear_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
+               return;
+       clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags);
+       pnfs_return_layout(inode);
+}
+
 static int filelayout_async_handle_error(struct rpc_task *task,
                                         struct nfs4_state *state,
                                         struct nfs_client *clp,
                                         struct pnfs_layout_segment *lseg)
 {
-       struct inode *inode = lseg->pls_layout->plh_inode;
+       struct pnfs_layout_hdr *lo = lseg->pls_layout;
+       struct inode *inode = lo->plh_inode;
        struct nfs_server *mds_server = NFS_SERVER(inode);
        struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg);
        struct nfs_client *mds_client = mds_server->nfs_client;
@@ -204,10 +213,8 @@ static int filelayout_async_handle_error(struct rpc_task *task,
                dprintk("%s DS connection error %d\n", __func__,
                        task->tk_status);
                nfs4_mark_deviceid_unavailable(devid);
-               clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags);
-               _pnfs_return_layout(inode);
+               set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags);
                rpc_wake_up(&tbl->slot_tbl_waitq);
-               nfs4_ds_disconnect(clp);
                /* fall through */
        default:
 reset:
@@ -331,7 +338,9 @@ static void filelayout_read_count_stats(struct rpc_task *task, void *data)
 static void filelayout_read_release(void *data)
 {
        struct nfs_read_data *rdata = data;
+       struct pnfs_layout_hdr *lo = rdata->header->lseg->pls_layout;
 
+       filelayout_fenceme(lo->plh_inode, lo);
        nfs_put_client(rdata->ds_clp);
        rdata->header->mds_ops->rpc_release(data);
 }
@@ -429,7 +438,9 @@ static void filelayout_write_count_stats(struct rpc_task *task, void *data)
 static void filelayout_write_release(void *data)
 {
        struct nfs_write_data *wdata = data;
+       struct pnfs_layout_hdr *lo = wdata->header->lseg->pls_layout;
 
+       filelayout_fenceme(lo->plh_inode, lo);
        nfs_put_client(wdata->ds_clp);
        wdata->header->mds_ops->rpc_release(data);
 }
@@ -739,7 +750,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
                goto out_err;
 
        if (fl->num_fh > 0) {
-               fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *),
+               fl->fh_array = kcalloc(fl->num_fh, sizeof(fl->fh_array[0]),
                                       gfp_flags);
                if (!fl->fh_array)
                        goto out_err;
index dca47d78671026810c67b139763cd1b27548d42d..8c07241fe52b0ac86c7d1ef241923f20f0d56a1e 100644 (file)
@@ -149,6 +149,5 @@ extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr);
 extern void nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr);
 struct nfs4_file_layout_dsaddr *
 filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags);
-void nfs4_ds_disconnect(struct nfs_client *clp);
 
 #endif /* FS_NFS_NFS4FILELAYOUT_H */
index 3336d5eaf879adc07a2e95f64b512835935763a6..a8eaa9b7bb0f2c8fc704b8eb752c2ebc564b52bf 100644 (file)
@@ -148,28 +148,6 @@ _data_server_lookup_locked(const struct list_head *dsaddrs)
        return NULL;
 }
 
-/*
- * Lookup DS by nfs_client pointer. Zero data server client pointer
- */
-void nfs4_ds_disconnect(struct nfs_client *clp)
-{
-       struct nfs4_pnfs_ds *ds;
-       struct nfs_client *found = NULL;
-
-       dprintk("%s clp %p\n", __func__, clp);
-       spin_lock(&nfs4_ds_cache_lock);
-       list_for_each_entry(ds, &nfs4_data_server_cache, ds_node)
-               if (ds->ds_clp && ds->ds_clp == clp) {
-                       found = ds->ds_clp;
-                       ds->ds_clp = NULL;
-               }
-       spin_unlock(&nfs4_ds_cache_lock);
-       if (found) {
-               set_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state);
-               nfs_put_client(clp);
-       }
-}
-
 /*
  * Create an rpc connection to the nfs4_pnfs_ds data server
  * Currently only supports IPv4 and IPv6 addresses
index 6a83780e0ce6b9a9888ce51dfd303ca454b54ea8..549462e5b9b0633239a1b2766ce17433446874dc 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <linux/nfs_fs.h>
 #include "nfs4_fs.h"
+#include "internal.h"
 
 #define NFSDBG_FACILITY                NFSDBG_CLIENT
 
index 79fbb61ce202bcb90df2c8ad0f7f3ecf3bba7aac..1e09eb78543b2d50f9da025c733e52a99957ba64 100644 (file)
@@ -81,7 +81,8 @@ static char *nfs_path_component(const char *nfspath, const char *end)
 static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen)
 {
        char *limit;
-       char *path = nfs_path(&limit, dentry, buffer, buflen);
+       char *path = nfs_path(&limit, dentry, buffer, buflen,
+                             NFS_PATH_CANONICAL);
        if (!IS_ERR(path)) {
                char *path_component = nfs_path_component(path, limit);
                if (path_component)
index 68b21d81b7acfa79bef010023195c1f45023c82b..5eec4429970c6e98af7a18732794c6fceaba4951 100644 (file)
@@ -339,8 +339,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
                        dprintk("%s ERROR: %d Reset session\n", __func__,
                                errorcode);
                        nfs4_schedule_session_recovery(clp->cl_session, errorcode);
-                       exception->retry = 1;
-                       break;
+                       goto wait_on_recovery;
 #endif /* defined(CONFIG_NFS_V4_1) */
                case -NFS4ERR_FILE_OPEN:
                        if (exception->timeout > HZ) {
@@ -1572,9 +1571,11 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
        data->timestamp = jiffies;
        if (nfs4_setup_sequence(data->o_arg.server,
                                &data->o_arg.seq_args,
-                               &data->o_res.seq_res, task))
-               return;
-       rpc_call_start(task);
+                               &data->o_res.seq_res,
+                               task) != 0)
+               nfs_release_seqid(data->o_arg.seqid);
+       else
+               rpc_call_start(task);
        return;
 unlock_no_action:
        rcu_read_unlock();
@@ -1748,7 +1749,7 @@ static int nfs4_opendata_access(struct rpc_cred *cred,
 
        /* even though OPEN succeeded, access is denied. Close the file */
        nfs4_close_state(state, fmode);
-       return -NFS4ERR_ACCESS;
+       return -EACCES;
 }
 
 /*
@@ -2196,7 +2197,7 @@ static void nfs4_free_closedata(void *data)
        nfs4_put_open_state(calldata->state);
        nfs_free_seqid(calldata->arg.seqid);
        nfs4_put_state_owner(sp);
-       nfs_sb_deactive(sb);
+       nfs_sb_deactive_async(sb);
        kfree(calldata);
 }
 
@@ -2296,9 +2297,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
        if (nfs4_setup_sequence(NFS_SERVER(inode),
                                &calldata->arg.seq_args,
                                &calldata->res.seq_res,
-                               task))
-               goto out;
-       rpc_call_start(task);
+                               task) != 0)
+               nfs_release_seqid(calldata->arg.seqid);
+       else
+               rpc_call_start(task);
 out:
        dprintk("%s: done!\n", __func__);
 }
@@ -4529,6 +4531,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
                        if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN)
                                rpc_restart_call_prepare(task);
        }
+       nfs_release_seqid(calldata->arg.seqid);
 }
 
 static void nfs4_locku_prepare(struct rpc_task *task, void *data)
@@ -4545,9 +4548,11 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
        calldata->timestamp = jiffies;
        if (nfs4_setup_sequence(calldata->server,
                                &calldata->arg.seq_args,
-                               &calldata->res.seq_res, task))
-               return;
-       rpc_call_start(task);
+                               &calldata->res.seq_res,
+                               task) != 0)
+               nfs_release_seqid(calldata->arg.seqid);
+       else
+               rpc_call_start(task);
 }
 
 static const struct rpc_call_ops nfs4_locku_ops = {
@@ -4692,7 +4697,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
        /* Do we need to do an open_to_lock_owner? */
        if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) {
                if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0)
-                       return;
+                       goto out_release_lock_seqid;
                data->arg.open_stateid = &state->stateid;
                data->arg.new_lock_owner = 1;
                data->res.open_seqid = data->arg.open_seqid;
@@ -4701,10 +4706,15 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
        data->timestamp = jiffies;
        if (nfs4_setup_sequence(data->server,
                                &data->arg.seq_args,
-                               &data->res.seq_res, task))
+                               &data->res.seq_res,
+                               task) == 0) {
+               rpc_call_start(task);
                return;
-       rpc_call_start(task);
-       dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status);
+       }
+       nfs_release_seqid(data->arg.open_seqid);
+out_release_lock_seqid:
+       nfs_release_seqid(data->arg.lock_seqid);
+       dprintk("%s: done!, ret = %d\n", __func__, task->tk_status);
 }
 
 static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata)
@@ -5667,7 +5677,7 @@ static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl,
                tbl->slots = new;
                tbl->max_slots = max_slots;
        }
-       tbl->highest_used_slotid = -1;  /* no slot is currently used */
+       tbl->highest_used_slotid = NFS4_NO_SLOT;
        for (i = 0; i < tbl->max_slots; i++)
                tbl->slots[i].seq_nr = ivalue;
        spin_unlock(&tbl->slot_tbl_lock);
index be731e6b7b9cc1781a0a1776f49f7e5aa8219a89..c6f990656f8905ed4911b471f7334e1a1a40582e 100644 (file)
@@ -369,7 +369,7 @@ void objio_free_result(struct objlayout_io_res *oir)
        kfree(objios);
 }
 
-enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep)
+static enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep)
 {
        switch (oep) {
        case OSD_ERR_PRI_NO_ERROR:
@@ -574,7 +574,7 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio,
                        (unsigned long)pgio->pg_layout_private;
 }
 
-void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
+static void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
 {
        pnfs_generic_pg_init_read(pgio, req);
        if (unlikely(pgio->pg_lseg == NULL))
@@ -604,7 +604,7 @@ static bool aligned_on_raid_stripe(u64 offset, struct ore_layout *layout,
        return false;
 }
 
-void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
+static void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
 {
        unsigned long stripe_end = 0;
        u64 wb_size;
index fe624c91bd006ef11f839f61cab54f833286edfa..2878f97bd78d5cf5343b88cfcac9b5a48a1abe60 100644 (file)
@@ -925,8 +925,8 @@ pnfs_find_alloc_layout(struct inode *ino,
        if (likely(nfsi->layout == NULL)) {     /* Won the race? */
                nfsi->layout = new;
                return new;
-       }
-       pnfs_free_layout_hdr(new);
+       } else if (new != NULL)
+               pnfs_free_layout_hdr(new);
 out_existing:
        pnfs_get_layout_hdr(nfsi->layout);
        return nfsi->layout;
index 2d722dba111181377e6f599adae06a8d341abe09..dbf7bba52da04086c0c0a2bbb8b4283b309b8758 100644 (file)
@@ -62,6 +62,7 @@ enum {
        NFS_LAYOUT_RW_FAILED,           /* get rw layout failed stop trying */
        NFS_LAYOUT_BULK_RECALL,         /* bulk recall affecting layout */
        NFS_LAYOUT_ROC,                 /* some lseg had roc bit set */
+       NFS_LAYOUT_RETURN,              /* Return this layout ASAP */
 };
 
 enum layoutdriver_policy_flags {
index e831bce497663e809e48bb7cc278f5ad6a74ba7b..652d3f7176a98fcc4e70e6f5e3d812e4b3d90b83 100644 (file)
@@ -54,6 +54,7 @@
 #include <linux/parser.h>
 #include <linux/nsproxy.h>
 #include <linux/rcupdate.h>
+#include <linux/kthread.h>
 
 #include <asm/uaccess.h>
 
@@ -415,6 +416,54 @@ void nfs_sb_deactive(struct super_block *sb)
 }
 EXPORT_SYMBOL_GPL(nfs_sb_deactive);
 
+static int nfs_deactivate_super_async_work(void *ptr)
+{
+       struct super_block *sb = ptr;
+
+       deactivate_super(sb);
+       module_put_and_exit(0);
+       return 0;
+}
+
+/*
+ * same effect as deactivate_super, but will do final unmount in kthread
+ * context
+ */
+static void nfs_deactivate_super_async(struct super_block *sb)
+{
+       struct task_struct *task;
+       char buf[INET6_ADDRSTRLEN + 1];
+       struct nfs_server *server = NFS_SB(sb);
+       struct nfs_client *clp = server->nfs_client;
+
+       if (!atomic_add_unless(&sb->s_active, -1, 1)) {
+               rcu_read_lock();
+               snprintf(buf, sizeof(buf),
+                       rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR));
+               rcu_read_unlock();
+
+               __module_get(THIS_MODULE);
+               task = kthread_run(nfs_deactivate_super_async_work, sb,
+                               "%s-deactivate-super", buf);
+               if (IS_ERR(task)) {
+                       pr_err("%s: kthread_run: %ld\n",
+                               __func__, PTR_ERR(task));
+                       /* make synchronous call and hope for the best */
+                       deactivate_super(sb);
+                       module_put(THIS_MODULE);
+               }
+       }
+}
+
+void nfs_sb_deactive_async(struct super_block *sb)
+{
+       struct nfs_server *server = NFS_SB(sb);
+
+       if (atomic_dec_and_test(&server->active))
+               nfs_deactivate_super_async(sb);
+}
+EXPORT_SYMBOL_GPL(nfs_sb_deactive_async);
+
 /*
  * Deliver file system statistics to userspace
  */
@@ -771,7 +820,7 @@ int nfs_show_devname(struct seq_file *m, struct dentry *root)
        int err = 0;
        if (!page)
                return -ENOMEM;
-       devname = nfs_path(&dummy, root, page, PAGE_SIZE);
+       devname = nfs_path(&dummy, root, page, PAGE_SIZE, 0);
        if (IS_ERR(devname))
                err = PTR_ERR(devname);
        else
index 13cea637eff82288f2f5508023a592e60db3fa7a..3f79c77153b8fe827cd24310209301e0132b96ad 100644 (file)
@@ -95,7 +95,7 @@ static void nfs_async_unlink_release(void *calldata)
 
        nfs_dec_sillycount(data->dir);
        nfs_free_unlinkdata(data);
-       nfs_sb_deactive(sb);
+       nfs_sb_deactive_async(sb);
 }
 
 static void nfs_unlink_prepare(struct rpc_task *task, void *calldata)
index 64c3b3172367abbd1c1464b9372f33ee4efa7acb..e296572c73ed651dd7d81cc33eb3dd1b64de5d0d 100644 (file)
@@ -45,10 +45,13 @@ static cputime64_t get_iowait_time(int cpu)
 
 static u64 get_idle_time(int cpu)
 {
-       u64 idle, idle_time = get_cpu_idle_time_us(cpu, NULL);
+       u64 idle, idle_time = -1ULL;
+
+       if (cpu_online(cpu))
+               idle_time = get_cpu_idle_time_us(cpu, NULL);
 
        if (idle_time == -1ULL)
-               /* !NO_HZ so we can rely on cpustat.idle */
+               /* !NO_HZ or cpu offline so we can rely on cpustat.idle */
                idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE];
        else
                idle = usecs_to_cputime64(idle_time);
@@ -58,10 +61,13 @@ static u64 get_idle_time(int cpu)
 
 static u64 get_iowait_time(int cpu)
 {
-       u64 iowait, iowait_time = get_cpu_iowait_time_us(cpu, NULL);
+       u64 iowait, iowait_time = -1ULL;
+
+       if (cpu_online(cpu))
+               iowait_time = get_cpu_iowait_time_us(cpu, NULL);
 
        if (iowait_time == -1ULL)
-               /* !NO_HZ so we can rely on cpustat.iowait */
+               /* !NO_HZ or cpu offline so we can rely on cpustat.iowait */
                iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT];
        else
                iowait = usecs_to_cputime64(iowait_time);
index 6b0bb00d4d2b6061add5a1f266371df257e5c4a9..2fbdff6be25ce3d546e17fa4e72783e9d3f03637 100644 (file)
@@ -485,20 +485,18 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
 /**
  *     sysfs_pathname - return full path to sysfs dirent
  *     @sd: sysfs_dirent whose path we want
- *     @path: caller allocated buffer
+ *     @path: caller allocated buffer of size PATH_MAX
  *
  *     Gives the name "/" to the sysfs_root entry; any path returned
  *     is relative to wherever sysfs is mounted.
- *
- *     XXX: does no error checking on @path size
  */
 static char *sysfs_pathname(struct sysfs_dirent *sd, char *path)
 {
        if (sd->s_parent) {
                sysfs_pathname(sd->s_parent, path);
-               strcat(path, "/");
+               strlcat(path, "/", PATH_MAX);
        }
-       strcat(path, sd->s_name);
+       strlcat(path, sd->s_name, PATH_MAX);
        return path;
 }
 
@@ -531,9 +529,11 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
                char *path = kzalloc(PATH_MAX, GFP_KERNEL);
                WARN(1, KERN_WARNING
                     "sysfs: cannot create duplicate filename '%s'\n",
-                    (path == NULL) ? sd->s_name :
-                    strcat(strcat(sysfs_pathname(acxt->parent_sd, path), "/"),
-                           sd->s_name));
+                    (path == NULL) ? sd->s_name
+                                   : (sysfs_pathname(acxt->parent_sd, path),
+                                      strlcat(path, "/", PATH_MAX),
+                                      strlcat(path, sd->s_name, PATH_MAX),
+                                      path));
                kfree(path);
        }
 
index c78bb997e2c60846a1f5e261664d96ee1656fe6d..af1cbaf535edeb395954583d1d1c1cd0c255c64c 100644 (file)
        {0x1002, 0x6788, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x678A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6790, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x6791, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x6792, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6798, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6799, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x679A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6810, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x6811, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6816, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6817, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6818, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
index 4eb31752e2b77592e8a2fdbf3fde779d4851504d..1ca0e3292bc98e1cd1ade0ad74f54f0939f9d745 100644 (file)
@@ -5,10 +5,15 @@
 #include <linux/list.h>
 #include <linux/io.h>
 
+struct atmel_ssc_platform_data {
+       int                     use_dma;
+};
+
 struct ssc_device {
        struct list_head        list;
        void __iomem            *regs;
        struct platform_device  *pdev;
+       struct atmel_ssc_platform_data *pdata;
        struct clk              *clk;
        int                     user;
        int                     irq;
index c18257b0fa7219df00fb5c991cfcfe7c8f5e135a..6dd4787a798a2a561afefbe39021bea303bd785c 100644 (file)
@@ -61,7 +61,7 @@ int __dynamic_netdev_dbg(struct _ddebug *descriptor,
                         const char *fmt, ...);
 
 #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)               \
-       static struct _ddebug __used __aligned(8)               \
+       static struct _ddebug  __aligned(8)                     \
        __attribute__((section("__verbose"))) name = {          \
                .modname = KBUILD_MODNAME,                      \
                .function = __func__,                           \
index 7443a560c9d059d106e7ce18dcf8813b18502c65..2c26c14cd7100d79ff046b9187409e2f430571eb 100644 (file)
@@ -68,7 +68,7 @@ enum extcon_cable_name {
        EXTCON_VIDEO_OUT,
        EXTCON_MECHANICAL,
 };
-extern const char *extcon_cable_name[];
+extern const char extcon_cable_name[][CABLE_NAME_MAX + 1];
 
 struct extcon_cable;
 
diff --git a/include/linux/hashtable.h b/include/linux/hashtable.h
new file mode 100644 (file)
index 0000000..227c624
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Statically sized hash table implementation
+ * (C) 2012  Sasha Levin <levinsasha928@gmail.com>
+ */
+
+#ifndef _LINUX_HASHTABLE_H
+#define _LINUX_HASHTABLE_H
+
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/hash.h>
+#include <linux/rculist.h>
+
+#define DEFINE_HASHTABLE(name, bits)                                           \
+       struct hlist_head name[1 << (bits)] =                                   \
+                       { [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT }
+
+#define DECLARE_HASHTABLE(name, bits)                                          \
+       struct hlist_head name[1 << (bits)]
+
+#define HASH_SIZE(name) (ARRAY_SIZE(name))
+#define HASH_BITS(name) ilog2(HASH_SIZE(name))
+
+/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */
+#define hash_min(val, bits)                                                    \
+       (sizeof(val) <= 4 ? hash_32(val, bits) : hash_long(val, bits))
+
+static inline void __hash_init(struct hlist_head *ht, unsigned int sz)
+{
+       unsigned int i;
+
+       for (i = 0; i < sz; i++)
+               INIT_HLIST_HEAD(&ht[i]);
+}
+
+/**
+ * hash_init - initialize a hash table
+ * @hashtable: hashtable to be initialized
+ *
+ * Calculates the size of the hashtable from the given parameter, otherwise
+ * same as hash_init_size.
+ *
+ * This has to be a macro since HASH_BITS() will not work on pointers since
+ * it calculates the size during preprocessing.
+ */
+#define hash_init(hashtable) __hash_init(hashtable, HASH_SIZE(hashtable))
+
+/**
+ * hash_add - add an object to a hashtable
+ * @hashtable: hashtable to add to
+ * @node: the &struct hlist_node of the object to be added
+ * @key: the key of the object to be added
+ */
+#define hash_add(hashtable, node, key)                                         \
+       hlist_add_head(node, &hashtable[hash_min(key, HASH_BITS(hashtable))])
+
+/**
+ * hash_add_rcu - add an object to a rcu enabled hashtable
+ * @hashtable: hashtable to add to
+ * @node: the &struct hlist_node of the object to be added
+ * @key: the key of the object to be added
+ */
+#define hash_add_rcu(hashtable, node, key)                                     \
+       hlist_add_head_rcu(node, &hashtable[hash_min(key, HASH_BITS(hashtable))])
+
+/**
+ * hash_hashed - check whether an object is in any hashtable
+ * @node: the &struct hlist_node of the object to be checked
+ */
+static inline bool hash_hashed(struct hlist_node *node)
+{
+       return !hlist_unhashed(node);
+}
+
+static inline bool __hash_empty(struct hlist_head *ht, unsigned int sz)
+{
+       unsigned int i;
+
+       for (i = 0; i < sz; i++)
+               if (!hlist_empty(&ht[i]))
+                       return false;
+
+       return true;
+}
+
+/**
+ * hash_empty - check whether a hashtable is empty
+ * @hashtable: hashtable to check
+ *
+ * This has to be a macro since HASH_BITS() will not work on pointers since
+ * it calculates the size during preprocessing.
+ */
+#define hash_empty(hashtable) __hash_empty(hashtable, HASH_SIZE(hashtable))
+
+/**
+ * hash_del - remove an object from a hashtable
+ * @node: &struct hlist_node of the object to remove
+ */
+static inline void hash_del(struct hlist_node *node)
+{
+       hlist_del_init(node);
+}
+
+/**
+ * hash_del_rcu - remove an object from a rcu enabled hashtable
+ * @node: &struct hlist_node of the object to remove
+ */
+static inline void hash_del_rcu(struct hlist_node *node)
+{
+       hlist_del_init_rcu(node);
+}
+
+/**
+ * hash_for_each - iterate over a hashtable
+ * @name: hashtable to iterate
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each(name, bkt, node, obj, member)                            \
+       for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
+               hlist_for_each_entry(obj, node, &name[bkt], member)
+
+/**
+ * hash_for_each_rcu - iterate over a rcu enabled hashtable
+ * @name: hashtable to iterate
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each_rcu(name, bkt, node, obj, member)                                \
+       for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
+               hlist_for_each_entry_rcu(obj, node, &name[bkt], member)
+
+/**
+ * hash_for_each_safe - iterate over a hashtable safe against removal of
+ * hash entry
+ * @name: hashtable to iterate
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @tmp: a &struct used for temporary storage
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each_safe(name, bkt, node, tmp, obj, member)                  \
+       for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
+               hlist_for_each_entry_safe(obj, node, tmp, &name[bkt], member)
+
+/**
+ * hash_for_each_possible - iterate over all possible objects hashing to the
+ * same bucket
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible(name, obj, node, member, key)                   \
+       hlist_for_each_entry(obj, node, &name[hash_min(key, HASH_BITS(name))], member)
+
+/**
+ * hash_for_each_possible_rcu - iterate over all possible objects hashing to the
+ * same bucket in an rcu enabled hashtable
+ * in a rcu enabled hashtable
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible_rcu(name, obj, node, member, key)               \
+       hlist_for_each_entry_rcu(obj, node, &name[hash_min(key, HASH_BITS(name))], member)
+
+/**
+ * hash_for_each_possible_safe - iterate over all possible objects hashing to the
+ * same bucket safe against removals
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @tmp: a &struct used for temporary storage
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible_safe(name, obj, node, tmp, member, key)         \
+       hlist_for_each_entry_safe(obj, node, tmp,                               \
+               &name[hash_min(key, HASH_BITS(name))], member)
+
+
+#endif
index c0ae76ac4e0b87e905d358e846bd8459f0f10023..7806c24e5bc8173a004597a1dd266f8e14900de6 100644 (file)
@@ -618,4 +618,20 @@ static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev)
 };
 #endif
 
+/**
+ * IIO_DEGREE_TO_RAD() - Convert degree to rad
+ * @deg: A value in degree
+ *
+ * Returns the given value converted from degree to rad
+ */
+#define IIO_DEGREE_TO_RAD(deg) (((deg) * 314159ULL + 9000000ULL) / 18000000ULL)
+
+/**
+ * IIO_G_TO_M_S_2() - Convert g to meter / second**2
+ * @g: A value in g
+ *
+ * Returns the given value converted from g to meter / second**2
+ */
+#define IIO_G_TO_M_S_2(g) ((g) * 980665ULL / 100000ULL)
+
 #endif /* _INDUSTRIAL_IO_H_ */
index 93bfc9f9815c7fa178ad70b555e7a2afb86b3f02..ecc554374e440a73df8aaf5b5787f86705e647b0 100644 (file)
  */
 #define KVM_MEMSLOT_INVALID    (1UL << 16)
 
-/*
- * If we support unaligned MMIO, at most one fragment will be split into two:
- */
-#ifdef KVM_UNALIGNED_MMIO
-#  define KVM_EXTRA_MMIO_FRAGMENTS 1
-#else
-#  define KVM_EXTRA_MMIO_FRAGMENTS 0
-#endif
-
-#define KVM_USER_MMIO_SIZE 8
-
-#define KVM_MAX_MMIO_FRAGMENTS \
-       (KVM_MMIO_SIZE / KVM_USER_MMIO_SIZE + KVM_EXTRA_MMIO_FRAGMENTS)
+/* Two fragments for cross MMIO pages. */
+#define KVM_MAX_MMIO_FRAGMENTS 2
 
 /*
  * For the normal pfn, the highest 12 bits should be zero,
index 569d67d4243ed99c4b896fac81442531b9d05cbc..d452ee191066456278080c92322e093986baa1fb 100644 (file)
@@ -57,6 +57,7 @@ int memblock_add(phys_addr_t base, phys_addr_t size);
 int memblock_remove(phys_addr_t base, phys_addr_t size);
 int memblock_free(phys_addr_t base, phys_addr_t size);
 int memblock_reserve(phys_addr_t base, phys_addr_t size);
+void memblock_trim_memory(phys_addr_t align);
 
 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
 void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
index 1d28ae90384ed42e9c43a63a01d3a63c91a9c812..fe03b2d35d4f39178a9227a5eeeeeb7355e19192 100644 (file)
 #ifndef __LINUX_MFD_MAX77693_H
 #define __LINUX_MFD_MAX77693_H
 
+struct max77693_reg_data {
+       u8 addr;
+       u8 data;
+};
+
+struct max77693_muic_platform_data {
+       struct max77693_reg_data *init_data;
+       int num_init_data;
+};
+
 struct max77693_platform_data {
        int wakeup;
+
+       /* muic data */
+       struct max77693_muic_platform_data *muic_data;
 };
 #endif /* __LINUX_MFD_MAX77693_H */
index fc87be4fdc2501a8106b18664102c793ccdb588b..8e21a094836d21566bec6f08c027ad5c765fa715 100644 (file)
@@ -176,6 +176,11 @@ struct wm8994_pdata {
         unsigned int lineout1fb:1;
         unsigned int lineout2fb:1;
 
+       /* Delay between detecting a jack and starting microphone
+        * detect (specified in ms)
+        */
+       int micdet_delay;
+
        /* IRQ for microphone detection if brought out directly as a
         * signal.
         */
index cf80f7e5277f14dcce2931232a808e592344e7aa..250a4acddb2b8975a6c8278a3c5b1d803f36b585 100644 (file)
@@ -12,34 +12,27 @@ struct percpu_rw_semaphore {
        struct mutex mtx;
 };
 
+#define light_mb()     barrier()
+#define heavy_mb()     synchronize_sched()
+
 static inline void percpu_down_read(struct percpu_rw_semaphore *p)
 {
-       rcu_read_lock();
+       rcu_read_lock_sched();
        if (unlikely(p->locked)) {
-               rcu_read_unlock();
+               rcu_read_unlock_sched();
                mutex_lock(&p->mtx);
                this_cpu_inc(*p->counters);
                mutex_unlock(&p->mtx);
                return;
        }
        this_cpu_inc(*p->counters);
-       rcu_read_unlock();
+       rcu_read_unlock_sched();
+       light_mb(); /* A, between read of p->locked and read of data, paired with D */
 }
 
 static inline void percpu_up_read(struct percpu_rw_semaphore *p)
 {
-       /*
-        * On X86, write operation in this_cpu_dec serves as a memory unlock
-        * barrier (i.e. memory accesses may be moved before the write, but
-        * no memory accesses are moved past the write).
-        * On other architectures this may not be the case, so we need smp_mb()
-        * there.
-        */
-#if defined(CONFIG_X86) && (!defined(CONFIG_X86_PPRO_FENCE) && !defined(CONFIG_X86_OOSTORE))
-       barrier();
-#else
-       smp_mb();
-#endif
+       light_mb(); /* B, between read of the data and write to p->counter, paired with C */
        this_cpu_dec(*p->counters);
 }
 
@@ -58,14 +51,15 @@ static inline void percpu_down_write(struct percpu_rw_semaphore *p)
 {
        mutex_lock(&p->mtx);
        p->locked = true;
-       synchronize_rcu();
+       synchronize_sched(); /* make sure that all readers exit the rcu_read_lock_sched region */
        while (__percpu_count(p->counters))
                msleep(1);
-       smp_rmb(); /* paired with smp_mb() in percpu_sem_up_read() */
+       heavy_mb(); /* C, between read of p->counter and write to data, paired with B */
 }
 
 static inline void percpu_up_write(struct percpu_rw_semaphore *p)
 {
+       heavy_mb(); /* D, between write to data and write to p->locked, paired with A */
        p->locked = false;
        mutex_unlock(&p->mtx);
 }
index 2e902359aee596f128dee568d06e0e0ab3149dfe..6bfb2faa0b1937555f5ca8fa937c7007bf5b3bc4 100644 (file)
@@ -803,12 +803,16 @@ static inline void perf_event_task_tick(void)                             { }
 do {                                                                   \
        static struct notifier_block fn##_nb __cpuinitdata =            \
                { .notifier_call = fn, .priority = CPU_PRI_PERF };      \
+       unsigned long cpu = smp_processor_id();                         \
+       unsigned long flags;                                            \
        fn(&fn##_nb, (unsigned long)CPU_UP_PREPARE,                     \
-               (void *)(unsigned long)smp_processor_id());             \
+               (void *)(unsigned long)cpu);                            \
+       local_irq_save(flags);                                          \
        fn(&fn##_nb, (unsigned long)CPU_STARTING,                       \
-               (void *)(unsigned long)smp_processor_id());             \
+               (void *)(unsigned long)cpu);                            \
+       local_irq_restore(flags);                                       \
        fn(&fn##_nb, (unsigned long)CPU_ONLINE,                         \
-               (void *)(unsigned long)smp_processor_id());             \
+               (void *)(unsigned long)cpu);                            \
        register_cpu_notifier(&fn##_nb);                                \
 } while (0)
 
index d0c5825876f8a2d1d124a3d51fac880951a63b2f..f3d6e4f20962e6761811758f6b32f6f09a441a21 100644 (file)
@@ -16,6 +16,8 @@
 #ifndef __DAVINCI_ASP_H
 #define __DAVINCI_ASP_H
 
+#include <linux/genalloc.h>
+
 struct snd_platform_data {
        u32 tx_dma_offset;
        u32 rx_dma_offset;
@@ -30,6 +32,7 @@ struct snd_platform_data {
        unsigned enable_channel_combine:1;
        unsigned sram_size_playback;
        unsigned sram_size_capture;
+       struct gen_pool *sram_pool;
 
        /*
         * If McBSP peripheral gets the clock from an external pin,
index 2415a64c5e51d937ba0fc7d20cf78011b1b77dd6..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,2 +0,0 @@
-header-y += md_p.h
-header-y += md_u.h
index fb1abb3367e9520a7e68cf738709e7510abe80f0..358c04bfbe2ad31c691ac07e87b5988395f2c2f3 100644 (file)
    (for example /usr/src/linux/COPYING); if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
 */
-
 #ifndef _MD_U_H
 #define _MD_U_H
 
-/*
- * Different major versions are not compatible.
- * Different minor versions are only downward compatible.
- * Different patchlevel versions are downward and upward compatible.
- */
-#define MD_MAJOR_VERSION                0
-#define MD_MINOR_VERSION                90
-/*
- * MD_PATCHLEVEL_VERSION indicates kernel functionality.
- * >=1 means different superblock formats are selectable using SET_ARRAY_INFO
- *     and major_version/minor_version accordingly
- * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT
- *     in the super status byte
- * >=3 means that bitmap superblock version 4 is supported, which uses
- *     little-ending representation rather than host-endian
- */
-#define MD_PATCHLEVEL_VERSION           3
-
-/* ioctls */
-
-/* status */
-#define RAID_VERSION           _IOR (MD_MAJOR, 0x10, mdu_version_t)
-#define GET_ARRAY_INFO         _IOR (MD_MAJOR, 0x11, mdu_array_info_t)
-#define GET_DISK_INFO          _IOR (MD_MAJOR, 0x12, mdu_disk_info_t)
-#define PRINT_RAID_DEBUG       _IO (MD_MAJOR, 0x13)
-#define RAID_AUTORUN           _IO (MD_MAJOR, 0x14)
-#define GET_BITMAP_FILE                _IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t)
-
-/* configuration */
-#define CLEAR_ARRAY            _IO (MD_MAJOR, 0x20)
-#define ADD_NEW_DISK           _IOW (MD_MAJOR, 0x21, mdu_disk_info_t)
-#define HOT_REMOVE_DISK                _IO (MD_MAJOR, 0x22)
-#define SET_ARRAY_INFO         _IOW (MD_MAJOR, 0x23, mdu_array_info_t)
-#define SET_DISK_INFO          _IO (MD_MAJOR, 0x24)
-#define WRITE_RAID_INFO                _IO (MD_MAJOR, 0x25)
-#define UNPROTECT_ARRAY                _IO (MD_MAJOR, 0x26)
-#define PROTECT_ARRAY          _IO (MD_MAJOR, 0x27)
-#define HOT_ADD_DISK           _IO (MD_MAJOR, 0x28)
-#define SET_DISK_FAULTY                _IO (MD_MAJOR, 0x29)
-#define HOT_GENERATE_ERROR     _IO (MD_MAJOR, 0x2a)
-#define SET_BITMAP_FILE                _IOW (MD_MAJOR, 0x2b, int)
+#include <uapi/linux/raid/md_u.h>
 
-/* usage */
-#define RUN_ARRAY              _IOW (MD_MAJOR, 0x30, mdu_param_t)
-/*  0x31 was START_ARRAY  */
-#define STOP_ARRAY             _IO (MD_MAJOR, 0x32)
-#define STOP_ARRAY_RO          _IO (MD_MAJOR, 0x33)
-#define RESTART_ARRAY_RW       _IO (MD_MAJOR, 0x34)
-
-/* 63 partitions with the alternate major number (mdp) */
-#define MdpMinorShift 6
-#ifdef __KERNEL__
 extern int mdp_major;
-#endif
-
-typedef struct mdu_version_s {
-       int major;
-       int minor;
-       int patchlevel;
-} mdu_version_t;
-
-typedef struct mdu_array_info_s {
-       /*
-        * Generic constant information
-        */
-       int major_version;
-       int minor_version;
-       int patch_version;
-       int ctime;
-       int level;
-       int size;
-       int nr_disks;
-       int raid_disks;
-       int md_minor;
-       int not_persistent;
-
-       /*
-        * Generic state information
-        */
-       int utime;              /*  0 Superblock update time                  */
-       int state;              /*  1 State bits (clean, ...)                 */
-       int active_disks;       /*  2 Number of currently active disks        */
-       int working_disks;      /*  3 Number of working disks                 */
-       int failed_disks;       /*  4 Number of failed disks                  */
-       int spare_disks;        /*  5 Number of spare disks                   */
-
-       /*
-        * Personality information
-        */
-       int layout;             /*  0 the array's physical layout             */
-       int chunk_size; /*  1 chunk size in bytes                     */
-
-} mdu_array_info_t;
-
-/* non-obvious values for 'level' */
-#define        LEVEL_MULTIPATH         (-4)
-#define        LEVEL_LINEAR            (-1)
-#define        LEVEL_FAULTY            (-5)
-
-/* we need a value for 'no level specified' and 0
- * means 'raid0', so we need something else.  This is
- * for internal use only
- */
-#define        LEVEL_NONE              (-1000000)
-
-typedef struct mdu_disk_info_s {
-       /*
-        * configuration/status of one particular disk
-        */
-       int number;
-       int major;
-       int minor;
-       int raid_disk;
-       int state;
-
-} mdu_disk_info_t;
-
-typedef struct mdu_start_info_s {
-       /*
-        * configuration/status of one particular disk
-        */
-       int major;
-       int minor;
-       int raid_disk;
-       int state;
-
-} mdu_start_info_t;
-
-typedef struct mdu_bitmap_file_s
-{
-       char pathname[4096];
-} mdu_bitmap_file_t;
-
-typedef struct mdu_param_s
-{
-       int                     personality;    /* 1,2,3,4 */
-       int                     chunk_size;     /* in bytes */
-       int                     max_fault;      /* unused for now */
-} mdu_param_t;
-
 #endif 
-
index 214caa33433b9a58d4635d1f3214b099c515c8e5..2ac60c9cf6448fac839074e752d61f2de7b56c0a 100644 (file)
@@ -24,6 +24,7 @@
 #ifndef _LINUX_RBTREE_AUGMENTED_H
 #define _LINUX_RBTREE_AUGMENTED_H
 
+#include <linux/compiler.h>
 #include <linux/rbtree.h>
 
 /*
index e3bcc3f4dcb8426c4e5e487016417e0e43113666..9f228d7f7ac48da7e8875a816a73b505686a586c 100644 (file)
@@ -133,7 +133,7 @@ struct regmap_config {
        enum regmap_endian val_format_endian;
 
        const struct regmap_range_cfg *ranges;
-       unsigned int n_ranges;
+       unsigned int num_ranges;
 };
 
 /**
@@ -142,6 +142,8 @@ struct regmap_config {
  *     1. page selector register update;
  *     2. access through data window registers.
  *
+ * @name: Descriptive name for diagnostics
+ *
  * @range_min: Address of the lowest register address in virtual range.
  * @range_max: Address of the highest register in virtual range.
  *
@@ -153,6 +155,8 @@ struct regmap_config {
  * @window_len: Number of registers in data window.
  */
 struct regmap_range_cfg {
+       const char *name;
+
        /* Registers of virtual address range */
        unsigned int range_min;
        unsigned int range_max;
index d9b0c84220c73897630f7cc7d35864c4eeeadb69..8f721e465e05b968ed1b5223c4b1e7eb61be78e2 100644 (file)
@@ -3,8 +3,6 @@
  *
  * Copyright (C) 2009-2010 Nokia Corporation
  *
- * Contact: Aaro Koskinen <aaro.koskinen@nokia.com>
- *
  * 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
index 8a7fc4be2d75f11d0ff774e727940dd16a2c64aa..60b7aac15e0e436b9b6451321d421a286fa9a40b 100644 (file)
@@ -191,7 +191,8 @@ struct tcp_sock {
        u8      do_early_retrans:1,/* Enable RFC5827 early-retransmit  */
                early_retrans_delayed:1, /* Delayed ER timer installed */
                syn_data:1,     /* SYN includes data */
-               syn_fastopen:1; /* SYN includes Fast Open option */
+               syn_fastopen:1, /* SYN includes Fast Open option */
+               syn_data_acked:1;/* data in SYN is acked by SYN-ACK */
 
 /* RTT measurement */
        u32     srtt;           /* smoothed round trip time << 3        */
index e6f0331e3d456281c87370e8c0275961c04ca084..24594571c5a3aa8a094d9cca3795420e32cb4ce0 100644 (file)
@@ -35,16 +35,6 @@ struct inode;
 # include <asm/uprobes.h>
 #endif
 
-/* flags that denote/change uprobes behaviour */
-
-/* Have a copy of original instruction */
-#define UPROBE_COPY_INSN       0x1
-
-/* Dont run handlers when first register/ last unregister in progress*/
-#define UPROBE_RUN_HANDLER     0x2
-/* Can skip singlestep */
-#define UPROBE_SKIP_SSTEP      0x4
-
 struct uprobe_consumer {
        int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs);
        /*
@@ -59,7 +49,6 @@ struct uprobe_consumer {
 #ifdef CONFIG_UPROBES
 enum uprobe_task_state {
        UTASK_RUNNING,
-       UTASK_BP_HIT,
        UTASK_SSTEP,
        UTASK_SSTEP_ACK,
        UTASK_SSTEP_TRAPPED,
index 1b49890822449df661d576219181b10c64d57a6c..7d5b6000378bbbdaf8a4fe7316ab93786429cf3a 100644 (file)
@@ -1218,6 +1218,7 @@ struct cfg80211_deauth_request {
        const u8 *ie;
        size_t ie_len;
        u16 reason_code;
+       bool local_state_change;
 };
 
 /**
@@ -2650,6 +2651,15 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);
  */
 unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc);
 
+/**
+ * ieee80211_get_mesh_hdrlen - get mesh extension header length
+ * @meshhdr: the mesh extension header, only the flags field
+ *     (first byte) will be accessed
+ * Returns the length of the extension header, which is always at
+ * least 6 bytes and at most 18 if address 5 and 6 are present.
+ */
+unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
+
 /**
  * DOC: Data path helpers
  *
index bc056687f647f7aa9965d5ec4b297bbe9459e557..93896ad1fcdd70164c4254bd792d9b10da992b68 100644 (file)
@@ -132,6 +132,7 @@ struct snd_card {
        int shutdown;                   /* this card is going down */
        int free_on_last_close;         /* free in context of file_release */
        wait_queue_head_t shutdown_sleep;
+       atomic_t refcount;              /* refcount for disconnection */
        struct device *dev;             /* device assigned to this card */
        struct device *card_dev;        /* cardX object for sysfs */
 
@@ -189,6 +190,7 @@ struct snd_minor {
        const struct file_operations *f_ops;    /* file operations */
        void *private_data;             /* private data for f_ops->open */
        struct device *dev;             /* device for sysfs */
+       struct snd_card *card_ptr;      /* assigned card instance */
 };
 
 /* return a device pointer linked to each sound device as a parent */
@@ -295,6 +297,7 @@ int snd_card_info_done(void);
 int snd_component_add(struct snd_card *card, const char *component);
 int snd_card_file_add(struct snd_card *card, struct file *file);
 int snd_card_file_remove(struct snd_card *card, struct file *file);
+void snd_card_unref(struct snd_card *card);
 
 #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr))
 
index 50a059e7d11616d4eb836cf7f0cc738cc0eaed3f..6d9e15ed1dcf0cb2875a10ca6795b14f3d4e0c51 100644 (file)
@@ -19,6 +19,7 @@
 
 struct cs4271_platform_data {
        int gpio_nreset;        /* GPIO driving Reset pin, if any */
+       int amutec_eq_bmutec:1; /* flag to enable AMUTEC=BMUTEC */
 };
 
 #endif /* __CS4271_H */
index 906010344dd7e0a227449f674d64b00a07dc1e86..27ee1dcc3e2e4f5111c14d40fd89f09f8810a40f 100644 (file)
@@ -26,6 +26,7 @@
  * A:  inversion
  * B:  format mode
  * C:  chip specific
+ * D:  clock selecter if master mode
  */
 
 /* A: clock inversion */
 #define SH_FSI_OPTION_MASK     0x00000F00
 #define SH_FSI_ENABLE_STREAM_MODE      (1 << 8) /* for 16bit data */
 
+/* D:  clock selecter if master mode */
+#define SH_FSI_CLK_MASK                0x0000F000
+#define SH_FSI_CLK_EXTERNAL    (1 << 12)
+#define SH_FSI_CLK_CPG         (2 << 12) /* FSIxCK + FSI-DIV */
+
 /*
  * set_rate return value
  *
index c009f70b40293a70fa4b54afeb8fb4b879cac449..24e5d991f148be2d8b16cc309e1af7dca5f5f14b 100644 (file)
@@ -26,6 +26,7 @@ struct aic32x4_pdata {
        u32 power_cfg;
        u32 micpga_routing;
        bool swapdacs;
+       int rstn_gpio;
 };
 
 #endif
index 15ba03bdd7c69e9b4426aa3396ac772512b3e163..d06b6da5c1e3e146d500bae9b012b809d831cb25 100644 (file)
@@ -377,6 +377,14 @@ DECLARE_EVENT_CLASS(xen_mmu_pgd,
 DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin);
 DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin);
 
+TRACE_EVENT(xen_mmu_flush_tlb_all,
+           TP_PROTO(int x),
+           TP_ARGS(x),
+           TP_STRUCT__entry(__array(char, x, 0)),
+           TP_fast_assign((void)x),
+           TP_printk("%s", "")
+       );
+
 TRACE_EVENT(xen_mmu_flush_tlb,
            TP_PROTO(int x),
            TP_ARGS(x),
index aafaa5aa54d46bb9a93a8137a22344408298223f..e2c3d25405d7e20de2dc708088b0399350bd861f 100644 (file)
@@ -1 +1,3 @@
 # UAPI Header export list
+header-y += md_p.h
+header-y += md_u.h
diff --git a/include/uapi/linux/raid/md_u.h b/include/uapi/linux/raid/md_u.h
new file mode 100644 (file)
index 0000000..4133e74
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+   md_u.h : user <=> kernel API between Linux raidtools and RAID drivers
+          Copyright (C) 1998 Ingo Molnar
+         
+   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, or (at your option)
+   any later version.
+   
+   You should have received a copy of the GNU General Public License
+   (for example /usr/src/linux/COPYING); if not, write to the Free
+   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+*/
+
+#ifndef _UAPI_MD_U_H
+#define _UAPI_MD_U_H
+
+/*
+ * Different major versions are not compatible.
+ * Different minor versions are only downward compatible.
+ * Different patchlevel versions are downward and upward compatible.
+ */
+#define MD_MAJOR_VERSION                0
+#define MD_MINOR_VERSION                90
+/*
+ * MD_PATCHLEVEL_VERSION indicates kernel functionality.
+ * >=1 means different superblock formats are selectable using SET_ARRAY_INFO
+ *     and major_version/minor_version accordingly
+ * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT
+ *     in the super status byte
+ * >=3 means that bitmap superblock version 4 is supported, which uses
+ *     little-ending representation rather than host-endian
+ */
+#define MD_PATCHLEVEL_VERSION           3
+
+/* ioctls */
+
+/* status */
+#define RAID_VERSION           _IOR (MD_MAJOR, 0x10, mdu_version_t)
+#define GET_ARRAY_INFO         _IOR (MD_MAJOR, 0x11, mdu_array_info_t)
+#define GET_DISK_INFO          _IOR (MD_MAJOR, 0x12, mdu_disk_info_t)
+#define PRINT_RAID_DEBUG       _IO (MD_MAJOR, 0x13)
+#define RAID_AUTORUN           _IO (MD_MAJOR, 0x14)
+#define GET_BITMAP_FILE                _IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t)
+
+/* configuration */
+#define CLEAR_ARRAY            _IO (MD_MAJOR, 0x20)
+#define ADD_NEW_DISK           _IOW (MD_MAJOR, 0x21, mdu_disk_info_t)
+#define HOT_REMOVE_DISK                _IO (MD_MAJOR, 0x22)
+#define SET_ARRAY_INFO         _IOW (MD_MAJOR, 0x23, mdu_array_info_t)
+#define SET_DISK_INFO          _IO (MD_MAJOR, 0x24)
+#define WRITE_RAID_INFO                _IO (MD_MAJOR, 0x25)
+#define UNPROTECT_ARRAY                _IO (MD_MAJOR, 0x26)
+#define PROTECT_ARRAY          _IO (MD_MAJOR, 0x27)
+#define HOT_ADD_DISK           _IO (MD_MAJOR, 0x28)
+#define SET_DISK_FAULTY                _IO (MD_MAJOR, 0x29)
+#define HOT_GENERATE_ERROR     _IO (MD_MAJOR, 0x2a)
+#define SET_BITMAP_FILE                _IOW (MD_MAJOR, 0x2b, int)
+
+/* usage */
+#define RUN_ARRAY              _IOW (MD_MAJOR, 0x30, mdu_param_t)
+/*  0x31 was START_ARRAY  */
+#define STOP_ARRAY             _IO (MD_MAJOR, 0x32)
+#define STOP_ARRAY_RO          _IO (MD_MAJOR, 0x33)
+#define RESTART_ARRAY_RW       _IO (MD_MAJOR, 0x34)
+
+/* 63 partitions with the alternate major number (mdp) */
+#define MdpMinorShift 6
+
+typedef struct mdu_version_s {
+       int major;
+       int minor;
+       int patchlevel;
+} mdu_version_t;
+
+typedef struct mdu_array_info_s {
+       /*
+        * Generic constant information
+        */
+       int major_version;
+       int minor_version;
+       int patch_version;
+       int ctime;
+       int level;
+       int size;
+       int nr_disks;
+       int raid_disks;
+       int md_minor;
+       int not_persistent;
+
+       /*
+        * Generic state information
+        */
+       int utime;              /*  0 Superblock update time                  */
+       int state;              /*  1 State bits (clean, ...)                 */
+       int active_disks;       /*  2 Number of currently active disks        */
+       int working_disks;      /*  3 Number of working disks                 */
+       int failed_disks;       /*  4 Number of failed disks                  */
+       int spare_disks;        /*  5 Number of spare disks                   */
+
+       /*
+        * Personality information
+        */
+       int layout;             /*  0 the array's physical layout             */
+       int chunk_size; /*  1 chunk size in bytes                     */
+
+} mdu_array_info_t;
+
+/* non-obvious values for 'level' */
+#define        LEVEL_MULTIPATH         (-4)
+#define        LEVEL_LINEAR            (-1)
+#define        LEVEL_FAULTY            (-5)
+
+/* we need a value for 'no level specified' and 0
+ * means 'raid0', so we need something else.  This is
+ * for internal use only
+ */
+#define        LEVEL_NONE              (-1000000)
+
+typedef struct mdu_disk_info_s {
+       /*
+        * configuration/status of one particular disk
+        */
+       int number;
+       int major;
+       int minor;
+       int raid_disk;
+       int state;
+
+} mdu_disk_info_t;
+
+typedef struct mdu_start_info_s {
+       /*
+        * configuration/status of one particular disk
+        */
+       int major;
+       int minor;
+       int raid_disk;
+       int state;
+
+} mdu_start_info_t;
+
+typedef struct mdu_bitmap_file_s
+{
+       char pathname[4096];
+} mdu_bitmap_file_t;
+
+typedef struct mdu_param_s
+{
+       int                     personality;    /* 1,2,3,4 */
+       int                     chunk_size;     /* in bytes */
+       int                     max_fault;      /* unused for now */
+} mdu_param_t;
+
+#endif /* _UAPI_MD_U_H */
index c4b89a5cb7df4ffa3f93a0206e1f03bf19829d31..e962faa5ab0dcf9d58909b0256a78f51029e290b 100644 (file)
@@ -130,6 +130,7 @@ enum {
 #define TCPI_OPT_WSCALE                4
 #define TCPI_OPT_ECN           8 /* ECN was negociated at TCP session init */
 #define TCPI_OPT_ECN_SEEN      16 /* we received at least one packet with ECT */
+#define TCPI_OPT_SYN_DATA      32 /* SYN-ACK acked data in SYN sent or rcvd */
 
 enum tcp_ca_state {
        TCP_CA_Open = 0,
index aecee9d112cbe6aea2532652c8c3f768bb829cce..694dcaf266e635335dfdaf22994624d3d5e3d9d4 100644 (file)
@@ -170,7 +170,7 @@ gnttab_set_unmap_op(struct gnttab_unmap_grant_ref *unmap, phys_addr_t addr,
        unmap->dev_bus_addr = 0;
 }
 
-int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
+int arch_gnttab_map_shared(xen_pfn_t *frames, unsigned long nr_gframes,
                           unsigned long max_nr_gframes,
                           void **__shared);
 int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes,
index f9f8b975ae7448bfdae47100ad7da63a34fbe39b..e40fae9bf11acd67b64ece81bae1d04efefc44fd 100644 (file)
@@ -310,7 +310,7 @@ struct gnttab_setup_table {
     uint32_t nr_frames;
     /* OUT parameters. */
     int16_t  status;              /* GNTST_* */
-    GUEST_HANDLE(ulong) frame_list;
+    GUEST_HANDLE(xen_pfn_t) frame_list;
 };
 DEFINE_GUEST_HANDLE_STRUCT(gnttab_setup_table);
 
index b66d04ce6957549a1097c532bc483e5ee6ab38d8..90712e2072d57ba6c6154549352266d253ab3615 100644 (file)
@@ -179,28 +179,8 @@ struct xen_add_to_physmap {
 };
 DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap);
 
-/*
- * Translates a list of domain-specific GPFNs into MFNs. Returns a -ve error
- * code on failure. This call only works for auto-translated guests.
- */
-#define XENMEM_translate_gpfn_list  8
-struct xen_translate_gpfn_list {
-    /* Which domain to translate for? */
-    domid_t domid;
-
-    /* Length of list. */
-    xen_ulong_t nr_gpfns;
-
-    /* List of GPFNs to translate. */
-    GUEST_HANDLE(ulong) gpfn_list;
-
-    /*
-     * Output list to contain MFN translations. May be the same as the input
-     * list (in which case each input GPFN is overwritten with the output MFN).
-     */
-    GUEST_HANDLE(ulong) mfn_list;
-};
-DEFINE_GUEST_HANDLE_STRUCT(xen_translate_gpfn_list);
+/*** REMOVED ***/
+/*#define XENMEM_translate_gpfn_list  8*/
 
 /*
  * Returns the pseudo-physical memory map as it was when the domain
index 9cf77ab138a68738bb6926b8b31aaf6ba8cd4f6e..e33e09df3cbc61ad11736776ef4138010df1de8e 100644 (file)
@@ -442,9 +442,11 @@ void __init __weak smp_setup_processor_id(void)
 {
 }
 
+# if THREAD_SIZE >= PAGE_SIZE
 void __init __weak thread_info_cache_init(void)
 {
 }
+#endif
 
 /*
  * Set up kernel memory allocators
index 0dfeca4324ee06dbb6566db568b9874758344232..86e3285ae7e5b48fd9b123291da2d8dbfe0d7460 100644 (file)
@@ -174,10 +174,8 @@ signing_key.priv signing_key.x509: x509.genkey
        @echo "###"
        @echo "### If this takes a long time, you might wish to run rngd in the"
        @echo "### background to keep the supply of entropy topped up.  It"
-       @echo "### needs to be run as root, and should use a hardware random"
-       @echo "### number generator if one is available, eg:"
-       @echo "###"
-       @echo "###     rngd -r /dev/hwrandom"
+       @echo "### needs to be run as root, and uses a hardware random"
+       @echo "### number generator if one is available."
        @echo "###"
        openssl req -new -nodes -utf8 $(sign_key_with_hash) -days 36500 -batch \
                -x509 -config x509.genkey \
index 13774b3b39aac9b73e25ba34a366d5402b70df00..f24f724620dd8489fc2e3cb9781433df84096c96 100644 (file)
@@ -1962,9 +1962,8 @@ static void cgroup_task_migrate(struct cgroup *cgrp, struct cgroup *oldcgrp,
         * trading it for newcg is protected by cgroup_mutex, we're safe to drop
         * it here; it will be freed under RCU.
         */
-       put_css_set(oldcg);
-
        set_bit(CGRP_RELEASABLE, &oldcgrp->flags);
+       put_css_set(oldcg);
 }
 
 /**
@@ -4815,31 +4814,20 @@ static const struct file_operations proc_cgroupstats_operations = {
  *
  * A pointer to the shared css_set was automatically copied in
  * fork.c by dup_task_struct().  However, we ignore that copy, since
- * it was not made under the protection of RCU, cgroup_mutex or
- * threadgroup_change_begin(), so it might no longer be a valid
- * cgroup pointer.  cgroup_attach_task() might have already changed
- * current->cgroups, allowing the previously referenced cgroup
- * group to be removed and freed.
- *
- * Outside the pointer validity we also need to process the css_set
- * inheritance between threadgoup_change_begin() and
- * threadgoup_change_end(), this way there is no leak in any process
- * wide migration performed by cgroup_attach_proc() that could otherwise
- * miss a thread because it is too early or too late in the fork stage.
+ * it was not made under the protection of RCU or cgroup_mutex, so
+ * might no longer be a valid cgroup pointer.  cgroup_attach_task() might
+ * have already changed current->cgroups, allowing the previously
+ * referenced cgroup group to be removed and freed.
  *
  * At the point that cgroup_fork() is called, 'current' is the parent
  * task, and the passed argument 'child' points to the child task.
  */
 void cgroup_fork(struct task_struct *child)
 {
-       /*
-        * We don't need to task_lock() current because current->cgroups
-        * can't be changed concurrently here. The parent obviously hasn't
-        * exited and called cgroup_exit(), and we are synchronized against
-        * cgroup migration through threadgroup_change_begin().
-        */
+       task_lock(current);
        child->cgroups = current->cgroups;
        get_css_set(child->cgroups);
+       task_unlock(current);
        INIT_LIST_HEAD(&child->cg_list);
 }
 
@@ -4895,19 +4883,10 @@ void cgroup_post_fork(struct task_struct *child)
         */
        if (use_task_css_set_links) {
                write_lock(&css_set_lock);
-               if (list_empty(&child->cg_list)) {
-                       /*
-                        * It's safe to use child->cgroups without task_lock()
-                        * here because we are protected through
-                        * threadgroup_change_begin() against concurrent
-                        * css_set change in cgroup_task_migrate(). Also
-                        * the task can't exit at that point until
-                        * wake_up_new_task() is called, so we are protected
-                        * against cgroup_exit() setting child->cgroup to
-                        * init_css_set.
-                        */
+               task_lock(child);
+               if (list_empty(&child->cg_list))
                        list_add(&child->cg_list, &child->cgroups->tasks);
-               }
+               task_unlock(child);
                write_unlock(&css_set_lock);
        }
 }
index 98256bc71ee136915b126b81dd1e61b8990a8ce3..5cc4e7e42e689a7076ece7eb252f5a1f3a1eb5b6 100644 (file)
@@ -78,15 +78,23 @@ static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ];
  */
 static atomic_t uprobe_events = ATOMIC_INIT(0);
 
+/* Have a copy of original instruction */
+#define UPROBE_COPY_INSN       0
+/* Dont run handlers when first register/ last unregister in progress*/
+#define UPROBE_RUN_HANDLER     1
+/* Can skip singlestep */
+#define UPROBE_SKIP_SSTEP      2
+
 struct uprobe {
        struct rb_node          rb_node;        /* node in the rb tree */
        atomic_t                ref;
        struct rw_semaphore     consumer_rwsem;
+       struct mutex            copy_mutex;     /* TODO: kill me and UPROBE_COPY_INSN */
        struct list_head        pending_list;
        struct uprobe_consumer  *consumers;
        struct inode            *inode;         /* Also hold a ref to inode */
        loff_t                  offset;
-       int                     flags;
+       unsigned long           flags;
        struct arch_uprobe      arch;
 };
 
@@ -100,17 +108,12 @@ struct uprobe {
  */
 static bool valid_vma(struct vm_area_struct *vma, bool is_register)
 {
-       if (!vma->vm_file)
-               return false;
-
-       if (!is_register)
-               return true;
+       vm_flags_t flags = VM_HUGETLB | VM_MAYEXEC | VM_SHARED;
 
-       if ((vma->vm_flags & (VM_HUGETLB|VM_READ|VM_WRITE|VM_EXEC|VM_SHARED))
-                               == (VM_READ|VM_EXEC))
-               return true;
+       if (is_register)
+               flags |= VM_WRITE;
 
-       return false;
+       return vma->vm_file && (vma->vm_flags & flags) == VM_MAYEXEC;
 }
 
 static unsigned long offset_to_vaddr(struct vm_area_struct *vma, loff_t offset)
@@ -193,19 +196,44 @@ bool __weak is_swbp_insn(uprobe_opcode_t *insn)
        return *insn == UPROBE_SWBP_INSN;
 }
 
+static void copy_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *opcode)
+{
+       void *kaddr = kmap_atomic(page);
+       memcpy(opcode, kaddr + (vaddr & ~PAGE_MASK), UPROBE_SWBP_INSN_SIZE);
+       kunmap_atomic(kaddr);
+}
+
+static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *new_opcode)
+{
+       uprobe_opcode_t old_opcode;
+       bool is_swbp;
+
+       copy_opcode(page, vaddr, &old_opcode);
+       is_swbp = is_swbp_insn(&old_opcode);
+
+       if (is_swbp_insn(new_opcode)) {
+               if (is_swbp)            /* register: already installed? */
+                       return 0;
+       } else {
+               if (!is_swbp)           /* unregister: was it changed by us? */
+                       return 0;
+       }
+
+       return 1;
+}
+
 /*
  * NOTE:
  * Expect the breakpoint instruction to be the smallest size instruction for
  * the architecture. If an arch has variable length instruction and the
  * breakpoint instruction is not of the smallest length instruction
- * supported by that architecture then we need to modify read_opcode /
+ * supported by that architecture then we need to modify is_swbp_at_addr and
  * write_opcode accordingly. This would never be a problem for archs that
  * have fixed length instructions.
  */
 
 /*
  * write_opcode - write the opcode at a given virtual address.
- * @auprobe: arch breakpointing information.
  * @mm: the probed process address space.
  * @vaddr: the virtual address to store the opcode.
  * @opcode: opcode to be written at @vaddr.
@@ -216,8 +244,8 @@ bool __weak is_swbp_insn(uprobe_opcode_t *insn)
  * For mm @mm, write the opcode at @vaddr.
  * Return 0 (success) or a negative errno.
  */
-static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
-                       unsigned long vaddr, uprobe_opcode_t opcode)
+static int write_opcode(struct mm_struct *mm, unsigned long vaddr,
+                       uprobe_opcode_t opcode)
 {
        struct page *old_page, *new_page;
        void *vaddr_old, *vaddr_new;
@@ -226,10 +254,14 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
 
 retry:
        /* Read the page with vaddr into memory */
-       ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &old_page, &vma);
+       ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &old_page, &vma);
        if (ret <= 0)
                return ret;
 
+       ret = verify_opcode(old_page, vaddr, &opcode);
+       if (ret <= 0)
+               goto put_old;
+
        ret = -ENOMEM;
        new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr);
        if (!new_page)
@@ -263,63 +295,6 @@ put_old:
        return ret;
 }
 
-/**
- * read_opcode - read the opcode at a given virtual address.
- * @mm: the probed process address space.
- * @vaddr: the virtual address to read the opcode.
- * @opcode: location to store the read opcode.
- *
- * Called with mm->mmap_sem held (for read and with a reference to
- * mm.
- *
- * For mm @mm, read the opcode at @vaddr and store it in @opcode.
- * Return 0 (success) or a negative errno.
- */
-static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t *opcode)
-{
-       struct page *page;
-       void *vaddr_new;
-       int ret;
-
-       ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
-       if (ret <= 0)
-               return ret;
-
-       vaddr_new = kmap_atomic(page);
-       vaddr &= ~PAGE_MASK;
-       memcpy(opcode, vaddr_new + vaddr, UPROBE_SWBP_INSN_SIZE);
-       kunmap_atomic(vaddr_new);
-
-       put_page(page);
-
-       return 0;
-}
-
-static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
-{
-       uprobe_opcode_t opcode;
-       int result;
-
-       if (current->mm == mm) {
-               pagefault_disable();
-               result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr,
-                                                               sizeof(opcode));
-               pagefault_enable();
-
-               if (likely(result == 0))
-                       goto out;
-       }
-
-       result = read_opcode(mm, vaddr, &opcode);
-       if (result)
-               return result;
-out:
-       if (is_swbp_insn(&opcode))
-               return 1;
-
-       return 0;
-}
-
 /**
  * set_swbp - store breakpoint at a given address.
  * @auprobe: arch specific probepoint information.
@@ -331,18 +306,7 @@ out:
  */
 int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
 {
-       int result;
-       /*
-        * See the comment near uprobes_hash().
-        */
-       result = is_swbp_at_addr(mm, vaddr);
-       if (result == 1)
-               return 0;
-
-       if (result)
-               return result;
-
-       return write_opcode(auprobe, mm, vaddr, UPROBE_SWBP_INSN);
+       return write_opcode(mm, vaddr, UPROBE_SWBP_INSN);
 }
 
 /**
@@ -357,16 +321,7 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned
 int __weak
 set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
 {
-       int result;
-
-       result = is_swbp_at_addr(mm, vaddr);
-       if (!result)
-               return -EINVAL;
-
-       if (result != 1)
-               return result;
-
-       return write_opcode(auprobe, mm, vaddr, *(uprobe_opcode_t *)auprobe->insn);
+       return write_opcode(mm, vaddr, *(uprobe_opcode_t *)auprobe->insn);
 }
 
 static int match_uprobe(struct uprobe *l, struct uprobe *r)
@@ -473,7 +428,7 @@ static struct uprobe *insert_uprobe(struct uprobe *uprobe)
        spin_unlock(&uprobes_treelock);
 
        /* For now assume that the instruction need not be single-stepped */
-       uprobe->flags |= UPROBE_SKIP_SSTEP;
+       __set_bit(UPROBE_SKIP_SSTEP, &uprobe->flags);
 
        return u;
 }
@@ -495,6 +450,7 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset)
        uprobe->inode = igrab(inode);
        uprobe->offset = offset;
        init_rwsem(&uprobe->consumer_rwsem);
+       mutex_init(&uprobe->copy_mutex);
 
        /* add to uprobes_tree, sorted on inode:offset */
        cur_uprobe = insert_uprobe(uprobe);
@@ -515,7 +471,7 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
 {
        struct uprobe_consumer *uc;
 
-       if (!(uprobe->flags & UPROBE_RUN_HANDLER))
+       if (!test_bit(UPROBE_RUN_HANDLER, &uprobe->flags))
                return;
 
        down_read(&uprobe->consumer_rwsem);
@@ -621,29 +577,43 @@ static int copy_insn(struct uprobe *uprobe, struct file *filp)
        return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset);
 }
 
-/*
- * How mm->uprobes_state.count gets updated
- * uprobe_mmap() increments the count if
- *     - it successfully adds a breakpoint.
- *     - it cannot add a breakpoint, but sees that there is a underlying
- *       breakpoint (via a is_swbp_at_addr()).
- *
- * uprobe_munmap() decrements the count if
- *     - it sees a underlying breakpoint, (via is_swbp_at_addr)
- *       (Subsequent uprobe_unregister wouldnt find the breakpoint
- *       unless a uprobe_mmap kicks in, since the old vma would be
- *       dropped just after uprobe_munmap.)
- *
- * uprobe_register increments the count if:
- *     - it successfully adds a breakpoint.
- *
- * uprobe_unregister decrements the count if:
- *     - it sees a underlying breakpoint and removes successfully.
- *       (via is_swbp_at_addr)
- *       (Subsequent uprobe_munmap wouldnt find the breakpoint
- *       since there is no underlying breakpoint after the
- *       breakpoint removal.)
- */
+static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
+                               struct mm_struct *mm, unsigned long vaddr)
+{
+       int ret = 0;
+
+       if (test_bit(UPROBE_COPY_INSN, &uprobe->flags))
+               return ret;
+
+       mutex_lock(&uprobe->copy_mutex);
+       if (test_bit(UPROBE_COPY_INSN, &uprobe->flags))
+               goto out;
+
+       ret = copy_insn(uprobe, file);
+       if (ret)
+               goto out;
+
+       ret = -ENOTSUPP;
+       if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn))
+               goto out;
+
+       ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr);
+       if (ret)
+               goto out;
+
+       /* write_opcode() assumes we don't cross page boundary */
+       BUG_ON((uprobe->offset & ~PAGE_MASK) +
+                       UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
+
+       smp_wmb(); /* pairs with rmb() in find_active_uprobe() */
+       set_bit(UPROBE_COPY_INSN, &uprobe->flags);
+
+ out:
+       mutex_unlock(&uprobe->copy_mutex);
+
+       return ret;
+}
+
 static int
 install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
                        struct vm_area_struct *vma, unsigned long vaddr)
@@ -661,24 +631,9 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
        if (!uprobe->consumers)
                return 0;
 
-       if (!(uprobe->flags & UPROBE_COPY_INSN)) {
-               ret = copy_insn(uprobe, vma->vm_file);
-               if (ret)
-                       return ret;
-
-               if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn))
-                       return -ENOTSUPP;
-
-               ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr);
-               if (ret)
-                       return ret;
-
-               /* write_opcode() assumes we don't cross page boundary */
-               BUG_ON((uprobe->offset & ~PAGE_MASK) +
-                               UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
-
-               uprobe->flags |= UPROBE_COPY_INSN;
-       }
+       ret = prepare_uprobe(uprobe, vma->vm_file, mm, vaddr);
+       if (ret)
+               return ret;
 
        /*
         * set MMF_HAS_UPROBES in advance for uprobe_pre_sstep_notifier(),
@@ -697,15 +652,15 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
        return ret;
 }
 
-static void
+static int
 remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr)
 {
        /* can happen if uprobe_register() fails */
        if (!test_bit(MMF_HAS_UPROBES, &mm->flags))
-               return;
+               return 0;
 
        set_bit(MMF_RECALC_UPROBES, &mm->flags);
-       set_orig_insn(&uprobe->arch, mm, vaddr);
+       return set_orig_insn(&uprobe->arch, mm, vaddr);
 }
 
 /*
@@ -820,7 +775,7 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
                struct mm_struct *mm = info->mm;
                struct vm_area_struct *vma;
 
-               if (err)
+               if (err && is_register)
                        goto free;
 
                down_write(&mm->mmap_sem);
@@ -836,7 +791,7 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
                if (is_register)
                        err = install_breakpoint(uprobe, mm, vma, info->vaddr);
                else
-                       remove_breakpoint(uprobe, mm, info->vaddr);
+                       err |= remove_breakpoint(uprobe, mm, info->vaddr);
 
  unlock:
                up_write(&mm->mmap_sem);
@@ -893,13 +848,15 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *
        mutex_lock(uprobes_hash(inode));
        uprobe = alloc_uprobe(inode, offset);
 
-       if (uprobe && !consumer_add(uprobe, uc)) {
+       if (!uprobe) {
+               ret = -ENOMEM;
+       } else if (!consumer_add(uprobe, uc)) {
                ret = __uprobe_register(uprobe);
                if (ret) {
                        uprobe->consumers = NULL;
                        __uprobe_unregister(uprobe);
                } else {
-                       uprobe->flags |= UPROBE_RUN_HANDLER;
+                       set_bit(UPROBE_RUN_HANDLER, &uprobe->flags);
                }
        }
 
@@ -932,7 +889,7 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume
        if (consumer_del(uprobe, uc)) {
                if (!uprobe->consumers) {
                        __uprobe_unregister(uprobe);
-                       uprobe->flags &= ~UPROBE_RUN_HANDLER;
+                       clear_bit(UPROBE_RUN_HANDLER, &uprobe->flags);
                }
        }
 
@@ -1393,10 +1350,11 @@ bool uprobe_deny_signal(void)
  */
 static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs)
 {
-       if (arch_uprobe_skip_sstep(&uprobe->arch, regs))
-               return true;
-
-       uprobe->flags &= ~UPROBE_SKIP_SSTEP;
+       if (test_bit(UPROBE_SKIP_SSTEP, &uprobe->flags)) {
+               if (arch_uprobe_skip_sstep(&uprobe->arch, regs))
+                       return true;
+               clear_bit(UPROBE_SKIP_SSTEP, &uprobe->flags);
+       }
        return false;
 }
 
@@ -1419,6 +1377,30 @@ static void mmf_recalc_uprobes(struct mm_struct *mm)
        clear_bit(MMF_HAS_UPROBES, &mm->flags);
 }
 
+static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
+{
+       struct page *page;
+       uprobe_opcode_t opcode;
+       int result;
+
+       pagefault_disable();
+       result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr,
+                                                       sizeof(opcode));
+       pagefault_enable();
+
+       if (likely(result == 0))
+               goto out;
+
+       result = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
+       if (result < 0)
+               return result;
+
+       copy_opcode(page, vaddr, &opcode);
+       put_page(page);
+ out:
+       return is_swbp_insn(&opcode);
+}
+
 static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
 {
        struct mm_struct *mm = current->mm;
@@ -1489,38 +1471,41 @@ static void handle_swbp(struct pt_regs *regs)
                }
                return;
        }
+       /*
+        * TODO: move copy_insn/etc into _register and remove this hack.
+        * After we hit the bp, _unregister + _register can install the
+        * new and not-yet-analyzed uprobe at the same address, restart.
+        */
+       smp_rmb(); /* pairs with wmb() in install_breakpoint() */
+       if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags)))
+               goto restart;
 
        utask = current->utask;
        if (!utask) {
                utask = add_utask();
                /* Cannot allocate; re-execute the instruction. */
                if (!utask)
-                       goto cleanup_ret;
+                       goto restart;
        }
-       utask->active_uprobe = uprobe;
+
        handler_chain(uprobe, regs);
-       if (uprobe->flags & UPROBE_SKIP_SSTEP && can_skip_sstep(uprobe, regs))
-               goto cleanup_ret;
+       if (can_skip_sstep(uprobe, regs))
+               goto out;
 
-       utask->state = UTASK_SSTEP;
        if (!pre_ssout(uprobe, regs, bp_vaddr)) {
                arch_uprobe_enable_step(&uprobe->arch);
+               utask->active_uprobe = uprobe;
+               utask->state = UTASK_SSTEP;
                return;
        }
 
-cleanup_ret:
-       if (utask) {
-               utask->active_uprobe = NULL;
-               utask->state = UTASK_RUNNING;
-       }
-       if (!(uprobe->flags & UPROBE_SKIP_SSTEP))
-
-               /*
-                * cannot singlestep; cannot skip instruction;
-                * re-execute the instruction.
-                */
-               instruction_pointer_set(regs, bp_vaddr);
-
+restart:
+       /*
+        * cannot singlestep; cannot skip instruction;
+        * re-execute the instruction.
+        */
+       instruction_pointer_set(regs, bp_vaddr);
+out:
        put_uprobe(uprobe);
 }
 
@@ -1552,13 +1537,12 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs)
 }
 
 /*
- * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag.  (and on
- * subsequent probe hits on the thread sets the state to UTASK_BP_HIT) and
- * allows the thread to return from interrupt.
+ * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag and
+ * allows the thread to return from interrupt. After that handle_swbp()
+ * sets utask->active_uprobe.
  *
- * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag and
- * also sets the state to UTASK_SSTEP_ACK and allows the thread to return from
- * interrupt.
+ * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag
+ * and allows the thread to return from interrupt.
  *
  * While returning to userspace, thread notices the TIF_UPROBE flag and calls
  * uprobe_notify_resume().
@@ -1567,11 +1551,13 @@ void uprobe_notify_resume(struct pt_regs *regs)
 {
        struct uprobe_task *utask;
 
+       clear_thread_flag(TIF_UPROBE);
+
        utask = current->utask;
-       if (!utask || utask->state == UTASK_BP_HIT)
-               handle_swbp(regs);
-       else
+       if (utask && utask->active_uprobe)
                handle_singlestep(utask, regs);
+       else
+               handle_swbp(regs);
 }
 
 /*
@@ -1580,17 +1566,10 @@ void uprobe_notify_resume(struct pt_regs *regs)
  */
 int uprobe_pre_sstep_notifier(struct pt_regs *regs)
 {
-       struct uprobe_task *utask;
-
        if (!current->mm || !test_bit(MMF_HAS_UPROBES, &current->mm->flags))
                return 0;
 
-       utask = current->utask;
-       if (utask)
-               utask->state = UTASK_BP_HIT;
-
        set_thread_flag(TIF_UPROBE);
-
        return 1;
 }
 
index d492a23df99c8a4fa99527b89c1223941229cb41..ea1b1df5dbb0077a167caaf8e013b8baf765e902 100644 (file)
@@ -192,7 +192,7 @@ int mod_verify_sig(const void *mod, unsigned long *_modlen)
        size_t modlen = *_modlen, sig_len;
        int ret;
 
-       pr_devel("==>%s(,%lu)\n", __func__, modlen);
+       pr_devel("==>%s(,%zu)\n", __func__, modlen);
 
        if (modlen <= sizeof(ms))
                return -EBADMSG;
index eb00be205811959c708fe2bf5e3aee0547dcfa36..7b07cc0dfb75fb6b2f2f802178abf82565d9c1a4 100644 (file)
@@ -71,12 +71,22 @@ err_alloc:
        return NULL;
 }
 
+/* MAX_PID_NS_LEVEL is needed for limiting size of 'struct pid' */
+#define MAX_PID_NS_LEVEL 32
+
 static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_pid_ns)
 {
        struct pid_namespace *ns;
        unsigned int level = parent_pid_ns->level + 1;
-       int i, err = -ENOMEM;
+       int i;
+       int err;
+
+       if (level > MAX_PID_NS_LEVEL) {
+               err = -EINVAL;
+               goto out;
+       }
 
+       err = -ENOMEM;
        ns = kmem_cache_zalloc(pid_ns_cachep, GFP_KERNEL);
        if (ns == NULL)
                goto out;
index b32ed0e385a59b40b971bd04e0e374d333992749..b979426d16c6efc48e743b6a9df48a78bcaa9f4b 100644 (file)
@@ -1567,6 +1567,10 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size,
 
                put_online_cpus();
        } else {
+               /* Make sure this CPU has been intitialized */
+               if (!cpumask_test_cpu(cpu_id, buffer->cpumask))
+                       goto out;
+
                cpu_buffer = buffer->buffers[cpu_id];
 
                if (nr_pages == cpu_buffer->nr_pages)
index d951daa0ca9a81b21f6b1387b140f537b53c27c1..042d221d33cc1675fadf7ee291e86717f2c8f6c9 100644 (file)
@@ -2982,7 +2982,7 @@ bool cancel_delayed_work(struct delayed_work *dwork)
 
        set_work_cpu_and_clear_pending(&dwork->work, work_cpu(&dwork->work));
        local_irq_restore(flags);
-       return true;
+       return ret;
 }
 EXPORT_SYMBOL(cancel_delayed_work);
 
index ca208a92628c1b49a6f5c1fece1a81592a65ecaa..54920433705adbff385b319574a9f04b50d8ca77 100644 (file)
@@ -178,7 +178,7 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy
        struct gen_pool_chunk *chunk;
        int nbits = size >> pool->min_alloc_order;
        int nbytes = sizeof(struct gen_pool_chunk) +
-                               (nbits + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
+                               BITS_TO_LONGS(nbits) * sizeof(long);
 
        chunk = kmalloc_node(nbytes, GFP_KERNEL | __GFP_ZERO, nid);
        if (unlikely(chunk == NULL))
index 931eef145af5eed370ed6f2b0c9dc577295be6ff..625905523c2a1592f539c46f6721723d62376648 100644 (file)
@@ -930,6 +930,30 @@ int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t si
        return memblock_overlaps_region(&memblock.reserved, base, size) >= 0;
 }
 
+void __init_memblock memblock_trim_memory(phys_addr_t align)
+{
+       int i;
+       phys_addr_t start, end, orig_start, orig_end;
+       struct memblock_type *mem = &memblock.memory;
+
+       for (i = 0; i < mem->cnt; i++) {
+               orig_start = mem->regions[i].base;
+               orig_end = mem->regions[i].base + mem->regions[i].size;
+               start = round_up(orig_start, align);
+               end = round_down(orig_end, align);
+
+               if (start == orig_start && end == orig_end)
+                       continue;
+
+               if (start < end) {
+                       mem->regions[i].base = start;
+                       mem->regions[i].size = end - start;
+               } else {
+                       memblock_remove_region(mem, i);
+                       i--;
+               }
+       }
+}
 
 void __init_memblock memblock_set_current_limit(phys_addr_t limit)
 {
index 479a1e751a73fb4781e1b856db60b2381909c9e6..8a5ac8c686b03480fae7d5b193a5c714c7c2397b 100644 (file)
@@ -196,28 +196,28 @@ static int do_mmu_notifier_register(struct mmu_notifier *mn,
        BUG_ON(atomic_read(&mm->mm_users) <= 0);
 
        /*
-       * Verify that mmu_notifier_init() already run and the global srcu is
-       * initialized.
-       */
+        * Verify that mmu_notifier_init() already run and the global srcu is
+        * initialized.
+        */
        BUG_ON(!srcu.per_cpu_ref);
 
+       ret = -ENOMEM;
+       mmu_notifier_mm = kmalloc(sizeof(struct mmu_notifier_mm), GFP_KERNEL);
+       if (unlikely(!mmu_notifier_mm))
+               goto out;
+
        if (take_mmap_sem)
                down_write(&mm->mmap_sem);
        ret = mm_take_all_locks(mm);
        if (unlikely(ret))
-               goto out;
+               goto out_clean;
 
        if (!mm_has_notifiers(mm)) {
-               mmu_notifier_mm = kmalloc(sizeof(struct mmu_notifier_mm),
-                                       GFP_KERNEL);
-               if (unlikely(!mmu_notifier_mm)) {
-                       ret = -ENOMEM;
-                       goto out_of_mem;
-               }
                INIT_HLIST_HEAD(&mmu_notifier_mm->list);
                spin_lock_init(&mmu_notifier_mm->lock);
 
                mm->mmu_notifier_mm = mmu_notifier_mm;
+               mmu_notifier_mm = NULL;
        }
        atomic_inc(&mm->mm_count);
 
@@ -233,12 +233,12 @@ static int do_mmu_notifier_register(struct mmu_notifier *mn,
        hlist_add_head(&mn->hlist, &mm->mmu_notifier_mm->list);
        spin_unlock(&mm->mmu_notifier_mm->lock);
 
-out_of_mem:
        mm_drop_all_locks(mm);
-out:
+out_clean:
        if (take_mmap_sem)
                up_write(&mm->mmap_sem);
-
+       kfree(mmu_notifier_mm);
+out:
        BUG_ON(atomic_read(&mm->mm_users) <= 0);
        return ret;
 }
index bb90971182bd8c833e40f508e3c8b8677d6913c8..5b74de6702e06587e0d4f36060f810526ff8fbe3 100644 (file)
@@ -1809,10 +1809,10 @@ static void __paginginit init_zone_allows_reclaim(int nid)
        int i;
 
        for_each_online_node(i)
-               if (node_distance(nid, i) <= RECLAIM_DISTANCE) {
+               if (node_distance(nid, i) <= RECLAIM_DISTANCE)
                        node_set(i, NODE_DATA(nid)->reclaim_nodes);
+               else
                        zone_reclaim_mode = 1;
-               }
 }
 
 #else  /* CONFIG_NUMA */
@@ -5825,7 +5825,7 @@ int alloc_contig_range(unsigned long start, unsigned long end,
        ret = start_isolate_page_range(pfn_max_align_down(start),
                                       pfn_max_align_up(end), migratetype);
        if (ret)
-               goto done;
+               return ret;
 
        ret = __alloc_contig_migrate_range(&cc, start, end);
        if (ret)
index 7df7984d476c8661b900725c0e2c3f33c883a32d..2ee1ef0f317b7487bfb21b7a6717b1e12d1f7ef4 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -56,6 +56,7 @@
 #include <linux/mmu_notifier.h>
 #include <linux/migrate.h>
 #include <linux/hugetlb.h>
+#include <linux/backing-dev.h>
 
 #include <asm/tlbflush.h>
 
@@ -926,11 +927,8 @@ int page_mkclean(struct page *page)
 
        if (page_mapped(page)) {
                struct address_space *mapping = page_mapping(page);
-               if (mapping) {
+               if (mapping)
                        ret = page_mkclean_file(mapping, page);
-                       if (page_test_and_clear_dirty(page_to_pfn(page), 1))
-                               ret = 1;
-               }
        }
 
        return ret;
@@ -1116,6 +1114,7 @@ void page_add_file_rmap(struct page *page)
  */
 void page_remove_rmap(struct page *page)
 {
+       struct address_space *mapping = page_mapping(page);
        bool anon = PageAnon(page);
        bool locked;
        unsigned long flags;
@@ -1138,8 +1137,19 @@ void page_remove_rmap(struct page *page)
         * this if the page is anon, so about to be freed; but perhaps
         * not if it's in swapcache - there might be another pte slot
         * containing the swap entry, but page not yet written to swap.
+        *
+        * And we can skip it on file pages, so long as the filesystem
+        * participates in dirty tracking; but need to catch shm and tmpfs
+        * and ramfs pages which have been modified since creation by read
+        * fault.
+        *
+        * Note that mapping must be decided above, before decrementing
+        * mapcount (which luckily provides a barrier): once page is unmapped,
+        * it could be truncated and page->mapping reset to NULL at any moment.
+        * Note also that we are relying on page_mapping(page) to set mapping
+        * to &swapper_space when PageSwapCache(page).
         */
-       if ((!anon || PageSwapCache(page)) &&
+       if (mapping && !mapping_cap_account_dirty(mapping) &&
            page_test_and_clear_dirty(page_to_pfn(page), 1))
                set_page_dirty(page);
        /*
index 9096bcb081326c92bb64b6dedb11033073998ca5..ee070722a3a36f1916b385e8872ea505105d06bb 100644 (file)
@@ -463,7 +463,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
 
        case NETDEV_PRE_TYPE_CHANGE:
                /* Forbid underlaying device to change its type. */
-               return NOTIFY_BAD;
+               if (vlan_uses_dev(dev))
+                       return NOTIFY_BAD;
+               break;
 
        case NETDEV_NOTIFY_PEERS:
        case NETDEV_BONDING_FAILOVER:
index 0a9084ad19a60f71a2f9f70a8879e7ada24ccf6c..fd8d5afec0ddb372d514367df3a6a81996eeac49 100644 (file)
@@ -1167,6 +1167,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
        uint16_t crc;
        unsigned long entrytime;
 
+       spin_lock_init(&bat_priv->bla.bcast_duplist_lock);
+
        batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n");
 
        /* setting claim destination address */
@@ -1210,8 +1212,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
 /**
  * batadv_bla_check_bcast_duplist
  * @bat_priv: the bat priv with all the soft interface information
- * @bcast_packet: originator mac address
- * @hdr_size: maximum length of the frame
+ * @bcast_packet: encapsulated broadcast frame plus batman header
+ * @bcast_packet_len: length of encapsulated broadcast frame plus batman header
  *
  * check if it is on our broadcast list. Another gateway might
  * have sent the same packet because it is connected to the same backbone,
@@ -1224,20 +1226,22 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
  */
 int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
                                   struct batadv_bcast_packet *bcast_packet,
-                                  int hdr_size)
+                                  int bcast_packet_len)
 {
-       int i, length, curr;
+       int i, length, curr, ret = 0;
        uint8_t *content;
        uint16_t crc;
        struct batadv_bcast_duplist_entry *entry;
 
-       length = hdr_size - sizeof(*bcast_packet);
+       length = bcast_packet_len - sizeof(*bcast_packet);
        content = (uint8_t *)bcast_packet;
        content += sizeof(*bcast_packet);
 
        /* calculate the crc ... */
        crc = crc16(0, content, length);
 
+       spin_lock_bh(&bat_priv->bla.bcast_duplist_lock);
+
        for (i = 0; i < BATADV_DUPLIST_SIZE; i++) {
                curr = (bat_priv->bla.bcast_duplist_curr + i);
                curr %= BATADV_DUPLIST_SIZE;
@@ -1259,9 +1263,12 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
                /* this entry seems to match: same crc, not too old,
                 * and from another gw. therefore return 1 to forbid it.
                 */
-               return 1;
+               ret = 1;
+               goto out;
        }
-       /* not found, add a new entry (overwrite the oldest entry) */
+       /* not found, add a new entry (overwrite the oldest entry)
+        * and allow it, its the first occurence.
+        */
        curr = (bat_priv->bla.bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1);
        curr %= BATADV_DUPLIST_SIZE;
        entry = &bat_priv->bla.bcast_duplist[curr];
@@ -1270,8 +1277,10 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
        memcpy(entry->orig, bcast_packet->orig, ETH_ALEN);
        bat_priv->bla.bcast_duplist_curr = curr;
 
-       /* allow it, its the first occurence. */
-       return 0;
+out:
+       spin_unlock_bh(&bat_priv->bla.bcast_duplist_lock);
+
+       return ret;
 }
 
 
index 939fc01371dff0c209665b297b69ec6502887b1a..376b4cc6ca821ffb4279e2b4df81e61899be038f 100644 (file)
@@ -1124,8 +1124,14 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
 
        spin_unlock_bh(&orig_node->bcast_seqno_lock);
 
+       /* keep skb linear for crc calculation */
+       if (skb_linearize(skb) < 0)
+               goto out;
+
+       bcast_packet = (struct batadv_bcast_packet *)skb->data;
+
        /* check whether this has been sent by another originator before */
-       if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, hdr_size))
+       if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, skb->len))
                goto out;
 
        /* rebroadcast packet */
index 2ed82caacdca4bfa0cf429d74a7311523874b4c2..ac1e07a8045475ed9ce367d39440940f29ab0852 100644 (file)
@@ -205,6 +205,8 @@ struct batadv_priv_bla {
        struct batadv_hashtable *backbone_hash;
        struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE];
        int bcast_duplist_curr;
+       /* protects bcast_duplist and bcast_duplist_curr */
+       spinlock_t bcast_duplist_lock;
        struct batadv_bla_claim_dst claim_dest;
        struct delayed_work work;
 };
index 8c225ef349cd733614dfeaca0f2f1bceccdae064..2ac8d50861e08165bca0747d840e99672bb105de 100644 (file)
@@ -32,6 +32,8 @@
 
 #define SMP_TIMEOUT    msecs_to_jiffies(30000)
 
+#define AUTH_REQ_MASK   0x07
+
 static inline void swap128(u8 src[16], u8 dst[16])
 {
        int i;
@@ -230,7 +232,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
                req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
                req->init_key_dist = 0;
                req->resp_key_dist = dist_keys;
-               req->auth_req = authreq;
+               req->auth_req = (authreq & AUTH_REQ_MASK);
                return;
        }
 
@@ -239,7 +241,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
        rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
        rsp->init_key_dist = 0;
        rsp->resp_key_dist = req->resp_key_dist & dist_keys;
-       rsp->auth_req = authreq;
+       rsp->auth_req = (authreq & AUTH_REQ_MASK);
 }
 
 static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
index 159aa8bef9e7fe2f89f9b508c39a209aa92d3c0d..3ef1759403b411fe53595e2ddf1eb6314a4f9ef8 100644 (file)
@@ -2300,10 +2300,11 @@ restart:
                        mutex_unlock(&con->mutex);
                        return;
                } else {
-                       con->ops->put(con);
                        dout("con_work %p FAILED to back off %lu\n", con,
                             con->delay);
+                       set_bit(CON_FLAG_BACKOFF, &con->flags);
                }
+               goto done;
        }
 
        if (con->state == CON_STATE_STANDBY) {
@@ -2749,7 +2750,8 @@ static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip)
                msg = con->ops->alloc_msg(con, hdr, skip);
                mutex_lock(&con->mutex);
                if (con->state != CON_STATE_OPEN) {
-                       ceph_msg_put(msg);
+                       if (msg)
+                               ceph_msg_put(msg);
                        return -EAGAIN;
                }
                con->in_msg = msg;
index 6e04b1fa11f2d4c6d0e0aacb27441688c5fe1438..4007c1437fdaf615bbf197ad52e545529e7bce59 100644 (file)
@@ -3379,10 +3379,12 @@ EXPORT_SYMBOL(__skb_warn_lro_forwarding);
 
 void kfree_skb_partial(struct sk_buff *skb, bool head_stolen)
 {
-       if (head_stolen)
+       if (head_stolen) {
+               skb_release_head_state(skb);
                kmem_cache_free(skbuff_head_cache, skb);
-       else
+       } else {
                __kfree_skb(skb);
+       }
 }
 EXPORT_SYMBOL(kfree_skb_partial);
 
index 9e0ffaf1d942624cf44d9693922e13312fc77ff2..a82047282dbbe2513615ae0c0e60dc1c54b2aa92 100644 (file)
@@ -184,7 +184,8 @@ nf_nat_ipv4_out(unsigned int hooknum,
 
                if ((ct->tuplehash[dir].tuple.src.u3.ip !=
                     ct->tuplehash[!dir].tuple.dst.u3.ip) ||
-                   (ct->tuplehash[dir].tuple.src.u.all !=
+                   (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
+                    ct->tuplehash[dir].tuple.src.u.all !=
                     ct->tuplehash[!dir].tuple.dst.u.all))
                        if (nf_xfrm_me_harder(skb, AF_INET) < 0)
                                ret = NF_DROP;
@@ -221,6 +222,7 @@ nf_nat_ipv4_local_fn(unsigned int hooknum,
                }
 #ifdef CONFIG_XFRM
                else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
+                        ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
                         ct->tuplehash[dir].tuple.dst.u.all !=
                         ct->tuplehash[!dir].tuple.src.u.all)
                        if (nf_xfrm_me_harder(skb, AF_INET) < 0)
index 432f4bb77238fcc5c80d5ab7c6ad35bb55609c53..a8c651216fa62a44d9226eed3294e3e5f3484a3d 100644 (file)
@@ -1163,8 +1163,12 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
        spin_lock_bh(&fnhe_lock);
 
        if (daddr == fnhe->fnhe_daddr) {
-               struct rtable *orig;
-
+               struct rtable *orig = rcu_dereference(fnhe->fnhe_rth);
+               if (orig && rt_is_expired(orig)) {
+                       fnhe->fnhe_gw = 0;
+                       fnhe->fnhe_pmtu = 0;
+                       fnhe->fnhe_expires = 0;
+               }
                if (fnhe->fnhe_pmtu) {
                        unsigned long expires = fnhe->fnhe_expires;
                        unsigned long diff = expires - jiffies;
@@ -1181,7 +1185,6 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
                } else if (!rt->rt_gateway)
                        rt->rt_gateway = daddr;
 
-               orig = rcu_dereference(fnhe->fnhe_rth);
                rcu_assign_pointer(fnhe->fnhe_rth, rt);
                if (orig)
                        rt_free(orig);
index f32c02e2a54346cf4e120d39e17d4d1b5e966189..197c0008503c8dc0dc01adc3c1c63ea60f3d374d 100644 (file)
@@ -549,14 +549,12 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
                         !tp->urg_data ||
                         before(tp->urg_seq, tp->copied_seq) ||
                         !before(tp->urg_seq, tp->rcv_nxt)) {
-                       struct sk_buff *skb;
 
                        answ = tp->rcv_nxt - tp->copied_seq;
 
-                       /* Subtract 1, if FIN is in queue. */
-                       skb = skb_peek_tail(&sk->sk_receive_queue);
-                       if (answ && skb)
-                               answ -= tcp_hdr(skb)->fin;
+                       /* Subtract 1, if FIN was received */
+                       if (answ && sock_flag(sk, SOCK_DONE))
+                               answ--;
                } else
                        answ = tp->urg_seq - tp->copied_seq;
                release_sock(sk);
@@ -2766,6 +2764,8 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info)
                info->tcpi_options |= TCPI_OPT_ECN;
        if (tp->ecn_flags & TCP_ECN_SEEN)
                info->tcpi_options |= TCPI_OPT_ECN_SEEN;
+       if (tp->syn_data_acked)
+               info->tcpi_options |= TCPI_OPT_SYN_DATA;
 
        info->tcpi_rto = jiffies_to_usecs(icsk->icsk_rto);
        info->tcpi_ato = jiffies_to_usecs(icsk->icsk_ack.ato);
index 813b43a76fece71e2614878a5830962d55f35a22..834857f3c8713e8d8b80ab7b4f413725ec0ca9b4 100644 (file)
@@ -313,11 +313,13 @@ static void tcp_illinois_info(struct sock *sk, u32 ext,
                        .tcpv_rttcnt = ca->cnt_rtt,
                        .tcpv_minrtt = ca->base_rtt,
                };
-               u64 t = ca->sum_rtt;
 
-               do_div(t, ca->cnt_rtt);
-               info.tcpv_rtt = t;
+               if (info.tcpv_rttcnt > 0) {
+                       u64 t = ca->sum_rtt;
 
+                       do_div(t, info.tcpv_rttcnt);
+                       info.tcpv_rtt = t;
+               }
                nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info);
        }
 }
index 432c36649db3dd8d579ddb05ae886dd3251dcb66..2c2b13a999eae522c264a97a3d43baaa45c53c7b 100644 (file)
@@ -4529,6 +4529,9 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size)
        struct tcphdr *th;
        bool fragstolen;
 
+       if (size == 0)
+               return 0;
+
        skb = alloc_skb(size + sizeof(*th), sk->sk_allocation);
        if (!skb)
                goto err;
@@ -5646,6 +5649,7 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
                tcp_rearm_rto(sk);
                return true;
        }
+       tp->syn_data_acked = tp->syn_data;
        return false;
 }
 
@@ -5963,7 +5967,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
 
        req = tp->fastopen_rsk;
        if (req != NULL) {
-               BUG_ON(sk->sk_state != TCP_SYN_RECV &&
+               WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&
                    sk->sk_state != TCP_FIN_WAIT1);
 
                if (tcp_check_req(sk, skb, req, NULL, true) == NULL)
@@ -6052,7 +6056,15 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                         * ACK we have received, this would have acknowledged
                         * our SYNACK so stop the SYNACK timer.
                         */
-                       if (acceptable && req != NULL) {
+                       if (req != NULL) {
+                               /* Return RST if ack_seq is invalid.
+                                * Note that RFC793 only says to generate a
+                                * DUPACK for it but for TCP Fast Open it seems
+                                * better to treat this case like TCP_SYN_RECV
+                                * above.
+                                */
+                               if (!acceptable)
+                                       return 1;
                                /* We no longer need the request sock. */
                                reqsk_fastopen_remove(sk, req, false);
                                tcp_rearm_rto(sk);
index ef998b008a570ba0976b911d85d0b98bb6d834fb..0c4a643556037871c1c6a202aa99ba338a7a92d5 100644 (file)
@@ -1461,6 +1461,7 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk,
                skb_set_owner_r(skb, child);
                __skb_queue_tail(&child->sk_receive_queue, skb);
                tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+               tp->syn_data_acked = 1;
        }
        sk->sk_data_ready(sk, 0);
        bh_unlock_sock(child);
index 4c752a6e0bcd91b0b932b483a2b9f988908c04a2..53bc5847bfa882a34c3d5a34257ec82a3fe92873 100644 (file)
@@ -864,7 +864,7 @@ static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr,
        }
        a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV6];
        if (a) {
-               if (nla_len(a) != sizeof(sizeof(struct in6_addr)))
+               if (nla_len(a) != sizeof(struct in6_addr))
                        return -EINVAL;
                addr->family = AF_INET6;
                memcpy(addr->addr.a6, nla_data(a), sizeof(addr->addr.a6));
index 27536ba16c9da7b89d5385073c7ae4d4f9e27f3c..a7302d974f32ca563e4aeb589a193e7617c396a5 100644 (file)
@@ -510,6 +510,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
                newtp->rx_opt.mss_clamp = req->mss;
                TCP_ECN_openreq_child(newtp, req);
                newtp->fastopen_rsk = NULL;
+               newtp->syn_data_acked = 0;
 
                TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_PASSIVEOPENS);
        }
index fc04711e80c89dd0dc92ff1027efaa7324b218c3..d47c1b4421a339a3378ef23646c8f99b41d7490b 100644 (file)
@@ -347,8 +347,8 @@ void tcp_retransmit_timer(struct sock *sk)
                return;
        }
        if (tp->fastopen_rsk) {
-               BUG_ON(sk->sk_state != TCP_SYN_RECV &&
-                   sk->sk_state != TCP_FIN_WAIT1);
+               WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&
+                            sk->sk_state != TCP_FIN_WAIT1);
                tcp_fastopen_synack_timer(sk);
                /* Before we receive ACK to our SYN-ACK don't retransmit
                 * anything else (e.g., data or FIN segments).
index e418bd6350a405c9912f09207b876d1151961551..d57dab17a18251fcb8c63fc27c2dddfe8bc2a89e 100644 (file)
@@ -186,7 +186,8 @@ nf_nat_ipv6_out(unsigned int hooknum,
 
                if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
                                      &ct->tuplehash[!dir].tuple.dst.u3) ||
-                   (ct->tuplehash[dir].tuple.src.u.all !=
+                   (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
+                    ct->tuplehash[dir].tuple.src.u.all !=
                     ct->tuplehash[!dir].tuple.dst.u.all))
                        if (nf_xfrm_me_harder(skb, AF_INET6) < 0)
                                ret = NF_DROP;
@@ -222,6 +223,7 @@ nf_nat_ipv6_local_fn(unsigned int hooknum,
                }
 #ifdef CONFIG_XFRM
                else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
+                        ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
                         ct->tuplehash[dir].tuple.dst.u.all !=
                         ct->tuplehash[!dir].tuple.src.u.all)
                        if (nf_xfrm_me_harder(skb, AF_INET6))
index 18bd9bbbd1c6c0f50d8bf74c947c05f91a4f20cd..22c8ea9511852e963b982ad68ed7066bda262ad2 100644 (file)
@@ -85,7 +85,7 @@ static struct ctl_table nf_ct_frag6_sysctl_table[] = {
        { }
 };
 
-static int __net_init nf_ct_frag6_sysctl_register(struct net *net)
+static int nf_ct_frag6_sysctl_register(struct net *net)
 {
        struct ctl_table *table;
        struct ctl_table_header *hdr;
@@ -127,7 +127,7 @@ static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net)
 }
 
 #else
-static int __net_init nf_ct_frag6_sysctl_register(struct net *net)
+static int nf_ct_frag6_sysctl_register(struct net *net)
 {
        return 0;
 }
index 7c7e963260e1792be01a329d4298dc1123c8f738..b1e6cf0b95fd9bf3546420e8cb48578d1a7d2190 100644 (file)
@@ -219,7 +219,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
 };
 
 static const u32 ip6_template_metrics[RTAX_MAX] = {
-       [RTAX_HOPLIMIT - 1] = 255,
+       [RTAX_HOPLIMIT - 1] = 0,
 };
 
 static const struct rt6_info ip6_null_entry_template = {
@@ -1232,7 +1232,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
        rt->rt6i_dst.addr = fl6->daddr;
        rt->rt6i_dst.plen = 128;
        rt->rt6i_idev     = idev;
-       dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255);
+       dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0);
 
        spin_lock_bh(&icmp6_dst_lock);
        rt->dst.next = icmp6_dst_gc_list;
index 37b8b8ba31f7395001cd2f36e234d82878bc22c7..76125c57ee6dddd2396a8a0bef4f19e7720e43ed 100644 (file)
@@ -291,6 +291,7 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p
 
 out_del_dev:
        free_netdev(dev);
+       spriv->dev = NULL;
 out_del_session:
        l2tp_session_delete(session);
 out:
index 5f3620f0bc0a651257aa53e28b91c4b2114be637..bf87c70ac6c5fe1e2b920c6db827e1e9da6abe36 100644 (file)
@@ -1108,7 +1108,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
        sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
        sdata->u.ibss.ibss_join_req = jiffies;
 
-       memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN);
+       memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len);
        sdata->u.ibss.ssid_len = params->ssid_len;
 
        mutex_unlock(&sdata->u.ibss.mtx);
index 6f8a73c64fb31bde831609fa88a9b4e0425f02b9..7de7717ad67d97c7f75afca4c6a8c13fbec63404 100644 (file)
@@ -853,7 +853,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
                        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
                        if (info->control.vif == &sdata->vif) {
                                __skb_unlink(skb, &local->pending[i]);
-                               dev_kfree_skb_irq(skb);
+                               ieee80211_free_txskb(&local->hw, skb);
                        }
                }
        }
index e714ed8bb198727c6738c1e3ae7650243dd2a07e..1b7eed252fe9fe0082596d8716c1e0f5e029db7f 100644 (file)
@@ -3099,22 +3099,32 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
                                   ht_cfreq, ht_oper->primary_chan,
                                   cbss->channel->band);
                        ht_oper = NULL;
+               } else {
+                       channel_type = NL80211_CHAN_HT20;
                }
        }
 
-       if (ht_oper) {
-               channel_type = NL80211_CHAN_HT20;
+       if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
+               /*
+                * cfg80211 already verified that the channel itself can
+                * be used, but it didn't check that we can do the right
+                * HT type, so do that here as well. If HT40 isn't allowed
+                * on this channel, disable 40 MHz operation.
+                */
 
-               if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
-                       switch (ht_oper->ht_param &
-                                       IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
-                       case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+               switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
+               case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+                       if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS)
+                               ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
+                       else
                                channel_type = NL80211_CHAN_HT40PLUS;
-                               break;
-                       case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+                       break;
+               case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+                       if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS)
+                               ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
+                       else
                                channel_type = NL80211_CHAN_HT40MINUS;
-                               break;
-                       }
+                       break;
                }
        }
 
@@ -3549,6 +3559,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
+       bool tx = !req->local_state_change;
 
        mutex_lock(&ifmgd->mtx);
 
@@ -3565,12 +3576,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
        if (ifmgd->associated &&
            ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
                ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
-                                      req->reason_code, true, frame_buf);
+                                      req->reason_code, tx, frame_buf);
        } else {
                drv_mgd_prepare_tx(sdata->local, sdata);
                ieee80211_send_deauth_disassoc(sdata, req->bssid,
                                               IEEE80211_STYPE_DEAUTH,
-                                              req->reason_code, true,
+                                              req->reason_code, tx,
                                               frame_buf);
        }
 
index 61c621e9273fe70c26978d42433d58fca60a80b8..00ade7feb2e3a3b84af12be5bfad378bd8907182 100644 (file)
@@ -531,6 +531,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
 
                if (ieee80211_is_action(hdr->frame_control)) {
                        u8 category;
+
+                       /* make sure category field is present */
+                       if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE)
+                               return RX_DROP_MONITOR;
+
                        mgmt = (struct ieee80211_mgmt *)hdr;
                        category = mgmt->u.action.category;
                        if (category != WLAN_CATEGORY_MESH_ACTION &&
@@ -883,14 +888,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
                 */
                if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
                    ieee80211_is_data_present(hdr->frame_control)) {
-                       u16 ethertype;
-                       u8 *payload;
-
-                       payload = rx->skb->data +
-                               ieee80211_hdrlen(hdr->frame_control);
-                       ethertype = (payload[6] << 8) | payload[7];
-                       if (cpu_to_be16(ethertype) ==
-                           rx->sdata->control_port_protocol)
+                       unsigned int hdrlen;
+                       __be16 ethertype;
+
+                       hdrlen = ieee80211_hdrlen(hdr->frame_control);
+
+                       if (rx->skb->len < hdrlen + 8)
+                               return RX_DROP_MONITOR;
+
+                       skb_copy_bits(rx->skb, hdrlen + 6, &ethertype, 2);
+                       if (ethertype == rx->sdata->control_port_protocol)
                                return RX_CONTINUE;
                }
 
@@ -1462,11 +1469,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
 
        hdr = (struct ieee80211_hdr *)rx->skb->data;
        fc = hdr->frame_control;
+
+       if (ieee80211_is_ctl(fc))
+               return RX_CONTINUE;
+
        sc = le16_to_cpu(hdr->seq_ctrl);
        frag = sc & IEEE80211_SCTL_FRAG;
 
        if (likely((!ieee80211_has_morefrags(fc) && frag == 0) ||
-                  (rx->skb)->len < 24 ||
                   is_multicast_ether_addr(hdr->addr1))) {
                /* not fragmented */
                goto out;
@@ -1889,6 +1899,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
 
        hdr = (struct ieee80211_hdr *) skb->data;
        hdrlen = ieee80211_hdrlen(hdr->frame_control);
+
+       /* make sure fixed part of mesh header is there, also checks skb len */
+       if (!pskb_may_pull(rx->skb, hdrlen + 6))
+               return RX_DROP_MONITOR;
+
+       mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
+
+       /* make sure full mesh header is there, also checks skb len */
+       if (!pskb_may_pull(rx->skb,
+                          hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr)))
+               return RX_DROP_MONITOR;
+
+       /* reload pointers */
+       hdr = (struct ieee80211_hdr *) skb->data;
        mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);
 
        /* frame is in RMC, don't forward */
@@ -1897,7 +1921,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
            mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata))
                return RX_DROP_MONITOR;
 
-       if (!ieee80211_is_data(hdr->frame_control))
+       if (!ieee80211_is_data(hdr->frame_control) ||
+           !(status->rx_flags & IEEE80211_RX_RA_MATCH))
                return RX_CONTINUE;
 
        if (!mesh_hdr->ttl)
@@ -1911,9 +1936,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
                if (is_multicast_ether_addr(hdr->addr1)) {
                        mpp_addr = hdr->addr3;
                        proxied_addr = mesh_hdr->eaddr1;
-               } else {
+               } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) {
+                       /* has_a4 already checked in ieee80211_rx_mesh_check */
                        mpp_addr = hdr->addr4;
                        proxied_addr = mesh_hdr->eaddr2;
+               } else {
+                       return RX_DROP_MONITOR;
                }
 
                rcu_read_lock();
@@ -1941,12 +1969,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        }
        skb_set_queue_mapping(skb, q);
 
-       if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
-               goto out;
-
        if (!--mesh_hdr->ttl) {
                IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
-               return RX_DROP_MONITOR;
+               goto out;
        }
 
        if (!ifmsh->mshcfg.dot11MeshForwarding)
@@ -2353,6 +2378,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                }
                break;
        case WLAN_CATEGORY_SELF_PROTECTED:
+               if (len < (IEEE80211_MIN_ACTION_SIZE +
+                          sizeof(mgmt->u.action.u.self_prot.action_code)))
+                       break;
+
                switch (mgmt->u.action.u.self_prot.action_code) {
                case WLAN_SP_MESH_PEERING_OPEN:
                case WLAN_SP_MESH_PEERING_CLOSE:
@@ -2371,6 +2400,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                }
                break;
        case WLAN_CATEGORY_MESH_ACTION:
+               if (len < (IEEE80211_MIN_ACTION_SIZE +
+                          sizeof(mgmt->u.action.u.mesh_action.action_code)))
+                       break;
+
                if (!ieee80211_vif_is_mesh(&sdata->vif))
                        break;
                if (mesh_action_is_path_sel(mgmt) &&
@@ -2913,10 +2946,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
        if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
                local->dot11ReceivedFragmentCount++;
 
-       if (ieee80211_is_mgmt(fc))
-               err = skb_linearize(skb);
-       else
+       if (ieee80211_is_mgmt(fc)) {
+               /* drop frame if too short for header */
+               if (skb->len < ieee80211_hdrlen(fc))
+                       err = -ENOBUFS;
+               else
+                       err = skb_linearize(skb);
+       } else {
                err = !pskb_may_pull(skb, ieee80211_hdrlen(fc));
+       }
 
        if (err) {
                dev_kfree_skb(skb);
index 797dd36a220d92ac549067a9cd4d59a7ebfc09a3..0a4e4c04db89c5ba43a7f0e8d487385734a841b9 100644 (file)
@@ -650,7 +650,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local,
                 */
                if (!skb)
                        break;
-               dev_kfree_skb(skb);
+               ieee80211_free_txskb(&local->hw, skb);
        }
 
        /*
@@ -679,7 +679,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local,
                local->total_ps_buffered--;
                ps_dbg(sta->sdata, "Buffered frame expired (STA %pM)\n",
                       sta->sta.addr);
-               dev_kfree_skb(skb);
+               ieee80211_free_txskb(&local->hw, skb);
        }
 
        /*
index 22ca35054dd065753b9e7d6c4f3e5ab990903e83..239391807ca9cff116576d07975c2ce31db393d3 100644 (file)
@@ -406,7 +406,7 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local,
        int queue = info->hw_queue;
 
        if (WARN_ON(!info->control.vif)) {
-               kfree_skb(skb);
+               ieee80211_free_txskb(&local->hw, skb);
                return;
        }
 
@@ -431,7 +431,7 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
                struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 
                if (WARN_ON(!info->control.vif)) {
-                       kfree_skb(skb);
+                       ieee80211_free_txskb(&local->hw, skb);
                        continue;
                }
 
@@ -643,13 +643,41 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
                        break;
                }
 
-               if (id != WLAN_EID_VENDOR_SPECIFIC &&
-                   id != WLAN_EID_QUIET &&
-                   test_bit(id, seen_elems)) {
-                       elems->parse_error = true;
-                       left -= elen;
-                       pos += elen;
-                       continue;
+               switch (id) {
+               case WLAN_EID_SSID:
+               case WLAN_EID_SUPP_RATES:
+               case WLAN_EID_FH_PARAMS:
+               case WLAN_EID_DS_PARAMS:
+               case WLAN_EID_CF_PARAMS:
+               case WLAN_EID_TIM:
+               case WLAN_EID_IBSS_PARAMS:
+               case WLAN_EID_CHALLENGE:
+               case WLAN_EID_RSN:
+               case WLAN_EID_ERP_INFO:
+               case WLAN_EID_EXT_SUPP_RATES:
+               case WLAN_EID_HT_CAPABILITY:
+               case WLAN_EID_HT_OPERATION:
+               case WLAN_EID_VHT_CAPABILITY:
+               case WLAN_EID_VHT_OPERATION:
+               case WLAN_EID_MESH_ID:
+               case WLAN_EID_MESH_CONFIG:
+               case WLAN_EID_PEER_MGMT:
+               case WLAN_EID_PREQ:
+               case WLAN_EID_PREP:
+               case WLAN_EID_PERR:
+               case WLAN_EID_RANN:
+               case WLAN_EID_CHANNEL_SWITCH:
+               case WLAN_EID_EXT_CHANSWITCH_ANN:
+               case WLAN_EID_COUNTRY:
+               case WLAN_EID_PWR_CONSTRAINT:
+               case WLAN_EID_TIMEOUT_INTERVAL:
+                       if (test_bit(id, seen_elems)) {
+                               elems->parse_error = true;
+                               left -= elen;
+                               pos += elen;
+                               continue;
+                       }
+                       break;
                }
 
                if (calc_crc && id < 64 && (filter & (1ULL << id)))
index bdb53aba888e147cfd3bae984cd69811f520261a..8bd2f5c6a56edfa26193de6da2560c88d5ac75ce 100644 (file)
@@ -106,7 +106,8 @@ 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) && rx->key)
+               if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key &&
+                   rx->key->conf.cipher == WLAN_CIPHER_SUITE_TKIP)
                        goto update_iv;
 
                return RX_CONTINUE;
@@ -545,14 +546,19 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
 
 static void bip_aad(struct sk_buff *skb, u8 *aad)
 {
+       __le16 mask_fc;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+
        /* BIP AAD: FC(masked) || A1 || A2 || A3 */
 
        /* FC type/subtype */
-       aad[0] = skb->data[0];
        /* Mask FC Retry, PwrMgt, MoreData flags to zero */
-       aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6));
+       mask_fc = hdr->frame_control;
+       mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | IEEE80211_FCTL_PM |
+                               IEEE80211_FCTL_MOREDATA);
+       put_unaligned(mask_fc, (__le16 *) &aad[0]);
        /* A1 || A2 || A3 */
-       memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN);
+       memcpy(aad + 2, &hdr->addr1, 3 * ETH_ALEN);
 }
 
 
index 7e7198b51c068a7ea10446af4d390a9e6e2044f4..c4ee43710aab63ce34657a06ba9d26d3862a6a61 100644 (file)
@@ -2589,6 +2589,8 @@ __ip_vs_get_timeouts(struct net *net, struct ip_vs_timeout_user *u)
        struct ip_vs_proto_data *pd;
 #endif
 
+       memset(u, 0, sizeof (*u));
+
 #ifdef CONFIG_IP_VS_PROTO_TCP
        pd = ip_vs_proto_data_get(net, IPPROTO_TCP);
        u->tcp_timeout = pd->timeout_table[IP_VS_TCP_S_ESTABLISHED] / HZ;
@@ -2766,7 +2768,6 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
        {
                struct ip_vs_timeout_user t;
 
-               memset(&t, 0, sizeof(t));
                __ip_vs_get_timeouts(net, &t);
                if (copy_to_user(user, &t, sizeof(t)) != 0)
                        ret = -EFAULT;
index 1b30b0dee70818c4842b1835964ffc5f59e6b6e3..962795e839ab099ce426a27a1dcd4d887bc56eef 100644 (file)
@@ -753,7 +753,8 @@ static int callforward_do_filter(const union nf_inet_addr *src,
                                   flowi4_to_flowi(&fl1), false)) {
                        if (!afinfo->route(&init_net, (struct dst_entry **)&rt2,
                                           flowi4_to_flowi(&fl2), false)) {
-                               if (rt1->rt_gateway == rt2->rt_gateway &&
+                               if (rt_nexthop(rt1, fl1.daddr) ==
+                                   rt_nexthop(rt2, fl2.daddr) &&
                                    rt1->dst.dev  == rt2->dst.dev)
                                        ret = 1;
                                dst_release(&rt2->dst);
index 16c712563860bad8b8ba03041b06cf2c386d43ab..ae7f5daeee4362bff5aee9a30a85347de70a2ccc 100644 (file)
@@ -180,9 +180,9 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
        typeof(nf_ct_timeout_find_get_hook) timeout_find_get;
        struct ctnl_timeout *timeout;
        struct nf_conn_timeout *timeout_ext;
-       const struct ipt_entry *e = par->entryinfo;
        struct nf_conntrack_l4proto *l4proto;
        int ret = 0;
+       u8 proto;
 
        rcu_read_lock();
        timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook);
@@ -192,9 +192,11 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
                goto out;
        }
 
-       if (e->ip.invflags & IPT_INV_PROTO) {
+       proto = xt_ct_find_proto(par);
+       if (!proto) {
                ret = -EINVAL;
-               pr_info("You cannot use inversion on L4 protocol\n");
+               pr_info("You must specify a L4 protocol, and not use "
+                       "inversions on it.\n");
                goto out;
        }
 
@@ -214,7 +216,7 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
        /* Make sure the timeout policy matches any existing protocol tracker,
         * otherwise default to generic.
         */
-       l4proto = __nf_ct_l4proto_find(par->family, e->ip.proto);
+       l4proto = __nf_ct_l4proto_find(par->family, proto);
        if (timeout->l4proto->l4proto != l4proto->l4proto) {
                ret = -EINVAL;
                pr_info("Timeout policy `%s' can only be used by L4 protocol "
index ee2e5bc5a8c7b506842b6d143fba3f7aa04f3a8d..bd93e51d30acc4eded7e5e4da0898e0838dd7c43 100644 (file)
@@ -70,6 +70,7 @@ tee_tg_route4(struct sk_buff *skb, const struct xt_tee_tginfo *info)
        fl4.daddr = info->gw.ip;
        fl4.flowi4_tos = RT_TOS(iph->tos);
        fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
+       fl4.flowi4_flags = FLOWI_FLAG_KNOWN_NH;
        rt = ip_route_output_key(net, &fl4);
        if (IS_ERR(rt))
                return false;
index 81aafa8e4fef894e9f24d7c460b627108884bba6..bea7464cc43fd9ced593ece7d073b66ea85d18de 100644 (file)
@@ -111,7 +111,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
                .family         = NFPROTO_IPV4,
                .table          = "nat",
                .hooks          = (1 << NF_INET_POST_ROUTING) |
-                                 (1 << NF_INET_LOCAL_OUT),
+                                 (1 << NF_INET_LOCAL_IN),
                .me             = THIS_MODULE,
        },
        {
@@ -123,7 +123,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
                .family         = NFPROTO_IPV4,
                .table          = "nat",
                .hooks          = (1 << NF_INET_PRE_ROUTING) |
-                                 (1 << NF_INET_LOCAL_IN),
+                                 (1 << NF_INET_LOCAL_OUT),
                .me             = THIS_MODULE,
        },
        {
@@ -133,7 +133,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
                .targetsize     = sizeof(struct nf_nat_range),
                .table          = "nat",
                .hooks          = (1 << NF_INET_POST_ROUTING) |
-                                 (1 << NF_INET_LOCAL_OUT),
+                                 (1 << NF_INET_LOCAL_IN),
                .me             = THIS_MODULE,
        },
        {
@@ -143,7 +143,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
                .targetsize     = sizeof(struct nf_nat_range),
                .table          = "nat",
                .hooks          = (1 << NF_INET_PRE_ROUTING) |
-                                 (1 << NF_INET_LOCAL_IN),
+                                 (1 << NF_INET_LOCAL_OUT),
                .me             = THIS_MODULE,
        },
 };
index 01e944a017a4db6be96c3d4a8e7adc8d7890b34e..4da797fa5ec57641a0fa70b5dd1e6e517884fad4 100644 (file)
@@ -138,6 +138,8 @@ static int netlink_dump(struct sock *sk);
 static DEFINE_RWLOCK(nl_table_lock);
 static atomic_t nl_table_users = ATOMIC_INIT(0);
 
+#define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock));
+
 static ATOMIC_NOTIFIER_HEAD(netlink_chain);
 
 static inline u32 netlink_group_mask(u32 group)
@@ -345,6 +347,11 @@ netlink_update_listeners(struct sock *sk)
        struct hlist_node *node;
        unsigned long mask;
        unsigned int i;
+       struct listeners *listeners;
+
+       listeners = nl_deref_protected(tbl->listeners);
+       if (!listeners)
+               return;
 
        for (i = 0; i < NLGRPLONGS(tbl->groups); i++) {
                mask = 0;
@@ -352,7 +359,7 @@ netlink_update_listeners(struct sock *sk)
                        if (i < NLGRPLONGS(nlk_sk(sk)->ngroups))
                                mask |= nlk_sk(sk)->groups[i];
                }
-               tbl->listeners->masks[i] = mask;
+               listeners->masks[i] = mask;
        }
        /* this function is only called with the netlink table "grabbed", which
         * makes sure updates are visible before bind or setsockopt return. */
@@ -536,7 +543,11 @@ static int netlink_release(struct socket *sock)
        if (netlink_is_kernel(sk)) {
                BUG_ON(nl_table[sk->sk_protocol].registered == 0);
                if (--nl_table[sk->sk_protocol].registered == 0) {
-                       kfree(nl_table[sk->sk_protocol].listeners);
+                       struct listeners *old;
+
+                       old = nl_deref_protected(nl_table[sk->sk_protocol].listeners);
+                       RCU_INIT_POINTER(nl_table[sk->sk_protocol].listeners, NULL);
+                       kfree_rcu(old, rcu);
                        nl_table[sk->sk_protocol].module = NULL;
                        nl_table[sk->sk_protocol].bind = NULL;
                        nl_table[sk->sk_protocol].flags = 0;
@@ -982,7 +993,7 @@ int netlink_has_listeners(struct sock *sk, unsigned int group)
        rcu_read_lock();
        listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners);
 
-       if (group - 1 < nl_table[sk->sk_protocol].groups)
+       if (listeners && group - 1 < nl_table[sk->sk_protocol].groups)
                res = test_bit(group - 1, listeners->masks);
 
        rcu_read_unlock();
@@ -1625,7 +1636,7 @@ int __netlink_change_ngroups(struct sock *sk, unsigned int groups)
                new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC);
                if (!new)
                        return -ENOMEM;
-               old = rcu_dereference_protected(tbl->listeners, 1);
+               old = nl_deref_protected(tbl->listeners);
                memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups));
                rcu_assign_pointer(tbl->listeners, new);
 
index 59d16ea927f0f83d706d3a59c79d13be0a95c1e8..a60d1f8b41c5e2330e837265e175202aba322fcb 100644 (file)
@@ -974,7 +974,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
        void *addr_buf;
        struct sctp_af *af;
 
-       SCTP_DEBUG_PRINTK("sctp_setsocktopt_bindx: sk %p addrs %p"
+       SCTP_DEBUG_PRINTK("sctp_setsockopt_bindx: sk %p addrs %p"
                          " addrs_size %d opt %d\n", sk, addrs, addrs_size, op);
 
        if (unlikely(addrs_size <= 0))
index 5a3d675d2f2f9f3971b4707474cc511ad328ac2a..a9c0bbccad6bfb787b4ff1630a1eb7a28918e634 100644 (file)
@@ -172,7 +172,7 @@ out_free:
                xprt_free_allocation(req);
 
        dprintk("RPC:       setup backchannel transport failed\n");
-       return -1;
+       return -ENOMEM;
 }
 EXPORT_SYMBOL_GPL(xprt_setup_backchannel);
 
index aaaadfbe36e9525a42a86e1f649bf66e59eb7274..75853cabf4c97b153873eda4ce67cd228581fd15 100644 (file)
@@ -254,7 +254,6 @@ struct sock_xprt {
        void                    (*old_data_ready)(struct sock *, int);
        void                    (*old_state_change)(struct sock *);
        void                    (*old_write_space)(struct sock *);
-       void                    (*old_error_report)(struct sock *);
 };
 
 /*
@@ -737,10 +736,10 @@ static int xs_tcp_send_request(struct rpc_task *task)
                dprintk("RPC:       sendmsg returned unrecognized error %d\n",
                        -status);
        case -ECONNRESET:
-       case -EPIPE:
                xs_tcp_shutdown(xprt);
        case -ECONNREFUSED:
        case -ENOTCONN:
+       case -EPIPE:
                clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
        }
 
@@ -781,7 +780,6 @@ static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk)
        transport->old_data_ready = sk->sk_data_ready;
        transport->old_state_change = sk->sk_state_change;
        transport->old_write_space = sk->sk_write_space;
-       transport->old_error_report = sk->sk_error_report;
 }
 
 static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk)
@@ -789,7 +787,6 @@ static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *s
        sk->sk_data_ready = transport->old_data_ready;
        sk->sk_state_change = transport->old_state_change;
        sk->sk_write_space = transport->old_write_space;
-       sk->sk_error_report = transport->old_error_report;
 }
 
 static void xs_reset_transport(struct sock_xprt *transport)
@@ -1453,7 +1450,7 @@ static void xs_tcp_cancel_linger_timeout(struct rpc_xprt *xprt)
        xprt_clear_connecting(xprt);
 }
 
-static void xs_sock_mark_closed(struct rpc_xprt *xprt)
+static void xs_sock_reset_connection_flags(struct rpc_xprt *xprt)
 {
        smp_mb__before_clear_bit();
        clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
@@ -1461,6 +1458,11 @@ static void xs_sock_mark_closed(struct rpc_xprt *xprt)
        clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
        clear_bit(XPRT_CLOSING, &xprt->state);
        smp_mb__after_clear_bit();
+}
+
+static void xs_sock_mark_closed(struct rpc_xprt *xprt)
+{
+       xs_sock_reset_connection_flags(xprt);
        /* Mark transport as closed and wake up all pending tasks */
        xprt_disconnect_done(xprt);
 }
@@ -1516,6 +1518,7 @@ static void xs_tcp_state_change(struct sock *sk)
        case TCP_CLOSE_WAIT:
                /* The server initiated a shutdown of the socket */
                xprt->connect_cookie++;
+               clear_bit(XPRT_CONNECTED, &xprt->state);
                xs_tcp_force_close(xprt);
        case TCP_CLOSING:
                /*
@@ -1540,25 +1543,6 @@ static void xs_tcp_state_change(struct sock *sk)
        read_unlock_bh(&sk->sk_callback_lock);
 }
 
-/**
- * xs_error_report - callback mainly for catching socket errors
- * @sk: socket
- */
-static void xs_error_report(struct sock *sk)
-{
-       struct rpc_xprt *xprt;
-
-       read_lock_bh(&sk->sk_callback_lock);
-       if (!(xprt = xprt_from_sock(sk)))
-               goto out;
-       dprintk("RPC:       %s client %p...\n"
-                       "RPC:       error %d\n",
-                       __func__, xprt, sk->sk_err);
-       xprt_wake_pending_tasks(xprt, -EAGAIN);
-out:
-       read_unlock_bh(&sk->sk_callback_lock);
-}
-
 static void xs_write_space(struct sock *sk)
 {
        struct socket *sock;
@@ -1858,7 +1842,6 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt,
                sk->sk_user_data = xprt;
                sk->sk_data_ready = xs_local_data_ready;
                sk->sk_write_space = xs_udp_write_space;
-               sk->sk_error_report = xs_error_report;
                sk->sk_allocation = GFP_ATOMIC;
 
                xprt_clear_connected(xprt);
@@ -1983,7 +1966,6 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
                sk->sk_user_data = xprt;
                sk->sk_data_ready = xs_udp_data_ready;
                sk->sk_write_space = xs_udp_write_space;
-               sk->sk_error_report = xs_error_report;
                sk->sk_no_check = UDP_CSUM_NORCV;
                sk->sk_allocation = GFP_ATOMIC;
 
@@ -2050,10 +2032,8 @@ static void xs_abort_connection(struct sock_xprt *transport)
        any.sa_family = AF_UNSPEC;
        result = kernel_connect(transport->sock, &any, sizeof(any), 0);
        if (!result)
-               xs_sock_mark_closed(&transport->xprt);
-       else
-               dprintk("RPC:       AF_UNSPEC connect return code %d\n",
-                               result);
+               xs_sock_reset_connection_flags(&transport->xprt);
+       dprintk("RPC:       AF_UNSPEC connect return code %d\n", result);
 }
 
 static void xs_tcp_reuse_connection(struct sock_xprt *transport)
@@ -2098,7 +2078,6 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
                sk->sk_data_ready = xs_tcp_data_ready;
                sk->sk_state_change = xs_tcp_state_change;
                sk->sk_write_space = xs_tcp_write_space;
-               sk->sk_error_report = xs_error_report;
                sk->sk_allocation = GFP_ATOMIC;
 
                /* socket options */
index 443d4d7deea299c7e997045d22d8b2b146d2c877..3f72530520883ae4aa510516bf7a4ce641c646d8 100644 (file)
@@ -526,8 +526,7 @@ int wiphy_register(struct wiphy *wiphy)
                for (i = 0; i < sband->n_channels; i++) {
                        sband->channels[i].orig_flags =
                                sband->channels[i].flags;
-                       sband->channels[i].orig_mag =
-                               sband->channels[i].max_antenna_gain;
+                       sband->channels[i].orig_mag = INT_MAX;
                        sband->channels[i].orig_mpwr =
                                sband->channels[i].max_power;
                        sband->channels[i].band = band;
index 8016fee0752b0325a20409b7b1b93b5433c73872..904a7f36832531cbe2fa3d50f220b94775eaf8a9 100644 (file)
@@ -457,20 +457,14 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
                .reason_code = reason,
                .ie = ie,
                .ie_len = ie_len,
+               .local_state_change = local_state_change,
        };
 
        ASSERT_WDEV_LOCK(wdev);
 
-       if (local_state_change) {
-               if (wdev->current_bss &&
-                   ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) {
-                       cfg80211_unhold_bss(wdev->current_bss);
-                       cfg80211_put_bss(&wdev->current_bss->pub);
-                       wdev->current_bss = NULL;
-               }
-
+       if (local_state_change && (!wdev->current_bss ||
+           !ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
                return 0;
-       }
 
        return rdev->ops->deauth(&rdev->wiphy, dev, &req);
 }
index 3b8cbbc214db563ba962ecda1e49fe6929c263cc..bcc7d7ee5a516b8263c93a2556ab079d6d369280 100644 (file)
@@ -908,7 +908,7 @@ static void handle_channel(struct wiphy *wiphy,
                        map_regdom_flags(reg_rule->flags) | bw_flags;
                chan->max_antenna_gain = chan->orig_mag =
                        (int) MBI_TO_DBI(power_rule->max_antenna_gain);
-               chan->max_power = chan->orig_mpwr =
+               chan->max_reg_power = chan->max_power = chan->orig_mpwr =
                        (int) MBM_TO_DBM(power_rule->max_eirp);
                return;
        }
@@ -1331,7 +1331,8 @@ static void handle_channel_custom(struct wiphy *wiphy,
 
        chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
        chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
-       chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp);
+       chan->max_reg_power = chan->max_power =
+               (int) MBM_TO_DBM(power_rule->max_eirp);
 }
 
 static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band,
index ef35f4ef2aa623d16f3556a5e3f4709fba363db4..2762e8329986afd57efd3f7735d1904e221ab05e 100644 (file)
@@ -309,23 +309,21 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
 }
 EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
 
-static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
+unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
 {
        int ae = meshhdr->flags & MESH_FLAGS_AE;
-       /* 7.1.3.5a.2 */
+       /* 802.11-2012, 8.2.4.7.3 */
        switch (ae) {
+       default:
        case 0:
                return 6;
        case MESH_FLAGS_AE_A4:
                return 12;
        case MESH_FLAGS_AE_A5_A6:
                return 18;
-       case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6):
-               return 24;
-       default:
-               return 6;
        }
 }
+EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
 
 int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
                           enum nl80211_iftype iftype)
@@ -373,6 +371,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
                        /* make sure meshdr->flags is on the linear part */
                        if (!pskb_may_pull(skb, hdrlen + 1))
                                return -1;
+                       if (meshdr->flags & MESH_FLAGS_AE_A4)
+                               return -1;
                        if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
                                skb_copy_bits(skb, hdrlen +
                                        offsetof(struct ieee80211s_hdr, eaddr1),
@@ -397,6 +397,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
                        /* make sure meshdr->flags is on the linear part */
                        if (!pskb_may_pull(skb, hdrlen + 1))
                                return -1;
+                       if (meshdr->flags & MESH_FLAGS_AE_A5_A6)
+                               return -1;
                        if (meshdr->flags & MESH_FLAGS_AE_A4)
                                skb_copy_bits(skb, hdrlen +
                                        offsetof(struct ieee80211s_hdr, eaddr1),
index cf5fd220309be40d597ac7ca02e0d61658cd8eee..813200384d97cfc7f06a76e9b2f6286be7dfa7ab 100644 (file)
@@ -724,6 +724,8 @@ fail:
  */
 static void free_profile(struct aa_profile *profile)
 {
+       struct aa_profile *p;
+
        AA_DEBUG("%s(%p)\n", __func__, profile);
 
        if (!profile)
@@ -751,7 +753,27 @@ static void free_profile(struct aa_profile *profile)
        aa_put_dfa(profile->xmatch);
        aa_put_dfa(profile->policy.dfa);
 
-       aa_put_profile(profile->replacedby);
+       /* put the profile reference for replacedby, but not via
+        * put_profile(kref_put).
+        * replacedby can form a long chain that can result in cascading
+        * frees that blows the stack because kref_put makes a nested fn
+        * call (it looks like recursion, with free_profile calling
+        * free_profile) for each profile in the chain lp#1056078.
+        */
+       for (p = profile->replacedby; p; ) {
+               if (atomic_dec_and_test(&p->base.count.refcount)) {
+                       /* no more refs on p, grab its replacedby */
+                       struct aa_profile *next = p->replacedby;
+                       /* break the chain */
+                       p->replacedby = NULL;
+                       /* now free p, chain is broken */
+                       free_profile(p);
+
+                       /* follow up with next profile in the chain */
+                       p = next;
+               } else
+                       break;
+       }
 
        kzfree(profile);
 }
index 44dfc415a379afc9c327388664e949bfcc855bcb..842c254396dbe8ab2a54fd566b37d29ce6fd4d8b 100644 (file)
@@ -42,7 +42,10 @@ struct dev_exception_item {
 struct dev_cgroup {
        struct cgroup_subsys_state css;
        struct list_head exceptions;
-       bool deny_all;
+       enum {
+               DEVCG_DEFAULT_ALLOW,
+               DEVCG_DEFAULT_DENY,
+       } behavior;
 };
 
 static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s)
@@ -182,13 +185,13 @@ static struct cgroup_subsys_state *devcgroup_create(struct cgroup *cgroup)
        parent_cgroup = cgroup->parent;
 
        if (parent_cgroup == NULL)
-               dev_cgroup->deny_all = false;
+               dev_cgroup->behavior = DEVCG_DEFAULT_ALLOW;
        else {
                parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup);
                mutex_lock(&devcgroup_mutex);
                ret = dev_exceptions_copy(&dev_cgroup->exceptions,
                                          &parent_dev_cgroup->exceptions);
-               dev_cgroup->deny_all = parent_dev_cgroup->deny_all;
+               dev_cgroup->behavior = parent_dev_cgroup->behavior;
                mutex_unlock(&devcgroup_mutex);
                if (ret) {
                        kfree(dev_cgroup);
@@ -260,7 +263,7 @@ static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
         * - List the exceptions in case the default policy is to deny
         * This way, the file remains as a "whitelist of devices"
         */
-       if (devcgroup->deny_all == false) {
+       if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) {
                set_access(acc, ACC_MASK);
                set_majmin(maj, ~0);
                set_majmin(min, ~0);
@@ -314,12 +317,12 @@ static int may_access(struct dev_cgroup *dev_cgroup,
         * In two cases we'll consider this new exception valid:
         * - the dev cgroup has its default policy to allow + exception list:
         *   the new exception should *not* match any of the exceptions
-        *   (!deny_all, !match)
+        *   (behavior == DEVCG_DEFAULT_ALLOW, !match)
         * - the dev cgroup has its default policy to deny + exception list:
         *   the new exception *should* match the exceptions
-        *   (deny_all, match)
+        *   (behavior == DEVCG_DEFAULT_DENY, match)
         */
-       if (dev_cgroup->deny_all == match)
+       if ((dev_cgroup->behavior == DEVCG_DEFAULT_DENY) == match)
                return 1;
        return 0;
 }
@@ -341,6 +344,17 @@ static int parent_has_perm(struct dev_cgroup *childcg,
        return may_access(parent, ex);
 }
 
+/**
+ * may_allow_all - checks if it's possible to change the behavior to
+ *                allow based on parent's rules.
+ * @parent: device cgroup's parent
+ * returns: != 0 in case it's allowed, 0 otherwise
+ */
+static inline int may_allow_all(struct dev_cgroup *parent)
+{
+       return parent->behavior == DEVCG_DEFAULT_ALLOW;
+}
+
 /*
  * Modify the exception list using allow/deny rules.
  * CAP_SYS_ADMIN is needed for this.  It's at least separate from CAP_MKNOD
@@ -358,9 +372,11 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                                   int filetype, const char *buffer)
 {
        const char *b;
-       char *endp;
-       int count;
+       char temp[12];          /* 11 + 1 characters needed for a u32 */
+       int count, rc;
        struct dev_exception_item ex;
+       struct cgroup *p = devcgroup->css.cgroup;
+       struct dev_cgroup *parent = cgroup_to_devcgroup(p->parent);
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -372,14 +388,18 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
        case 'a':
                switch (filetype) {
                case DEVCG_ALLOW:
-                       if (!parent_has_perm(devcgroup, &ex))
+                       if (!may_allow_all(parent))
                                return -EPERM;
                        dev_exception_clean(devcgroup);
-                       devcgroup->deny_all = false;
+                       rc = dev_exceptions_copy(&devcgroup->exceptions,
+                                                &parent->exceptions);
+                       if (rc)
+                               return rc;
+                       devcgroup->behavior = DEVCG_DEFAULT_ALLOW;
                        break;
                case DEVCG_DENY:
                        dev_exception_clean(devcgroup);
-                       devcgroup->deny_all = true;
+                       devcgroup->behavior = DEVCG_DEFAULT_DENY;
                        break;
                default:
                        return -EINVAL;
@@ -402,8 +422,16 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                ex.major = ~0;
                b++;
        } else if (isdigit(*b)) {
-               ex.major = simple_strtoul(b, &endp, 10);
-               b = endp;
+               memset(temp, 0, sizeof(temp));
+               for (count = 0; count < sizeof(temp) - 1; count++) {
+                       temp[count] = *b;
+                       b++;
+                       if (!isdigit(*b))
+                               break;
+               }
+               rc = kstrtou32(temp, 10, &ex.major);
+               if (rc)
+                       return -EINVAL;
        } else {
                return -EINVAL;
        }
@@ -416,8 +444,16 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                ex.minor = ~0;
                b++;
        } else if (isdigit(*b)) {
-               ex.minor = simple_strtoul(b, &endp, 10);
-               b = endp;
+               memset(temp, 0, sizeof(temp));
+               for (count = 0; count < sizeof(temp) - 1; count++) {
+                       temp[count] = *b;
+                       b++;
+                       if (!isdigit(*b))
+                               break;
+               }
+               rc = kstrtou32(temp, 10, &ex.minor);
+               if (rc)
+                       return -EINVAL;
        } else {
                return -EINVAL;
        }
@@ -452,7 +488,7 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                 * an matching exception instead. And be silent about it: we
                 * don't want to break compatibility
                 */
-               if (devcgroup->deny_all == false) {
+               if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) {
                        dev_exception_rm(devcgroup, &ex);
                        return 0;
                }
@@ -463,7 +499,7 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                 * an matching exception instead. And be silent about it: we
                 * don't want to break compatibility
                 */
-               if (devcgroup->deny_all == true) {
+               if (devcgroup->behavior == DEVCG_DEFAULT_DENY) {
                        dev_exception_rm(devcgroup, &ex);
                        return 0;
                }
@@ -533,10 +569,10 @@ struct cgroup_subsys devices_subsys = {
  *
  * returns 0 on success, -EPERM case the operation is not permitted
  */
-static int __devcgroup_check_permission(struct dev_cgroup *dev_cgroup,
-                                       short type, u32 major, u32 minor,
+static int __devcgroup_check_permission(short type, u32 major, u32 minor,
                                        short access)
 {
+       struct dev_cgroup *dev_cgroup;
        struct dev_exception_item ex;
        int rc;
 
@@ -547,6 +583,7 @@ static int __devcgroup_check_permission(struct dev_cgroup *dev_cgroup,
        ex.access = access;
 
        rcu_read_lock();
+       dev_cgroup = task_devcgroup(current);
        rc = may_access(dev_cgroup, &ex);
        rcu_read_unlock();
 
@@ -558,7 +595,6 @@ static int __devcgroup_check_permission(struct dev_cgroup *dev_cgroup,
 
 int __devcgroup_inode_permission(struct inode *inode, int mask)
 {
-       struct dev_cgroup *dev_cgroup = task_devcgroup(current);
        short type, access = 0;
 
        if (S_ISBLK(inode->i_mode))
@@ -570,13 +606,12 @@ int __devcgroup_inode_permission(struct inode *inode, int mask)
        if (mask & MAY_READ)
                access |= ACC_READ;
 
-       return __devcgroup_check_permission(dev_cgroup, type, imajor(inode),
-                                           iminor(inode), access);
+       return __devcgroup_check_permission(type, imajor(inode), iminor(inode),
+                       access);
 }
 
 int devcgroup_inode_mknod(int mode, dev_t dev)
 {
-       struct dev_cgroup *dev_cgroup = task_devcgroup(current);
        short type;
 
        if (!S_ISBLK(mode) && !S_ISCHR(mode))
@@ -587,7 +622,7 @@ int devcgroup_inode_mknod(int mode, dev_t dev)
        else
                type = DEV_CHAR;
 
-       return __devcgroup_check_permission(dev_cgroup, type, MAJOR(dev),
-                                           MINOR(dev), ACC_MKNOD);
+       return __devcgroup_check_permission(type, MAJOR(dev), MINOR(dev),
+                       ACC_MKNOD);
 
 }
index c40ae573346dd140031af773c532dd4f32f32240..ad11dc994792b4bb080c49a7036b8761731e5a1d 100644 (file)
@@ -100,12 +100,15 @@ static int snd_compr_open(struct inode *inode, struct file *f)
 
        if (dirn != compr->direction) {
                pr_err("this device doesn't support this direction\n");
+               snd_card_unref(compr->card);
                return -EINVAL;
        }
 
        data = kzalloc(sizeof(*data), GFP_KERNEL);
-       if (!data)
+       if (!data) {
+               snd_card_unref(compr->card);
                return -ENOMEM;
+       }
        data->stream.ops = compr->ops;
        data->stream.direction = dirn;
        data->stream.private_data = compr->private_data;
@@ -113,6 +116,7 @@ static int snd_compr_open(struct inode *inode, struct file *f)
        runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
        if (!runtime) {
                kfree(data);
+               snd_card_unref(compr->card);
                return -ENOMEM;
        }
        runtime->state = SNDRV_PCM_STATE_OPEN;
@@ -126,7 +130,8 @@ static int snd_compr_open(struct inode *inode, struct file *f)
                kfree(runtime);
                kfree(data);
        }
-       return ret;
+       snd_card_unref(compr->card);
+       return 0;
 }
 
 static int snd_compr_free(struct inode *inode, struct file *f)
index 7e86a5b9f3b572f9c97f351027ed4e1b9b7b75b3..8c7c2c9bba61e4dd421eb6a0c797bd0cf17b81ae 100644 (file)
@@ -86,6 +86,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
        write_lock_irqsave(&card->ctl_files_rwlock, flags);
        list_add_tail(&ctl->list, &card->ctl_files);
        write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
+       snd_card_unref(card);
        return 0;
 
       __error:
@@ -93,6 +94,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
       __error2:
        snd_card_file_remove(card, file);
       __error1:
+       if (card)
+               snd_card_unref(card);
        return err;
 }
 
@@ -1434,6 +1437,8 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer,
                        spin_unlock_irq(&ctl->read_lock);
                        schedule();
                        remove_wait_queue(&ctl->change_sleep, &wait);
+                       if (ctl->card->shutdown)
+                               return -ENODEV;
                        if (signal_pending(current))
                                return -ERESTARTSYS;
                        spin_lock_irq(&ctl->read_lock);
index 75ea16f35b1aa1e1db985802e923c86e28f69af3..3f7f6628cf7b1704ed7cdb4094703416697af0a0 100644 (file)
@@ -100,8 +100,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
        if (hw == NULL)
                return -ENODEV;
 
-       if (!try_module_get(hw->card->module))
+       if (!try_module_get(hw->card->module)) {
+               snd_card_unref(hw->card);
                return -EFAULT;
+       }
 
        init_waitqueue_entry(&wait, current);
        add_wait_queue(&hw->open_wait, &wait);
@@ -129,6 +131,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
                mutex_unlock(&hw->open_mutex);
                schedule();
                mutex_lock(&hw->open_mutex);
+               if (hw->card->shutdown) {
+                       err = -ENODEV;
+                       break;
+               }
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
@@ -148,6 +154,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
        mutex_unlock(&hw->open_mutex);
        if (err < 0)
                module_put(hw->card->module);
+       snd_card_unref(hw->card);
        return err;
 }
 
@@ -459,12 +466,15 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device)
                mutex_unlock(&register_mutex);
                return -EINVAL;
        }
+       mutex_lock(&hwdep->open_mutex);
+       wake_up(&hwdep->open_wait);
 #ifdef CONFIG_SND_OSSEMUL
        if (hwdep->ossreg)
                snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device);
 #endif
        snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device);
        list_del_init(&hwdep->list);
+       mutex_unlock(&hwdep->open_mutex);
        mutex_unlock(&register_mutex);
        return 0;
 }
index d8ec849af128ed1d248effdd2f606baa52a5f06d..7b012d15c2cf1599e92d0ddc832a6b0ece653e9e 100644 (file)
@@ -213,6 +213,7 @@ int snd_card_create(int idx, const char *xid,
        spin_lock_init(&card->files_lock);
        INIT_LIST_HEAD(&card->files_list);
        init_waitqueue_head(&card->shutdown_sleep);
+       atomic_set(&card->refcount, 0);
 #ifdef CONFIG_PM
        mutex_init(&card->power_lock);
        init_waitqueue_head(&card->power_sleep);
@@ -446,21 +447,36 @@ static int snd_card_do_free(struct snd_card *card)
        return 0;
 }
 
+/**
+ * snd_card_unref - release the reference counter
+ * @card: the card instance
+ *
+ * Decrements the reference counter.  When it reaches to zero, wake up
+ * the sleeper and call the destructor if needed.
+ */
+void snd_card_unref(struct snd_card *card)
+{
+       if (atomic_dec_and_test(&card->refcount)) {
+               wake_up(&card->shutdown_sleep);
+               if (card->free_on_last_close)
+                       snd_card_do_free(card);
+       }
+}
+EXPORT_SYMBOL(snd_card_unref);
+
 int snd_card_free_when_closed(struct snd_card *card)
 {
-       int free_now = 0;
-       int ret = snd_card_disconnect(card);
-       if (ret)
-               return ret;
+       int ret;
 
-       spin_lock(&card->files_lock);
-       if (list_empty(&card->files_list))
-               free_now = 1;
-       else
-               card->free_on_last_close = 1;
-       spin_unlock(&card->files_lock);
+       atomic_inc(&card->refcount);
+       ret = snd_card_disconnect(card);
+       if (ret) {
+               atomic_dec(&card->refcount);
+               return ret;
+       }
 
-       if (free_now)
+       card->free_on_last_close = 1;
+       if (atomic_dec_and_test(&card->refcount))
                snd_card_do_free(card);
        return 0;
 }
@@ -474,7 +490,7 @@ int snd_card_free(struct snd_card *card)
                return ret;
 
        /* wait, until all devices are ready for the free operation */
-       wait_event(card->shutdown_sleep, list_empty(&card->files_list));
+       wait_event(card->shutdown_sleep, !atomic_read(&card->refcount));
        snd_card_do_free(card);
        return 0;
 }
@@ -886,6 +902,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
                return -ENODEV;
        }
        list_add(&mfile->list, &card->files_list);
+       atomic_inc(&card->refcount);
        spin_unlock(&card->files_lock);
        return 0;
 }
@@ -908,7 +925,6 @@ EXPORT_SYMBOL(snd_card_file_add);
 int snd_card_file_remove(struct snd_card *card, struct file *file)
 {
        struct snd_monitor_file *mfile, *found = NULL;
-       int last_close = 0;
 
        spin_lock(&card->files_lock);
        list_for_each_entry(mfile, &card->files_list, list) {
@@ -923,19 +939,13 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
                        break;
                }
        }
-       if (list_empty(&card->files_list))
-               last_close = 1;
        spin_unlock(&card->files_lock);
-       if (last_close) {
-               wake_up(&card->shutdown_sleep);
-               if (card->free_on_last_close)
-                       snd_card_do_free(card);
-       }
        if (!found) {
                snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);
                return -ENOENT;
        }
        kfree(found);
+       snd_card_unref(card);
        return 0;
 }
 
index 29f6ded02555568498473fb37547c9e7b0b96c2b..a9a2e63c0222cc838baef18870384586febab3d8 100644 (file)
@@ -52,14 +52,19 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
                                         SNDRV_OSS_DEVICE_TYPE_MIXER);
        if (card == NULL)
                return -ENODEV;
-       if (card->mixer_oss == NULL)
+       if (card->mixer_oss == NULL) {
+               snd_card_unref(card);
                return -ENODEV;
+       }
        err = snd_card_file_add(card, file);
-       if (err < 0)
+       if (err < 0) {
+               snd_card_unref(card);
                return err;
+       }
        fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL);
        if (fmixer == NULL) {
                snd_card_file_remove(card, file);
+               snd_card_unref(card);
                return -ENOMEM;
        }
        fmixer->card = card;
@@ -68,6 +73,7 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
        if (!try_module_get(card->module)) {
                kfree(fmixer);
                snd_card_file_remove(card, file);
+               snd_card_unref(card);
                return -EFAULT;
        }
        return 0;
index 08fde0060fd9377ee9f5e12dc1113858c73b3d20..f337b66a020b5bbbfbf15c6730c2ec0143bfd11b 100644 (file)
@@ -2441,6 +2441,10 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
                mutex_unlock(&pcm->open_mutex);
                schedule();
                mutex_lock(&pcm->open_mutex);
+               if (pcm->card->shutdown) {
+                       err = -ENODEV;
+                       break;
+               }
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
@@ -2457,6 +2461,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
       __error2:
        snd_card_file_remove(pcm->card, file);
       __error1:
+       if (pcm)
+               snd_card_unref(pcm->card);
        return err;
 }
 
index f2991940b271df46ef503173750a89d874fec6ad..030102caeee96b8080d9af6f2c99217278ec5a86 100644 (file)
@@ -1086,11 +1086,19 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
        if (list_empty(&pcm->list))
                goto unlock;
 
+       mutex_lock(&pcm->open_mutex);
+       wake_up(&pcm->open_wait);
        list_del_init(&pcm->list);
        for (cidx = 0; cidx < 2; cidx++)
-               for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
-                       if (substream->runtime)
+               for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
+                       snd_pcm_stream_lock_irq(substream);
+                       if (substream->runtime) {
                                substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
+                               wake_up(&substream->runtime->sleep);
+                               wake_up(&substream->runtime->tsleep);
+                       }
+                       snd_pcm_stream_unlock_irq(substream);
+               }
        list_for_each_entry(notify, &snd_pcm_notify_list, list) {
                notify->n_disconnect(pcm);
        }
@@ -1110,6 +1118,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
                        pcm->streams[cidx].chmap_kctl = NULL;
                }
        }
+       mutex_unlock(&pcm->open_mutex);
  unlock:
        mutex_unlock(&register_mutex);
        return 0;
index 5e12e5bacbba36cdf64c41a1d6e7e3d984902cf9..6e8872de5ba05f78864eba53fa577197370c33a9 100644 (file)
@@ -369,6 +369,14 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime)
        return usecs;
 }
 
+static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state)
+{
+       snd_pcm_stream_lock_irq(substream);
+       if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED)
+               substream->runtime->status->state = state;
+       snd_pcm_stream_unlock_irq(substream);
+}
+
 static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
                             struct snd_pcm_hw_params *params)
 {
@@ -452,7 +460,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
                runtime->boundary *= 2;
 
        snd_pcm_timer_resolution_change(substream);
-       runtime->status->state = SNDRV_PCM_STATE_SETUP;
+       snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);
 
        if (pm_qos_request_active(&substream->latency_pm_qos_req))
                pm_qos_remove_request(&substream->latency_pm_qos_req);
@@ -464,7 +472,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
        /* hardware might be unusable from this time,
           so we force application to retry to set
           the correct hardware parameter settings */
-       runtime->status->state = SNDRV_PCM_STATE_OPEN;
+       snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
        if (substream->ops->hw_free != NULL)
                substream->ops->hw_free(substream);
        return err;
@@ -512,7 +520,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
                return -EBADFD;
        if (substream->ops->hw_free)
                result = substream->ops->hw_free(substream);
-       runtime->status->state = SNDRV_PCM_STATE_OPEN;
+       snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
        pm_qos_remove_request(&substream->latency_pm_qos_req);
        return result;
 }
@@ -1320,7 +1328,7 @@ static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        runtime->control->appl_ptr = runtime->status->hw_ptr;
-       runtime->status->state = SNDRV_PCM_STATE_PREPARED;
+       snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED);
 }
 
 static struct action_ops snd_pcm_action_prepare = {
@@ -1510,6 +1518,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
                down_read(&snd_pcm_link_rwsem);
                snd_pcm_stream_lock_irq(substream);
                remove_wait_queue(&to_check->sleep, &wait);
+               if (card->shutdown) {
+                       result = -ENODEV;
+                       break;
+               }
                if (tout == 0) {
                        if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
                                result = -ESTRPIPE;
@@ -1634,6 +1646,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
        write_unlock_irq(&snd_pcm_link_rwlock);
        up_write(&snd_pcm_link_rwsem);
  _nolock:
+       snd_card_unref(substream1->pcm->card);
        fput_light(file, fput_needed);
        if (res < 0)
                kfree(group);
@@ -2108,7 +2121,9 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file)
                return err;
        pcm = snd_lookup_minor_data(iminor(inode),
                                    SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
-       return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
+       err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
+       snd_card_unref(pcm->card);
+       return err;
 }
 
 static int snd_pcm_capture_open(struct inode *inode, struct file *file)
@@ -2119,7 +2134,9 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file)
                return err;
        pcm = snd_lookup_minor_data(iminor(inode),
                                    SNDRV_DEVICE_TYPE_PCM_CAPTURE);
-       return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
+       err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
+       snd_card_unref(pcm->card);
+       return err;
 }
 
 static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
@@ -2156,6 +2173,10 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
                mutex_unlock(&pcm->open_mutex);
                schedule();
                mutex_lock(&pcm->open_mutex);
+               if (pcm->card->shutdown) {
+                       err = -ENODEV;
+                       break;
+               }
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
index ebf6e49ad3d461ba843131d903b0c66cc7840ba4..1bb95aeea084d33cd8225c53257058a23c25cf4e 100644 (file)
@@ -379,8 +379,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
        if (rmidi == NULL)
                return -ENODEV;
 
-       if (!try_module_get(rmidi->card->module))
+       if (!try_module_get(rmidi->card->module)) {
+               snd_card_unref(rmidi->card);
                return -ENXIO;
+       }
 
        mutex_lock(&rmidi->open_mutex);
        card = rmidi->card;
@@ -422,6 +424,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
                mutex_unlock(&rmidi->open_mutex);
                schedule();
                mutex_lock(&rmidi->open_mutex);
+               if (rmidi->card->shutdown) {
+                       err = -ENODEV;
+                       break;
+               }
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
@@ -440,6 +446,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
 #endif
        file->private_data = rawmidi_file;
        mutex_unlock(&rmidi->open_mutex);
+       snd_card_unref(rmidi->card);
        return 0;
 
  __error:
@@ -447,6 +454,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
  __error_card:
        mutex_unlock(&rmidi->open_mutex);
        module_put(rmidi->card->module);
+       snd_card_unref(rmidi->card);
        return err;
 }
 
@@ -991,6 +999,8 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
                        spin_unlock_irq(&runtime->lock);
                        schedule();
                        remove_wait_queue(&runtime->sleep, &wait);
+                       if (rfile->rmidi->card->shutdown)
+                               return -ENODEV;
                        if (signal_pending(current))
                                return result > 0 ? result : -ERESTARTSYS;
                        if (!runtime->avail)
@@ -1234,6 +1244,8 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,
                        spin_unlock_irq(&runtime->lock);
                        timeout = schedule_timeout(30 * HZ);
                        remove_wait_queue(&runtime->sleep, &wait);
+                       if (rfile->rmidi->card->shutdown)
+                               return -ENODEV;
                        if (signal_pending(current))
                                return result > 0 ? result : -ERESTARTSYS;
                        if (!runtime->avail && !timeout)
@@ -1609,9 +1621,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
 static int snd_rawmidi_dev_disconnect(struct snd_device *device)
 {
        struct snd_rawmidi *rmidi = device->device_data;
+       int dir;
 
        mutex_lock(&register_mutex);
+       mutex_lock(&rmidi->open_mutex);
+       wake_up(&rmidi->open_wait);
        list_del_init(&rmidi->list);
+       for (dir = 0; dir < 2; dir++) {
+               struct snd_rawmidi_substream *s;
+               list_for_each_entry(s, &rmidi->streams[dir].substreams, list) {
+                       if (s->runtime)
+                               wake_up(&s->runtime->sleep);
+               }
+       }
+
 #ifdef CONFIG_SND_OSSEMUL
        if (rmidi->ossreg) {
                if ((int)rmidi->device == midi_map[rmidi->card->number]) {
@@ -1626,6 +1649,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device)
        }
 #endif /* CONFIG_SND_OSSEMUL */
        snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);
+       mutex_unlock(&rmidi->open_mutex);
        mutex_unlock(&register_mutex);
        return 0;
 }
index 643976000ce825d1857fd3a3192fadeff0da4e5b..89780c323f19f817b81ecfbf7fad655e7b66265d 100644 (file)
@@ -98,6 +98,10 @@ static void snd_request_other(int minor)
  *
  * Checks that a minor device with the specified type is registered, and returns
  * its user data pointer.
+ *
+ * This function increments the reference counter of the card instance
+ * if an associated instance with the given minor number and type is found.
+ * The caller must call snd_card_unref() appropriately later.
  */
 void *snd_lookup_minor_data(unsigned int minor, int type)
 {
@@ -108,9 +112,11 @@ void *snd_lookup_minor_data(unsigned int minor, int type)
                return NULL;
        mutex_lock(&sound_mutex);
        mreg = snd_minors[minor];
-       if (mreg && mreg->type == type)
+       if (mreg && mreg->type == type) {
                private_data = mreg->private_data;
-       else
+               if (mreg->card_ptr)
+                       atomic_inc(&mreg->card_ptr->refcount);
+       } else
                private_data = NULL;
        mutex_unlock(&sound_mutex);
        return private_data;
@@ -275,6 +281,7 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev,
        preg->device = dev;
        preg->f_ops = f_ops;
        preg->private_data = private_data;
+       preg->card_ptr = card;
        mutex_lock(&sound_mutex);
 #ifdef CONFIG_SND_DYNAMIC_MINORS
        minor = snd_find_free_minor(type);
index e9528333e36d01e6e0282255639da08b7174e505..e1d79ee3590650d12e9d2c99a260ae63aed221c2 100644 (file)
@@ -40,6 +40,9 @@
 static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];
 static DEFINE_MUTEX(sound_oss_mutex);
 
+/* NOTE: This function increments the refcount of the associated card like
+ * snd_lookup_minor_data(); the caller must call snd_card_unref() appropriately
+ */
 void *snd_lookup_oss_minor_data(unsigned int minor, int type)
 {
        struct snd_minor *mreg;
@@ -49,9 +52,11 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type)
                return NULL;
        mutex_lock(&sound_oss_mutex);
        mreg = snd_oss_minors[minor];
-       if (mreg && mreg->type == type)
+       if (mreg && mreg->type == type) {
                private_data = mreg->private_data;
-       else
+               if (mreg->card_ptr)
+                       atomic_inc(&mreg->card_ptr->refcount);
+       } else
                private_data = NULL;
        mutex_unlock(&sound_oss_mutex);
        return private_data;
@@ -123,6 +128,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
        preg->device = dev;
        preg->f_ops = f_ops;
        preg->private_data = private_data;
+       preg->card_ptr = card;
        mutex_lock(&sound_oss_mutex);
        snd_oss_minors[minor] = preg;
        minor_unit = SNDRV_MINOR_OSS_DEVICE(minor);
index 3d1afb612b3548ade1db68d1b60af8f3e7e6ce4b..4a7ff4e8985ba2fe3b71ac7b57a191e694063ae2 100644 (file)
@@ -1286,7 +1286,6 @@ static int __devinit snd_miro_probe(struct snd_card *card)
 
        error = snd_card_miro_aci_detect(card, miro);
        if (error < 0) {
-               snd_card_free(card);
                snd_printk(KERN_ERR "unable to detect aci chip\n");
                return -ENODEV;
        }
index 00f157a2cf6411d8b1ad1b1ffef32f566d5e02b8..5af3cb6b0c18d36345aadfefee3d509404bbba80 100644 (file)
@@ -394,6 +394,8 @@ static int snd_als300_playback_open(struct snd_pcm_substream *substream)
        struct snd_als300_substream_data *data = kzalloc(sizeof(*data),
                                                                GFP_KERNEL);
 
+       if (!data)
+               return -ENOMEM;
        snd_als300_dbgcallenter();
        chip->playback_substream = substream;
        runtime->hw = snd_als300_playback_hw;
@@ -425,6 +427,8 @@ static int snd_als300_capture_open(struct snd_pcm_substream *substream)
        struct snd_als300_substream_data *data = kzalloc(sizeof(*data),
                                                                GFP_KERNEL);
 
+       if (!data)
+               return -ENOMEM;
        snd_als300_dbgcallenter();
        chip->capture_substream = substream;
        runtime->hw = snd_als300_capture_hw;
index 48d9d609f89b06bca17210b8ca9dfaec2a600c1d..f7397ad02a0dedbc872cbd7560704d4eb84cbb19 100644 (file)
@@ -5677,6 +5677,7 @@ static const struct hda_verb alc268_beep_init_verbs[] = {
 
 enum {
        ALC268_FIXUP_INV_DMIC,
+       ALC268_FIXUP_HP_EAPD,
 };
 
 static const struct alc_fixup alc268_fixups[] = {
@@ -5684,10 +5685,26 @@ static const struct alc_fixup alc268_fixups[] = {
                .type = ALC_FIXUP_FUNC,
                .v.func = alc_fixup_inv_dmic_0x12,
        },
+       [ALC268_FIXUP_HP_EAPD] = {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       {0x15, AC_VERB_SET_EAPD_BTLENABLE, 0},
+                       {}
+               }
+       },
 };
 
 static const struct alc_model_fixup alc268_fixup_models[] = {
        {.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"},
+       {.id = ALC268_FIXUP_HP_EAPD, .name = "hp-eapd"},
+       {}
+};
+
+static const struct snd_pci_quirk alc268_fixup_tbl[] = {
+       /* below is codec SSID since multiple Toshiba laptops have the
+        * same PCI SSID 1179:ff00
+        */
+       SND_PCI_QUIRK(0x1179, 0xff06, "Toshiba P200", ALC268_FIXUP_HP_EAPD),
        {}
 };
 
@@ -5722,7 +5739,7 @@ static int patch_alc268(struct hda_codec *codec)
 
        spec = codec->spec;
 
-       alc_pick_fixup(codec, alc268_fixup_models, NULL, alc268_fixups);
+       alc_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups);
        alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
 
        /* automatic parse from the BIOS config */
@@ -6188,6 +6205,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK),
+       SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
index 770013ff556f6be0500b14039a8e60df2fa74b2a..9ba8af05617080f8081a5a69d68bcaec81cfb847 100644 (file)
@@ -1763,6 +1763,8 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
                          "HP", STAC_HP_ZEPHYR),
        SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3660,
                          "HP Mini", STAC_92HD83XXX_HP_LED),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x144E,
+                         "HP Pavilion dv5", STAC_92HD83XXX_HP_INV_LED),
        {} /* terminator */
 };
 
index 3050a52792532ad3a58303f54a800dcc7c0ab883..245d874891ba25c2d993ea9de44536e0ab27ae6e 100644 (file)
@@ -2859,7 +2859,12 @@ static int snd_vt1724_resume(struct device *dev)
                ice->set_spdif_clock(ice, 0);
        } else {
                /* internal on-card clock */
-               snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1);
+               int rate;
+               if (ice->cur_rate)
+                       rate = ice->cur_rate;
+               else
+                       rate = ice->pro_rate_default;
+               snd_vt1724_set_pro_rate(ice, rate, 1);
        }
 
        update_spdif_bits(ice, ice->pm_saved_spdif_ctrl);
index b12308b5ba2a01170b56b5cd7b69a9d1d93aa6e3..f1cd1e387801bee9d73692f02ec7a2bca546ca28 100644 (file)
@@ -971,6 +971,7 @@ static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
 static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
 static int hdspm_autosync_ref(struct hdspm *hdspm);
 static int snd_hdspm_set_defaults(struct hdspm *hdspm);
+static int hdspm_system_clock_mode(struct hdspm *hdspm);
 static void hdspm_set_sgbuf(struct hdspm *hdspm,
                            struct snd_pcm_substream *substream,
                             unsigned int reg, int channels);
@@ -1989,10 +1990,14 @@ static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
        rate = hdspm_calc_dds_value(hdspm, period);
 
        if (rate > 207000) {
-               /* Unreasonable high sample rate as seen on PCI MADI cards.
-                * Use the cached value instead.
-                */
-               rate = hdspm->system_sample_rate;
+               /* Unreasonable high sample rate as seen on PCI MADI cards. */
+               if (0 == hdspm_system_clock_mode(hdspm)) {
+                       /* master mode, return internal sample rate */
+                       rate = hdspm->system_sample_rate;
+               } else {
+                       /* slave mode, return external sample rate */
+                       rate = hdspm_external_sample_rate(hdspm);
+               }
        }
 
        return rate;
@@ -2000,12 +2005,14 @@ static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
 
 
 #define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READ, \
-  .info = snd_hdspm_info_system_sample_rate, \
-  .get = snd_hdspm_get_system_sample_rate \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
+               SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+       .info = snd_hdspm_info_system_sample_rate, \
+       .put = snd_hdspm_put_system_sample_rate, \
+       .get = snd_hdspm_get_system_sample_rate \
 }
 
 static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
@@ -2030,6 +2037,16 @@ static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol,
+                                           struct snd_ctl_elem_value *
+                                           ucontrol)
+{
+       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+       hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]);
+       return 0;
+}
+
 
 /**
  * Returns the WordClock sample rate class for the given card.
@@ -2163,6 +2180,7 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
                                hdspm_get_s1_sample_rate(hdspm,
                                                kcontrol->private_value-1);
                }
+               break;
 
        case AIO:
                switch (kcontrol->private_value) {
@@ -2183,6 +2201,7 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
                                hdspm_get_s1_sample_rate(hdspm,
                                                ucontrol->id.index-1);
                }
+               break;
 
        case AES32:
 
@@ -2204,8 +2223,23 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
                                hdspm_get_s1_sample_rate(hdspm,
                                                kcontrol->private_value-1);
                        break;
+               }
+               break;
 
+       case MADI:
+       case MADIface:
+               {
+                       int rate = hdspm_external_sample_rate(hdspm);
+                       int i, selected_rate = 0;
+                       for (i = 1; i < 10; i++)
+                               if (HDSPM_bit2freq(i) == rate) {
+                                       selected_rate = i;
+                                       break;
+                               }
+                       ucontrol->value.enumerated.item[0] = selected_rate;
                }
+               break;
+
        default:
                break;
        }
@@ -2430,7 +2464,7 @@ static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_PREF_SYNC_REF(xname, xindex) \
-{.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
        .name = xname, \
        .index = xindex, \
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
@@ -2766,12 +2800,12 @@ static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_AUTOSYNC_REF(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READ, \
-  .info = snd_hdspm_info_autosync_ref, \
-  .get = snd_hdspm_get_autosync_ref, \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .access = SNDRV_CTL_ELEM_ACCESS_READ, \
+       .info = snd_hdspm_info_autosync_ref, \
+       .get = snd_hdspm_get_autosync_ref, \
 }
 
 static int hdspm_autosync_ref(struct hdspm *hdspm)
@@ -2855,12 +2889,12 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_LINE_OUT(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_line_out, \
-  .get = snd_hdspm_get_line_out, \
-  .put = snd_hdspm_put_line_out \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_line_out, \
+       .get = snd_hdspm_get_line_out, \
+       .put = snd_hdspm_put_line_out \
 }
 
 static int hdspm_line_out(struct hdspm * hdspm)
@@ -2912,12 +2946,12 @@ static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_TX_64(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_tx_64, \
-  .get = snd_hdspm_get_tx_64, \
-  .put = snd_hdspm_put_tx_64 \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_tx_64, \
+       .get = snd_hdspm_get_tx_64, \
+       .put = snd_hdspm_put_tx_64 \
 }
 
 static int hdspm_tx_64(struct hdspm * hdspm)
@@ -2968,12 +3002,12 @@ static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_C_TMS(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_c_tms, \
-  .get = snd_hdspm_get_c_tms, \
-  .put = snd_hdspm_put_c_tms \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_c_tms, \
+       .get = snd_hdspm_get_c_tms, \
+       .put = snd_hdspm_put_c_tms \
 }
 
 static int hdspm_c_tms(struct hdspm * hdspm)
@@ -3024,12 +3058,12 @@ static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_SAFE_MODE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_safe_mode, \
-  .get = snd_hdspm_get_safe_mode, \
-  .put = snd_hdspm_put_safe_mode \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_safe_mode, \
+       .get = snd_hdspm_get_safe_mode, \
+       .put = snd_hdspm_put_safe_mode \
 }
 
 static int hdspm_safe_mode(struct hdspm * hdspm)
@@ -3080,12 +3114,12 @@ static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_EMPHASIS(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_emphasis, \
-  .get = snd_hdspm_get_emphasis, \
-  .put = snd_hdspm_put_emphasis \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_emphasis, \
+       .get = snd_hdspm_get_emphasis, \
+       .put = snd_hdspm_put_emphasis \
 }
 
 static int hdspm_emphasis(struct hdspm * hdspm)
@@ -3136,12 +3170,12 @@ static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_DOLBY(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_dolby, \
-  .get = snd_hdspm_get_dolby, \
-  .put = snd_hdspm_put_dolby \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_dolby, \
+       .get = snd_hdspm_get_dolby, \
+       .put = snd_hdspm_put_dolby \
 }
 
 static int hdspm_dolby(struct hdspm * hdspm)
@@ -3192,12 +3226,12 @@ static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_PROFESSIONAL(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_professional, \
-  .get = snd_hdspm_get_professional, \
-  .put = snd_hdspm_put_professional \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_professional, \
+       .get = snd_hdspm_get_professional, \
+       .put = snd_hdspm_put_professional \
 }
 
 static int hdspm_professional(struct hdspm * hdspm)
@@ -3247,12 +3281,12 @@ static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
 }
 
 #define HDSPM_INPUT_SELECT(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_input_select, \
-  .get = snd_hdspm_get_input_select, \
-  .put = snd_hdspm_put_input_select \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_input_select, \
+       .get = snd_hdspm_get_input_select, \
+       .put = snd_hdspm_put_input_select \
 }
 
 static int hdspm_input_select(struct hdspm * hdspm)
@@ -3319,12 +3353,12 @@ static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_DS_WIRE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_ds_wire, \
-  .get = snd_hdspm_get_ds_wire, \
-  .put = snd_hdspm_put_ds_wire \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_ds_wire, \
+       .get = snd_hdspm_get_ds_wire, \
+       .put = snd_hdspm_put_ds_wire \
 }
 
 static int hdspm_ds_wire(struct hdspm * hdspm)
@@ -3391,12 +3425,12 @@ static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_QS_WIRE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_qs_wire, \
-  .get = snd_hdspm_get_qs_wire, \
-  .put = snd_hdspm_put_qs_wire \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_qs_wire, \
+       .get = snd_hdspm_get_qs_wire, \
+       .put = snd_hdspm_put_qs_wire \
 }
 
 static int hdspm_qs_wire(struct hdspm * hdspm)
@@ -3563,15 +3597,15 @@ static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol,
 }
 
 #define HDSPM_MIXER(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
-  .name = xname, \
-  .index = xindex, \
-  .device = 0, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
-                SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
-  .info = snd_hdspm_info_mixer, \
-  .get = snd_hdspm_get_mixer, \
-  .put = snd_hdspm_put_mixer \
+{      .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+       .name = xname, \
+       .index = xindex, \
+       .device = 0, \
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
+               SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+       .info = snd_hdspm_info_mixer, \
+       .get = snd_hdspm_get_mixer, \
+       .put = snd_hdspm_put_mixer \
 }
 
 static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
@@ -3670,12 +3704,12 @@ static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
 */
 
 #define HDSPM_PLAYBACK_MIXER \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
-                SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
-  .info = snd_hdspm_info_playback_mixer, \
-  .get = snd_hdspm_get_playback_mixer, \
-  .put = snd_hdspm_put_playback_mixer \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
+               SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+       .info = snd_hdspm_info_playback_mixer, \
+       .get = snd_hdspm_get_playback_mixer, \
+       .put = snd_hdspm_put_playback_mixer \
 }
 
 static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
@@ -3851,12 +3885,17 @@ static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
                break;
 
        case MADI:
-       case AES32:
-               status = hdspm_read(hdspm, HDSPM_statusRegister2);
+               status = hdspm_read(hdspm, HDSPM_statusRegister);
                lock = (status & HDSPM_syncInLock) ? 1 : 0;
                sync = (status & HDSPM_syncInSync) ? 1 : 0;
                break;
 
+       case AES32:
+               status = hdspm_read(hdspm, HDSPM_statusRegister2);
+               lock = (status & 0x100000) ? 1 : 0;
+               sync = (status & 0x200000) ? 1 : 0;
+               break;
+
        case MADIface:
                break;
        }
@@ -3942,6 +3981,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
                default:
                        val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
                }
+               break;
 
        case AIO:
                switch (kcontrol->private_value) {
@@ -3954,6 +3994,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
                default:
                        val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
                }
+               break;
 
        case MADI:
                switch (kcontrol->private_value) {
@@ -3966,6 +4007,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
                case 3: /* SYNC_IN */
                        val = hdspm_sync_in_sync_check(hdspm); break;
                }
+               break;
 
        case MADIface:
                val = hdspm_madi_sync_check(hdspm); /* MADI */
@@ -3983,6 +4025,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
                         val = hdspm_aes_sync_check(hdspm,
                                         kcontrol->private_value-1);
                }
+               break;
 
        }
 
@@ -4427,9 +4470,10 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
        HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
        HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
        HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
+       HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
        HDSPM_SYNC_CHECK("WC SyncCheck", 0),
        HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
-       HDSPM_SYNC_CHECK("TCO SyncCHeck", 2),
+       HDSPM_SYNC_CHECK("TCO SyncCheck", 2),
        HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
        HDSPM_LINE_OUT("Line Out", 0),
        HDSPM_TX_64("TX 64 channels mode", 0),
index c88351488f45c5c6adb0529a212ab257531a90fd..228ca6a8e77bf5d1a6d609fa4646c38607e21e5c 100644 (file)
@@ -195,22 +195,15 @@ static struct snd_soc_card snd_soc_at91sam9g20ek = {
        .set_bias_level = at91sam9g20ek_set_bias_level,
 };
 
-static struct platform_device *at91sam9g20ek_snd_device;
-
-static int __init at91sam9g20ek_init(void)
+static int __devinit at91sam9g20ek_audio_probe(struct platform_device *pdev)
 {
        struct clk *pllb;
+       struct snd_soc_card *card = &snd_soc_at91sam9g20ek;
        int ret;
 
        if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc()))
                return -ENODEV;
 
-       ret = atmel_ssc_set_audio(0);
-       if (ret != 0) {
-               pr_err("Failed to set SSC 0 for audio: %d\n", ret);
-               return ret;
-       }
-
        /*
         * Codec MCLK is supplied by PCK0 - set it up.
         */
@@ -236,26 +229,14 @@ static int __init at91sam9g20ek_init(void)
 
        clk_set_rate(mclk, MCLK_RATE);
 
-       at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1);
-       if (!at91sam9g20ek_snd_device) {
-               printk(KERN_ERR "ASoC: Platform device allocation failed\n");
-               ret = -ENOMEM;
-               goto err_mclk;
-       }
-
-       platform_set_drvdata(at91sam9g20ek_snd_device,
-                       &snd_soc_at91sam9g20ek);
-
-       ret = platform_device_add(at91sam9g20ek_snd_device);
+       card->dev = &pdev->dev;
+       ret = snd_soc_register_card(card);
        if (ret) {
-               printk(KERN_ERR "ASoC: Platform device allocation failed\n");
-               goto err_device_add;
+               printk(KERN_ERR "ASoC: snd_soc_register_card() failed\n");
        }
 
        return ret;
 
-err_device_add:
-       platform_device_put(at91sam9g20ek_snd_device);
 err_mclk:
        clk_put(mclk);
        mclk = NULL;
@@ -263,18 +244,30 @@ err:
        return ret;
 }
 
-static void __exit at91sam9g20ek_exit(void)
+static int __devexit at91sam9g20ek_audio_remove(struct platform_device *pdev)
 {
-       platform_device_unregister(at91sam9g20ek_snd_device);
-       at91sam9g20ek_snd_device = NULL;
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+       snd_soc_unregister_card(card);
        clk_put(mclk);
        mclk = NULL;
+
+       return 0;
 }
 
-module_init(at91sam9g20ek_init);
-module_exit(at91sam9g20ek_exit);
+static struct platform_driver at91sam9g20ek_audio_driver = {
+       .driver = {
+               .name   = "at91sam9g20ek-audio",
+               .owner  = THIS_MODULE,
+       },
+       .probe  = at91sam9g20ek_audio_probe,
+       .remove = __devexit_p(at91sam9g20ek_audio_remove),
+};
+
+module_platform_driver(at91sam9g20ek_audio_driver);
 
 /* Module information */
 MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
 MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK_WM8731");
+MODULE_ALIAS("platform:at91sam9g20ek-audio");
 MODULE_LICENSE("GPL");
index 7015db265614f22e0f9e15a1407bb33ab5d23e38..0e368d469764768ff7d113d13531e1d5c1f51ce6 100644 (file)
@@ -54,6 +54,7 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_PCM3008
        select SND_SOC_RT5631 if I2C
        select SND_SOC_SGTL5000 if I2C
+       select SND_SOC_SI476X if MFD_SI476X_CORE
        select SND_SOC_SN95031 if INTEL_SCU_IPC
        select SND_SOC_SPDIF
        select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI
@@ -146,6 +147,13 @@ config SND_SOC_WM_HUBS
        default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y
        default m if SND_SOC_WM8993=m || SND_SOC_WM8994=m
 
+config SND_SOC_WM_ADSP
+       tristate
+       default y if SND_SOC_WM5102=y
+       default y if SND_SOC_WM2200=y
+       default m if SND_SOC_WM5102=m
+       default m if SND_SOC_WM2200=m
+
 config SND_SOC_AB8500_CODEC
        tristate
 
@@ -278,6 +286,9 @@ config SND_SOC_RT5631
 config SND_SOC_SGTL5000
        tristate
 
+config SND_SOC_SI476X
+       tristate
+
 config SND_SOC_SIGMADSP
        tristate
        select CRC32
index 9bd4d95aab4ffcecb9abf5bff4e0c94d7203adee..aa5631220166e8f35af73211e3da9c0b5e6be1ac 100644 (file)
@@ -45,6 +45,7 @@ snd-soc-sgtl5000-objs := sgtl5000.o
 snd-soc-alc5623-objs := alc5623.o
 snd-soc-alc5632-objs := alc5632.o
 snd-soc-sigmadsp-objs := sigmadsp.o
+snd-soc-si476x-objs := si476x.o
 snd-soc-sn95031-objs := sn95031.o
 snd-soc-spdif-tx-objs := spdif_transciever.o
 snd-soc-spdif-rx-objs := spdif_receiver.o
@@ -62,6 +63,7 @@ snd-soc-twl6040-objs := twl6040.o
 snd-soc-uda134x-objs := uda134x.o
 snd-soc-uda1380-objs := uda1380.o
 snd-soc-wl1273-objs := wl1273.o
+snd-soc-wm-adsp-objs := wm_adsp.o
 snd-soc-wm0010-objs := wm0010.o
 snd-soc-wm1250-ev1-objs := wm1250-ev1.o
 snd-soc-wm2000-objs := wm2000.o
@@ -164,6 +166,7 @@ obj-$(CONFIG_SND_SOC_PCM3008)       += snd-soc-pcm3008.o
 obj-$(CONFIG_SND_SOC_RT5631)   += snd-soc-rt5631.o
 obj-$(CONFIG_SND_SOC_SGTL5000)  += snd-soc-sgtl5000.o
 obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
+obj-$(CONFIG_SND_SOC_SI476X)   += snd-soc-si476x.o
 obj-$(CONFIG_SND_SOC_SN95031)  +=snd-soc-sn95031.o
 obj-$(CONFIG_SND_SOC_SPDIF)    += snd-soc-spdif-rx.o snd-soc-spdif-tx.o
 obj-$(CONFIG_SND_SOC_SSM2602)  += snd-soc-ssm2602.o
@@ -229,6 +232,7 @@ obj-$(CONFIG_SND_SOC_WM9090)        += snd-soc-wm9090.o
 obj-$(CONFIG_SND_SOC_WM9705)   += snd-soc-wm9705.o
 obj-$(CONFIG_SND_SOC_WM9712)   += snd-soc-wm9712.o
 obj-$(CONFIG_SND_SOC_WM9713)   += snd-soc-wm9713.o
+obj-$(CONFIG_SND_SOC_WM_ADSP)  += snd-soc-wm-adsp.o
 obj-$(CONFIG_SND_SOC_WM_HUBS)  += snd-soc-wm-hubs.o
 
 # Amp
index 31d4483245d0db951584a0e1619b91c8ac8fa726..d4d4858088940526105002be6a22870b9d48c0e9 100644 (file)
@@ -98,14 +98,32 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
        val = 0;
 
        switch (params_rate(params)) {
+       case 22050:
+               val |= IEC958_AES3_CON_FS_22050;
+               break;
+       case 24000:
+               val |= IEC958_AES3_CON_FS_24000;
+               break;
+       case 32000:
+               val |= IEC958_AES3_CON_FS_32000;
+               break;
        case 44100:
                val |= IEC958_AES3_CON_FS_44100;
                break;
        case 48000:
                val |= IEC958_AES3_CON_FS_48000;
                break;
-       case 32000:
-               val |= IEC958_AES3_CON_FS_32000;
+       case 88200:
+               val |= IEC958_AES3_CON_FS_88200;
+               break;
+       case 96000:
+               val |= IEC958_AES3_CON_FS_96000;
+               break;
+       case 176400:
+               val |= IEC958_AES3_CON_FS_176400;
+               break;
+       case 192000:
+               val |= IEC958_AES3_CON_FS_192000;
                break;
        default:
                dev_err(codec->dev, "unsupported sampling rate\n");
@@ -240,10 +258,17 @@ static int __devexit ak4104_spi_remove(struct spi_device *spi)
        return 0;
 }
 
+static const struct of_device_id ak4104_of_match[] = {
+       { .compatible = "asahi-kasei,ak4104", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ak4104_of_match);
+
 static struct spi_driver ak4104_spi_driver = {
        .driver  = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
+               .of_match_table = ak4104_of_match,
        },
        .probe  = ak4104_spi_probe,
        .remove = __devexit_p(ak4104_spi_remove),
index 36ec64946120077455ab218c85aef34eaa29ef9a..5a09127fcbab4ee90f4a932d956683ff173ad146 100644 (file)
@@ -17,6 +17,8 @@
 
 #include <sound/soc.h>
 
+#include "wm_adsp.h"
+
 #define ARIZONA_CLK_SYSCLK         1
 #define ARIZONA_CLK_ASYNCCLK       2
 #define ARIZONA_CLK_OPCLK          3
 #define ARIZONA_MIXER_VOL_SHIFT                 1
 #define ARIZONA_MIXER_VOL_WIDTH                 7
 
-#define ARIZONA_MAX_DAI 3
+#define ARIZONA_MAX_DAI  4
+#define ARIZONA_MAX_ADSP 4
 
 struct arizona;
+struct wm_adsp;
 
 struct arizona_dai_priv {
        int clk;
 };
 
 struct arizona_priv {
+       struct wm_adsp adsp[ARIZONA_MAX_ADSP];
        struct arizona *arizona;
        int sysclk;
        int asyncclk;
@@ -99,6 +104,20 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
        static ARIZONA_MUX_CTL_DECL(name##_in3); \
        static ARIZONA_MUX_CTL_DECL(name##_in4)
 
+#define ARIZONA_DSP_AUX_ENUMS(name, base_reg) \
+       static ARIZONA_MUX_ENUM_DECL(name##_aux1_enum, base_reg);       \
+       static ARIZONA_MUX_ENUM_DECL(name##_aux2_enum, base_reg + 8);   \
+       static ARIZONA_MUX_ENUM_DECL(name##_aux3_enum, base_reg + 16);  \
+       static ARIZONA_MUX_ENUM_DECL(name##_aux4_enum, base_reg + 24);  \
+       static ARIZONA_MUX_ENUM_DECL(name##_aux5_enum, base_reg + 32);  \
+       static ARIZONA_MUX_ENUM_DECL(name##_aux6_enum, base_reg + 40);  \
+       static ARIZONA_MUX_CTL_DECL(name##_aux1); \
+       static ARIZONA_MUX_CTL_DECL(name##_aux2); \
+       static ARIZONA_MUX_CTL_DECL(name##_aux3); \
+       static ARIZONA_MUX_CTL_DECL(name##_aux4); \
+       static ARIZONA_MUX_CTL_DECL(name##_aux5); \
+       static ARIZONA_MUX_CTL_DECL(name##_aux6)
+
 #define ARIZONA_MUX(name, ctrl) \
        SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
 
@@ -109,6 +128,16 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
        ARIZONA_MUX(name_str " Input 4", &name##_in4_mux), \
        SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
 
+#define ARIZONA_DSP_WIDGETS(name, name_str) \
+       ARIZONA_MIXER_WIDGETS(name##L, name_str "L"), \
+       ARIZONA_MIXER_WIDGETS(name##R, name_str "R"), \
+       ARIZONA_MUX(name_str " Aux 1", &name##_aux1_mux), \
+       ARIZONA_MUX(name_str " Aux 2", &name##_aux2_mux), \
+       ARIZONA_MUX(name_str " Aux 3", &name##_aux3_mux), \
+       ARIZONA_MUX(name_str " Aux 4", &name##_aux4_mux), \
+       ARIZONA_MUX(name_str " Aux 5", &name##_aux5_mux), \
+       ARIZONA_MUX(name_str " Aux 6", &name##_aux6_mux)
+
 #define ARIZONA_MIXER_ROUTES(widget, name) \
        { widget, NULL, name " Mixer" },         \
        { name " Mixer", NULL, name " Input 1" }, \
@@ -120,6 +149,22 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS];
        ARIZONA_MIXER_INPUT_ROUTES(name " Input 3"), \
        ARIZONA_MIXER_INPUT_ROUTES(name " Input 4")
 
+#define ARIZONA_DSP_ROUTES(name) \
+       { name, NULL, name " Aux 1" }, \
+       { name, NULL, name " Aux 2" }, \
+       { name, NULL, name " Aux 3" }, \
+       { name, NULL, name " Aux 4" }, \
+       { name, NULL, name " Aux 5" }, \
+       { name, NULL, name " Aux 6" }, \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 1"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 2"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 3"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 4"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 5"), \
+       ARIZONA_MIXER_INPUT_ROUTES(name " Aux 6"), \
+       ARIZONA_MIXER_ROUTES(name, name "L"), \
+       ARIZONA_MIXER_ROUTES(name, name "R")
+
 extern const struct soc_enum arizona_lhpf1_mode;
 extern const struct soc_enum arizona_lhpf2_mode;
 extern const struct soc_enum arizona_lhpf3_mode;
index f994af34f552f4b08c4e01880c3410a4890afb7c..2ac5fe61a96c9f893cb09014b9fcb2772997fa4c 100644 (file)
@@ -474,15 +474,25 @@ static int cs4271_probe(struct snd_soc_codec *codec)
        struct cs4271_platform_data *cs4271plat = codec->dev->platform_data;
        int ret;
        int gpio_nreset = -EINVAL;
+       int amutec_eq_bmutec = 0;
 
 #ifdef CONFIG_OF
-       if (of_match_device(cs4271_dt_ids, codec->dev))
+       if (of_match_device(cs4271_dt_ids, codec->dev)) {
                gpio_nreset = of_get_named_gpio(codec->dev->of_node,
                                                "reset-gpio", 0);
+
+               if (!of_get_property(codec->dev->of_node,
+                                    "cirrus,amutec-eq-bmutec", NULL))
+                       amutec_eq_bmutec = 1;
+       }
 #endif
 
-       if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset))
-               gpio_nreset = cs4271plat->gpio_nreset;
+       if (cs4271plat) {
+               if (gpio_is_valid(cs4271plat->gpio_nreset))
+                       gpio_nreset = cs4271plat->gpio_nreset;
+
+               amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec;
+       }
 
        if (gpio_nreset >= 0)
                if (gpio_request(gpio_nreset, "CS4271 Reset"))
@@ -528,6 +538,11 @@ static int cs4271_probe(struct snd_soc_codec *codec)
        /* Power-up sequence requires 85 uS */
        udelay(85);
 
+       if (amutec_eq_bmutec)
+               snd_soc_update_bits(codec, CS4271_MODE2,
+                                   CS4271_MODE2_MUTECAEQUB,
+                                   CS4271_MODE2_MUTECAEQUB);
+
        return snd_soc_add_codec_controls(codec, cs4271_snd_controls,
                ARRAY_SIZE(cs4271_snd_controls));
 }
index 61599298fb26c32bdb193e1be0ccb33d2490a0af..f91136caa4c77060c0583e445ab92a69e58463ac 100644 (file)
@@ -773,7 +773,6 @@ static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
-       int ret = 0;
        u8 iface = 0;
 
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -822,7 +821,7 @@ static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        case SND_SOC_DAIFMT_NB_IF:
                break;
        default:
-               ret = -EINVAL;
+               return -EINVAL;
        }
        cs42l52->config.format = iface;
        snd_soc_write(codec, CS42L52_IFACE_CTL1, cs42l52->config.format);
index f379b085c39204dfeb2a6fc34d7c07d9f15c9f0b..d3a6de2e757b9f8d0b96fd2ac0f3444f2d017dc5 100644 (file)
 #define DA9055_AIF_FORMAT_I2S_MODE     (0 << 0)
 #define DA9055_AIF_FORMAT_LEFT_J       (1 << 0)
 #define DA9055_AIF_FORMAT_RIGHT_J      (2 << 0)
+#define DA9055_AIF_FORMAT_DSP          (3 << 0)
 #define DA9055_AIF_WORD_S16_LE         (0 << 2)
 #define DA9055_AIF_WORD_S20_3LE                (1 << 2)
 #define DA9055_AIF_WORD_S24_LE         (2 << 2)
@@ -752,6 +753,17 @@ static const struct snd_kcontrol_new da9055_dapm_mixoutr_controls[] = {
                        6, 1, 0),
 };
 
+/* Headphone Output Enable */
+static const struct snd_kcontrol_new da9055_dapm_hp_l_control =
+SOC_DAPM_SINGLE("Switch", DA9055_HP_L_CTRL, 3, 1, 0);
+
+static const struct snd_kcontrol_new da9055_dapm_hp_r_control =
+SOC_DAPM_SINGLE("Switch", DA9055_HP_R_CTRL, 3, 1, 0);
+
+/* Lineout Output Enable */
+static const struct snd_kcontrol_new da9055_dapm_lineout_control =
+SOC_DAPM_SINGLE("Switch", DA9055_LINE_CTRL, 3, 1, 0);
+
 /* DAPM widgets */
 static const struct snd_soc_dapm_widget da9055_dapm_widgets[] = {
        /* Input Side */
@@ -816,6 +828,14 @@ static const struct snd_soc_dapm_widget da9055_dapm_widgets[] = {
                           &da9055_dapm_mixoutr_controls[0],
                           ARRAY_SIZE(da9055_dapm_mixoutr_controls)),
 
+       /* Output Enable Switches */
+       SND_SOC_DAPM_SWITCH("Headphone Left Enable", SND_SOC_NOPM, 0, 0,
+                           &da9055_dapm_hp_l_control),
+       SND_SOC_DAPM_SWITCH("Headphone Right Enable", SND_SOC_NOPM, 0, 0,
+                           &da9055_dapm_hp_r_control),
+       SND_SOC_DAPM_SWITCH("Lineout Enable", SND_SOC_NOPM, 0, 0,
+                           &da9055_dapm_lineout_control),
+
        /* Output PGAs */
        SND_SOC_DAPM_PGA("MIXOUT Left", DA9055_MIXOUT_L_CTRL, 7, 0, NULL, 0),
        SND_SOC_DAPM_PGA("MIXOUT Right", DA9055_MIXOUT_R_CTRL, 7, 0, NULL, 0),
@@ -901,17 +921,20 @@ static const struct snd_soc_dapm_route da9055_audio_map[] = {
        {"Out Mixer Right", "DAC Right Switch", "DAC Right"},
 
        {"MIXOUT Left", NULL, "Out Mixer Left"},
-       {"Headphone Left", NULL, "MIXOUT Left"},
+       {"Headphone Left Enable", "Switch", "MIXOUT Left"},
+       {"Headphone Left", NULL, "Headphone Left Enable"},
        {"Headphone Left", NULL, "Charge Pump"},
        {"HPL", NULL, "Headphone Left"},
 
        {"MIXOUT Right", NULL, "Out Mixer Right"},
-       {"Headphone Right", NULL, "MIXOUT Right"},
+       {"Headphone Right Enable", "Switch", "MIXOUT Right"},
+       {"Headphone Right", NULL, "Headphone Right Enable"},
        {"Headphone Right", NULL, "Charge Pump"},
        {"HPR", NULL, "Headphone Right"},
 
        {"MIXOUT Right", NULL, "Out Mixer Right"},
-       {"Lineout", NULL, "MIXOUT Right"},
+       {"Lineout Enable", "Switch", "MIXOUT Right"},
+       {"Lineout", NULL, "Lineout Enable"},
        {"LINE", NULL, "Lineout"},
 };
 
@@ -1175,6 +1198,9 @@ static int da9055_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        case SND_SOC_DAIFMT_RIGHT_J:
                aif_ctrl = DA9055_AIF_FORMAT_RIGHT_J;
                break;
+       case SND_SOC_DAIFMT_DSP_A:
+               aif_ctrl = DA9055_AIF_FORMAT_DSP;
+               break;
        default:
                return -EINVAL;
        }
@@ -1390,8 +1416,7 @@ static int da9055_probe(struct snd_soc_codec *codec)
                            DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN);
 
        /*
-        * There are two separate control bits for input and output mixers as
-        * well as headphone and line outs.
+        * There are two separate control bits for input and output mixers.
         * One to enable corresponding amplifier and other to enable its
         * output. As amplifier bits are related to power control, they are
         * being managed by DAPM while other (non power related) bits are
@@ -1407,14 +1432,6 @@ static int da9055_probe(struct snd_soc_codec *codec)
        snd_soc_update_bits(codec, DA9055_MIXOUT_R_CTRL,
                            DA9055_MIXOUT_R_MIX_EN, DA9055_MIXOUT_R_MIX_EN);
 
-       snd_soc_update_bits(codec, DA9055_HP_L_CTRL,
-                           DA9055_HP_L_AMP_OE, DA9055_HP_L_AMP_OE);
-       snd_soc_update_bits(codec, DA9055_HP_R_CTRL,
-                           DA9055_HP_R_AMP_OE, DA9055_HP_R_AMP_OE);
-
-       snd_soc_update_bits(codec, DA9055_LINE_CTRL,
-                           DA9055_LINE_AMP_OE, DA9055_LINE_AMP_OE);
-
        /* Set this as per your system configuration */
        snd_soc_write(codec, DA9055_PLL_CTRL, DA9055_PLL_INDIV_10_20_MHZ);
 
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c
new file mode 100644 (file)
index 0000000..38145ba
--- /dev/null
@@ -0,0 +1,255 @@
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+
+#include <linux/i2c.h>
+
+#include <linux/mfd/si476x-core.h>
+
+enum si476x_audio_registers {
+       SI476X_DIGITAL_IO_OUTPUT_FORMAT         = 0x0203,
+       SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE    = 0x0202,
+};
+
+enum si476x_digital_io_output_format {
+       SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT       = 11,
+       SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT     = 8,
+};
+
+#define SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK    ((0b111 << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | \
+                                                 (0b111 << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT))
+#define SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK   (0b1111110)
+
+enum si476x_daudio_formats {
+       SI476X_DAUDIO_MODE_I2S          = (0x0 << 1),
+       SI476X_DAUDIO_MODE_DSP_A        = (0x6 << 1),
+       SI476X_DAUDIO_MODE_DSP_B        = (0x7 << 1),
+       SI476X_DAUDIO_MODE_LEFT_J       = (0x8 << 1),
+       SI476X_DAUDIO_MODE_RIGHT_J      = (0x9 << 1),
+
+       SI476X_DAUDIO_MODE_IB           = (1 << 5),
+       SI476X_DAUDIO_MODE_IF           = (1 << 6),
+};
+
+enum si476x_pcm_format {
+       SI476X_PCM_FORMAT_S8            = 2,
+       SI476X_PCM_FORMAT_S16_LE        = 4,
+       SI476X_PCM_FORMAT_S20_3LE       = 5,
+       SI476X_PCM_FORMAT_S24_LE        = 6,
+};
+
+static unsigned int si476x_codec_read(struct snd_soc_codec *codec,
+                                     unsigned int reg)
+{
+       int err;
+       struct si476x_core *core = codec->control_data;
+
+       si476x_core_lock(core);
+       err = si476x_core_cmd_get_property(core, reg);
+       si476x_core_unlock(core);
+
+       return err;
+}
+
+static int si476x_codec_write(struct snd_soc_codec *codec,
+                             unsigned int reg, unsigned int val)
+{
+       int err;
+       struct si476x_core *core = codec->control_data;
+
+       si476x_core_lock(core);
+       err = si476x_core_cmd_set_property(core, reg, val);
+       si476x_core_unlock(core);
+
+       return err;
+}
+
+static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
+                                   unsigned int fmt)
+{
+       int err;
+       u16 format = 0;
+
+       if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
+               return -EINVAL;
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_A:
+               format |= SI476X_DAUDIO_MODE_DSP_A;
+               break;
+       case SND_SOC_DAIFMT_DSP_B:
+               format |= SI476X_DAUDIO_MODE_DSP_B;
+               break;
+       case SND_SOC_DAIFMT_I2S:
+               format |= SI476X_DAUDIO_MODE_I2S;
+               break;
+       case SND_SOC_DAIFMT_RIGHT_J:
+               format |= SI476X_DAUDIO_MODE_RIGHT_J;
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               format |= SI476X_DAUDIO_MODE_LEFT_J;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_A:
+       case SND_SOC_DAIFMT_DSP_B:
+               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+               case SND_SOC_DAIFMT_NB_NF:
+                       break;
+               case SND_SOC_DAIFMT_IB_NF:
+                       format |= SI476X_DAUDIO_MODE_IB;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       case SND_SOC_DAIFMT_I2S:
+       case SND_SOC_DAIFMT_RIGHT_J:
+       case SND_SOC_DAIFMT_LEFT_J:
+               switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+               case SND_SOC_DAIFMT_NB_NF:
+                       break;
+               case SND_SOC_DAIFMT_IB_IF:
+                       format |= SI476X_DAUDIO_MODE_IB |
+                               SI476X_DAUDIO_MODE_IF;
+                       break;
+               case SND_SOC_DAIFMT_IB_NF:
+                       format |= SI476X_DAUDIO_MODE_IB;
+                       break;
+               case SND_SOC_DAIFMT_NB_IF:
+                       format |= SI476X_DAUDIO_MODE_IF;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       err = snd_soc_update_bits(codec_dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT,
+                                 SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK,
+                                 format);
+       if (err < 0) {
+               dev_err(codec_dai->codec->dev, "Failed to set output format\n");
+               return err;
+       }
+       
+       return 0;
+}
+
+static int si476x_codec_hw_params(struct snd_pcm_substream *substream,
+                                 struct snd_pcm_hw_params *params,
+                                 struct snd_soc_dai *dai)
+{
+       int rate, width, err;
+
+       rate = params_rate(params);
+       if (rate < 32000 || rate > 48000) {
+               dev_err(dai->codec->dev, "Rate: %d is not supported\n", rate);
+               return -EINVAL;
+       }
+
+       switch (params_format(params)) {
+       case SNDRV_PCM_FORMAT_S8:
+               width = SI476X_PCM_FORMAT_S8;
+       case SNDRV_PCM_FORMAT_S16_LE:
+               width = SI476X_PCM_FORMAT_S16_LE;
+               break;
+       case SNDRV_PCM_FORMAT_S20_3LE:
+               width = SI476X_PCM_FORMAT_S20_3LE;
+               break;
+       case SNDRV_PCM_FORMAT_S24_LE:
+               width = SI476X_PCM_FORMAT_S24_LE;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       err = snd_soc_write(dai->codec, SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE,
+                           rate);
+       if (err < 0) {
+               dev_err(dai->codec->dev, "Failed to set sample rate\n");
+               return err;
+       }
+
+       err = snd_soc_update_bits(dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT,
+                                 SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK,
+                                 (width << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | 
+                                 (width << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT));
+       if (err < 0) {
+               dev_err(dai->codec->dev, "Failed to set output width\n");
+               return err;
+       }
+
+       return 0;
+}
+
+static int si476x_codec_probe(struct snd_soc_codec *codec)
+{
+       codec->control_data = i2c_mfd_cell_to_core(codec->dev);
+       return 0;
+}
+
+static struct snd_soc_dai_ops si476x_dai_ops = {
+       .hw_params      = si476x_codec_hw_params,
+       .set_fmt        = si476x_codec_set_dai_fmt,
+};
+
+static struct snd_soc_dai_driver si476x_dai = {
+       .name           = "si476x-codec",
+       .capture        = {
+               .stream_name    = "Capture",
+               .channels_min   = 2,
+               .channels_max   = 2,
+
+               .rates = SNDRV_PCM_RATE_32000 |
+               SNDRV_PCM_RATE_44100 |
+               SNDRV_PCM_RATE_48000,
+               .formats = SNDRV_PCM_FMTBIT_S8 |
+               SNDRV_PCM_FMTBIT_S16_LE |
+               SNDRV_PCM_FMTBIT_S20_3LE |
+               SNDRV_PCM_FMTBIT_S24_LE
+       },
+       .ops            = &si476x_dai_ops,
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_si476x = {
+       .probe  = si476x_codec_probe,
+       .read   = si476x_codec_read,
+       .write  = si476x_codec_write,
+};
+
+static int __devinit si476x_platform_probe(struct platform_device *pdev)
+{
+       return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_si476x,
+                                     &si476x_dai, 1);
+}
+
+static int __devexit si476x_platform_remove(struct platform_device *pdev)
+{
+       snd_soc_unregister_codec(&pdev->dev);
+       return 0;
+}
+
+MODULE_ALIAS("platform:si476x-codec");
+
+static struct platform_driver si476x_platform_driver = {
+       .driver         = {
+               .name   = "si476x-codec",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = si476x_platform_probe,
+       .remove         = __devexit_p(si476x_platform_remove),
+};
+module_platform_driver(si476x_platform_driver);
+
+MODULE_AUTHOR("Andrey Smirnov <andrey.smirnov@convergeddevices.net>");
+MODULE_DESCRIPTION("ASoC Si4761/64 codec driver");
+MODULE_LICENSE("GPL");
index f230292ba96bbfc0c5cf7c7264dd4435de3d7590..e39e08d5d8e42429b8b2cb27bf1b08104a65454f 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
+#include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/cdev.h>
 #include <linux/slab.h>
@@ -65,6 +66,7 @@ struct aic32x4_priv {
        u32 power_cfg;
        u32 micpga_routing;
        bool swapdacs;
+       int rstn_gpio;
 };
 
 /* 0dB min, 1dB steps */
@@ -627,10 +629,20 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
 {
        struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
        u32 tmp_reg;
+       int ret;
 
        codec->hw_write = (hw_write_t) i2c_master_send;
        codec->control_data = aic32x4->control_data;
 
+       if (aic32x4->rstn_gpio >= 0) {
+               ret = devm_gpio_request_one(codec->dev, aic32x4->rstn_gpio,
+                               GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn");
+               if (ret != 0)
+                       return ret;
+               ndelay(10);
+               gpio_set_value(aic32x4->rstn_gpio, 1);
+       }
+
        snd_soc_write(codec, AIC32X4_RESET, 0x01);
 
        /* Power platform configuration */
@@ -675,6 +687,16 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
                             ARRAY_SIZE(aic32x4_snd_controls));
        aic32x4_add_widgets(codec);
 
+       /*
+        * Workaround: for an unknown reason, the ADC needs to be powered up
+        * and down for the first capture to work properly. It seems related to
+        * a HW BUG or some kind of behavior not documented in the datasheet.
+        */
+       tmp_reg = snd_soc_read(codec, AIC32X4_ADCSETUP);
+       snd_soc_write(codec, AIC32X4_ADCSETUP, tmp_reg |
+                               AIC32X4_LADC_EN | AIC32X4_RADC_EN);
+       snd_soc_write(codec, AIC32X4_ADCSETUP, tmp_reg);
+
        return 0;
 }
 
@@ -713,10 +735,12 @@ static __devinit int aic32x4_i2c_probe(struct i2c_client *i2c,
                aic32x4->power_cfg = pdata->power_cfg;
                aic32x4->swapdacs = pdata->swapdacs;
                aic32x4->micpga_routing = pdata->micpga_routing;
+               aic32x4->rstn_gpio = pdata->rstn_gpio;
        } else {
                aic32x4->power_cfg = 0;
                aic32x4->swapdacs = false;
                aic32x4->micpga_routing = 0;
+               aic32x4->rstn_gpio = -1;
        }
 
        ret = snd_soc_register_codec(&i2c->dev,
index aae2b2440398aaac19a62eac62b6e7788e41035c..35774223fd91f2a03c4ce4ed56c45df3f3ff2a3d 100644 (file)
@@ -94,6 +94,9 @@
 #define AIC32X4_WORD_LEN_24BITS                0x02
 #define AIC32X4_WORD_LEN_32BITS                0x03
 
+#define AIC32X4_LADC_EN                        (1 << 7)
+#define AIC32X4_RADC_EN                        (1 << 6)
+
 #define AIC32X4_I2S_MODE               0x00
 #define AIC32X4_DSP_MODE               0x01
 #define AIC32X4_RIGHT_JUSTIFIED_MODE   0x02
index 99afc003a084cabfc47511047247c0416da8931f..5c1291748326f537bbe281a835ef3f007f26f1b6 100644 (file)
@@ -97,7 +97,6 @@ struct wm0010_priv {
 
        enum wm0010_state state;
        bool boot_failed;
-       int boot_done;
        bool ready;
        bool pll_running;
        int max_spi_freq;
@@ -234,7 +233,7 @@ static void wm0010_boot_xfer_complete(void *data)
                        break;
 
                case 0x55555555:
-                       if (wm0010->boot_done == 0)
+                       if (wm0010->state < WM0010_STAGE2)
                                break;
                        dev_err(codec->dev,
                                "%d: ROM bootloader running in stage 2\n", i);
@@ -321,7 +320,6 @@ static void wm0010_boot_xfer_complete(void *data)
                        break;
        }
 
-       wm0010->boot_done++;
        if (xfer->done)
                complete(xfer->done);
 }
@@ -544,7 +542,6 @@ static int wm0010_boot(struct snd_soc_codec *codec)
 
        rec = (const struct dfw_binrec *)fw->data;
        offset = 0;
-       wm0010->boot_done = 0;
        wm0010->boot_failed = false;
        BUG_ON(!list_empty(&xfer_list));
        init_completion(&done);
index eab64a193989ac2917773a4df7613cbf644dd58f..1730df83839ce5f689138a5f29aa910198b06d4f 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
+#include <linux/firmware.h>
 #include <linux/gcd.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <sound/wm2200.h>
 
 #include "wm2200.h"
+#include "wmfw.h"
+#include "wm_adsp.h"
+
+#define WM2200_DSP_CONTROL_1                   0x00
+#define WM2200_DSP_CONTROL_2                   0x02
+#define WM2200_DSP_CONTROL_3                   0x03
+#define WM2200_DSP_CONTROL_4                   0x04
+#define WM2200_DSP_CONTROL_5                   0x06
+#define WM2200_DSP_CONTROL_6                   0x07
+#define WM2200_DSP_CONTROL_7                   0x08
+#define WM2200_DSP_CONTROL_8                   0x09
+#define WM2200_DSP_CONTROL_9                   0x0A
+#define WM2200_DSP_CONTROL_10                  0x0B
+#define WM2200_DSP_CONTROL_11                  0x0C
+#define WM2200_DSP_CONTROL_12                  0x0D
+#define WM2200_DSP_CONTROL_13                  0x0F
+#define WM2200_DSP_CONTROL_14                  0x10
+#define WM2200_DSP_CONTROL_15                  0x11
+#define WM2200_DSP_CONTROL_16                  0x12
+#define WM2200_DSP_CONTROL_17                  0x13
+#define WM2200_DSP_CONTROL_18                  0x14
+#define WM2200_DSP_CONTROL_19                  0x16
+#define WM2200_DSP_CONTROL_20                  0x17
+#define WM2200_DSP_CONTROL_21                  0x18
+#define WM2200_DSP_CONTROL_22                  0x1A
+#define WM2200_DSP_CONTROL_23                  0x1B
+#define WM2200_DSP_CONTROL_24                  0x1C
+#define WM2200_DSP_CONTROL_25                  0x1E
+#define WM2200_DSP_CONTROL_26                  0x20
+#define WM2200_DSP_CONTROL_27                  0x21
+#define WM2200_DSP_CONTROL_28                  0x22
+#define WM2200_DSP_CONTROL_29                  0x23
+#define WM2200_DSP_CONTROL_30                  0x24
+#define WM2200_DSP_CONTROL_31                  0x26
 
 /* The code assumes DCVDD is generated internally */
 #define WM2200_NUM_CORE_SUPPLIES 2
@@ -49,6 +84,7 @@ struct wm2200_fll {
 
 /* codec private data */
 struct wm2200_priv {
+       struct wm_adsp dsp[2];
        struct regmap *regmap;
        struct device *dev;
        struct snd_soc_codec *codec;
@@ -64,6 +100,72 @@ struct wm2200_priv {
        int sysclk;
 };
 
+#define WM2200_DSP_RANGE_BASE (WM2200_MAX_REGISTER + 1)
+#define WM2200_DSP_SPACING 12288
+
+#define WM2200_DSP1_DM_BASE (WM2200_DSP_RANGE_BASE + (0 * WM2200_DSP_SPACING))
+#define WM2200_DSP1_PM_BASE (WM2200_DSP_RANGE_BASE + (1 * WM2200_DSP_SPACING))
+#define WM2200_DSP1_ZM_BASE (WM2200_DSP_RANGE_BASE + (2 * WM2200_DSP_SPACING))
+#define WM2200_DSP2_DM_BASE (WM2200_DSP_RANGE_BASE + (3 * WM2200_DSP_SPACING))
+#define WM2200_DSP2_PM_BASE (WM2200_DSP_RANGE_BASE + (4 * WM2200_DSP_SPACING))
+#define WM2200_DSP2_ZM_BASE (WM2200_DSP_RANGE_BASE + (5 * WM2200_DSP_SPACING))
+
+static const struct regmap_range_cfg wm2200_ranges[] = {
+       { .name = "DSP1DM", .range_min = WM2200_DSP1_DM_BASE,
+         .range_max = WM2200_DSP1_DM_BASE + 12287,
+         .selector_reg = WM2200_DSP1_CONTROL_3,
+         .selector_mask = WM2200_DSP1_PAGE_BASE_DM_0_MASK,
+         .selector_shift = WM2200_DSP1_PAGE_BASE_DM_0_SHIFT,
+         .window_start = WM2200_DSP1_DM_0, .window_len = 2048, },
+
+       { .name = "DSP1PM", .range_min = WM2200_DSP1_PM_BASE,
+         .range_max = WM2200_DSP1_PM_BASE + 12287,
+         .selector_reg = WM2200_DSP1_CONTROL_2,
+         .selector_mask = WM2200_DSP1_PAGE_BASE_PM_0_MASK,
+         .selector_shift = WM2200_DSP1_PAGE_BASE_PM_0_SHIFT,
+         .window_start = WM2200_DSP1_PM_0, .window_len = 768, },
+
+       { .name = "DSP1ZM", .range_min = WM2200_DSP1_ZM_BASE,
+         .range_max = WM2200_DSP1_ZM_BASE + 2047,
+         .selector_reg = WM2200_DSP1_CONTROL_4,
+         .selector_mask = WM2200_DSP1_PAGE_BASE_ZM_0_MASK,
+         .selector_shift = WM2200_DSP1_PAGE_BASE_ZM_0_SHIFT,
+         .window_start = WM2200_DSP1_ZM_0, .window_len = 1024, },
+
+       { .name = "DSP2DM", .range_min = WM2200_DSP2_DM_BASE,
+         .range_max = WM2200_DSP2_DM_BASE + 4095,
+         .selector_reg = WM2200_DSP2_CONTROL_3,
+         .selector_mask = WM2200_DSP2_PAGE_BASE_DM_0_MASK,
+         .selector_shift = WM2200_DSP2_PAGE_BASE_DM_0_SHIFT,
+         .window_start = WM2200_DSP2_DM_0, .window_len = 2048, },
+
+       { .name = "DSP2PM", .range_min = WM2200_DSP2_PM_BASE,
+         .range_max = WM2200_DSP2_PM_BASE + 11287,
+         .selector_reg = WM2200_DSP2_CONTROL_2,
+         .selector_mask = WM2200_DSP2_PAGE_BASE_PM_0_MASK,
+         .selector_shift = WM2200_DSP2_PAGE_BASE_PM_0_SHIFT,
+         .window_start = WM2200_DSP2_PM_0, .window_len = 768, },
+
+       { .name = "DSP2ZM", .range_min = WM2200_DSP2_ZM_BASE,
+         .range_max = WM2200_DSP2_ZM_BASE + 2047,
+         .selector_reg = WM2200_DSP2_CONTROL_4,
+         .selector_mask = WM2200_DSP2_PAGE_BASE_ZM_0_MASK,
+         .selector_shift = WM2200_DSP2_PAGE_BASE_ZM_0_SHIFT,
+         .window_start = WM2200_DSP2_ZM_0, .window_len = 1024, },
+};
+
+static const struct wm_adsp_region wm2200_dsp1_regions[] = {
+       { .type = WMFW_ADSP1_PM, .base = WM2200_DSP1_PM_BASE },
+       { .type = WMFW_ADSP1_DM, .base = WM2200_DSP1_DM_BASE },
+       { .type = WMFW_ADSP1_ZM, .base = WM2200_DSP1_ZM_BASE },
+};
+
+static const struct wm_adsp_region wm2200_dsp2_regions[] = {
+       { .type = WMFW_ADSP1_PM, .base = WM2200_DSP2_PM_BASE },
+       { .type = WMFW_ADSP1_DM, .base = WM2200_DSP2_DM_BASE },
+       { .type = WMFW_ADSP1_ZM, .base = WM2200_DSP2_ZM_BASE },
+};
+
 static struct reg_default wm2200_reg_defaults[] = {
        { 0x000B, 0x0000 },   /* R11    - Tone Generator 1 */
        { 0x0102, 0x0000 },   /* R258   - Clocking 3 */
@@ -407,6 +509,16 @@ static struct reg_default wm2200_reg_defaults[] = {
 
 static bool wm2200_volatile_register(struct device *dev, unsigned int reg)
 {
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(wm2200_ranges); i++)
+               if ((reg >= wm2200_ranges[i].window_start &&
+                    reg <= wm2200_ranges[i].window_start +
+                    wm2200_ranges[i].window_len) ||
+                   (reg >= wm2200_ranges[i].range_min &&
+                    reg <= wm2200_ranges[i].range_max))
+                       return true;
+
        switch (reg) {
        case WM2200_SOFTWARE_RESET:
        case WM2200_DEVICE_REVISION:
@@ -423,6 +535,16 @@ static bool wm2200_volatile_register(struct device *dev, unsigned int reg)
 
 static bool wm2200_readable_register(struct device *dev, unsigned int reg)
 {
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(wm2200_ranges); i++)
+               if ((reg >= wm2200_ranges[i].window_start &&
+                    reg <= wm2200_ranges[i].window_start +
+                    wm2200_ranges[i].window_len) ||
+                   (reg >= wm2200_ranges[i].range_min &&
+                    reg <= wm2200_ranges[i].range_max))
+                       return true;
+
        switch (reg) {
        case WM2200_SOFTWARE_RESET:
        case WM2200_DEVICE_REVISION:
@@ -880,7 +1002,7 @@ static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0);
 static const char *wm2200_mixer_texts[] = {
        "None",
        "Tone Generator",
-       "AEC loopback",
+       "AEC Loopback",
        "IN1L",
        "IN1R",
        "IN2L",
@@ -976,6 +1098,20 @@ static int wm2200_mixer_values[] = {
        static WM2200_MUX_CTL_DECL(name##_in3); \
        static WM2200_MUX_CTL_DECL(name##_in4)
 
+#define WM2200_DSP_ENUMS(name, base_reg) \
+       static WM2200_MUX_ENUM_DECL(name##_aux1_enum, base_reg);     \
+       static WM2200_MUX_ENUM_DECL(name##_aux2_enum, base_reg + 1); \
+       static WM2200_MUX_ENUM_DECL(name##_aux3_enum, base_reg + 2); \
+       static WM2200_MUX_ENUM_DECL(name##_aux4_enum, base_reg + 3); \
+       static WM2200_MUX_ENUM_DECL(name##_aux5_enum, base_reg + 4); \
+       static WM2200_MUX_ENUM_DECL(name##_aux6_enum, base_reg + 5); \
+       static WM2200_MUX_CTL_DECL(name##_aux1); \
+       static WM2200_MUX_CTL_DECL(name##_aux2); \
+       static WM2200_MUX_CTL_DECL(name##_aux3); \
+       static WM2200_MUX_CTL_DECL(name##_aux4); \
+       static WM2200_MUX_CTL_DECL(name##_aux5); \
+       static WM2200_MUX_CTL_DECL(name##_aux6);
+
 static const struct snd_kcontrol_new wm2200_snd_controls[] = {
 SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL,
           WM2200_IN1_OSR_SHIFT, 1, 0),
@@ -1051,6 +1187,9 @@ WM2200_MIXER_ENUMS(DSP1R, WM2200_DSP1RMIX_INPUT_1_SOURCE);
 WM2200_MIXER_ENUMS(DSP2L, WM2200_DSP2LMIX_INPUT_1_SOURCE);
 WM2200_MIXER_ENUMS(DSP2R, WM2200_DSP2RMIX_INPUT_1_SOURCE);
 
+WM2200_DSP_ENUMS(DSP1, WM2200_DSP1AUX1MIX_INPUT_1_SOURCE);
+WM2200_DSP_ENUMS(DSP2, WM2200_DSP2AUX1MIX_INPUT_1_SOURCE);
+
 WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE);
 WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
 
@@ -1064,8 +1203,19 @@ WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
        WM2200_MUX(name_str " Input 4", &name##_in4_mux), \
        SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
 
+#define WM2200_DSP_WIDGETS(name, name_str) \
+       WM2200_MIXER_WIDGETS(name##L, name_str "L"), \
+       WM2200_MIXER_WIDGETS(name##R, name_str "R"), \
+       WM2200_MUX(name_str " Aux 1", &name##_aux1_mux), \
+       WM2200_MUX(name_str " Aux 2", &name##_aux2_mux), \
+       WM2200_MUX(name_str " Aux 3", &name##_aux3_mux), \
+       WM2200_MUX(name_str " Aux 4", &name##_aux4_mux), \
+       WM2200_MUX(name_str " Aux 5", &name##_aux5_mux), \
+       WM2200_MUX(name_str " Aux 6", &name##_aux6_mux)
+
 #define WM2200_MIXER_INPUT_ROUTES(name)        \
        { name, "Tone Generator", "Tone Generator" }, \
+       { name, "AEC Loopback", "AEC Loopback" }, \
         { name, "IN1L", "IN1L PGA" }, \
         { name, "IN1R", "IN1R PGA" }, \
         { name, "IN2L", "IN2L PGA" }, \
@@ -1106,6 +1256,33 @@ WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
        WM2200_MIXER_INPUT_ROUTES(name " Input 3"), \
        WM2200_MIXER_INPUT_ROUTES(name " Input 4")
 
+#define WM2200_DSP_AUX_ROUTES(name) \
+       { name, NULL, name " Aux 1" }, \
+       { name, NULL, name " Aux 2" }, \
+       { name, NULL, name " Aux 3" }, \
+       { name, NULL, name " Aux 4" }, \
+       { name, NULL, name " Aux 5" }, \
+       { name, NULL, name " Aux 6" }, \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 1"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 2"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 3"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 4"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 5"), \
+       WM2200_MIXER_INPUT_ROUTES(name " Aux 6")
+
+static const char *wm2200_aec_loopback_texts[] = {
+       "OUT1L", "OUT1R", "OUT2L", "OUT2R",
+};
+
+static const struct soc_enum wm2200_aec_loopback =
+       SOC_ENUM_SINGLE(WM2200_DAC_AEC_CONTROL_1,
+                       WM2200_AEC_LOOPBACK_SRC_SHIFT,
+                       ARRAY_SIZE(wm2200_aec_loopback_texts),
+                       wm2200_aec_loopback_texts);
+
+static const struct snd_kcontrol_new wm2200_aec_loopback_mux =
+       SOC_DAPM_ENUM("AEC Loopback", wm2200_aec_loopback);
+
 static const struct snd_soc_dapm_widget wm2200_dapm_widgets[] = {
 SND_SOC_DAPM_SUPPLY("SYSCLK", WM2200_CLOCKING_3, WM2200_SYSCLK_ENA_SHIFT, 0,
                    NULL, 0),
@@ -1165,8 +1342,8 @@ SND_SOC_DAPM_PGA("LHPF1", WM2200_HPLPF1_1, WM2200_LHPF1_ENA_SHIFT, 0,
 SND_SOC_DAPM_PGA("LHPF2", WM2200_HPLPF2_1, WM2200_LHPF2_ENA_SHIFT, 0,
                 NULL, 0),
 
-SND_SOC_DAPM_PGA_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),
-SND_SOC_DAPM_PGA_E("DSP2", SND_SOC_NOPM, 1, 0, NULL, 0, NULL, 0),
+WM_ADSP1("DSP1", 0),
+WM_ADSP1("DSP2", 1),
 
 SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0,
                    WM2200_AUDIO_IF_1_22, WM2200_AIF1TX1_ENA_SHIFT, 0),
@@ -1181,6 +1358,9 @@ SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 4,
 SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 5,
                    WM2200_AUDIO_IF_1_22, WM2200_AIF1TX6_ENA_SHIFT, 0),
 
+SND_SOC_DAPM_MUX("AEC Loopback", WM2200_DAC_AEC_CONTROL_1,
+                WM2200_AEC_LOOPBACK_ENA_SHIFT, 0, &wm2200_aec_loopback_mux),
+
 SND_SOC_DAPM_PGA_S("OUT1L", 0, WM2200_OUTPUT_ENABLES,
                   WM2200_OUT1L_ENA_SHIFT, 0, NULL, 0),
 SND_SOC_DAPM_PGA_S("OUT1R", 0, WM2200_OUTPUT_ENABLES,
@@ -1231,10 +1411,8 @@ WM2200_MIXER_WIDGETS(EQR, "EQR"),
 WM2200_MIXER_WIDGETS(LHPF1, "LHPF1"),
 WM2200_MIXER_WIDGETS(LHPF2, "LHPF2"),
 
-WM2200_MIXER_WIDGETS(DSP1L, "DSP1L"),
-WM2200_MIXER_WIDGETS(DSP1R, "DSP1R"),
-WM2200_MIXER_WIDGETS(DSP2L, "DSP2L"),
-WM2200_MIXER_WIDGETS(DSP2R, "DSP2R"),
+WM2200_DSP_WIDGETS(DSP1, "DSP1"),
+WM2200_DSP_WIDGETS(DSP2, "DSP2"),
 
 WM2200_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
 WM2200_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
@@ -1326,11 +1504,19 @@ static const struct snd_soc_dapm_route wm2200_dapm_routes[] = {
        { "SPK", NULL, "OUT2L" },
        { "SPK", NULL, "OUT2R" },
 
+       { "AEC Loopback", "OUT1L", "OUT1L" },
+       { "AEC Loopback", "OUT1R", "OUT1R" },
+       { "AEC Loopback", "OUT2L", "OUT2L" },
+       { "AEC Loopback", "OUT2R", "OUT2R" },
+
        WM2200_MIXER_ROUTES("DSP1", "DSP1L"),
        WM2200_MIXER_ROUTES("DSP1", "DSP1R"),
        WM2200_MIXER_ROUTES("DSP2", "DSP2L"),
        WM2200_MIXER_ROUTES("DSP2", "DSP2R"),
 
+       WM2200_DSP_AUX_ROUTES("DSP1"),
+       WM2200_DSP_AUX_ROUTES("DSP2"),
+
        WM2200_MIXER_ROUTES("OUT1L", "OUT1L"),
        WM2200_MIXER_ROUTES("OUT1R", "OUT1R"),
        WM2200_MIXER_ROUTES("OUT2L", "OUT2L"),
@@ -1968,12 +2154,15 @@ static const struct regmap_config wm2200_regmap = {
        .reg_bits = 16,
        .val_bits = 16,
 
-       .max_register = WM2200_MAX_REGISTER,
+       .max_register = WM2200_MAX_REGISTER + (ARRAY_SIZE(wm2200_ranges) *
+                                              WM2200_DSP_SPACING),
        .reg_defaults = wm2200_reg_defaults,
        .num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults),
        .volatile_reg = wm2200_volatile_register,
        .readable_reg = wm2200_readable_register,
        .cache_type = REGCACHE_RBTREE,
+       .ranges = wm2200_ranges,
+       .num_ranges = ARRAY_SIZE(wm2200_ranges),
 };
 
 static const unsigned int wm2200_dig_vu[] = {
@@ -2011,7 +2200,7 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
        wm2200->dev = &i2c->dev;
        init_completion(&wm2200->fll_lock);
 
-       wm2200->regmap = regmap_init_i2c(i2c, &wm2200_regmap);
+       wm2200->regmap = devm_regmap_init_i2c(i2c, &wm2200_regmap);
        if (IS_ERR(wm2200->regmap)) {
                ret = PTR_ERR(wm2200->regmap);
                dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
@@ -2019,6 +2208,22 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
                goto err;
        }
 
+       for (i = 0; i < 2; i++) {
+               wm2200->dsp[i].type = WMFW_ADSP1;
+               wm2200->dsp[i].part = "wm2200";
+               wm2200->dsp[i].num = i + 1;
+               wm2200->dsp[i].dev = &i2c->dev;
+               wm2200->dsp[i].regmap = wm2200->regmap;
+       }
+
+       wm2200->dsp[0].base = WM2200_DSP1_CONTROL_1;
+       wm2200->dsp[0].mem = wm2200_dsp1_regions;
+       wm2200->dsp[0].num_mems = ARRAY_SIZE(wm2200_dsp1_regions);
+
+       wm2200->dsp[1].base = WM2200_DSP2_CONTROL_1;
+       wm2200->dsp[1].mem = wm2200_dsp2_regions;
+       wm2200->dsp[1].num_mems = ARRAY_SIZE(wm2200_dsp2_regions);
+
        if (pdata)
                wm2200->pdata = *pdata;
 
@@ -2027,8 +2232,9 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
        for (i = 0; i < ARRAY_SIZE(wm2200->core_supplies); i++)
                wm2200->core_supplies[i].supply = wm2200_core_supply_names[i];
 
-       ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm2200->core_supplies),
-                                wm2200->core_supplies);
+       ret = devm_regulator_bulk_get(&i2c->dev,
+                                     ARRAY_SIZE(wm2200->core_supplies),
+                                     wm2200->core_supplies);
        if (ret != 0) {
                dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
                        ret);
@@ -2044,8 +2250,9 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
        }
 
        if (wm2200->pdata.ldo_ena) {
-               ret = gpio_request_one(wm2200->pdata.ldo_ena,
-                                      GPIOF_OUT_INIT_HIGH, "WM2200 LDOENA");
+               ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.ldo_ena,
+                                           GPIOF_OUT_INIT_HIGH,
+                                           "WM2200 LDOENA");
                if (ret < 0) {
                        dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
                                wm2200->pdata.ldo_ena, ret);
@@ -2055,8 +2262,9 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
        }
 
        if (wm2200->pdata.reset) {
-               ret = gpio_request_one(wm2200->pdata.reset,
-                                      GPIOF_OUT_INIT_HIGH, "WM2200 /RESET");
+               ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.reset,
+                                           GPIOF_OUT_INIT_HIGH,
+                                           "WM2200 /RESET");
                if (ret < 0) {
                        dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
                                wm2200->pdata.reset, ret);
@@ -2166,23 +2374,16 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
 err_pm_runtime:
        pm_runtime_disable(&i2c->dev);
 err_reset:
-       if (wm2200->pdata.reset) {
+       if (wm2200->pdata.reset)
                gpio_set_value_cansleep(wm2200->pdata.reset, 0);
-               gpio_free(wm2200->pdata.reset);
-       }
 err_ldo:
-       if (wm2200->pdata.ldo_ena) {
+       if (wm2200->pdata.ldo_ena)
                gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
-               gpio_free(wm2200->pdata.ldo_ena);
-       }
 err_enable:
        regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
                               wm2200->core_supplies);
 err_core:
-       regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
-                           wm2200->core_supplies);
 err_regmap:
-       regmap_exit(wm2200->regmap);
 err:
        return ret;
 }
@@ -2194,17 +2395,10 @@ static __devexit int wm2200_i2c_remove(struct i2c_client *i2c)
        snd_soc_unregister_codec(&i2c->dev);
        if (i2c->irq)
                free_irq(i2c->irq, wm2200);
-       if (wm2200->pdata.reset) {
+       if (wm2200->pdata.reset)
                gpio_set_value_cansleep(wm2200->pdata.reset, 0);
-               gpio_free(wm2200->pdata.reset);
-       }
-       if (wm2200->pdata.ldo_ena) {
+       if (wm2200->pdata.ldo_ena)
                gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
-               gpio_free(wm2200->pdata.ldo_ena);
-       }
-       regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
-                           wm2200->core_supplies);
-       regmap_exit(wm2200->regmap);
 
        return 0;
 }
index 1722b586bdba65bde94d9d3cb5cc1ca51cd44aee..bca9d33c1f0b9b9442aac49535f8e4eb1c35a78b 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "arizona.h"
 #include "wm5102.h"
+#include "wm_adsp.h"
 
 struct wm5102_priv {
        struct arizona_priv core;
@@ -42,6 +43,563 @@ static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
 static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
 static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0);
 
+static const struct wm_adsp_region wm5102_dsp1_regions[] = {
+       { .type = WMFW_ADSP2_PM, .base = 0x100000 },
+       { .type = WMFW_ADSP2_ZM, .base = 0x180000 },
+       { .type = WMFW_ADSP2_XM, .base = 0x190000 },
+       { .type = WMFW_ADSP2_YM, .base = 0x1a0000 },
+};
+
+static const struct reg_default wm5102_sysclk_reva_patch[] = {
+       { 0x3000, 0x2225 },
+       { 0x3001, 0x3a03 },
+       { 0x3002, 0x0225 },
+       { 0x3003, 0x0801 },
+       { 0x3004, 0x6249 },
+       { 0x3005, 0x0c04 },
+       { 0x3006, 0x0225 },
+       { 0x3007, 0x5901 },
+       { 0x3008, 0xe249 },
+       { 0x3009, 0x030d },
+       { 0x300a, 0x0249 },
+       { 0x300b, 0x2c01 },
+       { 0x300c, 0xe249 },
+       { 0x300d, 0x4342 },
+       { 0x300e, 0xe249 },
+       { 0x300f, 0x73c0 },
+       { 0x3010, 0x4249 },
+       { 0x3011, 0x0c00 },
+       { 0x3012, 0x0225 },
+       { 0x3013, 0x1f01 },
+       { 0x3014, 0x0225 },
+       { 0x3015, 0x1e01 },
+       { 0x3016, 0x0225 },
+       { 0x3017, 0xfa00 },
+       { 0x3018, 0x0000 },
+       { 0x3019, 0xf000 },
+       { 0x301a, 0x0000 },
+       { 0x301b, 0xf000 },
+       { 0x301c, 0x0000 },
+       { 0x301d, 0xf000 },
+       { 0x301e, 0x0000 },
+       { 0x301f, 0xf000 },
+       { 0x3020, 0x0000 },
+       { 0x3021, 0xf000 },
+       { 0x3022, 0x0000 },
+       { 0x3023, 0xf000 },
+       { 0x3024, 0x0000 },
+       { 0x3025, 0xf000 },
+       { 0x3026, 0x0000 },
+       { 0x3027, 0xf000 },
+       { 0x3028, 0x0000 },
+       { 0x3029, 0xf000 },
+       { 0x302a, 0x0000 },
+       { 0x302b, 0xf000 },
+       { 0x302c, 0x0000 },
+       { 0x302d, 0xf000 },
+       { 0x302e, 0x0000 },
+       { 0x302f, 0xf000 },
+       { 0x3030, 0x0225 },
+       { 0x3031, 0x1a01 },
+       { 0x3032, 0x0225 },
+       { 0x3033, 0x1e00 },
+       { 0x3034, 0x0225 },
+       { 0x3035, 0x1f00 },
+       { 0x3036, 0x6225 },
+       { 0x3037, 0xf800 },
+       { 0x3038, 0x0000 },
+       { 0x3039, 0xf000 },
+       { 0x303a, 0x0000 },
+       { 0x303b, 0xf000 },
+       { 0x303c, 0x0000 },
+       { 0x303d, 0xf000 },
+       { 0x303e, 0x0000 },
+       { 0x303f, 0xf000 },
+       { 0x3040, 0x2226 },
+       { 0x3041, 0x3a03 },
+       { 0x3042, 0x0226 },
+       { 0x3043, 0x0801 },
+       { 0x3044, 0x6249 },
+       { 0x3045, 0x0c06 },
+       { 0x3046, 0x0226 },
+       { 0x3047, 0x5901 },
+       { 0x3048, 0xe249 },
+       { 0x3049, 0x030d },
+       { 0x304a, 0x0249 },
+       { 0x304b, 0x2c01 },
+       { 0x304c, 0xe249 },
+       { 0x304d, 0x4342 },
+       { 0x304e, 0xe249 },
+       { 0x304f, 0x73c0 },
+       { 0x3050, 0x4249 },
+       { 0x3051, 0x0c00 },
+       { 0x3052, 0x0226 },
+       { 0x3053, 0x1f01 },
+       { 0x3054, 0x0226 },
+       { 0x3055, 0x1e01 },
+       { 0x3056, 0x0226 },
+       { 0x3057, 0xfa00 },
+       { 0x3058, 0x0000 },
+       { 0x3059, 0xf000 },
+       { 0x305a, 0x0000 },
+       { 0x305b, 0xf000 },
+       { 0x305c, 0x0000 },
+       { 0x305d, 0xf000 },
+       { 0x305e, 0x0000 },
+       { 0x305f, 0xf000 },
+       { 0x3060, 0x0000 },
+       { 0x3061, 0xf000 },
+       { 0x3062, 0x0000 },
+       { 0x3063, 0xf000 },
+       { 0x3064, 0x0000 },
+       { 0x3065, 0xf000 },
+       { 0x3066, 0x0000 },
+       { 0x3067, 0xf000 },
+       { 0x3068, 0x0000 },
+       { 0x3069, 0xf000 },
+       { 0x306a, 0x0000 },
+       { 0x306b, 0xf000 },
+       { 0x306c, 0x0000 },
+       { 0x306d, 0xf000 },
+       { 0x306e, 0x0000 },
+       { 0x306f, 0xf000 },
+       { 0x3070, 0x0226 },
+       { 0x3071, 0x1a01 },
+       { 0x3072, 0x0226 },
+       { 0x3073, 0x1e00 },
+       { 0x3074, 0x0226 },
+       { 0x3075, 0x1f00 },
+       { 0x3076, 0x6226 },
+       { 0x3077, 0xf800 },
+       { 0x3078, 0x0000 },
+       { 0x3079, 0xf000 },
+       { 0x307a, 0x0000 },
+       { 0x307b, 0xf000 },
+       { 0x307c, 0x0000 },
+       { 0x307d, 0xf000 },
+       { 0x307e, 0x0000 },
+       { 0x307f, 0xf000 },
+       { 0x3080, 0x2227 },
+       { 0x3081, 0x3a03 },
+       { 0x3082, 0x0227 },
+       { 0x3083, 0x0801 },
+       { 0x3084, 0x6255 },
+       { 0x3085, 0x0c04 },
+       { 0x3086, 0x0227 },
+       { 0x3087, 0x5901 },
+       { 0x3088, 0xe255 },
+       { 0x3089, 0x030d },
+       { 0x308a, 0x0255 },
+       { 0x308b, 0x2c01 },
+       { 0x308c, 0xe255 },
+       { 0x308d, 0x4342 },
+       { 0x308e, 0xe255 },
+       { 0x308f, 0x73c0 },
+       { 0x3090, 0x4255 },
+       { 0x3091, 0x0c00 },
+       { 0x3092, 0x0227 },
+       { 0x3093, 0x1f01 },
+       { 0x3094, 0x0227 },
+       { 0x3095, 0x1e01 },
+       { 0x3096, 0x0227 },
+       { 0x3097, 0xfa00 },
+       { 0x3098, 0x0000 },
+       { 0x3099, 0xf000 },
+       { 0x309a, 0x0000 },
+       { 0x309b, 0xf000 },
+       { 0x309c, 0x0000 },
+       { 0x309d, 0xf000 },
+       { 0x309e, 0x0000 },
+       { 0x309f, 0xf000 },
+       { 0x30a0, 0x0000 },
+       { 0x30a1, 0xf000 },
+       { 0x30a2, 0x0000 },
+       { 0x30a3, 0xf000 },
+       { 0x30a4, 0x0000 },
+       { 0x30a5, 0xf000 },
+       { 0x30a6, 0x0000 },
+       { 0x30a7, 0xf000 },
+       { 0x30a8, 0x0000 },
+       { 0x30a9, 0xf000 },
+       { 0x30aa, 0x0000 },
+       { 0x30ab, 0xf000 },
+       { 0x30ac, 0x0000 },
+       { 0x30ad, 0xf000 },
+       { 0x30ae, 0x0000 },
+       { 0x30af, 0xf000 },
+       { 0x30b0, 0x0227 },
+       { 0x30b1, 0x1a01 },
+       { 0x30b2, 0x0227 },
+       { 0x30b3, 0x1e00 },
+       { 0x30b4, 0x0227 },
+       { 0x30b5, 0x1f00 },
+       { 0x30b6, 0x6227 },
+       { 0x30b7, 0xf800 },
+       { 0x30b8, 0x0000 },
+       { 0x30b9, 0xf000 },
+       { 0x30ba, 0x0000 },
+       { 0x30bb, 0xf000 },
+       { 0x30bc, 0x0000 },
+       { 0x30bd, 0xf000 },
+       { 0x30be, 0x0000 },
+       { 0x30bf, 0xf000 },
+       { 0x30c0, 0x2228 },
+       { 0x30c1, 0x3a03 },
+       { 0x30c2, 0x0228 },
+       { 0x30c3, 0x0801 },
+       { 0x30c4, 0x6255 },
+       { 0x30c5, 0x0c06 },
+       { 0x30c6, 0x0228 },
+       { 0x30c7, 0x5901 },
+       { 0x30c8, 0xe255 },
+       { 0x30c9, 0x030d },
+       { 0x30ca, 0x0255 },
+       { 0x30cb, 0x2c01 },
+       { 0x30cc, 0xe255 },
+       { 0x30cd, 0x4342 },
+       { 0x30ce, 0xe255 },
+       { 0x30cf, 0x73c0 },
+       { 0x30d0, 0x4255 },
+       { 0x30d1, 0x0c00 },
+       { 0x30d2, 0x0228 },
+       { 0x30d3, 0x1f01 },
+       { 0x30d4, 0x0228 },
+       { 0x30d5, 0x1e01 },
+       { 0x30d6, 0x0228 },
+       { 0x30d7, 0xfa00 },
+       { 0x30d8, 0x0000 },
+       { 0x30d9, 0xf000 },
+       { 0x30da, 0x0000 },
+       { 0x30db, 0xf000 },
+       { 0x30dc, 0x0000 },
+       { 0x30dd, 0xf000 },
+       { 0x30de, 0x0000 },
+       { 0x30df, 0xf000 },
+       { 0x30e0, 0x0000 },
+       { 0x30e1, 0xf000 },
+       { 0x30e2, 0x0000 },
+       { 0x30e3, 0xf000 },
+       { 0x30e4, 0x0000 },
+       { 0x30e5, 0xf000 },
+       { 0x30e6, 0x0000 },
+       { 0x30e7, 0xf000 },
+       { 0x30e8, 0x0000 },
+       { 0x30e9, 0xf000 },
+       { 0x30ea, 0x0000 },
+       { 0x30eb, 0xf000 },
+       { 0x30ec, 0x0000 },
+       { 0x30ed, 0xf000 },
+       { 0x30ee, 0x0000 },
+       { 0x30ef, 0xf000 },
+       { 0x30f0, 0x0228 },
+       { 0x30f1, 0x1a01 },
+       { 0x30f2, 0x0228 },
+       { 0x30f3, 0x1e00 },
+       { 0x30f4, 0x0228 },
+       { 0x30f5, 0x1f00 },
+       { 0x30f6, 0x6228 },
+       { 0x30f7, 0xf800 },
+       { 0x30f8, 0x0000 },
+       { 0x30f9, 0xf000 },
+       { 0x30fa, 0x0000 },
+       { 0x30fb, 0xf000 },
+       { 0x30fc, 0x0000 },
+       { 0x30fd, 0xf000 },
+       { 0x30fe, 0x0000 },
+       { 0x30ff, 0xf000 },
+       { 0x3100, 0x222b },
+       { 0x3101, 0x3a03 },
+       { 0x3102, 0x222b },
+       { 0x3103, 0x5803 },
+       { 0x3104, 0xe26f },
+       { 0x3105, 0x030d },
+       { 0x3106, 0x626f },
+       { 0x3107, 0x2c01 },
+       { 0x3108, 0xe26f },
+       { 0x3109, 0x4342 },
+       { 0x310a, 0xe26f },
+       { 0x310b, 0x73c0 },
+       { 0x310c, 0x026f },
+       { 0x310d, 0x0c00 },
+       { 0x310e, 0x022b },
+       { 0x310f, 0x1f01 },
+       { 0x3110, 0x022b },
+       { 0x3111, 0x1e01 },
+       { 0x3112, 0x022b },
+       { 0x3113, 0xfa00 },
+       { 0x3114, 0x0000 },
+       { 0x3115, 0xf000 },
+       { 0x3116, 0x0000 },
+       { 0x3117, 0xf000 },
+       { 0x3118, 0x0000 },
+       { 0x3119, 0xf000 },
+       { 0x311a, 0x0000 },
+       { 0x311b, 0xf000 },
+       { 0x311c, 0x0000 },
+       { 0x311d, 0xf000 },
+       { 0x311e, 0x0000 },
+       { 0x311f, 0xf000 },
+       { 0x3120, 0x022b },
+       { 0x3121, 0x0a01 },
+       { 0x3122, 0x022b },
+       { 0x3123, 0x1e00 },
+       { 0x3124, 0x022b },
+       { 0x3125, 0x1f00 },
+       { 0x3126, 0x622b },
+       { 0x3127, 0xf800 },
+       { 0x3128, 0x0000 },
+       { 0x3129, 0xf000 },
+       { 0x312a, 0x0000 },
+       { 0x312b, 0xf000 },
+       { 0x312c, 0x0000 },
+       { 0x312d, 0xf000 },
+       { 0x312e, 0x0000 },
+       { 0x312f, 0xf000 },
+       { 0x3130, 0x0000 },
+       { 0x3131, 0xf000 },
+       { 0x3132, 0x0000 },
+       { 0x3133, 0xf000 },
+       { 0x3134, 0x0000 },
+       { 0x3135, 0xf000 },
+       { 0x3136, 0x0000 },
+       { 0x3137, 0xf000 },
+       { 0x3138, 0x0000 },
+       { 0x3139, 0xf000 },
+       { 0x313a, 0x0000 },
+       { 0x313b, 0xf000 },
+       { 0x313c, 0x0000 },
+       { 0x313d, 0xf000 },
+       { 0x313e, 0x0000 },
+       { 0x313f, 0xf000 },
+       { 0x3140, 0x0000 },
+       { 0x3141, 0xf000 },
+       { 0x3142, 0x0000 },
+       { 0x3143, 0xf000 },
+       { 0x3144, 0x0000 },
+       { 0x3145, 0xf000 },
+       { 0x3146, 0x0000 },
+       { 0x3147, 0xf000 },
+       { 0x3148, 0x0000 },
+       { 0x3149, 0xf000 },
+       { 0x314a, 0x0000 },
+       { 0x314b, 0xf000 },
+       { 0x314c, 0x0000 },
+       { 0x314d, 0xf000 },
+       { 0x314e, 0x0000 },
+       { 0x314f, 0xf000 },
+       { 0x3150, 0x0000 },
+       { 0x3151, 0xf000 },
+       { 0x3152, 0x0000 },
+       { 0x3153, 0xf000 },
+       { 0x3154, 0x0000 },
+       { 0x3155, 0xf000 },
+       { 0x3156, 0x0000 },
+       { 0x3157, 0xf000 },
+       { 0x3158, 0x0000 },
+       { 0x3159, 0xf000 },
+       { 0x315a, 0x0000 },
+       { 0x315b, 0xf000 },
+       { 0x315c, 0x0000 },
+       { 0x315d, 0xf000 },
+       { 0x315e, 0x0000 },
+       { 0x315f, 0xf000 },
+       { 0x3160, 0x0000 },
+       { 0x3161, 0xf000 },
+       { 0x3162, 0x0000 },
+       { 0x3163, 0xf000 },
+       { 0x3164, 0x0000 },
+       { 0x3165, 0xf000 },
+       { 0x3166, 0x0000 },
+       { 0x3167, 0xf000 },
+       { 0x3168, 0x0000 },
+       { 0x3169, 0xf000 },
+       { 0x316a, 0x0000 },
+       { 0x316b, 0xf000 },
+       { 0x316c, 0x0000 },
+       { 0x316d, 0xf000 },
+       { 0x316e, 0x0000 },
+       { 0x316f, 0xf000 },
+       { 0x3170, 0x0000 },
+       { 0x3171, 0xf000 },
+       { 0x3172, 0x0000 },
+       { 0x3173, 0xf000 },
+       { 0x3174, 0x0000 },
+       { 0x3175, 0xf000 },
+       { 0x3176, 0x0000 },
+       { 0x3177, 0xf000 },
+       { 0x3178, 0x0000 },
+       { 0x3179, 0xf000 },
+       { 0x317a, 0x0000 },
+       { 0x317b, 0xf000 },
+       { 0x317c, 0x0000 },
+       { 0x317d, 0xf000 },
+       { 0x317e, 0x0000 },
+       { 0x317f, 0xf000 },
+       { 0x3180, 0x2001 },
+       { 0x3181, 0xf101 },
+       { 0x3182, 0x0000 },
+       { 0x3183, 0xf000 },
+       { 0x3184, 0x0000 },
+       { 0x3185, 0xf000 },
+       { 0x3186, 0x0000 },
+       { 0x3187, 0xf000 },
+       { 0x3188, 0x0000 },
+       { 0x3189, 0xf000 },
+       { 0x318a, 0x0000 },
+       { 0x318b, 0xf000 },
+       { 0x318c, 0x0000 },
+       { 0x318d, 0xf000 },
+       { 0x318e, 0x0000 },
+       { 0x318f, 0xf000 },
+       { 0x3190, 0x0000 },
+       { 0x3191, 0xf000 },
+       { 0x3192, 0x0000 },
+       { 0x3193, 0xf000 },
+       { 0x3194, 0x0000 },
+       { 0x3195, 0xf000 },
+       { 0x3196, 0x0000 },
+       { 0x3197, 0xf000 },
+       { 0x3198, 0x0000 },
+       { 0x3199, 0xf000 },
+       { 0x319a, 0x0000 },
+       { 0x319b, 0xf000 },
+       { 0x319c, 0x0000 },
+       { 0x319d, 0xf000 },
+       { 0x319e, 0x0000 },
+       { 0x319f, 0xf000 },
+       { 0x31a0, 0x0000 },
+       { 0x31a1, 0xf000 },
+       { 0x31a2, 0x0000 },
+       { 0x31a3, 0xf000 },
+       { 0x31a4, 0x0000 },
+       { 0x31a5, 0xf000 },
+       { 0x31a6, 0x0000 },
+       { 0x31a7, 0xf000 },
+       { 0x31a8, 0x0000 },
+       { 0x31a9, 0xf000 },
+       { 0x31aa, 0x0000 },
+       { 0x31ab, 0xf000 },
+       { 0x31ac, 0x0000 },
+       { 0x31ad, 0xf000 },
+       { 0x31ae, 0x0000 },
+       { 0x31af, 0xf000 },
+       { 0x31b0, 0x0000 },
+       { 0x31b1, 0xf000 },
+       { 0x31b2, 0x0000 },
+       { 0x31b3, 0xf000 },
+       { 0x31b4, 0x0000 },
+       { 0x31b5, 0xf000 },
+       { 0x31b6, 0x0000 },
+       { 0x31b7, 0xf000 },
+       { 0x31b8, 0x0000 },
+       { 0x31b9, 0xf000 },
+       { 0x31ba, 0x0000 },
+       { 0x31bb, 0xf000 },
+       { 0x31bc, 0x0000 },
+       { 0x31bd, 0xf000 },
+       { 0x31be, 0x0000 },
+       { 0x31bf, 0xf000 },
+       { 0x31c0, 0x0000 },
+       { 0x31c1, 0xf000 },
+       { 0x31c2, 0x0000 },
+       { 0x31c3, 0xf000 },
+       { 0x31c4, 0x0000 },
+       { 0x31c5, 0xf000 },
+       { 0x31c6, 0x0000 },
+       { 0x31c7, 0xf000 },
+       { 0x31c8, 0x0000 },
+       { 0x31c9, 0xf000 },
+       { 0x31ca, 0x0000 },
+       { 0x31cb, 0xf000 },
+       { 0x31cc, 0x0000 },
+       { 0x31cd, 0xf000 },
+       { 0x31ce, 0x0000 },
+       { 0x31cf, 0xf000 },
+       { 0x31d0, 0x0000 },
+       { 0x31d1, 0xf000 },
+       { 0x31d2, 0x0000 },
+       { 0x31d3, 0xf000 },
+       { 0x31d4, 0x0000 },
+       { 0x31d5, 0xf000 },
+       { 0x31d6, 0x0000 },
+       { 0x31d7, 0xf000 },
+       { 0x31d8, 0x0000 },
+       { 0x31d9, 0xf000 },
+       { 0x31da, 0x0000 },
+       { 0x31db, 0xf000 },
+       { 0x31dc, 0x0000 },
+       { 0x31dd, 0xf000 },
+       { 0x31de, 0x0000 },
+       { 0x31df, 0xf000 },
+       { 0x31e0, 0x0000 },
+       { 0x31e1, 0xf000 },
+       { 0x31e2, 0x0000 },
+       { 0x31e3, 0xf000 },
+       { 0x31e4, 0x0000 },
+       { 0x31e5, 0xf000 },
+       { 0x31e6, 0x0000 },
+       { 0x31e7, 0xf000 },
+       { 0x31e8, 0x0000 },
+       { 0x31e9, 0xf000 },
+       { 0x31ea, 0x0000 },
+       { 0x31eb, 0xf000 },
+       { 0x31ec, 0x0000 },
+       { 0x31ed, 0xf000 },
+       { 0x31ee, 0x0000 },
+       { 0x31ef, 0xf000 },
+       { 0x31f0, 0x0000 },
+       { 0x31f1, 0xf000 },
+       { 0x31f2, 0x0000 },
+       { 0x31f3, 0xf000 },
+       { 0x31f4, 0x0000 },
+       { 0x31f5, 0xf000 },
+       { 0x31f6, 0x0000 },
+       { 0x31f7, 0xf000 },
+       { 0x31f8, 0x0000 },
+       { 0x31f9, 0xf000 },
+       { 0x31fa, 0x0000 },
+       { 0x31fb, 0xf000 },
+       { 0x31fc, 0x0000 },
+       { 0x31fd, 0xf000 },
+       { 0x31fe, 0x0000 },
+       { 0x31ff, 0xf000 },
+       { 0x024d, 0xff50 },
+       { 0x0252, 0xff50 },
+       { 0x0259, 0x0112 },
+       { 0x025e, 0x0112 },
+};
+
+static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
+                           struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct arizona *arizona = dev_get_drvdata(codec->dev);
+       struct regmap *regmap = codec->control_data;
+       const struct reg_default *patch = NULL;
+       int i, patch_size;
+
+       switch (arizona->rev) {
+       case 0:
+               patch = wm5102_sysclk_reva_patch;
+               patch_size = ARRAY_SIZE(wm5102_sysclk_reva_patch);
+               break;
+       }
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               if (patch)
+                       for (i = 0; i < patch_size; i++)
+                               regmap_write(regmap, patch[i].reg,
+                                            patch[i].def);
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+}
+
 static const struct snd_kcontrol_new wm5102_snd_controls[] = {
 SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL,
           ARIZONA_IN1_OSR_SHIFT, 1, 0),
@@ -137,6 +695,9 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE),
 ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE),
 
+ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE),
+ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE),
+
 SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode),
 SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode),
 SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode),
@@ -274,6 +835,10 @@ ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE);
 
+ARIZONA_MIXER_ENUMS(DSP1L, ARIZONA_DSP1LMIX_INPUT_1_SOURCE);
+ARIZONA_MIXER_ENUMS(DSP1R, ARIZONA_DSP1RMIX_INPUT_1_SOURCE);
+
+ARIZONA_DSP_AUX_ENUMS(DSP1, ARIZONA_DSP1AUX1MIX_INPUT_1_SOURCE);
 
 static const char *wm5102_aec_loopback_texts[] = {
        "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "EPOUT",
@@ -297,7 +862,7 @@ static const struct snd_kcontrol_new wm5102_aec_loopback_mux =
 
 static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = {
 SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
-                   0, NULL, 0),
+                   0, wm5102_sysclk_ev, SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1,
                    ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK,
@@ -344,9 +909,9 @@ SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT,
 SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1,
                    ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2,
-                   ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+                   ARIZONA_MICB2_ENA_SHIFT, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3,
-                   ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0),
+                   ARIZONA_MICB3_ENA_SHIFT, 0, NULL, 0),
 
 SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR,
                 ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0),
@@ -446,6 +1011,8 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0,
 SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0,
                    ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0),
 
+WM_ADSP2("DSP1", 0),
+
 SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1,
                       ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5102_aec_loopback_mux),
 
@@ -526,6 +1093,8 @@ ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"),
 ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"),
 ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"),
 
+WM_ADSP2("DSP1", 0),
+
 SND_SOC_DAPM_OUTPUT("HPOUT1L"),
 SND_SOC_DAPM_OUTPUT("HPOUT1R"),
 SND_SOC_DAPM_OUTPUT("HPOUT2L"),
@@ -577,7 +1146,13 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"),
        { name, "ASRC1L", "ASRC1L" }, \
        { name, "ASRC1R", "ASRC1R" }, \
        { name, "ASRC2L", "ASRC2L" }, \
-       { name, "ASRC2R", "ASRC2R" }
+       { name, "ASRC2R", "ASRC2R" }, \
+       { name, "DSP1.1", "DSP1" }, \
+       { name, "DSP1.2", "DSP1" }, \
+       { name, "DSP1.3", "DSP1" }, \
+       { name, "DSP1.4", "DSP1" }, \
+       { name, "DSP1.5", "DSP1" }, \
+       { name, "DSP1.6", "DSP1" }
 
 static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
        { "AIF2 Capture", NULL, "DBVDD2" },
@@ -710,6 +1285,8 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = {
        ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"),
        ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"),
 
+       ARIZONA_DSP_ROUTES("DSP1"),
+
        { "AEC Loopback", "HPOUT1L", "OUT1L" },
        { "AEC Loopback", "HPOUT1R", "OUT1R" },
        { "HPOUT1L", NULL, "OUT1L" },
@@ -884,6 +1461,15 @@ static int __devinit wm5102_probe(struct platform_device *pdev)
 
        wm5102->core.arizona = arizona;
 
+       wm5102->core.adsp[0].part = "wm5102";
+       wm5102->core.adsp[0].num = 1;
+       wm5102->core.adsp[0].type = WMFW_ADSP2;
+       wm5102->core.adsp[0].base = ARIZONA_DSP1_CONTROL_1;
+       wm5102->core.adsp[0].dev = arizona->dev;
+       wm5102->core.adsp[0].regmap = arizona->regmap;
+       wm5102->core.adsp[0].mem = wm5102_dsp1_regions;
+       wm5102->core.adsp[0].num_mems = ARRAY_SIZE(wm5102_dsp1_regions);
+
        for (i = 0; i < ARRAY_SIZE(wm5102->fll); i++)
                wm5102->fll[i].vco_mult = 1;
 
index 89151ca5e7766b69cd57447e611fcf1301fd301f..7665d68c4558ee071e8f8067ad92e458a3b3b9fd 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/spi/spi.h>
 #include <linux/slab.h>
 #include <linux/of_device.h>
  * We can't read the WM8750 register space when we
  * are using 2 wire for device control, so we cache them instead.
  */
-static const u16 wm8750_reg[] = {
-       0x0097, 0x0097, 0x0079, 0x0079,  /*  0 */
-       0x0000, 0x0008, 0x0000, 0x000a,  /*  4 */
-       0x0000, 0x0000, 0x00ff, 0x00ff,  /*  8 */
-       0x000f, 0x000f, 0x0000, 0x0000,  /* 12 */
-       0x0000, 0x007b, 0x0000, 0x0032,  /* 16 */
-       0x0000, 0x00c3, 0x00c3, 0x00c0,  /* 20 */
-       0x0000, 0x0000, 0x0000, 0x0000,  /* 24 */
-       0x0000, 0x0000, 0x0000, 0x0000,  /* 28 */
-       0x0000, 0x0000, 0x0050, 0x0050,  /* 32 */
-       0x0050, 0x0050, 0x0050, 0x0050,  /* 36 */
-       0x0079, 0x0079, 0x0079,          /* 40 */
+static const struct reg_default wm8750_reg_defaults[] = {
+       {  0, 0x0097 },
+       {  1, 0x0097 },
+       {  2, 0x0079 },
+       {  3, 0x0079 },
+       {  4, 0x0000 },
+       {  5, 0x0008 },
+       {  6, 0x0000 },
+       {  7, 0x000a },
+       {  8, 0x0000 },
+       {  9, 0x0000 },
+       { 10, 0x00ff },
+       { 11, 0x00ff },
+       { 12, 0x000f },
+       { 13, 0x000f },
+       { 14, 0x0000 },
+       { 15, 0x0000 },
+       { 16, 0x0000 },
+       { 17, 0x007b },
+       { 18, 0x0000 },
+       { 19, 0x0032 },
+       { 20, 0x0000 },
+       { 21, 0x00c3 },
+       { 22, 0x00c3 },
+       { 23, 0x00c0 },
+       { 24, 0x0000 },
+       { 25, 0x0000 },
+       { 26, 0x0000 },
+       { 27, 0x0000 },
+       { 28, 0x0000 },
+       { 29, 0x0000 },
+       { 30, 0x0000 },
+       { 31, 0x0000 },
+       { 32, 0x0000 },
+       { 33, 0x0000 },
+       { 34, 0x0050 },
+       { 35, 0x0050 },
+       { 36, 0x0050 },
+       { 37, 0x0050 },
+       { 38, 0x0050 },
+       { 39, 0x0050 },
+       { 40, 0x0079 },
+       { 41, 0x0079 },
+       { 42, 0x0079 },
 };
 
 /* codec private data */
 struct wm8750_priv {
        unsigned int sysclk;
-       enum snd_soc_control_type control_type;
 };
 
 #define wm8750_reset(c)        snd_soc_write(c, WM8750_RESET, 0)
@@ -668,10 +700,9 @@ static int wm8750_resume(struct snd_soc_codec *codec)
 
 static int wm8750_probe(struct snd_soc_codec *codec)
 {
-       struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
        int ret;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
        if (ret < 0) {
                printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret);
                return ret;
@@ -711,9 +742,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8750 = {
        .suspend =      wm8750_suspend,
        .resume =       wm8750_resume,
        .set_bias_level = wm8750_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8750_reg),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8750_reg,
 
        .controls = wm8750_snd_controls,
        .num_controls = ARRAY_SIZE(wm8750_snd_controls),
@@ -730,10 +758,21 @@ static const struct of_device_id wm8750_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, wm8750_of_match);
 
+static const struct regmap_config wm8750_regmap = {
+       .reg_bits = 7,
+       .val_bits = 9,
+       .max_register = WM8750_MOUTV,
+
+       .reg_defaults = wm8750_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8750_reg_defaults),
+       .cache_type = REGCACHE_RBTREE,
+};
+
 #if defined(CONFIG_SPI_MASTER)
 static int __devinit wm8750_spi_probe(struct spi_device *spi)
 {
        struct wm8750_priv *wm8750;
+       struct regmap *regmap;
        int ret;
 
        wm8750 = devm_kzalloc(&spi->dev, sizeof(struct wm8750_priv),
@@ -741,7 +780,10 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi)
        if (wm8750 == NULL)
                return -ENOMEM;
 
-       wm8750->control_type = SND_SOC_SPI;
+       regmap = devm_regmap_init_spi(spi, &wm8750_regmap);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
        spi_set_drvdata(spi, wm8750);
 
        ret = snd_soc_register_codec(&spi->dev,
@@ -779,6 +821,7 @@ static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct wm8750_priv *wm8750;
+       struct regmap *regmap;
        int ret;
 
        wm8750 = devm_kzalloc(&i2c->dev, sizeof(struct wm8750_priv),
@@ -787,7 +830,10 @@ static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, wm8750);
-       wm8750->control_type = SND_SOC_I2C;
+
+       regmap = devm_regmap_init_i2c(i2c, &wm8750_regmap);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
 
        ret =  snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8750, &wm8750_dai, 1);
index c7c0034d39669a5e4b548bd7a46f40eb716f00cd..0b690ba875f84ba1bd2df6934afc27930a81a29b 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/of_device.h>
 #include <linux/pm.h>
 #include <linux/spi/spi.h>
+#include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 #include <sound/core.h>
@@ -35,19 +36,52 @@ static const char *wm8770_supply_names[WM8770_NUM_SUPPLIES] = {
        "DVDD"
 };
 
-static const u16 wm8770_reg_defs[WM8770_CACHEREGNUM] = {
-       0x7f, 0x7f, 0x7f, 0x7f,
-       0x7f, 0x7f, 0x7f, 0x7f,
-       0x7f, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0xff, 0xff,
-       0xff, 0xff, 0, 0x90, 0,
-       0, 0x22, 0x22, 0x3e,
-       0xc, 0xc, 0x100, 0x189,
-       0x189, 0x8770
+static const struct reg_default wm8770_reg_defaults[] = {
+       {  0, 0x7f },
+       {  1, 0x7f },
+       {  2, 0x7f },
+       {  3, 0x7f },
+       {  4, 0x7f },
+       {  5, 0x7f },
+       {  6, 0x7f },
+       {  7, 0x7f },
+       {  8, 0x7f },
+       {  9, 0xff },
+       { 10, 0xff },
+       { 11, 0xff },
+       { 12, 0xff },
+       { 13, 0xff },
+       { 14, 0xff },
+       { 15, 0xff },
+       { 16, 0xff },
+       { 17, 0xff },
+       { 18, 0    },
+       { 19, 0x90 },
+       { 20, 0    },
+       { 21, 0    },
+       { 22, 0x22 },
+       { 23, 0x22 },
+       { 24, 0x3e },
+       { 25, 0xc  },
+       { 26, 0xc  },
+       { 27, 0x100 },
+       { 28, 0x189 },
+       { 29, 0x189 },
+       { 30, 0x8770 },
 };
 
+static bool wm8770_volatile_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case WM8770_RESET:
+               return true;
+       default:
+               return false;
+       }
+}
+
 struct wm8770_priv {
-       enum snd_soc_control_type control_type;
+       struct regmap *regmap;
        struct regulator_bulk_data supplies[WM8770_NUM_SUPPLIES];
        struct notifier_block disable_nb[WM8770_NUM_SUPPLIES];
        struct snd_soc_codec *codec;
@@ -71,7 +105,7 @@ static int wm8770_regulator_event_##n(struct notifier_block *nb, \
        struct wm8770_priv *wm8770 = container_of(nb, struct wm8770_priv, \
                                     disable_nb[n]); \
        if (event & REGULATOR_EVENT_DISABLE) { \
-               wm8770->codec->cache_sync = 1; \
+               regcache_mark_dirty(wm8770->regmap);    \
        } \
        return 0; \
 }
@@ -466,24 +500,6 @@ static int wm8770_set_sysclk(struct snd_soc_dai *dai,
        return 0;
 }
 
-static void wm8770_sync_cache(struct snd_soc_codec *codec)
-{
-       int i;
-       u16 *cache;
-
-       if (!codec->cache_sync)
-               return;
-
-       codec->cache_only = 0;
-       cache = codec->reg_cache;
-       for (i = 0; i < codec->driver->reg_cache_size; i++) {
-               if (i == WM8770_RESET || cache[i] == wm8770_reg_defs[i])
-                       continue;
-               snd_soc_write(codec, i, cache[i]);
-       }
-       codec->cache_sync = 0;
-}
-
 static int wm8770_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
@@ -507,7 +523,9 @@ static int wm8770_set_bias_level(struct snd_soc_codec *codec,
                                        ret);
                                return ret;
                        }
-                       wm8770_sync_cache(codec);
+
+                       regcache_sync(wm8770->regmap);
+
                        /* global powerup */
                        snd_soc_write(codec, WM8770_PWDNCTRL, 0);
                }
@@ -554,68 +572,25 @@ static struct snd_soc_dai_driver wm8770_dai = {
        .symmetric_rates = 1
 };
 
-#ifdef CONFIG_PM
-static int wm8770_suspend(struct snd_soc_codec *codec)
-{
-       wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF);
-       return 0;
-}
-
-static int wm8770_resume(struct snd_soc_codec *codec)
-{
-       wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-       return 0;
-}
-#else
-#define wm8770_suspend NULL
-#define wm8770_resume NULL
-#endif
-
 static int wm8770_probe(struct snd_soc_codec *codec)
 {
        struct wm8770_priv *wm8770;
        int ret;
-       int i;
 
        wm8770 = snd_soc_codec_get_drvdata(codec);
        wm8770->codec = codec;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8770->control_type);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
        if (ret < 0) {
                dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
                return ret;
        }
 
-       for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++)
-               wm8770->supplies[i].supply = wm8770_supply_names[i];
-
-       ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8770->supplies),
-                                wm8770->supplies);
-       if (ret) {
-               dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
-               return ret;
-       }
-
-       wm8770->disable_nb[0].notifier_call = wm8770_regulator_event_0;
-       wm8770->disable_nb[1].notifier_call = wm8770_regulator_event_1;
-       wm8770->disable_nb[2].notifier_call = wm8770_regulator_event_2;
-
-       /* This should really be moved into the regulator core */
-       for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) {
-               ret = regulator_register_notifier(wm8770->supplies[i].consumer,
-                                                 &wm8770->disable_nb[i]);
-               if (ret) {
-                       dev_err(codec->dev,
-                               "Failed to register regulator notifier: %d\n",
-                               ret);
-               }
-       }
-
        ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies),
                                    wm8770->supplies);
        if (ret) {
                dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
-               goto err_reg_get;
+               return ret;
        }
 
        ret = wm8770_reset(codec);
@@ -624,8 +599,6 @@ static int wm8770_probe(struct snd_soc_codec *codec)
                goto err_reg_enable;
        }
 
-       wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
        /* latch the volume update bits */
        snd_soc_update_bits(codec, WM8770_MSDIGVOL, 0x100, 0x100);
        snd_soc_update_bits(codec, WM8770_MSALGVOL, 0x100, 0x100);
@@ -641,46 +614,22 @@ static int wm8770_probe(struct snd_soc_codec *codec)
        /* mute all DACs */
        snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10, 0x10);
 
-       snd_soc_add_codec_controls(codec, wm8770_snd_controls,
-                            ARRAY_SIZE(wm8770_snd_controls));
-       snd_soc_dapm_new_controls(&codec->dapm, wm8770_dapm_widgets,
-                                 ARRAY_SIZE(wm8770_dapm_widgets));
-       snd_soc_dapm_add_routes(&codec->dapm, wm8770_intercon,
-                               ARRAY_SIZE(wm8770_intercon));
-       return 0;
-
 err_reg_enable:
        regulator_bulk_disable(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
-err_reg_get:
-       regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
        return ret;
 }
 
-static int wm8770_remove(struct snd_soc_codec *codec)
-{
-       struct wm8770_priv *wm8770;
-       int i;
-
-       wm8770 = snd_soc_codec_get_drvdata(codec);
-       wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
-       for (i = 0; i < ARRAY_SIZE(wm8770->supplies); ++i)
-               regulator_unregister_notifier(wm8770->supplies[i].consumer,
-                                             &wm8770->disable_nb[i]);
-       regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies);
-       return 0;
-}
-
 static struct snd_soc_codec_driver soc_codec_dev_wm8770 = {
        .probe = wm8770_probe,
-       .remove = wm8770_remove,
-       .suspend = wm8770_suspend,
-       .resume = wm8770_resume,
        .set_bias_level = wm8770_set_bias_level,
        .idle_bias_off = true,
-       .reg_cache_size = ARRAY_SIZE(wm8770_reg_defs),
-       .reg_word_size = sizeof (u16),
-       .reg_cache_default = wm8770_reg_defs
+
+       .controls = wm8770_snd_controls,
+       .num_controls = ARRAY_SIZE(wm8770_snd_controls),
+       .dapm_widgets = wm8770_dapm_widgets,
+       .num_dapm_widgets = ARRAY_SIZE(wm8770_dapm_widgets),
+       .dapm_routes = wm8770_intercon,
+       .num_dapm_routes = ARRAY_SIZE(wm8770_intercon),
 };
 
 static const struct of_device_id wm8770_of_match[] = {
@@ -689,17 +638,57 @@ static const struct of_device_id wm8770_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, wm8770_of_match);
 
+static const struct regmap_config wm8770_regmap = {
+       .reg_bits = 7,
+       .val_bits = 9,
+       .max_register = WM8770_RESET,
+
+       .reg_defaults = wm8770_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8770_reg_defaults),
+       .cache_type = REGCACHE_RBTREE,
+
+       .volatile_reg = wm8770_volatile_reg,
+};
+
 static int __devinit wm8770_spi_probe(struct spi_device *spi)
 {
        struct wm8770_priv *wm8770;
-       int ret;
+       int ret, i;
 
        wm8770 = devm_kzalloc(&spi->dev, sizeof(struct wm8770_priv),
                              GFP_KERNEL);
        if (!wm8770)
                return -ENOMEM;
 
-       wm8770->control_type = SND_SOC_SPI;
+       for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++)
+               wm8770->supplies[i].supply = wm8770_supply_names[i];
+
+       ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(wm8770->supplies),
+                                     wm8770->supplies);
+       if (ret) {
+               dev_err(&spi->dev, "Failed to request supplies: %d\n", ret);
+               return ret;
+       }
+
+       wm8770->disable_nb[0].notifier_call = wm8770_regulator_event_0;
+       wm8770->disable_nb[1].notifier_call = wm8770_regulator_event_1;
+       wm8770->disable_nb[2].notifier_call = wm8770_regulator_event_2;
+
+       /* This should really be moved into the regulator core */
+       for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) {
+               ret = regulator_register_notifier(wm8770->supplies[i].consumer,
+                                                 &wm8770->disable_nb[i]);
+               if (ret) {
+                       dev_err(&spi->dev,
+                               "Failed to register regulator notifier: %d\n",
+                               ret);
+               }
+       }
+
+       wm8770->regmap = devm_regmap_init_spi(spi, &wm8770_regmap);
+       if (IS_ERR(wm8770->regmap))
+               return PTR_ERR(wm8770->regmap);
+
        spi_set_drvdata(spi, wm8770);
 
        ret = snd_soc_register_codec(&spi->dev,
@@ -710,7 +699,15 @@ static int __devinit wm8770_spi_probe(struct spi_device *spi)
 
 static int __devexit wm8770_spi_remove(struct spi_device *spi)
 {
+       struct wm8770_priv *wm8770 = spi_get_drvdata(spi);
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(wm8770->supplies); ++i)
+               regulator_unregister_notifier(wm8770->supplies[i].consumer,
+                                             &wm8770->disable_nb[i]);
+
        snd_soc_unregister_codec(&spi->dev);
+
        return 0;
 }
 
index 00121ba3659718ab4c4af6ff5135373762de4765..bff96500c3f38bae8f279993ad432e06f21fbb46 100644 (file)
@@ -883,13 +883,6 @@ static void wm8958_mbc_vss_loaded(const struct firmware *fw, void *context)
                wm8994->mbc_vss = fw;
                mutex_unlock(&codec->mutex);
        }
-
-       /* We can't have more than one request outstanding at once so
-        * we daisy chain.
-        */
-       request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
-                               "wm8958_enh_eq.wfw", codec->dev, GFP_KERNEL,
-                               codec, wm8958_enh_eq_loaded);
 }
 
 static void wm8958_mbc_loaded(const struct firmware *fw, void *context)
@@ -897,19 +890,11 @@ static void wm8958_mbc_loaded(const struct firmware *fw, void *context)
        struct snd_soc_codec *codec = context;
        struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
 
-       if (wm8958_dsp2_fw(codec, "MBC", fw, true) != 0)
-               return;
-
-       mutex_lock(&codec->mutex);
-       wm8994->mbc = fw;
-       mutex_unlock(&codec->mutex);
-
-       /* We can't have more than one request outstanding at once so
-        * we daisy chain.
-        */
-       request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
-                               "wm8958_mbc_vss.wfw", codec->dev, GFP_KERNEL,
-                               codec, wm8958_mbc_vss_loaded);
+       if (fw && (wm8958_dsp2_fw(codec, "MBC", fw, true) == 0)) {
+               mutex_lock(&codec->mutex);
+               wm8994->mbc = fw;
+               mutex_unlock(&codec->mutex);
+       }
 }
 
 void wm8958_dsp2_init(struct snd_soc_codec *codec)
@@ -932,6 +917,12 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
        request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
                                "wm8958_mbc.wfw", codec->dev, GFP_KERNEL,
                                codec, wm8958_mbc_loaded);
+       request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+                               "wm8958_mbc_vss.wfw", codec->dev, GFP_KERNEL,
+                               codec, wm8958_mbc_vss_loaded);
+       request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+                               "wm8958_enh_eq.wfw", codec->dev, GFP_KERNEL,
+                               codec, wm8958_enh_eq_loaded);
 
        if (!pdata)
                return;
index 5ce6477584438b3a8555bada53f8e17c1dd7cc5e..70dd27e9451408c7af2dec5da5e938cdfb4ff000 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/delay.h>
 #include <linux/pm.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/slab.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -34,7 +35,6 @@ static struct workqueue_struct *wm8971_workq = NULL;
 
 /* codec private data */
 struct wm8971_priv {
-       enum snd_soc_control_type control_type;
        unsigned int sysclk;
 };
 
@@ -43,18 +43,50 @@ struct wm8971_priv {
  * We can't read the WM8971 register space when we
  * are using 2 wire for device control, so we cache them instead.
  */
-static const u16 wm8971_reg[] = {
-       0x0097, 0x0097, 0x0079, 0x0079,  /*  0 */
-       0x0000, 0x0008, 0x0000, 0x000a,  /*  4 */
-       0x0000, 0x0000, 0x00ff, 0x00ff,  /*  8 */
-       0x000f, 0x000f, 0x0000, 0x0000,  /* 12 */
-       0x0000, 0x007b, 0x0000, 0x0032,  /* 16 */
-       0x0000, 0x00c3, 0x00c3, 0x00c0,  /* 20 */
-       0x0000, 0x0000, 0x0000, 0x0000,  /* 24 */
-       0x0000, 0x0000, 0x0000, 0x0000,  /* 28 */
-       0x0000, 0x0000, 0x0050, 0x0050,  /* 32 */
-       0x0050, 0x0050, 0x0050, 0x0050,  /* 36 */
-       0x0079, 0x0079, 0x0079,          /* 40 */
+static const struct reg_default wm8971_reg_defaults[] = {
+       {  0, 0x0097 },
+       {  1, 0x0097 },
+       {  2, 0x0079 },
+       {  3, 0x0079 },
+       {  4, 0x0000 },
+       {  5, 0x0008 },
+       {  6, 0x0000 },
+       {  7, 0x000a },
+       {  8, 0x0000 },
+       {  9, 0x0000 },
+       { 10, 0x00ff },
+       { 11, 0x00ff },
+       { 12, 0x000f },
+       { 13, 0x000f },
+       { 14, 0x0000 },
+       { 15, 0x0000 },
+       { 16, 0x0000 },
+       { 17, 0x007b },
+       { 18, 0x0000 },
+       { 19, 0x0032 },
+       { 20, 0x0000 },
+       { 21, 0x00c3 },
+       { 22, 0x00c3 },
+       { 23, 0x00c0 },
+       { 24, 0x0000 },
+       { 25, 0x0000 },
+       { 26, 0x0000 },
+       { 27, 0x0000 },
+       { 28, 0x0000 },
+       { 29, 0x0000 },
+       { 30, 0x0000 },
+       { 31, 0x0000 },
+       { 32, 0x0000 },
+       { 33, 0x0000 },
+       { 34, 0x0050 },
+       { 35, 0x0050 },
+       { 36, 0x0050 },
+       { 37, 0x0050 },
+       { 38, 0x0050 },
+       { 39, 0x0050 },
+       { 40, 0x0079 },
+       { 41, 0x0079 },
+       { 42, 0x0079 },
 };
 
 #define wm8971_reset(c)        snd_soc_write(c, WM8971_RESET, 0)
@@ -613,11 +645,10 @@ static int wm8971_resume(struct snd_soc_codec *codec)
 
 static int wm8971_probe(struct snd_soc_codec *codec)
 {
-       struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec);
        int ret = 0;
        u16 reg;
 
-       ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8971->control_type);
+       ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
        if (ret < 0) {
                printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret);
                return ret;
@@ -667,9 +698,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8971 = {
        .suspend =      wm8971_suspend,
        .resume =       wm8971_resume,
        .set_bias_level = wm8971_set_bias_level,
-       .reg_cache_size = ARRAY_SIZE(wm8971_reg),
-       .reg_word_size = sizeof(u16),
-       .reg_cache_default = wm8971_reg,
 
        .controls = wm8971_snd_controls,
        .num_controls = ARRAY_SIZE(wm8971_snd_controls),
@@ -679,10 +707,21 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8971 = {
        .num_dapm_routes = ARRAY_SIZE(wm8971_dapm_routes),
 };
 
+static const struct regmap_config wm8971_regmap = {
+       .reg_bits = 7,
+       .val_bits = 9,
+       .max_register = WM8971_MOUTV,
+
+       .reg_defaults = wm8971_reg_defaults,
+       .num_reg_defaults = ARRAY_SIZE(wm8971_reg_defaults),
+       .cache_type = REGCACHE_RBTREE,
+};
+
 static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
                                      const struct i2c_device_id *id)
 {
        struct wm8971_priv *wm8971;
+       struct regmap *regmap;
        int ret;
 
        wm8971 = devm_kzalloc(&i2c->dev, sizeof(struct wm8971_priv),
@@ -690,7 +729,10 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
        if (wm8971 == NULL)
                return -ENOMEM;
 
-       wm8971->control_type = SND_SOC_I2C;
+       regmap = devm_regmap_init_i2c(i2c, &wm8971_regmap);
+       if (IS_ERR(regmap))
+               return PTR_ERR(regmap);
+
        i2c_set_clientdata(i2c, wm8971);
 
        ret = snd_soc_register_codec(&i2c->dev,
index 5421fd9fbcb5d37954e77f88962c31e9d953e2dc..4c0a8e496131c1cc2bf9933605dee7664928520d 100644 (file)
@@ -782,7 +782,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream,
                wm8978->mclk_idx = -1;
                f_sel = wm8978->f_mclk;
        } else {
-               if (!wm8978->f_pllout) {
+               if (!wm8978->f_opclk) {
                        /* We only enter here, if OPCLK is not used */
                        int ret = wm8978_configure_pll(codec);
                        if (ret < 0)
index 2b2dadc54dac5cfe729ddc2fd402e748195a6882..11982bf93a1db64ca877b1bdec2b87d68e5ecf31 100644 (file)
@@ -862,7 +862,7 @@ static void vmid_reference(struct snd_soc_codec *codec)
                                            WM8994_BIAS_SRC |
                                            WM8994_STARTUP_BIAS_ENA |
                                            WM8994_VMID_BUF_ENA |
-                                           (0x3 << WM8994_VMID_RAMP_SHIFT));
+                                           (0x2 << WM8994_VMID_RAMP_SHIFT));
 
                        /* Main bias enable, VMID=2x40k */
                        snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
@@ -870,7 +870,7 @@ static void vmid_reference(struct snd_soc_codec *codec)
                                            WM8994_VMID_SEL_MASK,
                                            WM8994_BIAS_ENA | 0x2);
 
-                       msleep(50);
+                       msleep(300);
 
                        snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
                                            WM8994_VMID_RAMP_MASK |
@@ -939,16 +939,10 @@ static void vmid_dereference(struct snd_soc_codec *codec)
                                    WM8994_BIAS_SRC |
                                    WM8994_VMID_DISCH);
 
-               switch (wm8994->vmid_mode) {
-               case WM8994_VMID_FORCE:
-                       msleep(350);
-                       break;
-               default:
-                       break;
-               }
+               snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+                                   WM8994_VMID_SEL_MASK, 0);
 
-               snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
-                                   WM8994_VROI, WM8994_VROI);
+               msleep(400);
 
                /* Active discharge */
                snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
@@ -957,17 +951,12 @@ static void vmid_dereference(struct snd_soc_codec *codec)
                                    WM8994_LINEOUT1_DISCH |
                                    WM8994_LINEOUT2_DISCH);
 
-               msleep(150);
-
                snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3,
                                    WM8994_LINEOUT1N_ENA |
                                    WM8994_LINEOUT1P_ENA |
                                    WM8994_LINEOUT2N_ENA |
                                    WM8994_LINEOUT2P_ENA, 0);
 
-               snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
-                                   WM8994_VROI, 0);
-
                /* Switch off startup biases */
                snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
                                    WM8994_BIAS_SRC |
@@ -976,10 +965,7 @@ static void vmid_dereference(struct snd_soc_codec *codec)
                                    WM8994_VMID_RAMP_MASK, 0);
 
                snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
-                                   WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0);
-
-               snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
-                                   WM8994_VMID_RAMP_MASK, 0);
+                                   WM8994_VMID_SEL_MASK, 0);
        }
 
        pm_runtime_put(codec->dev);
@@ -1045,6 +1031,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w,
                      struct snd_kcontrol *kcontrol, int event)
 {
        struct snd_soc_codec *codec = w->codec;
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994 *control = codec->control_data;
        int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA;
        int i;
@@ -1063,6 +1050,10 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w,
 
        switch (event) {
        case SND_SOC_DAPM_PRE_PMU:
+               /* Don't enable timeslot 2 if not in use */
+               if (wm8994->channels[0] <= 2)
+                       mask &= ~(WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA);
+
                val = snd_soc_read(codec, WM8994_AIF1_CONTROL_1);
                if ((val & WM8994_AIF1ADCL_SRC) &&
                    (val & WM8994_AIF1ADCR_SRC))
@@ -2687,7 +2678,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       bclk_rate = params_rate(params) * 4;
+       bclk_rate = params_rate(params);
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
                bclk_rate *= 16;
@@ -2708,6 +2699,17 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
+       wm8994->channels[id] = params_channels(params);
+       switch (params_channels(params)) {
+       case 1:
+       case 2:
+               bclk_rate *= 2;
+               break;
+       default:
+               bclk_rate *= 4;
+               break;
+       }
+
        /* Try to find an appropriate sample rate; look for an exact match. */
        for (i = 0; i < ARRAY_SIZE(srs); i++)
                if (srs[i].rate == params_rate(params))
@@ -3470,11 +3472,46 @@ static void wm8958_default_micdet(u16 status, void *data)
        }
 }
 
+/* Deferred mic detection to allow for extra settling time */
+static void wm1811_mic_work(struct work_struct *work)
+{
+       struct wm8994_priv *wm8994 = container_of(work, struct wm8994_priv,
+                                                 mic_work.work);
+       struct snd_soc_codec *codec = wm8994->hubs.codec;
+
+       pm_runtime_get_sync(codec->dev);
+
+       /* If required for an external cap force MICBIAS on */
+       if (wm8994->pdata->jd_ext_cap) {
+               snd_soc_dapm_force_enable_pin(&codec->dapm,
+                                             "MICBIAS2");
+               snd_soc_dapm_sync(&codec->dapm);
+       }
+
+       mutex_lock(&wm8994->accdet_lock);
+
+       dev_dbg(codec->dev, "Starting mic detection\n");
+
+       /*
+        * Start off measument of microphone impedence to find out
+        * what's actually there.
+        */
+       wm8994->mic_detecting = true;
+       wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC);
+
+       snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+                           WM8958_MICD_ENA, WM8958_MICD_ENA);
+
+       mutex_unlock(&wm8994->accdet_lock);
+
+       pm_runtime_put(codec->dev);
+}
+
 static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
 {
        struct wm8994_priv *wm8994 = data;
        struct snd_soc_codec *codec = wm8994->hubs.codec;
-       int reg;
+       int reg, delay;
        bool present;
 
        pm_runtime_get_sync(codec->dev);
@@ -3505,18 +3542,14 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
                snd_soc_update_bits(codec, WM1811_JACKDET_CTRL,
                                    WM1811_JACKDET_DB, 0);
 
-               /*
-                * Start off measument of microphone impedence to find
-                * out what's actually there.
-                */
-               wm8994->mic_detecting = true;
-               wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC);
-
-               snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
-                                   WM8958_MICD_ENA, WM8958_MICD_ENA);
+               delay = wm8994->pdata->micdet_delay;
+               schedule_delayed_work(&wm8994->mic_work,
+                                     msecs_to_jiffies(delay));
        } else {
                dev_dbg(codec->dev, "Jack not detected\n");
 
+               cancel_delayed_work_sync(&wm8994->mic_work);
+
                snd_soc_update_bits(codec, WM8958_MICBIAS2,
                                    WM8958_MICB2_DISCH, WM8958_MICB2_DISCH);
 
@@ -3533,14 +3566,9 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
 
        mutex_unlock(&wm8994->accdet_lock);
 
-       /* If required for an external cap force MICBIAS on */
-       if (wm8994->pdata->jd_ext_cap) {
-               if (present)
-                       snd_soc_dapm_force_enable_pin(&codec->dapm,
-                                                     "MICBIAS2");
-               else
-                       snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
-       }
+       /* Turn off MICBIAS if it was on for an external cap */
+       if (wm8994->pdata->jd_ext_cap && !present)
+               snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
 
        if (present)
                snd_soc_jack_report(wm8994->micdet[0].jack,
@@ -3763,10 +3791,20 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
        snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
 
        mutex_init(&wm8994->accdet_lock);
-       INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work);
        INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap,
                          wm1811_jackdet_bootstrap);
 
+       switch (control->type) {
+       case WM8994:
+               INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work);
+               break;
+       case WM1811:
+               INIT_DELAYED_WORK(&wm8994->mic_work, wm1811_mic_work);
+               break;
+       default:
+               break;
+       }
+
        for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
                init_completion(&wm8994->fll_locked[i]);
 
index f142ec198db3dabfcfc5d1e20a51cdfd5e42874b..ccbce5791e95829b5d98ce472ac50d922e6e4703 100644 (file)
@@ -77,6 +77,7 @@ struct wm8994_priv {
        int sysclk_rate[2];
        int mclk[2];
        int aifclk[2];
+       int channels[2];
        struct wm8994_fll_config fll[2], fll_suspend[2];
        struct completion fll_locked[2];
        bool fll_locked_irq;
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
new file mode 100644 (file)
index 0000000..c72d3fa
--- /dev/null
@@ -0,0 +1,571 @@
+/*
+ * wm_adsp.c  --  Wolfson ADSP support
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include <linux/mfd/arizona/registers.h>
+
+#include "wm_adsp.h"
+
+#define adsp_crit(_dsp, fmt, ...) \
+       dev_crit(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_err(_dsp, fmt, ...) \
+       dev_err(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_warn(_dsp, fmt, ...) \
+       dev_warn(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_info(_dsp, fmt, ...) \
+       dev_info(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+#define adsp_dbg(_dsp, fmt, ...) \
+       dev_dbg(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__)
+
+#define ADSP1_CONTROL_1                   0x00
+#define ADSP1_CONTROL_2                   0x02
+#define ADSP1_CONTROL_3                   0x03
+#define ADSP1_CONTROL_4                   0x04
+#define ADSP1_CONTROL_5                   0x06
+#define ADSP1_CONTROL_6                   0x07
+#define ADSP1_CONTROL_7                   0x08
+#define ADSP1_CONTROL_8                   0x09
+#define ADSP1_CONTROL_9                   0x0A
+#define ADSP1_CONTROL_10                  0x0B
+#define ADSP1_CONTROL_11                  0x0C
+#define ADSP1_CONTROL_12                  0x0D
+#define ADSP1_CONTROL_13                  0x0F
+#define ADSP1_CONTROL_14                  0x10
+#define ADSP1_CONTROL_15                  0x11
+#define ADSP1_CONTROL_16                  0x12
+#define ADSP1_CONTROL_17                  0x13
+#define ADSP1_CONTROL_18                  0x14
+#define ADSP1_CONTROL_19                  0x16
+#define ADSP1_CONTROL_20                  0x17
+#define ADSP1_CONTROL_21                  0x18
+#define ADSP1_CONTROL_22                  0x1A
+#define ADSP1_CONTROL_23                  0x1B
+#define ADSP1_CONTROL_24                  0x1C
+#define ADSP1_CONTROL_25                  0x1E
+#define ADSP1_CONTROL_26                  0x20
+#define ADSP1_CONTROL_27                  0x21
+#define ADSP1_CONTROL_28                  0x22
+#define ADSP1_CONTROL_29                  0x23
+#define ADSP1_CONTROL_30                  0x24
+#define ADSP1_CONTROL_31                  0x26
+
+/*
+ * ADSP1 Control 19
+ */
+#define ADSP1_WDMA_BUFFER_LENGTH_MASK     0x00FF  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define ADSP1_WDMA_BUFFER_LENGTH_SHIFT         0  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define ADSP1_WDMA_BUFFER_LENGTH_WIDTH         8  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+
+
+/*
+ * ADSP1 Control 30
+ */
+#define ADSP1_DBG_CLK_ENA                 0x0008  /* DSP1_DBG_CLK_ENA */
+#define ADSP1_DBG_CLK_ENA_MASK            0x0008  /* DSP1_DBG_CLK_ENA */
+#define ADSP1_DBG_CLK_ENA_SHIFT                3  /* DSP1_DBG_CLK_ENA */
+#define ADSP1_DBG_CLK_ENA_WIDTH                1  /* DSP1_DBG_CLK_ENA */
+#define ADSP1_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
+#define ADSP1_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
+#define ADSP1_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
+#define ADSP1_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
+#define ADSP1_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
+#define ADSP1_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
+#define ADSP1_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
+#define ADSP1_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
+#define ADSP1_START                       0x0001  /* DSP1_START */
+#define ADSP1_START_MASK                  0x0001  /* DSP1_START */
+#define ADSP1_START_SHIFT                      0  /* DSP1_START */
+#define ADSP1_START_WIDTH                      1  /* DSP1_START */
+
+#define ADSP2_CONTROL 0
+#define ADSP2_STATUS1 4
+
+/*
+ * ADSP2 Control
+ */
+
+#define ADSP2_MEM_ENA                     0x0010  /* DSP1_MEM_ENA */
+#define ADSP2_MEM_ENA_MASK                0x0010  /* DSP1_MEM_ENA */
+#define ADSP2_MEM_ENA_SHIFT                    4  /* DSP1_MEM_ENA */
+#define ADSP2_MEM_ENA_WIDTH                    1  /* DSP1_MEM_ENA */
+#define ADSP2_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
+#define ADSP2_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
+#define ADSP2_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
+#define ADSP2_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
+#define ADSP2_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
+#define ADSP2_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
+#define ADSP2_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
+#define ADSP2_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
+#define ADSP2_START                       0x0001  /* DSP1_START */
+#define ADSP2_START_MASK                  0x0001  /* DSP1_START */
+#define ADSP2_START_SHIFT                      0  /* DSP1_START */
+#define ADSP2_START_WIDTH                      1  /* DSP1_START */
+
+/*
+ * ADSP2 Status 1
+ */
+#define ADSP2_RAM_RDY                     0x0001
+#define ADSP2_RAM_RDY_MASK                0x0001
+#define ADSP2_RAM_RDY_SHIFT                    0
+#define ADSP2_RAM_RDY_WIDTH                    1
+
+
+static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp,
+                                                       int type)
+{
+       int i;
+
+       for (i = 0; i < dsp->num_mems; i++)
+               if (dsp->mem[i].type == type)
+                       return &dsp->mem[i];
+
+       return NULL;
+}
+
+static int wm_adsp_load(struct wm_adsp *dsp)
+{
+       const struct firmware *firmware;
+       struct regmap *regmap = dsp->regmap;
+       unsigned int pos = 0;
+       const struct wmfw_header *header;
+       const struct wmfw_adsp1_sizes *adsp1_sizes;
+       const struct wmfw_adsp2_sizes *adsp2_sizes;
+       const struct wmfw_footer *footer;
+       const struct wmfw_region *region;
+       const struct wm_adsp_region *mem;
+       const char *region_name;
+       char *file, *text;
+       unsigned int reg;
+       int regions = 0;
+       int ret, offset, type, sizes;
+
+       file = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       if (file == NULL)
+               return -ENOMEM;
+
+       snprintf(file, PAGE_SIZE, "%s-dsp%d.wmfw", dsp->part, dsp->num);
+       file[PAGE_SIZE - 1] = '\0';
+
+       ret = request_firmware(&firmware, file, dsp->dev);
+       if (ret != 0) {
+               adsp_err(dsp, "Failed to request '%s'\n", file);
+               goto out;
+       }
+       ret = -EINVAL;
+
+       pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
+       if (pos >= firmware->size) {
+               adsp_err(dsp, "%s: file too short, %zu bytes\n",
+                        file, firmware->size);
+               goto out_fw;
+       }
+
+       header = (void*)&firmware->data[0];
+
+       if (memcmp(&header->magic[0], "WMFW", 4) != 0) {
+               adsp_err(dsp, "%s: invalid magic\n", file);
+               goto out_fw;
+       }
+
+       if (header->ver != 0) {
+               adsp_err(dsp, "%s: unknown file format %d\n",
+                        file, header->ver);
+               goto out_fw;
+       }
+
+       if (header->core != dsp->type) {
+               adsp_err(dsp, "%s: invalid core %d != %d\n",
+                        file, header->core, dsp->type);
+               goto out_fw;
+       }
+
+       switch (dsp->type) {
+       case WMFW_ADSP1:
+               pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
+               adsp1_sizes = (void *)&(header[1]);
+               footer = (void *)&(adsp1_sizes[1]);
+               sizes = sizeof(*adsp1_sizes);
+
+               adsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n",
+                        file, le32_to_cpu(adsp1_sizes->dm),
+                        le32_to_cpu(adsp1_sizes->pm),
+                        le32_to_cpu(adsp1_sizes->zm));
+               break;
+
+       case WMFW_ADSP2:
+               pos = sizeof(*header) + sizeof(*adsp2_sizes) + sizeof(*footer);
+               adsp2_sizes = (void *)&(header[1]);
+               footer = (void *)&(adsp2_sizes[1]);
+               sizes = sizeof(*adsp2_sizes);
+
+               adsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n",
+                        file, le32_to_cpu(adsp2_sizes->xm),
+                        le32_to_cpu(adsp2_sizes->ym),
+                        le32_to_cpu(adsp2_sizes->pm),
+                        le32_to_cpu(adsp2_sizes->zm));
+               break;
+
+       default:
+               BUG_ON(NULL == "Unknown DSP type");
+               goto out_fw;
+       }
+
+       if (le32_to_cpu(header->len) != sizeof(*header) +
+           sizes + sizeof(*footer)) {
+               adsp_err(dsp, "%s: unexpected header length %d\n",
+                        file, le32_to_cpu(header->len));
+               goto out_fw;
+       }
+
+       adsp_dbg(dsp, "%s: timestamp %llu\n", file,
+                le64_to_cpu(footer->timestamp));
+
+       while (pos < firmware->size &&
+              pos - firmware->size > sizeof(*region)) {
+               region = (void *)&(firmware->data[pos]);
+               region_name = "Unknown";
+               reg = 0;
+               text = NULL;
+               offset = le32_to_cpu(region->offset) & 0xffffff;
+               type = be32_to_cpu(region->type) & 0xff;
+               mem = wm_adsp_find_region(dsp, type);
+               
+               switch (type) {
+               case WMFW_NAME_TEXT:
+                       region_name = "Firmware name";
+                       text = kzalloc(le32_to_cpu(region->len) + 1,
+                                      GFP_KERNEL);
+                       break;
+               case WMFW_INFO_TEXT:
+                       region_name = "Information";
+                       text = kzalloc(le32_to_cpu(region->len) + 1,
+                                      GFP_KERNEL);
+                       break;
+               case WMFW_ABSOLUTE:
+                       region_name = "Absolute";
+                       reg = offset;
+                       break;
+               case WMFW_ADSP1_PM:
+                       BUG_ON(!mem);
+                       region_name = "PM";
+                       reg = mem->base + (offset * 3);
+                       break;
+               case WMFW_ADSP1_DM:
+                       BUG_ON(!mem);
+                       region_name = "DM";
+                       reg = mem->base + (offset * 2);
+                       break;
+               case WMFW_ADSP2_XM:
+                       BUG_ON(!mem);
+                       region_name = "XM";
+                       reg = mem->base + (offset * 2);
+                       break;
+               case WMFW_ADSP2_YM:
+                       BUG_ON(!mem);
+                       region_name = "YM";
+                       reg = mem->base + (offset * 2);
+                       break;
+               case WMFW_ADSP1_ZM:
+                       BUG_ON(!mem);
+                       region_name = "ZM";
+                       reg = mem->base + (offset * 2);
+                       break;
+               default:
+                       adsp_warn(dsp,
+                                 "%s.%d: Unknown region type %x at %d(%x)\n",
+                                 file, regions, type, pos, pos);
+                       break;
+               }
+
+               adsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file,
+                        regions, le32_to_cpu(region->len), offset,
+                        region_name);
+
+               if (text) {
+                       memcpy(text, region->data, le32_to_cpu(region->len));
+                       adsp_info(dsp, "%s: %s\n", file, text);
+                       kfree(text);
+               }
+
+               if (reg) {
+                       ret = regmap_raw_write(regmap, reg, region->data,
+                                              le32_to_cpu(region->len));
+                       if (ret != 0) {
+                               adsp_err(dsp,
+                                       "%s.%d: Failed to write %d bytes at %d in %s: %d\n",
+                                       file, regions,
+                                       le32_to_cpu(region->len), offset,
+                                       region_name, ret);
+                               goto out_fw;
+                       }
+               }
+
+               pos += le32_to_cpu(region->len) + sizeof(*region);
+               regions++;
+       }
+       
+       if (pos > firmware->size)
+               adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
+                         file, regions, pos - firmware->size);
+
+out_fw:
+       release_firmware(firmware);
+out:
+       kfree(file);
+
+       return ret;
+}
+
+static int wm_adsp_load_coeff(struct wm_adsp *dsp)
+{
+       struct regmap *regmap = dsp->regmap;
+       struct wmfw_coeff_hdr *hdr;
+       struct wmfw_coeff_item *blk;
+       const struct firmware *firmware;
+       const char *region_name;
+       int ret, pos, blocks, type, offset, reg;
+       char *file;
+
+       file = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       if (file == NULL)
+               return -ENOMEM;
+
+       snprintf(file, PAGE_SIZE, "%s-dsp%d.bin", dsp->part, dsp->num);
+       file[PAGE_SIZE - 1] = '\0';
+
+       ret = request_firmware(&firmware, file, dsp->dev);
+       if (ret != 0) {
+               adsp_warn(dsp, "Failed to request '%s'\n", file);
+               ret = 0;
+               goto out;
+       }
+       ret = -EINVAL;
+
+       if (sizeof(*hdr) >= firmware->size) {
+               adsp_err(dsp, "%s: file too short, %zu bytes\n",
+                       file, firmware->size);
+               goto out_fw;
+       }
+
+       hdr = (void*)&firmware->data[0];
+       if (memcmp(hdr->magic, "WMDR", 4) != 0) {
+               adsp_err(dsp, "%s: invalid magic\n", file);
+               return -EINVAL;
+       }
+
+       adsp_dbg(dsp, "%s: v%d.%d.%d\n", file,
+               (le32_to_cpu(hdr->ver) >> 16) & 0xff,
+               (le32_to_cpu(hdr->ver) >>  8) & 0xff,
+               le32_to_cpu(hdr->ver) & 0xff);
+
+       pos = le32_to_cpu(hdr->len);
+
+       blocks = 0;
+       while (pos < firmware->size &&
+              pos - firmware->size > sizeof(*blk)) {
+               blk = (void*)(&firmware->data[pos]);
+
+               type = be32_to_cpu(blk->type) & 0xff;
+               offset = le32_to_cpu(blk->offset) & 0xffffff;
+
+               adsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n",
+                        file, blocks, le32_to_cpu(blk->id),
+                        (le32_to_cpu(blk->ver) >> 16) & 0xff,
+                        (le32_to_cpu(blk->ver) >>  8) & 0xff,
+                        le32_to_cpu(blk->ver) & 0xff);
+               adsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n",
+                        file, blocks, le32_to_cpu(blk->len), offset, type);
+
+               reg = 0;
+               region_name = "Unknown";
+               switch (type) {
+               case WMFW_NAME_TEXT:
+               case WMFW_INFO_TEXT:
+                       break;
+               case WMFW_ABSOLUTE:
+                       region_name = "register";
+                       reg = offset;
+                       break;
+               default:
+                       adsp_err(dsp, "Unknown region type %x\n", type);
+                       break;
+               }
+
+               if (reg) {
+                       ret = regmap_raw_write(regmap, reg, blk->data,
+                                              le32_to_cpu(blk->len));
+                       if (ret != 0) {
+                               adsp_err(dsp,
+                                       "%s.%d: Failed to write to %x in %s\n",
+                                       file, blocks, reg, region_name);
+                       }
+               }
+
+               pos += le32_to_cpu(blk->len) + sizeof(*blk);
+               blocks++;
+       }
+
+       if (pos > firmware->size)
+               adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
+                         file, blocks, pos - firmware->size);
+
+out_fw:
+       release_firmware(firmware);
+out:
+       kfree(file);
+       return 0;
+}
+
+int wm_adsp1_event(struct snd_soc_dapm_widget *w,
+                  struct snd_kcontrol *kcontrol,
+                  int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
+       struct wm_adsp *dsp = &dsps[w->shift];
+       int ret;
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+                                  ADSP1_SYS_ENA, ADSP1_SYS_ENA);
+
+               ret = wm_adsp_load(dsp);
+               if (ret != 0)
+                       goto err;
+
+               ret = wm_adsp_load_coeff(dsp);
+               if (ret != 0)
+                       goto err;
+
+               /* Start the core running */
+               regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+                                  ADSP1_CORE_ENA | ADSP1_START,
+                                  ADSP1_CORE_ENA | ADSP1_START);
+               break;
+
+       case SND_SOC_DAPM_PRE_PMD:
+               /* Halt the core */
+               regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+                                  ADSP1_CORE_ENA | ADSP1_START, 0);
+
+               regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19,
+                                  ADSP1_WDMA_BUFFER_LENGTH_MASK, 0);
+
+               regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+                                  ADSP1_SYS_ENA, 0);
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+
+err:
+       regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
+                          ADSP1_SYS_ENA, 0);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(wm_adsp1_event);
+
+static int wm_adsp2_ena(struct wm_adsp *dsp)
+{
+       unsigned int val;
+       int ret, count;
+
+       ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+                                ADSP2_SYS_ENA, ADSP2_SYS_ENA);
+       if (ret != 0)
+               return ret;
+
+       /* Wait for the RAM to start, should be near instantaneous */
+       count = 0;
+       do {
+               ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1,
+                                 &val);
+               if (ret != 0)
+                       return ret;
+       } while (!(val & ADSP2_RAM_RDY) && ++count < 10);
+
+       if (!(val & ADSP2_RAM_RDY)) {
+               adsp_err(dsp, "Failed to start DSP RAM\n");
+               return -EBUSY;
+       }
+
+       adsp_dbg(dsp, "RAM ready after %d polls\n", count);
+       adsp_info(dsp, "RAM ready after %d polls\n", count);
+
+       return 0;
+}
+
+int wm_adsp2_event(struct snd_soc_dapm_widget *w,
+                  struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
+       struct wm_adsp *dsp = &dsps[w->shift];
+       int ret;
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               ret = wm_adsp2_ena(dsp);
+               if (ret != 0)
+                       return ret;
+
+               ret = wm_adsp_load(dsp);
+               if (ret != 0)
+                       goto err;
+
+               ret = wm_adsp_load_coeff(dsp);
+               if (ret != 0)
+                       goto err;
+
+               ret = regmap_update_bits(dsp->regmap,
+                                        dsp->base + ADSP2_CONTROL,
+                                        ADSP2_SYS_ENA | ADSP2_START, 0);
+               if (ret != 0)
+                       goto err;
+               break;
+
+       case SND_SOC_DAPM_PRE_PMD:
+               regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+                                  ADSP2_SYS_ENA | ADSP2_START, 0);
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+err:
+       regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
+                          ADSP2_SYS_ENA | ADSP2_START, 0);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(wm_adsp2_event);
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
new file mode 100644 (file)
index 0000000..b303b1f
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * wm_adsp.h  --  Wolfson ADSP support
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * 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.
+ */
+
+#ifndef __WM_ADSP_H
+#define __WM_ADSP_H
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+
+#include "wmfw.h"
+
+struct wm_adsp_region {
+       int type;
+       unsigned int base;
+};
+
+struct wm_adsp {
+       const char *part;
+       int num;
+       int type;
+       struct device *dev;
+       struct regmap *regmap;
+
+       int base;
+
+       const struct wm_adsp_region *mem;
+       int num_mems;
+};
+
+#define WM_ADSP1(wname, num) \
+       { .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \
+       .shift = num, .event = wm_adsp1_event, \
+       .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
+
+#define WM_ADSP2(wname, num) \
+{      .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \
+       .shift = num, .event = wm_adsp2_event, \
+       .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD }
+
+int wm_adsp1_event(struct snd_soc_dapm_widget *w,
+                  struct snd_kcontrol *kcontrol, int event);
+int wm_adsp2_event(struct snd_soc_dapm_widget *w,
+                  struct snd_kcontrol *kcontrol, int event);
+
+#endif
diff --git a/sound/soc/codecs/wmfw.h b/sound/soc/codecs/wmfw.h
new file mode 100644 (file)
index 0000000..5632ded
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * wmfw.h - Wolfson firmware format information
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * 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.
+ */
+
+#ifndef __WMFW_H
+#define __WMFW_H
+
+#include <linux/types.h>
+
+struct wmfw_header {
+       char magic[4];
+       __le32 len;
+       __le16 rev;
+       u8 core;
+       u8 ver;
+} __packed;
+
+struct wmfw_footer {
+       __le64 timestamp;
+       __le32 checksum;
+} __packed;
+
+struct wmfw_adsp1_sizes {
+       __le32 dm;
+       __le32 pm;
+       __le32 zm;
+} __packed;
+
+struct wmfw_adsp2_sizes {
+       __le32 xm;
+       __le32 ym;
+       __le32 pm;
+       __le32 zm;
+} __packed;
+
+struct wmfw_region {
+       union {
+               __be32 type;
+               __le32 offset;
+       };
+       __le32 len;
+       u8 data[];
+} __packed;
+
+struct wmfw_id_hdr {
+       __be32 core_id;
+       __be32 core_rev;
+       __be32 id;
+       __be32 ver;
+} __packed;
+
+struct wmfw_adsp1_id_hdr {
+       struct wmfw_id_hdr fw;
+       __be32 zm;
+       __be32 dm;
+       __be32 algs;
+} __packed;
+
+struct wmfw_adsp2_id_hdr {
+       struct wmfw_id_hdr fw;
+       __be32 zm;
+       __be32 xm;
+       __be32 ym;
+       __be32 algs;
+} __packed;
+
+struct wmfw_alg_hdr {
+       __be32 id;
+       __be32 ver;
+} __packed;
+
+struct wmfw_adsp1_alg_hdr {
+       struct wmfw_alg_hdr alg;
+       __be32 zm;
+       __be32 dm;
+} __packed;
+
+struct wmfw_adsp2_alg_hdr {
+       struct wmfw_alg_hdr alg;
+       __be32 zm;
+       __be32 xm;
+       __be32 ym;
+} __packed;
+
+struct wmfw_coeff_hdr {
+       u8 magic[4];
+       __le32 len;
+       __le32 ver;
+       u8 data[];
+} __packed;
+
+struct wmfw_coeff_item {
+       union {
+               __be32 type;
+               __le32 offset;
+       };
+       __le32 id;
+       __le32 ver;
+       __le32 sr;
+       __le32 len;
+       u8 data[];
+} __packed;
+
+#define WMFW_ADSP1 1
+#define WMFW_ADSP2 2
+
+#define WMFW_ABSOLUTE  0xf0
+#define WMFW_NAME_TEXT 0xfe
+#define WMFW_INFO_TEXT 0xff
+
+#define WMFW_ADSP1_PM 2
+#define WMFW_ADSP1_DM 3
+#define WMFW_ADSP1_ZM 4
+
+#define WMFW_ADSP2_PM 2
+#define WMFW_ADSP2_ZM 4
+#define WMFW_ADSP2_XM 5
+#define WMFW_ADSP2_YM 6
+
+#endif
index 6fac5af13298ffa2c64ebf5bad1b5fde6a0ac6f6..d55e6477bff0c9a855379d26db50538ff7b5e178 100644 (file)
@@ -71,6 +71,11 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
        if (ret < 0)
                return ret;
 
+       /* set the CPU system clock */
+       ret = snd_soc_dai_set_sysclk(cpu_dai, 0, sysclk, SND_SOC_CLOCK_OUT);
+       if (ret < 0)
+               return ret;
+
        return 0;
 }
 
index 714e51e5be5bd2c7038f1965a74545a01c5a268c..571559501b0b6f79854701e74753347b2edd21ca 100644 (file)
 #define ACLKXE         BIT(5)
 #define TX_ASYNC       BIT(6)
 #define ACLKXPOL       BIT(7)
+#define ACLKXDIV_MASK  0x1f
 
 /*
  * DAVINCI_MCASP_ACLKRCTL_REG Receive Clock Control Register Bits
 #define ACLKRE         BIT(5)
 #define RX_ASYNC       BIT(6)
 #define ACLKRPOL       BIT(7)
+#define ACLKRDIV_MASK  0x1f
 
 /*
  * DAVINCI_MCASP_AHCLKXCTL_REG - High Frequency Transmit Clock Control
 #define AHCLKXDIV(val) (val)
 #define AHCLKXPOL      BIT(14)
 #define AHCLKXE                BIT(15)
+#define AHCLKXDIV_MASK 0xfff
 
 /*
  * DAVINCI_MCASP_AHCLKRCTL_REG - High Frequency Receive Clock Control
 #define AHCLKRDIV(val) (val)
 #define AHCLKRPOL      BIT(14)
 #define AHCLKRE                BIT(15)
+#define AHCLKRDIV_MASK 0xfff
 
 /*
  * DAVINCI_MCASP_XRSRCTL_BASE_REG -  Serializer Control Register Bits
@@ -473,6 +477,23 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
        void __iomem *base = dev->base;
 
+       switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_DSP_B:
+       case SND_SOC_DAIFMT_AC97:
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
+               break;
+       default:
+               /* configure a full-word SYNC pulse (LRCLK) */
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
+
+               /* make 1st data bit occur one ACLK cycle after the frame sync */
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, FSXDLY(1));
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, FSRDLY(1));
+               break;
+       }
+
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
        case SND_SOC_DAIFMT_CBS_CFS:
                /* codec is clock and frame slave */
@@ -482,8 +503,7 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                mcasp_set_bits(base + DAVINCI_MCASP_ACLKRCTL_REG, ACLKRE);
                mcasp_set_bits(base + DAVINCI_MCASP_RXFMCTL_REG, AFSRE);
 
-               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG,
-                               ACLKX | AHCLKX | AFSX);
+               mcasp_set_bits(base + DAVINCI_MCASP_PDIR_REG, ACLKX | AFSX);
                break;
        case SND_SOC_DAIFMT_CBM_CFS:
                /* codec is clock master and frame slave */
@@ -554,6 +574,50 @@ static int davinci_mcasp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        return 0;
 }
 
+static int davinci_mcasp_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
+{
+       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+       switch (div_id) {
+       case 0:         /* MCLK divider */
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
+                              AHCLKXDIV(div - 1), AHCLKXDIV_MASK);
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
+                              AHCLKRDIV(div - 1), AHCLKRDIV_MASK);
+               break;
+
+       case 1:         /* BCLK divider */
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKXCTL_REG,
+                              ACLKXDIV(div - 1), ACLKXDIV_MASK);
+               mcasp_mod_bits(dev->base + DAVINCI_MCASP_ACLKRCTL_REG,
+                              ACLKRDIV(div - 1), ACLKRDIV_MASK);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int davinci_mcasp_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+                                   unsigned int freq, int dir)
+{
+       struct davinci_audio_dev *dev = snd_soc_dai_get_drvdata(dai);
+
+       if (dir == SND_SOC_CLOCK_OUT) {
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
+               mcasp_set_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AHCLKX);
+       } else {
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG, AHCLKXE);
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG, AHCLKRE);
+               mcasp_clr_bits(dev->base + DAVINCI_MCASP_PDIR_REG, AHCLKX);
+       }
+
+       return 0;
+}
+
 static int davinci_config_channel_size(struct davinci_audio_dev *dev,
                                       int channel_size)
 {
@@ -709,8 +773,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
        if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
                /* bit stream is MSB first  with no delay */
                /* DSP_B mode */
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKXCTL_REG,
-                               AHCLKXE);
                mcasp_set_reg(dev->base + DAVINCI_MCASP_TXTDM_REG, mask);
                mcasp_set_bits(dev->base + DAVINCI_MCASP_TXFMT_REG, TXORD);
 
@@ -720,14 +782,10 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
                else
                        printk(KERN_ERR "playback tdm slot %d not supported\n",
                                dev->tdm_slots);
-
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_TXFMCTL_REG, FSXDUR);
        } else {
                /* bit stream is MSB first with no delay */
                /* DSP_B mode */
                mcasp_set_bits(dev->base + DAVINCI_MCASP_RXFMT_REG, RXORD);
-               mcasp_set_bits(dev->base + DAVINCI_MCASP_AHCLKRCTL_REG,
-                               AHCLKRE);
                mcasp_set_reg(dev->base + DAVINCI_MCASP_RXTDM_REG, mask);
 
                if ((dev->tdm_slots >= 2) && (dev->tdm_slots <= 32))
@@ -736,8 +794,6 @@ static void davinci_hw_param(struct davinci_audio_dev *dev, int stream)
                else
                        printk(KERN_ERR "capture tdm slot %d not supported\n",
                                dev->tdm_slots);
-
-               mcasp_clr_bits(dev->base + DAVINCI_MCASP_RXFMCTL_REG, FSRDUR);
        }
 }
 
@@ -809,6 +865,14 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
                word_length = DAVINCI_AUDIO_WORD_16;
                break;
 
+       case SNDRV_PCM_FORMAT_U24_3LE:
+       case SNDRV_PCM_FORMAT_S24_3LE:
+               dma_params->data_type = 3;
+               word_length = DAVINCI_AUDIO_WORD_24;
+               break;
+
+       case SNDRV_PCM_FORMAT_U24_LE:
+       case SNDRV_PCM_FORMAT_S24_LE:
        case SNDRV_PCM_FORMAT_U32_LE:
        case SNDRV_PCM_FORMAT_S32_LE:
                dma_params->data_type = 4;
@@ -880,13 +944,18 @@ static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
        .trigger        = davinci_mcasp_trigger,
        .hw_params      = davinci_mcasp_hw_params,
        .set_fmt        = davinci_mcasp_set_dai_fmt,
-
+       .set_clkdiv     = davinci_mcasp_set_clkdiv,
+       .set_sysclk     = davinci_mcasp_set_sysclk,
 };
 
 #define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \
                                SNDRV_PCM_FMTBIT_U8 | \
                                SNDRV_PCM_FMTBIT_S16_LE | \
                                SNDRV_PCM_FMTBIT_U16_LE | \
+                               SNDRV_PCM_FMTBIT_S24_LE | \
+                               SNDRV_PCM_FMTBIT_U24_LE | \
+                               SNDRV_PCM_FMTBIT_S24_3LE | \
+                               SNDRV_PCM_FMTBIT_U24_3LE | \
                                SNDRV_PCM_FMTBIT_S32_LE | \
                                SNDRV_PCM_FMTBIT_U32_LE)
 
@@ -1098,6 +1167,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK];
        dma_data->asp_chan_q = pdata->asp_chan_q;
        dma_data->ram_chan_q = pdata->ram_chan_q;
+       dma_data->sram_pool = pdata->sram_pool;
        dma_data->sram_size = pdata->sram_size_playback;
        dma_data->dma_addr = (dma_addr_t) (pdata->tx_dma_offset +
                                                        mem->start);
@@ -1115,6 +1185,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        dma_data = &dev->dma_params[SNDRV_PCM_STREAM_CAPTURE];
        dma_data->asp_chan_q = pdata->asp_chan_q;
        dma_data->ram_chan_q = pdata->ram_chan_q;
+       dma_data->sram_pool = pdata->sram_pool;
        dma_data->sram_size = pdata->sram_size_capture;
        dma_data->dma_addr = (dma_addr_t)(pdata->rx_dma_offset +
                                                        mem->start);
index 0de9ed6ce038a8472aeb762d403fbf26d579bc24..156f15f55744582dadff2a350f8b581466128134 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "davinci-pcm.h"
 
-#define DAVINCI_MCASP_RATES    SNDRV_PCM_RATE_8000_96000
+#define DAVINCI_MCASP_RATES    SNDRV_PCM_RATE_8000_192000
 #define DAVINCI_MCASP_I2S_DAI  0
 #define DAVINCI_MCASP_DIT_DAI  1
 
index 93ea3bf567e1fd1835ff643ff4e73d67fecdce12..afab81f844ae82c32418d6d1f83301c2d29d1f4e 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/kernel.h>
+#include <linux/genalloc.h>
 
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -23,7 +24,6 @@
 #include <sound/soc.h>
 
 #include <asm/dma.h>
-#include <mach/sram.h>
 
 #include "davinci-pcm.h"
 
@@ -67,13 +67,9 @@ static struct snd_pcm_hardware pcm_hardware_playback = {
                 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME|
                 SNDRV_PCM_INFO_BATCH),
        .formats = DAVINCI_PCM_FMTBITS,
-       .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
-                 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
-                 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
-                 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
-                 SNDRV_PCM_RATE_KNOT),
+       .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT,
        .rate_min = 8000,
-       .rate_max = 96000,
+       .rate_max = 192000,
        .channels_min = 2,
        .channels_max = 384,
        .buffer_bytes_max = 128 * 1024,
@@ -90,13 +86,9 @@ static struct snd_pcm_hardware pcm_hardware_capture = {
                 SNDRV_PCM_INFO_PAUSE |
                 SNDRV_PCM_INFO_BATCH),
        .formats = DAVINCI_PCM_FMTBITS,
-       .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
-                 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
-                 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
-                 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
-                 SNDRV_PCM_RATE_KNOT),
+       .rates = SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT,
        .rate_min = 8000,
-       .rate_max = 96000,
+       .rate_max = 192000,
        .channels_min = 2,
        .channels_max = 384,
        .buffer_bytes_max = 128 * 1024,
@@ -259,7 +251,9 @@ static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
        }
 }
 
-static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
+#ifdef CONFIG_GENERIC_ALLOCATOR
+static int allocate_sram(struct snd_pcm_substream *substream,
+               struct gen_pool *sram_pool, unsigned size,
                struct snd_pcm_hardware *ppcm)
 {
        struct snd_dma_buffer *buf = &substream->dma_buffer;
@@ -271,9 +265,10 @@ static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
                return 0;
 
        ppcm->period_bytes_max = size;
-       iram_virt = sram_alloc(size, &iram_phys);
+       iram_virt = (void *)gen_pool_alloc(sram_pool, size);
        if (!iram_virt)
                goto exit1;
+       iram_phys = gen_pool_virt_to_phys(sram_pool, (unsigned)iram_virt);
        iram_dma = kzalloc(sizeof(*iram_dma), GFP_KERNEL);
        if (!iram_dma)
                goto exit2;
@@ -285,11 +280,33 @@ static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
        return 0;
 exit2:
        if (iram_virt)
-               sram_free(iram_virt, size);
+               gen_pool_free(sram_pool, (unsigned)iram_virt, size);
 exit1:
        return -ENOMEM;
 }
 
+static void davinci_free_sram(struct snd_pcm_substream *substream,
+                             struct snd_dma_buffer *iram_dma)
+{
+       struct davinci_runtime_data *prtd = substream->runtime->private_data;
+       struct gen_pool *sram_pool = prtd->params->sram_pool;
+
+       gen_pool_free(sram_pool, (unsigned) iram_dma->area, iram_dma->bytes);
+}
+#else
+static int allocate_sram(struct snd_pcm_substream *substream,
+               struct gen_pool *sram_pool, unsigned size,
+               struct snd_pcm_hardware *ppcm)
+{
+       return 0;
+}
+
+static void davinci_free_sram(struct snd_pcm_substream *substream,
+                             struct snd_dma_buffer *iram_dma)
+{
+}
+#endif
+
 /*
  * Only used with ping/pong.
  * This is called after runtime->dma_addr, period_bytes and data_type are valid
@@ -676,7 +693,7 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)
 
        ppcm = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
                        &pcm_hardware_playback : &pcm_hardware_capture;
-       allocate_sram(substream, params->sram_size, ppcm);
+       allocate_sram(substream, params->sram_pool, params->sram_size, ppcm);
        snd_soc_set_runtime_hwparams(substream, ppcm);
        /* ensure that buffer size is a multiple of period size */
        ret = snd_pcm_hw_constraint_integer(runtime,
@@ -819,7 +836,7 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
                buf->area = NULL;
                iram_dma = buf->private_data;
                if (iram_dma) {
-                       sram_free(iram_dma->area, iram_dma->bytes);
+                       davinci_free_sram(substream, iram_dma);
                        kfree(iram_dma);
                }
        }
index fc4d01cdd8c95c92b11694faece56d77fc648bd9..b6ef7039dd097b4ac99c6e9b14a0c35ed59fd203 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef _DAVINCI_PCM_H
 #define _DAVINCI_PCM_H
 
+#include <linux/genalloc.h>
 #include <linux/platform_data/davinci_asp.h>
 #include <mach/edma.h>
 
@@ -20,6 +21,7 @@ struct davinci_pcm_dma_params {
        unsigned short acnt;
        dma_addr_t dma_addr;            /* device physical address for DMA */
        unsigned sram_size;
+       struct gen_pool *sram_pool;     /* SRAM gen_pool for ping pong */
        enum dma_event_q asp_chan_q;    /* event queue number for ASP channel */
        enum dma_event_q ram_chan_q;    /* event queue number for RAM channel */
        unsigned char data_type;        /* xfer data type */
index 4563b28bd6254ddbeda6f0cd8229f22b10159ef7..10fd172ee3c6777064c654e3fe4d361fd23b4dfe 100644 (file)
@@ -46,6 +46,20 @@ config SND_SOC_P1022_DS
          This will also include the Wolfson Microelectronics WM8776 codec
          driver.
 
+config SND_SOC_P1022_RDK
+       tristate "ALSA SoC support for the Freescale / iVeia P1022 RDK board"
+       # I2C is necessary for the WM8960 driver
+       depends on P1022_RDK && I2C
+       select SND_SOC_FSL_SSI
+       select SND_SOC_FSL_UTILS
+       select SND_SOC_POWERPC_DMA
+       select SND_SOC_WM8960
+       default y if P1022_RDK
+       help
+         Say Y if you want to enable audio on the Freescale / iVeia
+         P1022 RDK board.  This will also include the Wolfson
+         Microelectronics WM8960 codec driver.
+
 config SND_SOC_MPC5200_I2S
        tristate "Freescale MPC5200 PSC in I2S mode driver"
        depends on PPC_MPC52xx && PPC_BESTCOMM
@@ -112,7 +126,7 @@ config SND_SOC_IMX_AUDMUX
 
 config SND_MXC_SOC_WM1133_EV1
        tristate "Audio on the i.MX31ADS with WM1133-EV1 fitted"
-       depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL
+       depends on MACH_MX31ADS_WM1133_EV1
        select SND_SOC_WM8350
        select SND_SOC_IMX_PCM_FIQ
        select SND_SOC_IMX_AUDMUX
index 5f3cf3f52ea03e16a1a374ca530f6daec7a2ed35..515ba665f97c222714f5b138f1a8c03b95b74724 100644 (file)
@@ -6,6 +6,10 @@ obj-$(CONFIG_SND_SOC_MPC8610_HPCD) += snd-soc-mpc8610-hpcd.o
 snd-soc-p1022-ds-objs := p1022_ds.o
 obj-$(CONFIG_SND_SOC_P1022_DS) += snd-soc-p1022-ds.o
 
+# P1022 RDK Machine Support
+snd-soc-p1022-rdk-objs := p1022_rdk.o
+obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o
+
 # Freescale PowerPC SSI/DMA Platform Support
 snd-soc-fsl-ssi-objs := fsl_ssi.o
 snd-soc-fsl-utils-objs := fsl_utils.o
diff --git a/sound/soc/fsl/p1022_rdk.c b/sound/soc/fsl/p1022_rdk.c
new file mode 100644 (file)
index 0000000..897e32f
--- /dev/null
@@ -0,0 +1,392 @@
+/**
+ * Freescale P1022RDK ALSA SoC Machine driver
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ * Note: in order for audio to work correctly, the output controls need
+ * to be enabled, because they control the clock.  So for playback, for
+ * example:
+ *
+ *      amixer sset 'Left Output Mixer PCM' on
+ *      amixer sset 'Right Output Mixer PCM' on
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <sound/soc.h>
+#include <asm/fsl_guts.h>
+
+#include "fsl_dma.h"
+#include "fsl_ssi.h"
+#include "fsl_utils.h"
+
+/* P1022-specific PMUXCR and DMUXCR bit definitions */
+
+#define CCSR_GUTS_PMUXCR_UART0_I2C1_MASK       0x0001c000
+#define CCSR_GUTS_PMUXCR_UART0_I2C1_UART0_SSI  0x00010000
+#define CCSR_GUTS_PMUXCR_UART0_I2C1_SSI                0x00018000
+
+#define CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK      0x00000c00
+#define CCSR_GUTS_PMUXCR_SSI_DMA_TDM_SSI       0x00000000
+
+#define CCSR_GUTS_DMUXCR_PAD   1       /* DMA controller/channel set to pad */
+#define CCSR_GUTS_DMUXCR_SSI   2       /* DMA controller/channel set to SSI */
+
+/*
+ * Set the DMACR register in the GUTS
+ *
+ * The DMACR register determines the source of initiated transfers for each
+ * channel on each DMA controller.  Rather than have a bunch of repetitive
+ * macros for the bit patterns, we just have a function that calculates
+ * them.
+ *
+ * guts: Pointer to GUTS structure
+ * co: The DMA controller (0 or 1)
+ * ch: The channel on the DMA controller (0, 1, 2, or 3)
+ * device: The device to set as the target (CCSR_GUTS_DMUXCR_xxx)
+ */
+static inline void guts_set_dmuxcr(struct ccsr_guts __iomem *guts,
+       unsigned int co, unsigned int ch, unsigned int device)
+{
+       unsigned int shift = 16 + (8 * (1 - co) + 2 * (3 - ch));
+
+       clrsetbits_be32(&guts->dmuxcr, 3 << shift, device << shift);
+}
+
+/* There's only one global utilities register */
+static phys_addr_t guts_phys;
+
+/**
+ * machine_data: machine-specific ASoC device data
+ *
+ * This structure contains data for a single sound platform device on an
+ * P1022 RDK.  Some of the data is taken from the device tree.
+ */
+struct machine_data {
+       struct snd_soc_dai_link dai[2];
+       struct snd_soc_card card;
+       unsigned int dai_format;
+       unsigned int codec_clk_direction;
+       unsigned int cpu_clk_direction;
+       unsigned int clk_frequency;
+       unsigned int dma_id[2];         /* 0 = DMA1, 1 = DMA2, etc */
+       unsigned int dma_channel_id[2]; /* 0 = ch 0, 1 = ch 1, etc*/
+       char platform_name[2][DAI_NAME_SIZE]; /* One for each DMA channel */
+};
+
+/**
+ * p1022_rdk_machine_probe: initialize the board
+ *
+ * This function is used to initialize the board-specific hardware.
+ *
+ * Here we program the DMACR and PMUXCR registers.
+ */
+static int p1022_rdk_machine_probe(struct snd_soc_card *card)
+{
+       struct machine_data *mdata =
+               container_of(card, struct machine_data, card);
+       struct ccsr_guts __iomem *guts;
+
+       guts = ioremap(guts_phys, sizeof(struct ccsr_guts));
+       if (!guts) {
+               dev_err(card->dev, "could not map global utilities\n");
+               return -ENOMEM;
+       }
+
+       /* Enable SSI Tx signal */
+       clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_UART0_I2C1_MASK,
+                       CCSR_GUTS_PMUXCR_UART0_I2C1_UART0_SSI);
+
+       /* Enable SSI Rx signal */
+       clrsetbits_be32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK,
+                       CCSR_GUTS_PMUXCR_SSI_DMA_TDM_SSI);
+
+       /* Enable DMA Channel for SSI */
+       guts_set_dmuxcr(guts, mdata->dma_id[0], mdata->dma_channel_id[0],
+                       CCSR_GUTS_DMUXCR_SSI);
+
+       guts_set_dmuxcr(guts, mdata->dma_id[1], mdata->dma_channel_id[1],
+                       CCSR_GUTS_DMUXCR_SSI);
+
+       iounmap(guts);
+
+       return 0;
+}
+
+/**
+ * p1022_rdk_startup: program the board with various hardware parameters
+ *
+ * This function takes board-specific information, like clock frequencies
+ * and serial data formats, and passes that information to the codec and
+ * transport drivers.
+ */
+static int p1022_rdk_startup(struct snd_pcm_substream *substream)
+{
+       struct snd_soc_pcm_runtime *rtd = substream->private_data;
+       struct machine_data *mdata =
+               container_of(rtd->card, struct machine_data, card);
+       struct device *dev = rtd->card->dev;
+       int ret = 0;
+
+       /* Tell the codec driver what the serial protocol is. */
+       ret = snd_soc_dai_set_fmt(rtd->codec_dai, mdata->dai_format);
+       if (ret < 0) {
+               dev_err(dev, "could not set codec driver audio format (ret=%i)\n",
+                       ret);
+               return ret;
+       }
+
+       ret = snd_soc_dai_set_pll(rtd->codec_dai, 0, 0, mdata->clk_frequency,
+               mdata->clk_frequency);
+       if (ret < 0) {
+               dev_err(dev, "could not set codec PLL frequency (ret=%i)\n",
+                       ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+/**
+ * p1022_rdk_machine_remove: Remove the sound device
+ *
+ * This function is called to remove the sound device for one SSI.  We
+ * de-program the DMACR and PMUXCR register.
+ */
+static int p1022_rdk_machine_remove(struct snd_soc_card *card)
+{
+       struct machine_data *mdata =
+               container_of(card, struct machine_data, card);
+       struct ccsr_guts __iomem *guts;
+
+       guts = ioremap(guts_phys, sizeof(struct ccsr_guts));
+       if (!guts) {
+               dev_err(card->dev, "could not map global utilities\n");
+               return -ENOMEM;
+       }
+
+       /* Restore the signal routing */
+       clrbits32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_UART0_I2C1_MASK);
+       clrbits32(&guts->pmuxcr, CCSR_GUTS_PMUXCR_SSI_DMA_TDM_MASK);
+       guts_set_dmuxcr(guts, mdata->dma_id[0], mdata->dma_channel_id[0], 0);
+       guts_set_dmuxcr(guts, mdata->dma_id[1], mdata->dma_channel_id[1], 0);
+
+       iounmap(guts);
+
+       return 0;
+}
+
+/**
+ * p1022_rdk_ops: ASoC machine driver operations
+ */
+static struct snd_soc_ops p1022_rdk_ops = {
+       .startup = p1022_rdk_startup,
+};
+
+/**
+ * p1022_rdk_probe: platform probe function for the machine driver
+ *
+ * Although this is a machine driver, the SSI node is the "master" node with
+ * respect to audio hardware connections.  Therefore, we create a new ASoC
+ * device for each new SSI node that has a codec attached.
+ */
+static int p1022_rdk_probe(struct platform_device *pdev)
+{
+       struct device *dev = pdev->dev.parent;
+       /* ssi_pdev is the platform device for the SSI node that probed us */
+       struct platform_device *ssi_pdev =
+               container_of(dev, struct platform_device, dev);
+       struct device_node *np = ssi_pdev->dev.of_node;
+       struct device_node *codec_np = NULL;
+       struct machine_data *mdata;
+       const u32 *iprop;
+       int ret;
+
+       /* Find the codec node for this SSI. */
+       codec_np = of_parse_phandle(np, "codec-handle", 0);
+       if (!codec_np) {
+               dev_err(dev, "could not find codec node\n");
+               return -EINVAL;
+       }
+
+       mdata = kzalloc(sizeof(struct machine_data), GFP_KERNEL);
+       if (!mdata) {
+               ret = -ENOMEM;
+               goto error_put;
+       }
+
+       mdata->dai[0].cpu_dai_name = dev_name(&ssi_pdev->dev);
+       mdata->dai[0].ops = &p1022_rdk_ops;
+
+       /* ASoC core can match codec with device node */
+       mdata->dai[0].codec_of_node = codec_np;
+
+       /*
+        * We register two DAIs per SSI, one for playback and the other for
+        * capture.  We support codecs that have separate DAIs for both playback
+        * and capture.
+        */
+       memcpy(&mdata->dai[1], &mdata->dai[0], sizeof(struct snd_soc_dai_link));
+
+       /* The DAI names from the codec (snd_soc_dai_driver.name) */
+       mdata->dai[0].codec_dai_name = "wm8960-hifi";
+       mdata->dai[1].codec_dai_name = mdata->dai[0].codec_dai_name;
+
+       /*
+        * Configure the SSI for I2S slave mode.  Older device trees have
+        * an fsl,mode property, but we ignore that since there's really
+        * only one way to configure the SSI.
+        */
+       mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+               SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM;
+       mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
+       mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
+
+       /*
+        * In i2s-slave mode, the codec has its own clock source, so we
+        * need to get the frequency from the device tree and pass it to
+        * the codec driver.
+        */
+       iprop = of_get_property(codec_np, "clock-frequency", NULL);
+       if (!iprop || !*iprop) {
+               dev_err(&pdev->dev, "codec bus-frequency property is missing or invalid\n");
+               ret = -EINVAL;
+               goto error;
+       }
+       mdata->clk_frequency = be32_to_cpup(iprop);
+
+       if (!mdata->clk_frequency) {
+               dev_err(&pdev->dev, "unknown clock frequency\n");
+               ret = -EINVAL;
+               goto error;
+       }
+
+       /* Find the playback DMA channel to use. */
+       mdata->dai[0].platform_name = mdata->platform_name[0];
+       ret = fsl_asoc_get_dma_channel(np, "fsl,playback-dma", &mdata->dai[0],
+                                      &mdata->dma_channel_id[0],
+                                      &mdata->dma_id[0]);
+       if (ret) {
+               dev_err(&pdev->dev, "missing/invalid playback DMA phandle (ret=%i)\n",
+                       ret);
+               goto error;
+       }
+
+       /* Find the capture DMA channel to use. */
+       mdata->dai[1].platform_name = mdata->platform_name[1];
+       ret = fsl_asoc_get_dma_channel(np, "fsl,capture-dma", &mdata->dai[1],
+                                      &mdata->dma_channel_id[1],
+                                      &mdata->dma_id[1]);
+       if (ret) {
+               dev_err(&pdev->dev, "missing/invalid capture DMA phandle (ret=%i)\n",
+                       ret);
+               goto error;
+       }
+
+       /* Initialize our DAI data structure.  */
+       mdata->dai[0].stream_name = "playback";
+       mdata->dai[1].stream_name = "capture";
+       mdata->dai[0].name = mdata->dai[0].stream_name;
+       mdata->dai[1].name = mdata->dai[1].stream_name;
+
+       mdata->card.probe = p1022_rdk_machine_probe;
+       mdata->card.remove = p1022_rdk_machine_remove;
+       mdata->card.name = pdev->name; /* The platform driver name */
+       mdata->card.owner = THIS_MODULE;
+       mdata->card.dev = &pdev->dev;
+       mdata->card.num_links = 2;
+       mdata->card.dai_link = mdata->dai;
+
+       /* Register with ASoC */
+       ret = snd_soc_register_card(&mdata->card);
+       if (ret) {
+               dev_err(&pdev->dev, "could not register card (ret=%i)\n", ret);
+               goto error;
+       }
+
+       return 0;
+
+error:
+       kfree(mdata);
+error_put:
+       of_node_put(codec_np);
+       return ret;
+}
+
+/**
+ * p1022_rdk_remove: remove the platform device
+ *
+ * This function is called when the platform device is removed.
+ */
+static int __devexit p1022_rdk_remove(struct platform_device *pdev)
+{
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+       struct machine_data *mdata =
+               container_of(card, struct machine_data, card);
+
+       snd_soc_unregister_card(card);
+       kfree(mdata);
+
+       return 0;
+}
+
+static struct platform_driver p1022_rdk_driver = {
+       .probe = p1022_rdk_probe,
+       .remove = __devexit_p(p1022_rdk_remove),
+       .driver = {
+               /*
+                * The name must match 'compatible' property in the device tree,
+                * in lowercase letters.
+                */
+               .name = "snd-soc-p1022rdk",
+               .owner = THIS_MODULE,
+       },
+};
+
+/**
+ * p1022_rdk_init: machine driver initialization.
+ *
+ * This function is called when this module is loaded.
+ */
+static int __init p1022_rdk_init(void)
+{
+       struct device_node *guts_np;
+       struct resource res;
+
+       /* Get the physical address of the global utilities registers */
+       guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
+       if (of_address_to_resource(guts_np, 0, &res)) {
+               pr_err("snd-soc-p1022rdk: missing/invalid global utils node\n");
+               of_node_put(guts_np);
+               return -EINVAL;
+       }
+       guts_phys = res.start;
+       of_node_put(guts_np);
+
+       return platform_driver_register(&p1022_rdk_driver);
+}
+
+/**
+ * p1022_rdk_exit: machine driver exit
+ *
+ * This function is called when this driver is unloaded.
+ */
+static void __exit p1022_rdk_exit(void)
+{
+       platform_driver_unregister(&p1022_rdk_driver);
+}
+
+late_initcall(p1022_rdk_init);
+module_exit(p1022_rdk_exit);
+
+MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
+MODULE_DESCRIPTION("Freescale / iVeia P1022 RDK ALSA SoC machine driver");
+MODULE_LICENSE("GPL v2");
index 4b63ec8eb372ee917a06c314764a2d7f6804a892..4d261927662ff123cca004beb025919eaee508fe 100644 (file)
@@ -29,14 +29,14 @@ struct pcm030_audio_data {
 
 static struct snd_soc_dai_link pcm030_fabric_dai[] = {
 {
-       .name = "AC97",
+       .name = "AC97.0",
        .stream_name = "AC97 Analog",
        .codec_dai_name = "wm9712-hifi",
        .cpu_dai_name = "mpc5200-psc-ac97.0",
        .codec_name = "wm9712-codec",
 },
 {
-       .name = "AC97",
+       .name = "AC97.1",
        .stream_name = "AC97 IEC958",
        .codec_dai_name = "wm9712-aux",
        .cpu_dai_name = "mpc5200-psc-ac97.1",
index aa037b292f3dc05a9b6300c3cc4890988c0c2faf..c294fbb523fce2dac76a70d9e5537a47fee40042 100644 (file)
@@ -523,16 +523,24 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
 
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                        /*
-                        * write a data to saif data register to trigger
-                        * the transfer
+                        * write data to saif data register to trigger
+                        * the transfer.
+                        * For 24-bit format the 32-bit FIFO register stores
+                        * only one channel, so we need to write twice.
+                        * This is also safe for the other non 24-bit formats.
                         */
                        __raw_writel(0, saif->base + SAIF_DATA);
+                       __raw_writel(0, saif->base + SAIF_DATA);
                } else {
                        /*
-                        * read a data from saif data register to trigger
-                        * the receive
+                        * read data from saif data register to trigger
+                        * the receive.
+                        * For 24-bit format the 32-bit FIFO register stores
+                        * only one channel, so we need to read twice.
+                        * This is also safe for the other non 24-bit formats.
                         */
                        __raw_readl(saif->base + SAIF_DATA);
+                       __raw_readl(saif->base + SAIF_DATA);
                }
 
                master_saif->ongoing = 1;
@@ -812,3 +820,4 @@ module_platform_driver(mxs_saif_driver);
 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
 MODULE_DESCRIPTION("MXS ASoC SAIF driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mxs-saif");
index 68f2cd1a92061504bd332c683d286c8ffe8414eb..5a6aeaf552a89666672e4bc2a46a3106ba26a532 100644 (file)
@@ -464,9 +464,9 @@ static __devinit int asoc_dmic_probe(struct platform_device *pdev)
 
        mutex_init(&dmic->mutex);
 
-       dmic->fclk = clk_get(dmic->dev, "dmic_fck");
+       dmic->fclk = clk_get(dmic->dev, "fck");
        if (IS_ERR(dmic->fclk)) {
-               dev_err(dmic->dev, "cant get dmic_fck\n");
+               dev_err(dmic->dev, "cant get fck\n");
                return -ENODEV;
        }
 
index 677b567935f8055b6899f74e276bd4c0a39dd213..1ff6bb9ade5c98fd1ac644b0567f42f367d543d8 100644 (file)
 
 #include <linux/clk.h>
 #include <linux/platform_device.h>
+#include <linux/gpio.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
 
 #include <asm/mach-types.h>
-#include <mach/hardware.h>
-#include <mach/gpio.h>
-#include <mach/board-zoom.h>
 #include <linux/platform_data/asoc-ti-mcbsp.h>
+#include <linux/platform_data/gpio-omap.h>
 
 /* Register descriptions for twl4030 codec part */
 #include <linux/mfd/twl4030-audio.h>
index e7b83179aca2b1469af4ec1e03f35e62df1227b2..3c7c3a59ed3987b9017e89c07cf130a2a54c4a39 100644 (file)
@@ -207,6 +207,8 @@ config SND_SOC_BELLS
        select SND_SOC_WM5102
        select SND_SOC_WM5110
        select SND_SOC_WM9081
+       select SND_SOC_WM0010
+       select SND_SOC_WM1250_EV1
 
 config SND_SOC_LOWLAND
        tristate "Audio support for Wolfson Lowland"
index 14fbcd30cae574dbc57b8f20eae191dc332c0f93..386bab1f99abe9d05032dbbe819edddace9fe42f 100644 (file)
@@ -442,7 +442,7 @@ static __devinit int s3c_ac97_probe(struct platform_device *pdev)
                ret = -ENODEV;
                goto err2;
        }
-       clk_enable(s3c_ac97.ac97_clk);
+       clk_prepare_enable(s3c_ac97.ac97_clk);
 
        if (ac97_pdata->cfg_gpio(pdev)) {
                dev_err(&pdev->dev, "Unable to configure gpio\n");
@@ -468,7 +468,7 @@ err5:
        free_irq(irq_res->start, NULL);
 err4:
 err3:
-       clk_disable(s3c_ac97.ac97_clk);
+       clk_disable_unprepare(s3c_ac97.ac97_clk);
        clk_put(s3c_ac97.ac97_clk);
 err2:
        iounmap(s3c_ac97.regs);
@@ -488,7 +488,7 @@ static __devexit int s3c_ac97_remove(struct platform_device *pdev)
        if (irq_res)
                free_irq(irq_res->start, NULL);
 
-       clk_disable(s3c_ac97.ac97_clk);
+       clk_disable_unprepare(s3c_ac97.ac97_clk);
        clk_put(s3c_ac97.ac97_clk);
 
        iounmap(s3c_ac97.regs);
index b0d46d63d55ea784f2f6970cd77bd2915a1c32fa..3d7ace796063e565a30219d39012804686855a06 100644 (file)
 #include "../codecs/wm5102.h"
 #include "../codecs/wm9081.h"
 
-/*
- * 44.1kHz based clocks for the SYSCLK domain, use a very high clock
- * to allow all the DSP functionality to be enabled if desired.
- */
-#define SYSCLK_RATE (44100 * 1024)
-
-/* 48kHz based clocks for the ASYNC domain */
-#define ASYNCCLK_RATE (48000 * 512)
-
 /* BCLK2 is fixed at this currently */
 #define BCLK2_RATE (64 * 8000)
 
  */
 #define MCLK_RATE 24576000
 
-#define WM9081_AUDIO_RATE 44100
-#define WM9081_MCLK_RATE  (WM9081_AUDIO_RATE * 256)
+#define SYS_AUDIO_RATE 44100
+#define SYS_MCLK_RATE  (SYS_AUDIO_RATE * 256)
+
+#define DAI_AP_DSP    0
+#define DAI_DSP_CODEC 1
+#define DAI_CODEC_CP  2
+#define DAI_CODEC_SUB 3
+
+struct bells_drvdata {
+       int sysclk_rate;
+       int asyncclk_rate;
+};
+
+static struct bells_drvdata wm2200_drvdata = {
+       .sysclk_rate = 22579200,
+};
+
+static struct bells_drvdata wm5102_drvdata = {
+       .sysclk_rate = 45158400,
+       .asyncclk_rate = 49152000,
+};
+
+static struct bells_drvdata wm5110_drvdata = {
+       .sysclk_rate = 135475200,
+       .asyncclk_rate = 147456000,
+};
 
 static int bells_set_bias_level(struct snd_soc_card *card,
                                struct snd_soc_dapm_context *dapm,
                                enum snd_soc_bias_level level)
 {
-       struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+       struct snd_soc_dai *codec_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
        struct snd_soc_codec *codec = codec_dai->codec;
+       struct bells_drvdata *bells = card->drvdata;
        int ret;
 
        if (dapm->dev != codec_dai->dev)
@@ -52,18 +68,21 @@ static int bells_set_bias_level(struct snd_soc_card *card,
 
        switch (level) {
        case SND_SOC_BIAS_PREPARE:
-               if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
-                       ret = snd_soc_codec_set_pll(codec, WM5102_FLL1,
-                                                   ARIZONA_FLL_SRC_MCLK1,
-                                                   MCLK_RATE,
-                                                   SYSCLK_RATE);
-                       if (ret < 0)
-                               pr_err("Failed to start FLL: %d\n", ret);
+               if (dapm->bias_level != SND_SOC_BIAS_STANDBY)
+                       break;
+
+               ret = snd_soc_codec_set_pll(codec, WM5102_FLL1,
+                                           ARIZONA_FLL_SRC_MCLK1,
+                                           MCLK_RATE,
+                                           bells->sysclk_rate);
+               if (ret < 0)
+                       pr_err("Failed to start FLL: %d\n", ret);
 
+               if (bells->asyncclk_rate) {
                        ret = snd_soc_codec_set_pll(codec, WM5102_FLL2,
                                                    ARIZONA_FLL_SRC_AIF2BCLK,
                                                    BCLK2_RATE,
-                                                   ASYNCCLK_RATE);
+                                                   bells->asyncclk_rate);
                        if (ret < 0)
                                pr_err("Failed to start FLL: %d\n", ret);
                }
@@ -80,8 +99,9 @@ static int bells_set_bias_level_post(struct snd_soc_card *card,
                                     struct snd_soc_dapm_context *dapm,
                                     enum snd_soc_bias_level level)
 {
-       struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+       struct snd_soc_dai *codec_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
        struct snd_soc_codec *codec = codec_dai->codec;
+       struct bells_drvdata *bells = card->drvdata;
        int ret;
 
        if (dapm->dev != codec_dai->dev)
@@ -95,10 +115,13 @@ static int bells_set_bias_level_post(struct snd_soc_card *card,
                        return ret;
                }
 
-               ret = snd_soc_codec_set_pll(codec, WM5102_FLL2, 0, 0, 0);
-               if (ret < 0) {
-                       pr_err("Failed to stop FLL: %d\n", ret);
-                       return ret;
+               if (bells->asyncclk_rate) {
+                       ret = snd_soc_codec_set_pll(codec, WM5102_FLL2,
+                                                   0, 0, 0);
+                       if (ret < 0) {
+                               pr_err("Failed to stop FLL: %d\n", ret);
+                               return ret;
+                       }
                }
                break;
 
@@ -113,56 +136,73 @@ static int bells_set_bias_level_post(struct snd_soc_card *card,
 
 static int bells_late_probe(struct snd_soc_card *card)
 {
-       struct snd_soc_codec *codec = card->rtd[0].codec;
-       struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai;
-       struct snd_soc_dai *aif2_dai = card->rtd[1].cpu_dai;
-       struct snd_soc_dai *aif3_dai = card->rtd[2].cpu_dai;
-       struct snd_soc_dai *wm9081_dai = card->rtd[2].codec_dai;
+       struct bells_drvdata *bells = card->drvdata;
+       struct snd_soc_codec *wm0010 = card->rtd[DAI_AP_DSP].codec;
+       struct snd_soc_codec *codec = card->rtd[DAI_DSP_CODEC].codec;
+       struct snd_soc_dai *aif1_dai = card->rtd[DAI_DSP_CODEC].codec_dai;
+       struct snd_soc_dai *aif2_dai;
+       struct snd_soc_dai *aif3_dai;
+       struct snd_soc_dai *wm9081_dai;
        int ret;
 
-       ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0);
+       ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK,
+                                      ARIZONA_CLK_SRC_FLL1,
+                                      bells->sysclk_rate,
+                                      SND_SOC_CLOCK_IN);
        if (ret != 0) {
-               dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
+               dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret);
                return ret;
        }
 
-       ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0);
+       ret = snd_soc_codec_set_sysclk(wm0010, 0, 0, SYS_MCLK_RATE, 0);
        if (ret != 0) {
-               dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret);
+               dev_err(wm0010->dev, "Failed to set WM0010 clock: %d\n", ret);
                return ret;
        }
 
-       ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0);
-       if (ret != 0) {
+       ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0);
+       if (ret != 0)
                dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
-               return ret;
-       }
 
-       ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK,
-                                      ARIZONA_CLK_SRC_FLL1, SYSCLK_RATE,
+       ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_OPCLK, 0,
+                                      SYS_MCLK_RATE, SND_SOC_CLOCK_OUT);
+       if (ret != 0)
+               dev_err(codec->dev, "Failed to set OPCLK: %d\n", ret);
+
+       if (card->num_rtd == DAI_CODEC_CP)
+               return 0;
+
+       ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK,
+                                      ARIZONA_CLK_SRC_FLL2,
+                                      bells->asyncclk_rate,
                                       SND_SOC_CLOCK_IN);
        if (ret != 0) {
-               dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret);
+               dev_err(codec->dev, "Failed to set ASYNCCLK: %d\n", ret);
                return ret;
        }
 
-       ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_OPCLK, 0,
-                                      WM9081_MCLK_RATE, SND_SOC_CLOCK_OUT);
+       aif2_dai = card->rtd[DAI_CODEC_CP].cpu_dai;
+
+       ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0);
        if (ret != 0) {
-               dev_err(codec->dev, "Failed to set OPCLK: %d\n", ret);
+               dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret);
                return ret;
        }
 
-       ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK,
-                                      ARIZONA_CLK_SRC_FLL2, ASYNCCLK_RATE,
-                                      SND_SOC_CLOCK_IN);
+       if (card->num_rtd == DAI_CODEC_SUB)
+               return 0;
+
+       aif3_dai = card->rtd[DAI_CODEC_SUB].cpu_dai;
+       wm9081_dai = card->rtd[DAI_CODEC_SUB].codec_dai;
+
+       ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0);
        if (ret != 0) {
-               dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret);
+               dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret);
                return ret;
        }
 
        ret = snd_soc_codec_set_sysclk(wm9081_dai->codec, WM9081_SYSCLK_MCLK,
-                                      0, WM9081_MCLK_RATE, 0);
+                                      0, SYS_MCLK_RATE, 0);
        if (ret != 0) {
                dev_err(wm9081_dai->dev, "Failed to set MCLK: %d\n", ret);
                return ret;
@@ -181,22 +221,57 @@ static const struct snd_soc_pcm_stream baseband_params = {
 
 static const struct snd_soc_pcm_stream sub_params = {
        .formats = SNDRV_PCM_FMTBIT_S32_LE,
-       .rate_min = WM9081_AUDIO_RATE,
-       .rate_max = WM9081_AUDIO_RATE,
+       .rate_min = SYS_AUDIO_RATE,
+       .rate_max = SYS_AUDIO_RATE,
        .channels_min = 2,
        .channels_max = 2,
 };
 
+static struct snd_soc_dai_link bells_dai_wm2200[] = {
+       {
+               .name = "CPU-DSP",
+               .stream_name = "CPU-DSP",
+               .cpu_dai_name = "samsung-i2s.0",
+               .codec_dai_name = "wm0010-sdi1",
+               .platform_name = "samsung-audio",
+               .codec_name = "spi0.0",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+                               | SND_SOC_DAIFMT_CBM_CFM,
+       },
+       {
+               .name = "DSP-CODEC",
+               .stream_name = "DSP-CODEC",
+               .cpu_dai_name = "wm0010-sdi2",
+               .codec_dai_name = "wm2200",
+               .codec_name = "wm2200.1-003a",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+                               | SND_SOC_DAIFMT_CBM_CFM,
+               .params = &sub_params,
+               .ignore_suspend = 1,
+       },
+};
+
 static struct snd_soc_dai_link bells_dai_wm5102[] = {
        {
-               .name = "CPU",
-               .stream_name = "CPU",
+               .name = "CPU-DSP",
+               .stream_name = "CPU-DSP",
                .cpu_dai_name = "samsung-i2s.0",
-               .codec_dai_name = "wm5102-aif1",
+               .codec_dai_name = "wm0010-sdi1",
                .platform_name = "samsung-audio",
+               .codec_name = "spi0.0",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+                               | SND_SOC_DAIFMT_CBM_CFM,
+       },
+       {
+               .name = "DSP-CODEC",
+               .stream_name = "DSP-CODEC",
+               .cpu_dai_name = "wm0010-sdi2",
+               .codec_dai_name = "wm5102-aif1",
                .codec_name = "wm5102-codec",
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
                                | SND_SOC_DAIFMT_CBM_CFM,
+               .params = &sub_params,
+               .ignore_suspend = 1,
        },
        {
                .name = "Baseband",
@@ -224,14 +299,25 @@ static struct snd_soc_dai_link bells_dai_wm5102[] = {
 
 static struct snd_soc_dai_link bells_dai_wm5110[] = {
        {
-               .name = "CPU",
-               .stream_name = "CPU",
+               .name = "CPU-DSP",
+               .stream_name = "CPU-DSP",
                .cpu_dai_name = "samsung-i2s.0",
-               .codec_dai_name = "wm5110-aif1",
+               .codec_dai_name = "wm0010-sdi1",
                .platform_name = "samsung-audio",
+               .codec_name = "spi0.0",
+               .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+                               | SND_SOC_DAIFMT_CBM_CFM,
+       },
+       {
+               .name = "DSP-CODEC",
+               .stream_name = "DSP-CODEC",
+               .cpu_dai_name = "wm0010-sdi2",
+               .codec_dai_name = "wm5110-aif1",
                .codec_name = "wm5110-codec",
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
                                | SND_SOC_DAIFMT_CBM_CFM,
+               .params = &sub_params,
+               .ignore_suspend = 1,
        },
        {
                .name = "Baseband",
@@ -269,6 +355,24 @@ static struct snd_soc_dapm_route bells_routes[] = {
 };
 
 static struct snd_soc_card bells_cards[] = {
+       {
+               .name = "Bells WM2200",
+               .owner = THIS_MODULE,
+               .dai_link = bells_dai_wm2200,
+               .num_links = ARRAY_SIZE(bells_dai_wm2200),
+               .codec_conf = bells_codec_conf,
+               .num_configs = ARRAY_SIZE(bells_codec_conf),
+
+               .late_probe = bells_late_probe,
+
+               .dapm_routes = bells_routes,
+               .num_dapm_routes = ARRAY_SIZE(bells_routes),
+
+               .set_bias_level = bells_set_bias_level,
+               .set_bias_level_post = bells_set_bias_level_post,
+
+               .drvdata = &wm2200_drvdata,
+       },
        {
                .name = "Bells WM5102",
                .owner = THIS_MODULE,
@@ -284,6 +388,8 @@ static struct snd_soc_card bells_cards[] = {
 
                .set_bias_level = bells_set_bias_level,
                .set_bias_level_post = bells_set_bias_level_post,
+
+               .drvdata = &wm5102_drvdata,
        },
        {
                .name = "Bells WM5110",
@@ -300,6 +406,8 @@ static struct snd_soc_card bells_cards[] = {
 
                .set_bias_level = bells_set_bias_level,
                .set_bias_level_post = bells_set_bias_level_post,
+
+               .drvdata = &wm5110_drvdata,
        },
 };
 
index 40b00a13dcd1b1c664636406ae693faa0bdf996f..547b9190c88f421b6ad2d9c803d7887c98e7f69f 100644 (file)
@@ -423,7 +423,7 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
                        if (i2s->op_clk) {
                                if ((clk_id && !(mod & MOD_IMS_SYSMUX)) ||
                                        (!clk_id && (mod & MOD_IMS_SYSMUX))) {
-                                       clk_disable(i2s->op_clk);
+                                       clk_disable_unprepare(i2s->op_clk);
                                        clk_put(i2s->op_clk);
                                } else {
                                        i2s->rclk_srcrate =
@@ -434,7 +434,7 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai,
 
                        i2s->op_clk = clk_get(&i2s->pdev->dev,
                                                i2s->src_clk[clk_id]);
-                       clk_enable(i2s->op_clk);
+                       clk_prepare_enable(i2s->op_clk);
                        i2s->rclk_srcrate = clk_get_rate(i2s->op_clk);
 
                        /* Over-ride the other's */
@@ -880,7 +880,7 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
                iounmap(i2s->addr);
                return -ENOENT;
        }
-       clk_enable(i2s->clk);
+       clk_prepare_enable(i2s->clk);
 
        if (other) {
                other->addr = i2s->addr;
@@ -922,7 +922,7 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai)
                if (i2s->quirks & QUIRK_NEED_RSTCLR)
                        writel(0, i2s->addr + I2SCON);
 
-               clk_disable(i2s->clk);
+               clk_disable_unprepare(i2s->clk);
                clk_put(i2s->clk);
 
                iounmap(i2s->addr);
index c86081992dfd9331eeaed79c97f656705162b450..45f4a752d2a007a476bbfdf1aec2efec2f43c2ce 100644 (file)
@@ -543,7 +543,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
                ret = PTR_ERR(pcm->cclk);
                goto err1;
        }
-       clk_enable(pcm->cclk);
+       clk_prepare_enable(pcm->cclk);
 
        /* record our pcm structure for later use in the callbacks */
        dev_set_drvdata(&pdev->dev, pcm);
@@ -568,7 +568,7 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
                ret = -ENOENT;
                goto err4;
        }
-       clk_enable(pcm->pclk);
+       clk_prepare_enable(pcm->pclk);
 
        s3c_pcm_stereo_in[pdev->id].dma_addr = mem_res->start
                                                        + S3C_PCM_RXFIFO;
@@ -592,14 +592,14 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
        return 0;
 
 err5:
-       clk_disable(pcm->pclk);
+       clk_disable_unprepare(pcm->pclk);
        clk_put(pcm->pclk);
 err4:
        iounmap(pcm->regs);
 err3:
        release_mem_region(mem_res->start, resource_size(mem_res));
 err2:
-       clk_disable(pcm->cclk);
+       clk_disable_unprepare(pcm->cclk);
        clk_put(pcm->cclk);
 err1:
        return ret;
@@ -619,8 +619,8 @@ static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)
        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(mem_res->start, resource_size(mem_res));
 
-       clk_disable(pcm->cclk);
-       clk_disable(pcm->pclk);
+       clk_disable_unprepare(pcm->cclk);
+       clk_disable_unprepare(pcm->pclk);
        clk_put(pcm->pclk);
        clk_put(pcm->cclk);
 
index bc24c7af02b2e23ff57342b1901841c879198fd1..5f3b06d36e9cfcd24cb84e26c78e5937e76836ad 100644 (file)
@@ -397,7 +397,7 @@ static __devinit int spdif_probe(struct platform_device *pdev)
                ret = -ENOENT;
                goto err0;
        }
-       clk_enable(spdif->pclk);
+       clk_prepare_enable(spdif->pclk);
 
        spdif->sclk = clk_get(&pdev->dev, "sclk_spdif");
        if (IS_ERR(spdif->sclk)) {
@@ -405,7 +405,7 @@ static __devinit int spdif_probe(struct platform_device *pdev)
                ret = -ENOENT;
                goto err1;
        }
-       clk_enable(spdif->sclk);
+       clk_prepare_enable(spdif->sclk);
 
        /* Request S/PDIF Register's memory region */
        if (!request_mem_region(mem_res->start,
@@ -444,10 +444,10 @@ err4:
 err3:
        release_mem_region(mem_res->start, resource_size(mem_res));
 err2:
-       clk_disable(spdif->sclk);
+       clk_disable_unprepare(spdif->sclk);
        clk_put(spdif->sclk);
 err1:
-       clk_disable(spdif->pclk);
+       clk_disable_unprepare(spdif->pclk);
        clk_put(spdif->pclk);
 err0:
        return ret;
@@ -466,9 +466,9 @@ static __devexit int spdif_remove(struct platform_device *pdev)
        if (mem_res)
                release_mem_region(mem_res->start, resource_size(mem_res));
 
-       clk_disable(spdif->sclk);
+       clk_disable_unprepare(spdif->sclk);
        clk_put(spdif->sclk);
-       clk_disable(spdif->pclk);
+       clk_disable_unprepare(spdif->pclk);
        clk_put(spdif->pclk);
 
        return 0;
index 9d7f30774a44d9524cb71f6697fc0ce96825295c..4a10e4d1bd43b1b9bcb4062c1d67f7a403d83156 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/workqueue.h>
 #include <sound/soc.h>
+#include <sound/pcm_params.h>
 #include <sound/sh_fsi.h>
 
 /* PortA/PortB register */
@@ -188,6 +189,14 @@ typedef int (*set_rate_func)(struct device *dev, int rate, int enable);
  *             --> go to codecs
  */
 
+/*
+ *     FSI clock
+ *
+ * FSIxCLK [CPG] (ick) ------->        |
+ *                             |-> FSI_DIV (div)-> FSI2
+ * FSIxCK [external] (xck) --->        |
+ */
+
 /*
  *             struct
  */
@@ -228,6 +237,20 @@ struct fsi_stream {
        dma_addr_t              dma;
 };
 
+struct fsi_clk {
+       /* see [FSI clock] */
+       struct clk *own;
+       struct clk *xck;
+       struct clk *ick;
+       struct clk *div;
+       int (*set_rate)(struct device *dev,
+                       struct fsi_priv *fsi,
+                       unsigned long rate);
+
+       unsigned long rate;
+       unsigned int count;
+};
+
 struct fsi_priv {
        void __iomem *base;
        struct fsi_master *master;
@@ -236,6 +259,8 @@ struct fsi_priv {
        struct fsi_stream playback;
        struct fsi_stream capture;
 
+       struct fsi_clk clock;
+
        u32 fmt;
 
        int chan_num:16;
@@ -717,14 +742,335 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable)
 /*
  *             clock function
  */
+static int fsi_clk_init(struct device *dev,
+                       struct fsi_priv *fsi,
+                       int xck,
+                       int ick,
+                       int div,
+                       int (*set_rate)(struct device *dev,
+                                       struct fsi_priv *fsi,
+                                       unsigned long rate))
+{
+       struct fsi_clk *clock = &fsi->clock;
+       int is_porta = fsi_is_port_a(fsi);
+
+       clock->xck      = NULL;
+       clock->ick      = NULL;
+       clock->div      = NULL;
+       clock->rate     = 0;
+       clock->count    = 0;
+       clock->set_rate = set_rate;
+
+       clock->own = devm_clk_get(dev, NULL);
+       if (IS_ERR(clock->own))
+               return -EINVAL;
+
+       /* external clock */
+       if (xck) {
+               clock->xck = devm_clk_get(dev, is_porta ? "xcka" : "xckb");
+               if (IS_ERR(clock->xck)) {
+                       dev_err(dev, "can't get xck clock\n");
+                       return -EINVAL;
+               }
+               if (clock->xck == clock->own) {
+                       dev_err(dev, "cpu doesn't support xck clock\n");
+                       return -EINVAL;
+               }
+       }
+
+       /* FSIACLK/FSIBCLK */
+       if (ick) {
+               clock->ick = devm_clk_get(dev,  is_porta ? "icka" : "ickb");
+               if (IS_ERR(clock->ick)) {
+                       dev_err(dev, "can't get ick clock\n");
+                       return -EINVAL;
+               }
+               if (clock->ick == clock->own) {
+                       dev_err(dev, "cpu doesn't support ick clock\n");
+                       return -EINVAL;
+               }
+       }
+
+       /* FSI-DIV */
+       if (div) {
+               clock->div = devm_clk_get(dev,  is_porta ? "diva" : "divb");
+               if (IS_ERR(clock->div)) {
+                       dev_err(dev, "can't get div clock\n");
+                       return -EINVAL;
+               }
+               if (clock->div == clock->own) {
+                       dev_err(dev, "cpu doens't support div clock\n");
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+#define fsi_clk_invalid(fsi) fsi_clk_valid(fsi, 0)
+static void fsi_clk_valid(struct fsi_priv *fsi, unsigned long rate)
+{
+       fsi->clock.rate = rate;
+}
+
+static int fsi_clk_is_valid(struct fsi_priv *fsi)
+{
+       return  fsi->clock.set_rate &&
+               fsi->clock.rate;
+}
+
+static int fsi_clk_enable(struct device *dev,
+                         struct fsi_priv *fsi,
+                         unsigned long rate)
+{
+       struct fsi_clk *clock = &fsi->clock;
+       int ret = -EINVAL;
+
+       if (!fsi_clk_is_valid(fsi))
+               return ret;
+
+       if (0 == clock->count) {
+               ret = clock->set_rate(dev, fsi, rate);
+               if (ret < 0) {
+                       fsi_clk_invalid(fsi);
+                       return ret;
+               }
+
+               if (clock->xck)
+                       clk_enable(clock->xck);
+               if (clock->ick)
+                       clk_enable(clock->ick);
+               if (clock->div)
+                       clk_enable(clock->div);
+
+               clock->count++;
+       }
+
+       return ret;
+}
+
+static int fsi_clk_disable(struct device *dev,
+                           struct fsi_priv *fsi)
+{
+       struct fsi_clk *clock = &fsi->clock;
+
+       if (!fsi_clk_is_valid(fsi))
+               return -EINVAL;
+
+       if (1 == clock->count--) {
+               if (clock->xck)
+                       clk_disable(clock->xck);
+               if (clock->ick)
+                       clk_disable(clock->ick);
+               if (clock->div)
+                       clk_disable(clock->div);
+       }
+
+       return 0;
+}
+
+static int fsi_clk_set_ackbpf(struct device *dev,
+                             struct fsi_priv *fsi,
+                             int ackmd, int bpfmd)
+{
+       u32 data = 0;
+
+       /* check ackmd/bpfmd relationship */
+       if (bpfmd > ackmd) {
+               dev_err(dev, "unsupported rate (%d/%d)\n", ackmd, bpfmd);
+               return -EINVAL;
+       }
+
+       /*  ACKMD */
+       switch (ackmd) {
+       case 512:
+               data |= (0x0 << 12);
+               break;
+       case 256:
+               data |= (0x1 << 12);
+               break;
+       case 128:
+               data |= (0x2 << 12);
+               break;
+       case 64:
+               data |= (0x3 << 12);
+               break;
+       case 32:
+               data |= (0x4 << 12);
+               break;
+       default:
+               dev_err(dev, "unsupported ackmd (%d)\n", ackmd);
+               return -EINVAL;
+       }
+
+       /* BPFMD */
+       switch (bpfmd) {
+       case 32:
+               data |= (0x0 << 8);
+               break;
+       case 64:
+               data |= (0x1 << 8);
+               break;
+       case 128:
+               data |= (0x2 << 8);
+               break;
+       case 256:
+               data |= (0x3 << 8);
+               break;
+       case 512:
+               data |= (0x4 << 8);
+               break;
+       case 16:
+               data |= (0x7 << 8);
+               break;
+       default:
+               dev_err(dev, "unsupported bpfmd (%d)\n", bpfmd);
+               return -EINVAL;
+       }
+
+       dev_dbg(dev, "ACKMD/BPFMD = %d/%d\n", ackmd, bpfmd);
+
+       fsi_reg_mask_set(fsi, CKG1, (ACKMD_MASK | BPFMD_MASK) , data);
+       udelay(10);
+
+       return 0;
+}
+
+static int fsi_clk_set_rate_external(struct device *dev,
+                                    struct fsi_priv *fsi,
+                                    unsigned long rate)
+{
+       struct clk *xck = fsi->clock.xck;
+       struct clk *ick = fsi->clock.ick;
+       unsigned long xrate;
+       int ackmd, bpfmd;
+       int ret = 0;
+
+       /* check clock rate */
+       xrate = clk_get_rate(xck);
+       if (xrate % rate) {
+               dev_err(dev, "unsupported clock rate\n");
+               return -EINVAL;
+       }
+
+       clk_set_parent(ick, xck);
+       clk_set_rate(ick, xrate);
+
+       bpfmd = fsi->chan_num * 32;
+       ackmd = xrate / rate;
+
+       dev_dbg(dev, "external/rate = %ld/%ld\n", xrate, rate);
+
+       ret = fsi_clk_set_ackbpf(dev, fsi, ackmd, bpfmd);
+       if (ret < 0)
+               dev_err(dev, "%s failed", __func__);
+
+       return ret;
+}
+
+static int fsi_clk_set_rate_cpg(struct device *dev,
+                               struct fsi_priv *fsi,
+                               unsigned long rate)
+{
+       struct clk *ick = fsi->clock.ick;
+       struct clk *div = fsi->clock.div;
+       unsigned long target = 0; /* 12288000 or 11289600 */
+       unsigned long actual, cout;
+       unsigned long diff, min;
+       unsigned long best_cout, best_act;
+       int adj;
+       int ackmd, bpfmd;
+       int ret = -EINVAL;
+
+       if (!(12288000 % rate))
+               target = 12288000;
+       if (!(11289600 % rate))
+               target = 11289600;
+       if (!target) {
+               dev_err(dev, "unsupported rate\n");
+               return ret;
+       }
+
+       bpfmd = fsi->chan_num * 32;
+       ackmd = target / rate;
+       ret = fsi_clk_set_ackbpf(dev, fsi, ackmd, bpfmd);
+       if (ret < 0) {
+               dev_err(dev, "%s failed", __func__);
+               return ret;
+       }
+
+       /*
+        * The clock flow is
+        *
+        * [CPG] = cout => [FSI_DIV] = audio => [FSI] => [codec]
+        *
+        * But, it needs to find best match of CPG and FSI_DIV
+        * combination, since it is difficult to generate correct
+        * frequency of audio clock from ick clock only.
+        * Because ick is created from its parent clock.
+        *
+        * target       = rate x [512/256/128/64]fs
+        * cout         = round(target x adjustment)
+        * actual       = cout / adjustment (by FSI-DIV) ~= target
+        * audio        = actual
+        */
+       min = ~0;
+       best_cout = 0;
+       best_act = 0;
+       for (adj = 1; adj < 0xffff; adj++) {
+
+               cout = target * adj;
+               if (cout > 100000000) /* max clock = 100MHz */
+                       break;
+
+               /* cout/actual audio clock */
+               cout    = clk_round_rate(ick, cout);
+               actual  = cout / adj;
+
+               /* find best frequency */
+               diff = abs(actual - target);
+               if (diff < min) {
+                       min             = diff;
+                       best_cout       = cout;
+                       best_act        = actual;
+               }
+       }
+
+       ret = clk_set_rate(ick, best_cout);
+       if (ret < 0) {
+               dev_err(dev, "ick clock failed\n");
+               return -EIO;
+       }
+
+       ret = clk_set_rate(div, clk_round_rate(div, best_act));
+       if (ret < 0) {
+               dev_err(dev, "div clock failed\n");
+               return -EIO;
+       }
+
+       dev_dbg(dev, "ick/div = %ld/%ld\n",
+               clk_get_rate(ick), clk_get_rate(div));
+
+       return ret;
+}
+
 static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
                              long rate, int enable)
 {
        set_rate_func set_rate = fsi_get_info_set_rate(fsi);
        int ret;
 
-       if (!set_rate)
-               return 0;
+       /*
+        * CAUTION
+        *
+        * set_rate will be deleted
+        */
+       if (!set_rate) {
+               if (enable)
+                       return fsi_clk_enable(dev, fsi, rate);
+               else
+                       return fsi_clk_disable(dev, fsi);
+       }
 
        ret = set_rate(dev, rate, enable);
        if (ret < 0) /* error */
@@ -1334,14 +1680,21 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
        /* fifo init */
        fsi_fifo_init(fsi, io, dev);
 
+       /* start master clock */
+       if (fsi_is_clk_master(fsi))
+               return fsi_set_master_clk(dev, fsi, fsi->rate, 1);
+
        return 0;
 }
 
-static void fsi_hw_shutdown(struct fsi_priv *fsi,
+static int fsi_hw_shutdown(struct fsi_priv *fsi,
                            struct device *dev)
 {
+       /* stop master clock */
        if (fsi_is_clk_master(fsi))
-               fsi_set_master_clk(dev, fsi, fsi->rate, 0);
+               return fsi_set_master_clk(dev, fsi, fsi->rate, 0);
+
+       return 0;
 }
 
 static int fsi_dai_startup(struct snd_pcm_substream *substream,
@@ -1349,6 +1702,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
 {
        struct fsi_priv *fsi = fsi_get_priv(substream);
 
+       fsi_clk_invalid(fsi);
        fsi->rate = 0;
 
        return 0;
@@ -1359,6 +1713,7 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
 {
        struct fsi_priv *fsi = fsi_get_priv(substream);
 
+       fsi_clk_invalid(fsi);
        fsi->rate = 0;
 }
 
@@ -1372,13 +1727,16 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
                fsi_stream_init(fsi, io, substream);
-               fsi_hw_startup(fsi, io, dai->dev);
-               ret = fsi_stream_transfer(io);
-               if (0 == ret)
+               if (!ret)
+                       ret = fsi_hw_startup(fsi, io, dai->dev);
+               if (!ret)
+                       ret = fsi_stream_transfer(io);
+               if (!ret)
                        fsi_stream_start(fsi, io);
                break;
        case SNDRV_PCM_TRIGGER_STOP:
-               fsi_hw_shutdown(fsi, dai->dev);
+               if (!ret)
+                       ret = fsi_hw_shutdown(fsi, dai->dev);
                fsi_stream_stop(fsi, io);
                fsi_stream_quit(fsi, io);
                break;
@@ -1437,9 +1795,25 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
                return -EINVAL;
        }
 
-       if (fsi_is_clk_master(fsi) && !set_rate) {
-               dev_err(dai->dev, "platform doesn't have set_rate\n");
-               return -EINVAL;
+       if (fsi_is_clk_master(fsi)) {
+               /*
+                * CAUTION
+                *
+                * set_rate will be deleted
+                */
+               if (set_rate)
+                       dev_warn(dai->dev, "set_rate will be removed soon\n");
+
+               switch (flags & SH_FSI_CLK_MASK) {
+               case SH_FSI_CLK_EXTERNAL:
+                       fsi_clk_init(dai->dev, fsi, 1, 1, 0,
+                                    fsi_clk_set_rate_external);
+                       break;
+               case SH_FSI_CLK_CPG:
+                       fsi_clk_init(dai->dev, fsi, 0, 1, 1,
+                                    fsi_clk_set_rate_cpg);
+                       break;
+               }
        }
 
        /* set format */
@@ -1462,19 +1836,13 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream,
                             struct snd_soc_dai *dai)
 {
        struct fsi_priv *fsi = fsi_get_priv(substream);
-       long rate = params_rate(params);
-       int ret;
-
-       if (!fsi_is_clk_master(fsi))
-               return 0;
 
-       ret = fsi_set_master_clk(dai->dev, fsi, rate, 1);
-       if (ret < 0)
-               return ret;
-
-       fsi->rate = rate;
+       if (fsi_is_clk_master(fsi)) {
+               fsi->rate = params_rate(params);
+               fsi_clk_valid(fsi, fsi->rate);
+       }
 
-       return ret;
+       return 0;
 }
 
 static const struct snd_soc_dai_ops fsi_dai_ops = {
@@ -1498,7 +1866,7 @@ static struct snd_pcm_hardware fsi_pcm_hardware = {
        .rates                  = FSI_RATES,
        .rate_min               = 8000,
        .rate_max               = 192000,
-       .channels_min           = 1,
+       .channels_min           = 2,
        .channels_max           = 2,
        .buffer_bytes_max       = 64 * 1024,
        .period_bytes_min       = 32,
@@ -1586,14 +1954,14 @@ static struct snd_soc_dai_driver fsi_soc_dai[] = {
                .playback = {
                        .rates          = FSI_RATES,
                        .formats        = FSI_FMTS,
-                       .channels_min   = 1,
-                       .channels_max   = 8,
+                       .channels_min   = 2,
+                       .channels_max   = 2,
                },
                .capture = {
                        .rates          = FSI_RATES,
                        .formats        = FSI_FMTS,
-                       .channels_min   = 1,
-                       .channels_max   = 8,
+                       .channels_min   = 2,
+                       .channels_max   = 2,
                },
                .ops = &fsi_dai_ops,
        },
@@ -1602,14 +1970,14 @@ static struct snd_soc_dai_driver fsi_soc_dai[] = {
                .playback = {
                        .rates          = FSI_RATES,
                        .formats        = FSI_FMTS,
-                       .channels_min   = 1,
-                       .channels_max   = 8,
+                       .channels_min   = 2,
+                       .channels_max   = 2,
                },
                .capture = {
                        .rates          = FSI_RATES,
                        .formats        = FSI_FMTS,
-                       .channels_min   = 1,
-                       .channels_max   = 8,
+                       .channels_min   = 2,
+                       .channels_max   = 2,
                },
                .ops = &fsi_dai_ops,
        },
@@ -1702,7 +2070,7 @@ static int fsi_probe(struct platform_device *pdev)
        pm_runtime_enable(&pdev->dev);
        dev_set_drvdata(&pdev->dev, master);
 
-       ret = request_irq(irq, &fsi_interrupt, 0,
+       ret = devm_request_irq(&pdev->dev, irq, &fsi_interrupt, 0,
                          id_entry->name, master);
        if (ret) {
                dev_err(&pdev->dev, "irq request err\n");
@@ -1712,7 +2080,7 @@ static int fsi_probe(struct platform_device *pdev)
        ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform);
        if (ret < 0) {
                dev_err(&pdev->dev, "cannot snd soc register\n");
-               goto exit_free_irq;
+               goto exit_fsib;
        }
 
        ret = snd_soc_register_dais(&pdev->dev, fsi_soc_dai,
@@ -1726,8 +2094,6 @@ static int fsi_probe(struct platform_device *pdev)
 
 exit_snd_soc:
        snd_soc_unregister_platform(&pdev->dev);
-exit_free_irq:
-       free_irq(irq, master);
 exit_fsib:
        pm_runtime_disable(&pdev->dev);
        fsi_stream_remove(&master->fsib);
@@ -1743,7 +2109,6 @@ static int fsi_remove(struct platform_device *pdev)
 
        master = dev_get_drvdata(&pdev->dev);
 
-       free_irq(master->irq, master);
        pm_runtime_disable(&pdev->dev);
 
        snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai));
@@ -1774,10 +2139,6 @@ static void __fsi_resume(struct fsi_priv *fsi,
                return;
 
        fsi_hw_startup(fsi, io, dev);
-
-       if (fsi_is_clk_master(fsi) && fsi->rate)
-               fsi_set_master_clk(dev, fsi, fsi->rate, 1);
-
        fsi_stream_start(fsi, io);
 }
 
index 1ab5fe04bfccb066853fc664d9db9bea68a9f8ce..e41e14c9565e76bf39f7bcdb99fd51561641dc54 100644 (file)
@@ -66,7 +66,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
        struct snd_soc_dapm_context *dapm;
        struct snd_soc_jack_pin *pin;
        int enable;
-       int oldstatus;
 
        trace_snd_soc_jack_report(jack, mask, status);
 
@@ -78,8 +77,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
 
        mutex_lock(&jack->mutex);
 
-       oldstatus = jack->status;
-
        jack->status &= ~mask;
        jack->status |= status & mask;
 
index 356611d9654db90e1f0206995de6b7064b83bdf9..54f7e25b6f7d479d30bed372ba5d12ce1abacb22 100644 (file)
@@ -57,6 +57,20 @@ static struct snd_soc_card mop500_card = {
        .num_links = ARRAY_SIZE(mop500_dai_links),
 };
 
+static void mop500_of_node_put(void)
+{
+       int i;
+
+       for (i = 0; i < 2; i++) {
+               if (mop500_dai_links[i].cpu_of_node)
+                       of_node_put((struct device_node *)
+                               mop500_dai_links[i].cpu_of_node);
+               if (mop500_dai_links[i].codec_of_node)
+                       of_node_put((struct device_node *)
+                               mop500_dai_links[i].codec_of_node);
+       }
+}
+
 static int __devinit mop500_of_probe(struct platform_device *pdev,
                                struct device_node *np)
 {
@@ -69,6 +83,7 @@ static int __devinit mop500_of_probe(struct platform_device *pdev,
 
        if (!(msp_np[0] && msp_np[1] && codec_np)) {
                dev_err(&pdev->dev, "Phandle missing or invalid\n");
+               mop500_of_node_put();
                return -EINVAL;
        }
 
@@ -83,6 +98,7 @@ static int __devinit mop500_of_probe(struct platform_device *pdev,
 
        return 0;
 }
+
 static int __devinit mop500_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -128,6 +144,7 @@ static int __devexit mop500_remove(struct platform_device *pdev)
 
        snd_soc_unregister_card(mop500_card);
        mop500_ab8500_remove(mop500_card);
+       mop500_of_node_put();
 
        return 0;
 }
index b7c996e77570bd527a0a92fd904276a40c44cd2b..a26c6bf0a29b2ad570050519b7e6c87e418e62a5 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <linux/of.h>
 
 #include <mach/hardware.h>
@@ -697,14 +698,11 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
                        platform_data = devm_kzalloc(&pdev->dev,
                                sizeof(struct msp_i2s_platform_data), GFP_KERNEL);
                        if (!platform_data)
-                               ret = -ENOMEM;
+                               return -ENOMEM;
                }
        } else
                if (!platform_data)
-                       ret = -EINVAL;
-
-       if (ret)
-               goto err_res;
+                       return -EINVAL;
 
        dev_dbg(&pdev->dev, "%s: Enter (name: %s, id: %d).\n", __func__,
                pdev->name, platform_data->id);
index 561bb74fd364ae388cb8dc2af548e014b0bb801b..282f0fc9fed1ef768bffc7f457b38de5dd39a429 100644 (file)
@@ -339,7 +339,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
        }
 
        mutex_init(&chip->mutex);
-       mutex_init(&chip->shutdown_mutex);
+       init_rwsem(&chip->shutdown_rwsem);
        chip->index = idx;
        chip->dev = dev;
        chip->card = card;
@@ -560,7 +560,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
 
        card = chip->card;
        mutex_lock(&register_mutex);
-       mutex_lock(&chip->shutdown_mutex);
+       down_write(&chip->shutdown_rwsem);
        chip->shutdown = 1;
        chip->num_interfaces--;
        if (chip->num_interfaces <= 0) {
@@ -582,11 +582,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
                        snd_usb_mixer_disconnect(p);
                }
                usb_chip[chip->index] = NULL;
-               mutex_unlock(&chip->shutdown_mutex);
+               up_write(&chip->shutdown_rwsem);
                mutex_unlock(&register_mutex);
                snd_card_free_when_closed(card);
        } else {
-               mutex_unlock(&chip->shutdown_mutex);
+               up_write(&chip->shutdown_rwsem);
                mutex_unlock(&register_mutex);
        }
 }
@@ -618,16 +618,20 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)
 {
        int err = -ENODEV;
 
+       down_read(&chip->shutdown_rwsem);
        if (!chip->shutdown && !chip->probing)
                err = usb_autopm_get_interface(chip->pm_intf);
+       up_read(&chip->shutdown_rwsem);
 
        return err;
 }
 
 void snd_usb_autosuspend(struct snd_usb_audio *chip)
 {
+       down_read(&chip->shutdown_rwsem);
        if (!chip->shutdown && !chip->probing)
                usb_autopm_put_interface(chip->pm_intf);
+       up_read(&chip->shutdown_rwsem);
 }
 
 static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
index afa4f9e9b27a2673b1fc955d680859cb7f964f02..814cb357ff88235dd87f37425985602867e3f5d5 100644 (file)
@@ -126,6 +126,7 @@ struct snd_usb_substream {
        struct snd_usb_endpoint *sync_endpoint;
        unsigned long flags;
        bool need_setup_ep;             /* (re)configure EP at prepare? */
+       unsigned int speed;             /* USB_SPEED_XXX */
 
        u64 formats;                    /* format bitmasks (all or'ed) */
        unsigned int num_formats;               /* number of supported audio formats (list) */
index fe56c9da38e9e6c78cdd6706f09e9639d8a502ab..298070e8f2d4e354da19dbca3e3d704a7b799321 100644 (file)
@@ -287,25 +287,32 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
        unsigned char buf[2];
        int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
        int timeout = 10;
-       int err;
+       int idx = 0, err;
 
        err = snd_usb_autoresume(cval->mixer->chip);
        if (err < 0)
                return -EIO;
+       down_read(&chip->shutdown_rwsem);
        while (timeout-- > 0) {
+               if (chip->shutdown)
+                       break;
+               idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
                if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,
                                    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                                   validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
-                                   buf, val_len) >= val_len) {
+                                   validx, idx, buf, val_len) >= val_len) {
                        *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
-                       snd_usb_autosuspend(cval->mixer->chip);
-                       return 0;
+                       err = 0;
+                       goto out;
                }
        }
-       snd_usb_autosuspend(cval->mixer->chip);
        snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
-                   request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
-       return -EINVAL;
+                   request, validx, idx, cval->val_type);
+       err = -EINVAL;
+
+ out:
+       up_read(&chip->shutdown_rwsem);
+       snd_usb_autosuspend(cval->mixer->chip);
+       return err;
 }
 
 static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
@@ -313,7 +320,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
        struct snd_usb_audio *chip = cval->mixer->chip;
        unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */
        unsigned char *val;
-       int ret, size;
+       int idx = 0, ret, size;
        __u8 bRequest;
 
        if (request == UAC_GET_CUR) {
@@ -330,16 +337,22 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
        if (ret)
                goto error;
 
-       ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
+       down_read(&chip->shutdown_rwsem);
+       if (chip->shutdown)
+               ret = -ENODEV;
+       else {
+               idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
+               ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
                              USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                             validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
-                             buf, size);
+                             validx, idx, buf, size);
+       }
+       up_read(&chip->shutdown_rwsem);
        snd_usb_autosuspend(chip);
 
        if (ret < 0) {
 error:
                snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
-                          request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
+                          request, validx, idx, cval->val_type);
                return ret;
        }
 
@@ -417,7 +430,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
 {
        struct snd_usb_audio *chip = cval->mixer->chip;
        unsigned char buf[2];
-       int val_len, err, timeout = 10;
+       int idx = 0, val_len, err, timeout = 10;
 
        if (cval->mixer->protocol == UAC_VERSION_1) {
                val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
@@ -440,19 +453,27 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
        err = snd_usb_autoresume(chip);
        if (err < 0)
                return -EIO;
-       while (timeout-- > 0)
+       down_read(&chip->shutdown_rwsem);
+       while (timeout-- > 0) {
+               if (chip->shutdown)
+                       break;
+               idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
                if (snd_usb_ctl_msg(chip->dev,
                                    usb_sndctrlpipe(chip->dev, 0), request,
                                    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-                                   validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
-                                   buf, val_len) >= 0) {
-                       snd_usb_autosuspend(chip);
-                       return 0;
+                                   validx, idx, buf, val_len) >= 0) {
+                       err = 0;
+                       goto out;
                }
-       snd_usb_autosuspend(chip);
+       }
        snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
-                   request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]);
-       return -EINVAL;
+                   request, validx, idx, cval->val_type, buf[0], buf[1]);
+       err = -EINVAL;
+
+ out:
+       up_read(&chip->shutdown_rwsem);
+       snd_usb_autosuspend(chip);
+       return err;
 }
 
 static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value)
index 690000db0ec01bb97e215f1b8470bd278a544ebd..ae2b7143522097bffd2a6060721d4f3db6b8000e 100644 (file)
@@ -283,6 +283,11 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
        if (value > 1)
                return -EINVAL;
        changed = value != mixer->audigy2nx_leds[index];
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown) {
+               err = -ENODEV;
+               goto out;
+       }
        if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042))
                err = snd_usb_ctl_msg(mixer->chip->dev,
                              usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
@@ -299,6 +304,8 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
                              usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
                              value, index + 2, NULL, 0);
+ out:
+       up_read(&mixer->chip->shutdown_rwsem);
        if (err < 0)
                return err;
        mixer->audigy2nx_leds[index] = value;
@@ -392,11 +399,16 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
 
        for (i = 0; jacks[i].name; ++i) {
                snd_iprintf(buffer, "%s: ", jacks[i].name);
-               err = snd_usb_ctl_msg(mixer->chip->dev,
+               down_read(&mixer->chip->shutdown_rwsem);
+               if (mixer->chip->shutdown)
+                       err = 0;
+               else
+                       err = snd_usb_ctl_msg(mixer->chip->dev,
                                      usb_rcvctrlpipe(mixer->chip->dev, 0),
                                      UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS |
                                      USB_RECIP_INTERFACE, 0,
                                      jacks[i].unitid << 8, buf, 3);
+               up_read(&mixer->chip->shutdown_rwsem);
                if (err == 3 && (buf[0] == 3 || buf[0] == 6))
                        snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]);
                else
@@ -426,10 +438,15 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol,
        else
                new_status = old_status & ~0x02;
        changed = new_status != old_status;
-       err = snd_usb_ctl_msg(mixer->chip->dev,
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown)
+               err = -ENODEV;
+       else
+               err = snd_usb_ctl_msg(mixer->chip->dev,
                              usb_sndctrlpipe(mixer->chip->dev, 0), 0x08,
                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
                              50, 0, &new_status, 1);
+       up_read(&mixer->chip->shutdown_rwsem);
        if (err < 0)
                return err;
        mixer->xonar_u1_status = new_status;
@@ -468,11 +485,17 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol,
        u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
        u16 wIndex = kcontrol->private_value & 0xffff;
        u8 tmp;
+       int ret;
 
-       int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown)
+               ret = -ENODEV;
+       else
+               ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
                                  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
                                  0, cpu_to_le16(wIndex),
                                  &tmp, sizeof(tmp), 1000);
+       up_read(&mixer->chip->shutdown_rwsem);
 
        if (ret < 0) {
                snd_printk(KERN_ERR
@@ -493,11 +516,17 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,
        u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
        u16 wIndex = kcontrol->private_value & 0xffff;
        u16 wValue = ucontrol->value.integer.value[0];
+       int ret;
 
-       int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown)
+               ret = -ENODEV;
+       else
+               ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,
                                  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
                                  cpu_to_le16(wValue), cpu_to_le16(wIndex),
                                  NULL, 0, 1000);
+       up_read(&mixer->chip->shutdown_rwsem);
 
        if (ret < 0) {
                snd_printk(KERN_ERR
@@ -656,11 +685,16 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl,
                return -EINVAL;
 
 
-       err = snd_usb_ctl_msg(chip->dev,
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown)
+               err = -ENODEV;
+       else
+               err = snd_usb_ctl_msg(chip->dev,
                        usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,
                        USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
                        validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
                        value, val_len);
+       up_read(&mixer->chip->shutdown_rwsem);
        if (err < 0)
                return err;
 
@@ -703,11 +737,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
 
        if (!pval->is_cached) {
                /* Read current value */
-               err = snd_usb_ctl_msg(chip->dev,
+               down_read(&mixer->chip->shutdown_rwsem);
+               if (mixer->chip->shutdown)
+                       err = -ENODEV;
+               else
+                       err = snd_usb_ctl_msg(chip->dev,
                                usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,
                                USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
                                validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
                                value, val_len);
+               up_read(&mixer->chip->shutdown_rwsem);
                if (err < 0)
                        return err;
 
@@ -719,11 +758,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
        if (cur_val != new_val) {
                value[0] = new_val;
                value[1] = 0;
-               err = snd_usb_ctl_msg(chip->dev,
+               down_read(&mixer->chip->shutdown_rwsem);
+               if (mixer->chip->shutdown)
+                       err = -ENODEV;
+               else
+                       err = snd_usb_ctl_msg(chip->dev,
                                usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR,
                                USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
                                validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
                                value, val_len);
+               up_read(&mixer->chip->shutdown_rwsem);
                if (err < 0)
                        return err;
 
index 55e19e1b80ec4eeb282c91cea482ef7434cf8dce..37428f74dbb69f90ae5e9cc580f3d2a9f81811e8 100644 (file)
@@ -71,6 +71,8 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
        unsigned int hwptr_done;
 
        subs = (struct snd_usb_substream *)substream->runtime->private_data;
+       if (subs->stream->chip->shutdown)
+               return SNDRV_PCM_POS_XRUN;
        spin_lock(&subs->lock);
        hwptr_done = subs->hwptr_done;
        substream->runtime->delay = snd_usb_pcm_delay(subs,
@@ -444,7 +446,6 @@ static int configure_endpoint(struct snd_usb_substream *subs)
 {
        int ret;
 
-       mutex_lock(&subs->stream->chip->shutdown_mutex);
        /* format changed */
        stop_endpoints(subs, 0, 0, 0);
        ret = snd_usb_endpoint_set_params(subs->data_endpoint,
@@ -455,7 +456,7 @@ static int configure_endpoint(struct snd_usb_substream *subs)
                                          subs->cur_audiofmt,
                                          subs->sync_endpoint);
        if (ret < 0)
-               goto unlock;
+               return ret;
 
        if (subs->sync_endpoint)
                ret = snd_usb_endpoint_set_params(subs->data_endpoint,
@@ -465,9 +466,6 @@ static int configure_endpoint(struct snd_usb_substream *subs)
                                                  subs->cur_rate,
                                                  subs->cur_audiofmt,
                                                  NULL);
-
-unlock:
-       mutex_unlock(&subs->stream->chip->shutdown_mutex);
        return ret;
 }
 
@@ -505,7 +503,13 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       if ((ret = set_format(subs, fmt)) < 0)
+       down_read(&subs->stream->chip->shutdown_rwsem);
+       if (subs->stream->chip->shutdown)
+               ret = -ENODEV;
+       else
+               ret = set_format(subs, fmt);
+       up_read(&subs->stream->chip->shutdown_rwsem);
+       if (ret < 0)
                return ret;
 
        subs->interface = fmt->iface;
@@ -527,10 +531,12 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
        subs->cur_audiofmt = NULL;
        subs->cur_rate = 0;
        subs->period_bytes = 0;
-       mutex_lock(&subs->stream->chip->shutdown_mutex);
-       stop_endpoints(subs, 0, 1, 1);
-       deactivate_endpoints(subs);
-       mutex_unlock(&subs->stream->chip->shutdown_mutex);
+       down_read(&subs->stream->chip->shutdown_rwsem);
+       if (!subs->stream->chip->shutdown) {
+               stop_endpoints(subs, 0, 1, 1);
+               deactivate_endpoints(subs);
+       }
+       up_read(&subs->stream->chip->shutdown_rwsem);
        return snd_pcm_lib_free_vmalloc_buffer(substream);
 }
 
@@ -552,12 +558,19 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
                return -ENXIO;
        }
 
-       if (snd_BUG_ON(!subs->data_endpoint))
-               return -EIO;
+       down_read(&subs->stream->chip->shutdown_rwsem);
+       if (subs->stream->chip->shutdown) {
+               ret = -ENODEV;
+               goto unlock;
+       }
+       if (snd_BUG_ON(!subs->data_endpoint)) {
+               ret = -EIO;
+               goto unlock;
+       }
 
        ret = set_format(subs, subs->cur_audiofmt);
        if (ret < 0)
-               return ret;
+               goto unlock;
 
        iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface);
        alts = &iface->altsetting[subs->cur_audiofmt->altset_idx];
@@ -567,12 +580,12 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
                                       subs->cur_audiofmt,
                                       subs->cur_rate);
        if (ret < 0)
-               return ret;
+               goto unlock;
 
        if (subs->need_setup_ep) {
                ret = configure_endpoint(subs);
                if (ret < 0)
-                       return ret;
+                       goto unlock;
                subs->need_setup_ep = false;
        }
 
@@ -592,9 +605,11 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
        /* for playback, submit the URBs now; otherwise, the first hwptr_done
         * updates for all URBs would happen at the same time when starting */
        if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
-               return start_endpoints(subs, 1);
+               ret = start_endpoints(subs, 1);
 
-       return 0;
+ unlock:
+       up_read(&subs->stream->chip->shutdown_rwsem);
+       return ret;
 }
 
 static struct snd_pcm_hardware snd_usb_hardware =
@@ -647,7 +662,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs,
                return 0;
        }
        /* check whether the period time is >= the data packet interval */
-       if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) {
+       if (subs->speed != USB_SPEED_FULL) {
                ptime = 125 * (1 << fp->datainterval);
                if (ptime > pt->max || (ptime == pt->max && pt->openmax)) {
                        hwc_debug("   > check: ptime %u > max %u\n", ptime, pt->max);
@@ -925,7 +940,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
                return err;
 
        param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
-       if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
+       if (subs->speed == USB_SPEED_FULL)
                /* full speed devices have fixed data packet interval */
                ptmin = 1000;
        if (ptmin == 1000)
index ebc1a5b5b3f1ba79c4c25ea66aadd34fd053e6d6..d218f763501fcdb9c4d038826a4bb12b14e4197b 100644 (file)
@@ -108,7 +108,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
                        }
                        snd_iprintf(buffer, "\n");
                }
-               if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
+               if (subs->speed != USB_SPEED_FULL)
                        snd_iprintf(buffer, "    Data packet interval: %d us\n",
                                    125 * (1 << fp->datainterval));
                // snd_iprintf(buffer, "    Max Packet Size = %d\n", fp->maxpacksize);
@@ -124,7 +124,7 @@ static void proc_dump_ep_status(struct snd_usb_substream *subs,
                return;
        snd_iprintf(buffer, "    Packet Size = %d\n", ep->curpacksize);
        snd_iprintf(buffer, "    Momentary freq = %u Hz (%#x.%04x)\n",
-                   snd_usb_get_speed(subs->dev) == USB_SPEED_FULL
+                   subs->speed == USB_SPEED_FULL
                    ? get_full_speed_hz(ep->freqm)
                    : get_high_speed_hz(ep->freqm),
                    ep->freqm >> 16, ep->freqm & 0xffff);
index 083ed81160e58b094ee8f4fca637371aa5b5fff4..1de0c8c002a8a2d35bc80e7de9a9c764a5945fc2 100644 (file)
@@ -90,6 +90,7 @@ static void snd_usb_init_substream(struct snd_usb_stream *as,
        subs->direction = stream;
        subs->dev = as->chip->dev;
        subs->txfr_quirk = as->chip->txfr_quirk;
+       subs->speed = snd_usb_get_speed(subs->dev);
 
        snd_usb_set_pcm_ops(as->pcm, stream);
 
index b8233ebe250f88648cc0baf2f6cfcfd13aa6de8f..ef42797f56fb56adf950eef3b764c5533263a8d9 100644 (file)
@@ -37,7 +37,7 @@ struct snd_usb_audio {
        struct usb_interface *pm_intf;
        u32 usb_id;
        struct mutex mutex;
-       struct mutex shutdown_mutex;
+       struct rw_semaphore shutdown_rwsem;
        unsigned int shutdown:1;
        unsigned int probing:1;
        unsigned int autosuspended:1;   
index 411ee5664e98e1e765bf992f379c16ec30569585..178b88ae3d2f174a5a085f233163d54cef152337 100644 (file)
@@ -414,7 +414,7 @@ static int show_html_page(const char *perf_cmd)
 int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
 {
        bool show_all = false;
-       enum help_format help_format = HELP_FORMAT_NONE;
+       enum help_format help_format = HELP_FORMAT_MAN;
        struct option builtin_help_options[] = {
        OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
        OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
index dec8ced61fb00c2bc7114346db3edaf0f7dd89b7..7aaee39f6774f1fc49131dd7a3d67f002bee823c 100644 (file)
@@ -56,6 +56,10 @@ static int trace__read_syscall_info(struct trace *trace, int id)
 {
        char tp_name[128];
        struct syscall *sc;
+       const char *name = audit_syscall_to_name(id, trace->audit_machine);
+
+       if (name == NULL)
+               return -1;
 
        if (id > trace->syscalls.max) {
                struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
@@ -75,11 +79,8 @@ static int trace__read_syscall_info(struct trace *trace, int id)
        }
 
        sc = trace->syscalls.table + id;
-       sc->name = audit_syscall_to_name(id, trace->audit_machine);
-       if (sc->name == NULL)
-               return -1;
-
-       sc->fmt = syscall_fmt__find(sc->name);
+       sc->name = name;
+       sc->fmt  = syscall_fmt__find(sc->name);
 
        snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
        sc->tp_format = event_format__new("syscalls", tp_name);
@@ -267,6 +268,13 @@ again:
                        if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1)
                                printf("%d ", sample.tid);
 
+                       if (sample.raw_data == NULL) {
+                               printf("%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
+                                      perf_evsel__name(evsel), sample.tid,
+                                      sample.cpu, sample.raw_size);
+                               continue;
+                       }
+
                        handler = evsel->handler.func;
                        handler(trace, evsel, &sample);
                }
index 28c18d1d52c3efceeb2847a1b68bd3dd000d45b6..516ecd9ddd6ee275c1e3144abc8a3d091b6114bb 100644 (file)
@@ -513,7 +513,8 @@ static int test__group1(struct perf_evlist *evlist)
        TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
-       TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+       /* use of precise requires exclude_guest */
+       TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
        TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
        TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
@@ -599,7 +600,8 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
        TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
        TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
-       TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+       /* use of precise requires exclude_guest */
+       TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
        TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3);
        TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
@@ -662,7 +664,8 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
        TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
-       TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+       /* use of precise requires exclude_guest */
+       TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
        TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1);
        TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
@@ -676,7 +679,8 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
        TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
        TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
-       TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+       /* use of precise requires exclude_guest */
+       TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
        TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
        TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
index fb4b7ea6752fd86121a968fa77212727f603d7e9..8b3e5939afb6ea00ef6cd74275eae99f35de0c25 100644 (file)
@@ -39,7 +39,6 @@ int thread__set_comm(struct thread *self, const char *comm)
        err = self->comm == NULL ? -ENOMEM : 0;
        if (!err) {
                self->comm_set = true;
-               map_groups__flush(&self->mg);
        }
        return err;
 }
index b51d787176d323bb3a2d6f0016b2d2cf4db16d3d..c7ba7614061b22f04d78b5d60e3669dd8767fbed 100755 (executable)
@@ -1740,8 +1740,10 @@ sub install {
     open(IN, "$output_config") or dodie("Can't read config file");
     while (<IN>) {
        if (/CONFIG_MODULES(=y)?/) {
-           $install_mods = 1 if (defined($1));
-           last;
+           if (defined($1)) {
+               $install_mods = 1;
+               last;
+           }
        }
     }
     close(IN);
index e0fcff1e833107c8e91e35866e94fd847a300242..f7525392ce84f58e9668187bb3708869d5b7c35d 100644 (file)
@@ -162,14 +162,14 @@ void *write_thread_function(void *function_data)
        int index;
        struct write_thread_data *thread_data =
                (struct write_thread_data *)function_data;
-       while (!write_thread_data->stop)
+       while (!thread_data->stop)
                for (index = 0;
                     !thread_data->stop && (index < thread_data->n_fds);
                     ++index)
                        if ((write(thread_data->fds[index], &data, 1) < 1) &&
                                (errno != EAGAIN) &&
                                (errno != EWOULDBLOCK)) {
-                               write_thread_data->status = errno;
+                               thread_data->status = errno;
                                return;
                        }
 }
index cd1b03e80899960147c9fc18777a1f5a35f9e08f..b76edf2f833349c8762c95ec4fc20d36f44c73f0 100644 (file)
@@ -35,7 +35,7 @@
 #include <sys/mount.h>
 #include <sys/statfs.h>
 #include "../../include/uapi/linux/magic.h"
-#include "../../include/linux/kernel-page-flags.h"
+#include "../../include/uapi/linux/kernel-page-flags.h"
 
 
 #ifndef MAX_PATH
index af0f22fb1ef71e6dc94c620873bc3241c2883430..aca6edcbbc6fa09113389e87b3e76a55a871da98 100644 (file)
@@ -303,7 +303,7 @@ static int cpio_mkfile(const char *name, const char *location,
        int retval;
        int rc = -1;
        int namesize;
-       int i;
+       unsigned int i;
 
        mode |= S_IFREG;
 
@@ -381,25 +381,28 @@ error:
 
 static char *cpio_replace_env(char *new_location)
 {
-       char expanded[PATH_MAX + 1];
-       char env_var[PATH_MAX + 1];
-       char *start;
-       char *end;
-
-       for (start = NULL; (start = strstr(new_location, "${")); ) {
-               end = strchr(start, '}');
-               if (start < end) {
-                       *env_var = *expanded = '\0';
-                       strncat(env_var, start + 2, end - start - 2);
-                       strncat(expanded, new_location, start - new_location);
-                       strncat(expanded, getenv(env_var), PATH_MAX);
-                       strncat(expanded, end + 1, PATH_MAX);
-                       strncpy(new_location, expanded, PATH_MAX);
-               } else
-                       break;
-       }
-
-       return new_location;
+       char expanded[PATH_MAX + 1];
+       char env_var[PATH_MAX + 1];
+       char *start;
+       char *end;
+
+       for (start = NULL; (start = strstr(new_location, "${")); ) {
+               end = strchr(start, '}');
+               if (start < end) {
+                       *env_var = *expanded = '\0';
+                       strncat(env_var, start + 2, end - start - 2);
+                       strncat(expanded, new_location, start - new_location);
+                       strncat(expanded, getenv(env_var),
+                               PATH_MAX - strlen(expanded));
+                       strncat(expanded, end + 1,
+                               PATH_MAX - strlen(expanded));
+                       strncpy(new_location, expanded, PATH_MAX);
+                       new_location[PATH_MAX] = 0;
+               } else
+                       break;
+       }
+
+       return new_location;
 }
 
 
index e59bb63cb089634c7d9bed701be0581bf536726a..be70035fd42a14edad4c24ae411c4b9d3fdf396c 100644 (file)
@@ -1322,9 +1322,7 @@ EXPORT_SYMBOL_GPL(kvm_release_page_clean);
 
 void kvm_release_pfn_clean(pfn_t pfn)
 {
-       WARN_ON(is_error_pfn(pfn));
-
-       if (!kvm_is_mmio_pfn(pfn))
+       if (!is_error_pfn(pfn) && !kvm_is_mmio_pfn(pfn))
                put_page(pfn_to_page(pfn));
 }
 EXPORT_SYMBOL_GPL(kvm_release_pfn_clean);