Merge tag 'dm-3.17-fix2' of git://git.kernel.org/pub/scm/linux/kernel/git/device...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Sep 2014 17:04:10 +0000 (10:04 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Sep 2014 17:04:10 +0000 (10:04 -0700)
Pull device mapper fix from Mike Snitzer:
 "Fix a race in the DM cache target that caused dirty blocks to be
  marked as clean.  This could cause no writeback to occur or spurious
  dirty block counts"

* tag 'dm-3.17-fix2' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
  dm cache: fix race causing dirty blocks to be marked as clean

812 files changed:
Documentation/SubmittingPatches
Documentation/devicetree/bindings/dma/rcar-audmapp.txt
Documentation/devicetree/bindings/input/atmel,maxtouch.txt
Documentation/devicetree/bindings/mfd/tc3589x.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mtd/gpmc-nand.txt
Documentation/devicetree/bindings/net/stmmac.txt
Documentation/devicetree/bindings/pinctrl/qcom,apq8064-pinctrl.txt
Documentation/devicetree/bindings/regulator/tps65090.txt
Documentation/devicetree/bindings/sound/adi,axi-spdif-tx.txt
Documentation/devicetree/bindings/usb/mxs-phy.txt
Documentation/devicetree/bindings/video/analog-tv-connector.txt
Documentation/dma-buf-sharing.txt
Documentation/filesystems/nfs/nfs-rdma.txt
Documentation/filesystems/seq_file.txt
Documentation/gpio/consumer.txt
Documentation/i2c/dev-interface
Documentation/kdump/kdump.txt
Documentation/kernel-parameters.txt
Documentation/misc-devices/lis3lv02d
Documentation/power/regulator/consumer.txt
Documentation/power/regulator/design.txt
Documentation/power/regulator/machine.txt
Documentation/power/regulator/overview.txt
Documentation/power/regulator/regulator.txt
Documentation/this_cpu_ops.txt
MAINTAINERS
Makefile
arch/alpha/include/asm/io.h
arch/alpha/include/asm/unistd.h
arch/alpha/include/uapi/asm/unistd.h
arch/alpha/kernel/systbls.S
arch/arc/mm/cache_arc700.c
arch/arm/Kconfig
arch/arm/boot/dts/am4372.dtsi
arch/arm/boot/dts/am437x-gp-evm.dts
arch/arm/boot/dts/am43x-epos-evm.dts
arch/arm/boot/dts/at91rm9200.dtsi
arch/arm/boot/dts/at91sam9g20.dtsi
arch/arm/boot/dts/dra7-evm.dts
arch/arm/boot/dts/dra7.dtsi
arch/arm/boot/dts/imx53-qsrb.dts
arch/arm/boot/dts/imx6dl-hummingboard.dts
arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
arch/arm/boot/dts/imx6qdl-microsom-ar8035.dtsi
arch/arm/boot/dts/omap3-beagle.dts
arch/arm/boot/dts/omap3-n900.dts
arch/arm/boot/dts/omap3430-sdp.dts
arch/arm/boot/dts/omap3xxx-clocks.dtsi
arch/arm/boot/dts/omap54xx-clocks.dtsi
arch/arm/boot/dts/ste-snowball.dts
arch/arm/boot/dts/twl6030.dtsi
arch/arm/common/edma.c
arch/arm/include/asm/cacheflush.h
arch/arm/include/asm/cputype.h
arch/arm/include/asm/elf.h
arch/arm/include/asm/smp_plat.h
arch/arm/include/asm/xen/page-coherent.h
arch/arm/include/asm/xen/page.h
arch/arm/kernel/entry-header.S
arch/arm/kernel/module.c
arch/arm/kvm/handle_exit.c
arch/arm/kvm/init.S
arch/arm/mach-at91/board-dt-rm9200.c
arch/arm/mach-bcm/Makefile
arch/arm/mach-bcm/brcmstb.h [deleted file]
arch/arm/mach-bcm/headsmp-brcmstb.S [deleted file]
arch/arm/mach-bcm/platsmp-brcmstb.c [deleted file]
arch/arm/mach-exynos/mcpm-exynos.c
arch/arm/mach-omap2/board-flash.c
arch/arm/mach-omap2/gpmc-nand.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/id.c
arch/arm/mach-omap2/omap_device.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_7xx_data.c
arch/arm/mach-omap2/soc.h
arch/arm/mach-shmobile/clock-r8a7790.c
arch/arm/mach-shmobile/clock-r8a7791.c
arch/arm/mach-shmobile/clock-sh73a0.c
arch/arm/mach-vexpress/spc.c
arch/arm/mm/abort-ev6.S
arch/arm/mm/abort-ev7.S
arch/arm/xen/Makefile
arch/arm/xen/enlighten.c
arch/arm/xen/mm32.c [new file with mode: 0644]
arch/arm/xen/p2m.c
arch/arm64/crypto/sha2-ce-glue.c
arch/arm64/include/asm/hw_breakpoint.h
arch/arm64/include/asm/processor.h
arch/arm64/include/asm/ptrace.h
arch/arm64/kernel/fpsimd.c
arch/arm64/kernel/head.S
arch/arm64/kernel/irq.c
arch/arm64/kernel/perf_regs.c
arch/arm64/kernel/process.c
arch/arm64/kernel/ptrace.c
arch/arm64/kernel/setup.c
arch/arm64/kernel/sys_compat.c
arch/arm64/kvm/handle_exit.c
arch/arm64/kvm/hyp-init.S
arch/hexagon/mm/cache.c
arch/ia64/Kconfig
arch/m68k/Kconfig
arch/m68k/include/asm/unistd.h
arch/m68k/include/uapi/asm/unistd.h
arch/m68k/kernel/syscalltable.S
arch/microblaze/Kconfig
arch/microblaze/include/asm/entry.h
arch/microblaze/include/asm/uaccess.h
arch/microblaze/include/asm/unistd.h
arch/mips/Kconfig
arch/powerpc/Kconfig
arch/powerpc/configs/cell_defconfig
arch/powerpc/configs/celleb_defconfig
arch/powerpc/configs/corenet64_smp_defconfig
arch/powerpc/configs/g5_defconfig
arch/powerpc/configs/maple_defconfig
arch/powerpc/configs/pasemi_defconfig
arch/powerpc/configs/ppc64_defconfig
arch/powerpc/configs/ppc64e_defconfig
arch/powerpc/configs/ps3_defconfig
arch/powerpc/configs/pseries_defconfig
arch/powerpc/configs/pseries_le_defconfig
arch/powerpc/include/asm/ptrace.h
arch/powerpc/include/asm/systbl.h
arch/powerpc/include/asm/unistd.h
arch/powerpc/include/uapi/asm/unistd.h
arch/powerpc/kvm/book3s_64_mmu_hv.c
arch/powerpc/perf/callchain.c
arch/powerpc/platforms/powernv/opal-hmi.c
arch/powerpc/platforms/pseries/hotplug-memory.c
arch/s390/Kconfig
arch/s390/include/asm/ipl.h
arch/s390/include/asm/pgtable.h
arch/s390/include/uapi/asm/unistd.h
arch/s390/kernel/compat_wrapper.c
arch/s390/kernel/ipl.c
arch/s390/kernel/setup.c
arch/s390/kernel/syscalls.S
arch/s390/kernel/vdso32/clock_gettime.S
arch/s390/kernel/vdso64/clock_gettime.S
arch/s390/kvm/kvm-s390.c
arch/s390/mm/pgtable.c
arch/sh/Kconfig
arch/sh/mm/cache.c
arch/sh/mm/gup.c
arch/tile/Kconfig
arch/tile/kernel/smp.c
arch/unicore32/kernel/signal.c
arch/x86/Kbuild
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/include/asm/io_apic.h
arch/x86/include/asm/pgtable.h
arch/x86/include/asm/pgtable_64.h
arch/x86/kernel/Makefile
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/crash.c
arch/x86/kernel/irqinit.c
arch/x86/kernel/machine_kexec_64.c
arch/x86/kernel/time.c
arch/x86/pci/intel_mid_pci.c
arch/x86/pci/irq.c
arch/x86/purgatory/Makefile
arch/x86/xen/mmu.c
arch/xtensa/Kconfig
arch/xtensa/Makefile
arch/xtensa/boot/dts/kc705.dts
arch/xtensa/configs/common_defconfig
arch/xtensa/configs/iss_defconfig
arch/xtensa/configs/s6105_defconfig
arch/xtensa/include/asm/cacheflush.h
arch/xtensa/include/asm/fixmap.h
arch/xtensa/include/asm/highmem.h
arch/xtensa/include/asm/page.h
arch/xtensa/include/asm/pgtable.h
arch/xtensa/include/asm/uaccess.h
arch/xtensa/include/uapi/asm/ioctls.h
arch/xtensa/include/uapi/asm/unistd.h
arch/xtensa/kernel/align.S
arch/xtensa/kernel/entry.S
arch/xtensa/kernel/pci-dma.c
arch/xtensa/kernel/smp.c
arch/xtensa/kernel/traps.c
arch/xtensa/kernel/vectors.S
arch/xtensa/kernel/vmlinux.lds.S
arch/xtensa/mm/cache.c
arch/xtensa/mm/highmem.c
arch/xtensa/mm/misc.S
arch/xtensa/mm/mmu.c
block/bio-integrity.c
block/blk-core.c
block/blk-merge.c
block/blk-mq.c
block/blk-sysfs.c
block/cfq-iosched.c
block/genhd.c
block/partition-generic.c
block/scsi_ioctl.c
crypto/asymmetric_keys/public_key.c
crypto/asymmetric_keys/verify_pefile.c
drivers/acpi/acpi_cmos_rtc.c
drivers/acpi/acpi_lpss.c
drivers/acpi/acpica/nsprepkg.c
drivers/acpi/battery.c
drivers/acpi/ec.c
drivers/acpi/pci_irq.c
drivers/acpi/processor_idle.c
drivers/acpi/scan.c
drivers/acpi/video.c
drivers/ata/ahci.c
drivers/ata/ahci_tegra.c
drivers/ata/ahci_xgene.c
drivers/ata/ata_piix.c
drivers/ata/pata_jmicron.c
drivers/base/regmap/internal.h
drivers/base/regmap/regcache-rbtree.c
drivers/base/regmap/regcache.c
drivers/base/regmap/regmap-debugfs.c
drivers/base/regmap/regmap.c
drivers/bcma/host_pci.c
drivers/block/brd.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/null_blk.c
drivers/block/rbd.c
drivers/block/xsysace.c
drivers/block/zram/zram_drv.c
drivers/block/zram/zram_drv.h
drivers/bus/arm-ccn.c
drivers/cpufreq/cpufreq_opp.c
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/s5pv210-cpufreq.c
drivers/cpuidle/cpuidle-big_little.c
drivers/dma-buf/fence.c
drivers/dma/dma-jz4740.c
drivers/gpio/gpio-bt8xx.c
drivers/gpu/drm/ast/ast_main.c
drivers/gpu/drm/ast/ast_tables.h
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_userptr.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_bios.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_panel.c
drivers/gpu/drm/i915/intel_ringbuffer.c
drivers/gpu/drm/i915/intel_tv.c
drivers/gpu/drm/msm/hdmi/hdmi.c
drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
drivers/gpu/drm/msm/msm_drv.c
drivers/gpu/drm/msm/msm_fbdev.c
drivers/gpu/drm/msm/msm_iommu.c
drivers/gpu/drm/nouveau/core/core/parent.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_semaphore.c
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/sti/Kconfig
drivers/gpu/drm/sti/sti_drm_drv.c
drivers/gpu/drm/sti/sti_hda.c
drivers/gpu/drm/sti/sti_hdmi.c
drivers/gpu/drm/sti/sti_tvout.c
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
drivers/hid/hid-logitech-dj.c
drivers/hid/hid-logitech-dj.h
drivers/hid/hid-magicmouse.c
drivers/hid/hid-picolcd_core.c
drivers/hwmon/ds1621.c
drivers/i2c/busses/i2c-at91.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-rcar.c
drivers/i2c/busses/i2c-rk3x.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx4/qp.c
drivers/input/input-mt.c
drivers/input/keyboard/cap1106.c
drivers/input/keyboard/matrix_keypad.c
drivers/input/mouse/alps.c
drivers/input/mouse/elantech.c
drivers/input/mouse/elantech.h
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics.h
drivers/input/mouse/synaptics_usb.c
drivers/input/mouse/trackpoint.c
drivers/input/serio/i8042-sparcio.h
drivers/input/serio/serport.c
drivers/input/touchscreen/atmel_mxt_ts.c
drivers/input/touchscreen/wm9712.c
drivers/input/touchscreen/wm9713.c
drivers/iommu/arm-smmu.c
drivers/iommu/dmar.c
drivers/iommu/fsl_pamu_domain.c
drivers/iommu/iommu.c
drivers/leds/led-class.c
drivers/leds/led-core.c
drivers/mfd/ab8500-core.c
drivers/mfd/htc-i2cpld.c
drivers/mfd/omap-usb-host.c
drivers/mfd/twl4030-power.c
drivers/misc/lattice-ecp3-config.c
drivers/misc/mei/client.c
drivers/misc/mei/nfc.c
drivers/mtd/chips/cfi_cmdset_0002.c
drivers/mtd/nand/omap2.c
drivers/net/ethernet/3com/3c59x.c
drivers/net/ethernet/aeroflex/greth.c
drivers/net/ethernet/aeroflex/greth.h
drivers/net/ethernet/amd/xgbe/xgbe-debugfs.c
drivers/net/ethernet/amd/xgbe/xgbe-dev.c
drivers/net/ethernet/amd/xgbe/xgbe-drv.c
drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
drivers/net/ethernet/amd/xgbe/xgbe-main.c
drivers/net/ethernet/amd/xgbe/xgbe.h
drivers/net/ethernet/apm/xgene/Kconfig
drivers/net/ethernet/broadcom/Kconfig
drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/cnic.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/broadcom/tg3.h
drivers/net/ethernet/brocade/bna/bnad.c
drivers/net/ethernet/calxeda/Kconfig
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h
drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
drivers/net/ethernet/ibm/ehea/ehea_main.c
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/i40evf/i40e_txrx.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/mcg.c
drivers/net/ethernet/moxa/moxart_ether.c
drivers/net/ethernet/nxp/lpc_eth.c
drivers/net/ethernet/qlogic/qlge/qlge_main.c
drivers/net/ethernet/renesas/Kconfig
drivers/net/ethernet/stmicro/stmmac/chain_mode.c
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
drivers/net/ethernet/stmicro/stmmac/mmc.h
drivers/net/ethernet/stmicro/stmmac/mmc_core.c
drivers/net/ethernet/stmicro/stmmac/ring_mode.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
drivers/net/fddi/skfp/h/skfbi.h
drivers/net/phy/phy.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vmxnet3/vmxnet3_int.h
drivers/net/vxlan.c
drivers/net/wireless/at76c50x-usb.c
drivers/net/wireless/ath/ath9k/spectral.c
drivers/net/wireless/iwlwifi/Kconfig
drivers/net/wireless/iwlwifi/dvm/rxon.c
drivers/net/wireless/iwlwifi/iwl-7000.c
drivers/net/wireless/iwlwifi/iwl-8000.c
drivers/net/wireless/rtlwifi/btcoexist/halbtcoutsrc.c
drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
drivers/net/xen-netback/interface.c
drivers/pci/host/Kconfig
drivers/phy/Kconfig
drivers/phy/phy-exynos5-usbdrd.c
drivers/phy/phy-twl4030-usb.c
drivers/pinctrl/nomadik/pinctrl-abx500.c
drivers/pinctrl/pinctrl-at91.c
drivers/pinctrl/pinctrl-baytrail.c
drivers/pinctrl/pinctrl-rockchip.c
drivers/pinctrl/pinctrl-tegra-xusb.c
drivers/pinctrl/samsung/pinctrl-exynos.c
drivers/pinctrl/samsung/pinctrl-samsung.h
drivers/pinctrl/sh-pfc/pfc-r8a7791.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/toshiba_acpi.c
drivers/powercap/intel_rapl.c
drivers/rtc/rtc-s5m.c
drivers/s390/block/dasd_devmap.c
drivers/s390/char/con3215.c
drivers/s390/char/sclp_tty.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_sys.c
drivers/scsi/scsi_lib.c
drivers/spi/spi-au1550.c
drivers/spi/spi-davinci.c
drivers/spi/spi-dw-pci.c
drivers/spi/spi-dw.c
drivers/spi/spi-omap2-mcspi.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-rockchip.c
drivers/spi/spi-rspi.c
drivers/spi/spi-sh-msiof.c
drivers/spi/spi.c
drivers/ssb/b43_pci_bridge.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/android/logger.c
drivers/staging/android/sync.c
drivers/staging/et131x/et131x.c
drivers/staging/imx-drm/imx-ldb.c
drivers/staging/imx-drm/ipuv3-plane.c
drivers/staging/lustre/lustre/libcfs/workitem.c
drivers/staging/lustre/lustre/obdclass/class_obd.c
drivers/staging/rtl8188eu/os_dep/usb_intf.c
drivers/staging/usbip/Kconfig [deleted file]
drivers/staging/usbip/Makefile [deleted file]
drivers/staging/usbip/README [deleted file]
drivers/staging/usbip/stub.h [deleted file]
drivers/staging/usbip/stub_dev.c [deleted file]
drivers/staging/usbip/stub_main.c [deleted file]
drivers/staging/usbip/stub_rx.c [deleted file]
drivers/staging/usbip/stub_tx.c [deleted file]
drivers/staging/usbip/uapi/usbip.h [deleted file]
drivers/staging/usbip/usbip_common.c [deleted file]
drivers/staging/usbip/usbip_common.h [deleted file]
drivers/staging/usbip/usbip_event.c [deleted file]
drivers/staging/usbip/usbip_protocol.txt [deleted file]
drivers/staging/usbip/userspace/.gitignore [deleted file]
drivers/staging/usbip/userspace/AUTHORS [deleted file]
drivers/staging/usbip/userspace/COPYING [deleted file]
drivers/staging/usbip/userspace/INSTALL [deleted file]
drivers/staging/usbip/userspace/Makefile.am [deleted file]
drivers/staging/usbip/userspace/README [deleted file]
drivers/staging/usbip/userspace/autogen.sh [deleted file]
drivers/staging/usbip/userspace/cleanup.sh [deleted file]
drivers/staging/usbip/userspace/configure.ac [deleted file]
drivers/staging/usbip/userspace/doc/usbip.8 [deleted file]
drivers/staging/usbip/userspace/doc/usbipd.8 [deleted file]
drivers/staging/usbip/userspace/libsrc/Makefile.am [deleted file]
drivers/staging/usbip/userspace/libsrc/list.h [deleted file]
drivers/staging/usbip/userspace/libsrc/names.c [deleted file]
drivers/staging/usbip/userspace/libsrc/names.h [deleted file]
drivers/staging/usbip/userspace/libsrc/sysfs_utils.c [deleted file]
drivers/staging/usbip/userspace/libsrc/sysfs_utils.h [deleted file]
drivers/staging/usbip/userspace/libsrc/usbip_common.c [deleted file]
drivers/staging/usbip/userspace/libsrc/usbip_common.h [deleted file]
drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c [deleted file]
drivers/staging/usbip/userspace/libsrc/usbip_host_driver.h [deleted file]
drivers/staging/usbip/userspace/libsrc/vhci_driver.c [deleted file]
drivers/staging/usbip/userspace/libsrc/vhci_driver.h [deleted file]
drivers/staging/usbip/userspace/src/Makefile.am [deleted file]
drivers/staging/usbip/userspace/src/usbip.c [deleted file]
drivers/staging/usbip/userspace/src/usbip.h [deleted file]
drivers/staging/usbip/userspace/src/usbip_attach.c [deleted file]
drivers/staging/usbip/userspace/src/usbip_bind.c [deleted file]
drivers/staging/usbip/userspace/src/usbip_detach.c [deleted file]
drivers/staging/usbip/userspace/src/usbip_list.c [deleted file]
drivers/staging/usbip/userspace/src/usbip_network.c [deleted file]
drivers/staging/usbip/userspace/src/usbip_network.h [deleted file]
drivers/staging/usbip/userspace/src/usbip_port.c [deleted file]
drivers/staging/usbip/userspace/src/usbip_unbind.c [deleted file]
drivers/staging/usbip/userspace/src/usbipd.c [deleted file]
drivers/staging/usbip/userspace/src/utils.c [deleted file]
drivers/staging/usbip/userspace/src/utils.h [deleted file]
drivers/staging/usbip/vhci.h [deleted file]
drivers/staging/usbip/vhci_hcd.c [deleted file]
drivers/staging/usbip/vhci_rx.c [deleted file]
drivers/staging/usbip/vhci_sysfs.c [deleted file]
drivers/staging/usbip/vhci_tx.c [deleted file]
drivers/thunderbolt/path.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/xilinx_uartps.c
drivers/usb/Kconfig
drivers/usb/Makefile
drivers/usb/chipidea/ci_hdrc_msm.c
drivers/usb/core/hub.c
drivers/usb/dwc2/gadget.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/dwc3-omap.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/Makefile
drivers/usb/gadget/function/Makefile
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/u_ether.c
drivers/usb/gadget/function/u_fs.h
drivers/usb/gadget/function/uvc_video.c
drivers/usb/gadget/legacy/Makefile
drivers/usb/gadget/legacy/dbgp.c
drivers/usb/gadget/legacy/inode.c
drivers/usb/gadget/udc/Kconfig
drivers/usb/gadget/udc/atmel_usba_udc.c
drivers/usb/gadget/udc/fusb300_udc.c
drivers/usb/gadget/udc/fusb300_udc.h
drivers/usb/gadget/udc/net2280.c
drivers/usb/gadget/udc/pch_udc.c
drivers/usb/gadget/udc/r8a66597-udc.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/misc/sisusbvga/sisusb.c
drivers/usb/musb/musb_cppi41.c
drivers/usb/musb/ux500_dma.c
drivers/usb/phy/phy-gpio-vbus-usb.c
drivers/usb/phy/phy-msm-usb.c
drivers/usb/phy/phy-mxs-usb.c
drivers/usb/phy/phy-samsung-usb.h
drivers/usb/phy/phy-tegra-usb.c
drivers/usb/phy/phy.c
drivers/usb/renesas_usbhs/fifo.c
drivers/usb/renesas_usbhs/mod.c
drivers/usb/renesas_usbhs/pipe.c
drivers/usb/renesas_usbhs/pipe.h
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/serial/sierra.c
drivers/usb/serial/usb-serial.c
drivers/usb/serial/whiteheat.c
drivers/usb/serial/zte_ev.c
drivers/usb/storage/uas-detect.h
drivers/usb/storage/unusual_devs.h
drivers/usb/usbip/Kconfig [new file with mode: 0644]
drivers/usb/usbip/Makefile [new file with mode: 0644]
drivers/usb/usbip/README [new file with mode: 0644]
drivers/usb/usbip/stub.h [new file with mode: 0644]
drivers/usb/usbip/stub_dev.c [new file with mode: 0644]
drivers/usb/usbip/stub_main.c [new file with mode: 0644]
drivers/usb/usbip/stub_rx.c [new file with mode: 0644]
drivers/usb/usbip/stub_tx.c [new file with mode: 0644]
drivers/usb/usbip/usbip_common.c [new file with mode: 0644]
drivers/usb/usbip/usbip_common.h [new file with mode: 0644]
drivers/usb/usbip/usbip_event.c [new file with mode: 0644]
drivers/usb/usbip/usbip_protocol.txt [new file with mode: 0644]
drivers/usb/usbip/vhci.h [new file with mode: 0644]
drivers/usb/usbip/vhci_hcd.c [new file with mode: 0644]
drivers/usb/usbip/vhci_rx.c [new file with mode: 0644]
drivers/usb/usbip/vhci_sysfs.c [new file with mode: 0644]
drivers/usb/usbip/vhci_tx.c [new file with mode: 0644]
drivers/usb/wusbcore/wa-xfer.c
drivers/uwb/lc-dev.c
drivers/video/backlight/pwm_bl.c
drivers/video/fbdev/amba-clcd.c
drivers/video/fbdev/atmel_lcdfb.c
drivers/video/fbdev/chipsfb.c
drivers/video/fbdev/da8xx-fb.c
drivers/video/of_display_timing.c
drivers/xen/balloon.c
drivers/xen/gntalloc.c
drivers/xen/manage.c
fs/aio.c
fs/btrfs/async-thread.c
fs/btrfs/async-thread.h
fs/btrfs/delayed-inode.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/ordered-data.c
fs/btrfs/qgroup.c
fs/btrfs/raid56.c
fs/btrfs/reada.c
fs/btrfs/scrub.c
fs/btrfs/sysfs.c
fs/btrfs/tree-log.c
fs/btrfs/tree-log.h
fs/btrfs/volumes.c
fs/cifs/Kconfig
fs/cifs/cifsglob.h
fs/cifs/connect.c
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/readdir.c
fs/cifs/sess.c
fs/cifs/smb2file.c
fs/cifs/smb2inode.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/eventpoll.c
fs/ext4/ext4.h
fs/ext4/extents.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/namei.c
fs/ext4/resize.c
fs/ext4/super.c
fs/f2fs/Kconfig
fs/f2fs/checkpoint.c
fs/f2fs/data.c
fs/f2fs/debug.c
fs/f2fs/dir.c
fs/f2fs/f2fs.h
fs/f2fs/file.c
fs/f2fs/gc.c
fs/f2fs/gc.h
fs/f2fs/hash.c
fs/f2fs/inline.c
fs/f2fs/namei.c
fs/f2fs/node.c
fs/f2fs/recovery.c
fs/f2fs/segment.c
fs/f2fs/segment.h
fs/f2fs/super.c
fs/f2fs/xattr.c
fs/jbd2/commit.c
fs/jbd2/journal.c
fs/jbd2/recovery.c
fs/jbd2/revoke.c
fs/lockd/svc.c
fs/locks.c
fs/namespace.c
fs/nfs/client.c
fs/nfs/filelayout/filelayout.c
fs/nfs/nfs3acl.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/notify/fdinfo.c
fs/ocfs2/cluster/quorum.c
fs/ocfs2/cluster/tcp.c
fs/ocfs2/cluster/tcp.h
fs/ocfs2/ioctl.c
fs/pnode.c
fs/sync.c
fs/udf/ialloc.c
fs/udf/inode.c
fs/udf/namei.c
fs/udf/super.c
fs/udf/udfdecl.h
fs/ufs/inode.c
fs/ufs/namei.c
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_file.c
include/acpi/acpi_bus.h
include/linux/blk-mq.h
include/linux/f2fs_fs.h
include/linux/gpio/consumer.h
include/linux/jbd2.h
include/linux/leds.h
include/linux/mlx4/device.h
include/linux/mtd/nand.h
include/linux/netdevice.h
include/linux/netfilter.h
include/linux/platform_data/mtd-nand-omap2.h
include/linux/pm_domain.h
include/linux/regulator/driver.h
include/linux/regulator/machine.h
include/linux/seqno-fence.h
include/linux/spi/spi.h
include/linux/tick.h
include/net/bluetooth/hci_core.h
include/net/netns/ieee802154_6lowpan.h
include/net/regulatory.h
include/net/sctp/sctp.h
include/net/sock.h
include/net/wimax.h
include/sound/soc.h
include/trace/events/irq.h
include/uapi/linux/Kbuild
include/uapi/linux/input.h
include/uapi/linux/usbip.h [new file with mode: 0644]
include/uapi/linux/xattr.h
include/xen/interface/features.h
kernel/cgroup.c
kernel/compat.c
kernel/irq/chip.c
kernel/kcmp.c
kernel/kexec.c
kernel/power/power.h
kernel/power/suspend.c
kernel/power/suspend_test.c
kernel/printk/printk.c
kernel/rcu/tree.h
kernel/rcu/tree_plugin.h
kernel/resource.c
kernel/time/tick-sched.c
kernel/time/timekeeping.c
kernel/trace/ring_buffer.c
lib/Kconfig.debug
lib/assoc_array.c
mm/hugetlb_cgroup.c
mm/memblock.c
mm/memcontrol.c
mm/memory.c
mm/mmap.c
mm/nobootmem.c
mm/percpu-vm.c
mm/percpu.c
mm/pgtable-generic.c
mm/zbud.c
mm/zpool.c
mm/zsmalloc.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/ceph/auth_x.c
net/ceph/mon_client.c
net/core/datagram.c
net/core/dev.c
net/core/gen_estimator.c
net/core/gen_stats.c
net/core/skbuff.c
net/core/sock.c
net/ieee802154/6lowpan_rtnl.c
net/ieee802154/reassembly.c
net/ipv4/netfilter/Kconfig
net/ipv4/netfilter/Makefile
net/ipv6/addrconf.c
net/ipv6/anycast.c
net/ipv6/mcast.c
net/ipv6/netfilter/Kconfig
net/ipv6/netfilter/Makefile
net/l2tp/l2tp_ppp.c
net/mac80211/chan.c
net/mac80211/debugfs_sta.c
net/mac80211/iface.c
net/mac80211/mesh_plink.c
net/mac80211/mlme.c
net/mac80211/sta_info.c
net/mac802154/wpan.c
net/netfilter/Kconfig
net/netfilter/Makefile
net/netfilter/core.c
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/ipvs/ip_vs_xmit.c
net/netfilter/xt_cgroup.c
net/openvswitch/datapath.c
net/rfkill/rfkill-gpio.c
net/sctp/socket.c
net/socket.c
scripts/checkpatch.pl
scripts/kernel-doc
security/keys/key.c
security/tomoyo/realpath.c
sound/core/info.c
sound/core/pcm_misc.c
sound/firewire/amdtp.c
sound/firewire/amdtp.h
sound/firewire/dice.c
sound/pci/ctxfi/ct20k1reg.h
sound/pci/hda/ca0132_regs.h
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/cs4265.c
sound/soc/codecs/da732x.h
sound/soc/codecs/rt5640.c
sound/soc/codecs/rt5677.c
sound/soc/generic/simple-card.c
sound/soc/omap/omap-twl4030.c
sound/soc/sh/rcar/gen.c
sound/soc/soc-core.c
sound/soc/tegra/tegra_asoc_utils.h
tools/testing/selftests/ipc/Makefile
tools/testing/selftests/kcmp/Makefile
tools/testing/selftests/memfd/Makefile
tools/usb/usbip/.gitignore [new file with mode: 0644]
tools/usb/usbip/AUTHORS [new file with mode: 0644]
tools/usb/usbip/COPYING [new file with mode: 0644]
tools/usb/usbip/INSTALL [new file with mode: 0644]
tools/usb/usbip/Makefile.am [new file with mode: 0644]
tools/usb/usbip/README [new file with mode: 0644]
tools/usb/usbip/autogen.sh [new file with mode: 0755]
tools/usb/usbip/cleanup.sh [new file with mode: 0755]
tools/usb/usbip/configure.ac [new file with mode: 0644]
tools/usb/usbip/doc/usbip.8 [new file with mode: 0644]
tools/usb/usbip/doc/usbipd.8 [new file with mode: 0644]
tools/usb/usbip/libsrc/Makefile.am [new file with mode: 0644]
tools/usb/usbip/libsrc/list.h [new file with mode: 0644]
tools/usb/usbip/libsrc/names.c [new file with mode: 0644]
tools/usb/usbip/libsrc/names.h [new file with mode: 0644]
tools/usb/usbip/libsrc/sysfs_utils.c [new file with mode: 0644]
tools/usb/usbip/libsrc/sysfs_utils.h [new file with mode: 0644]
tools/usb/usbip/libsrc/usbip_common.c [new file with mode: 0644]
tools/usb/usbip/libsrc/usbip_common.h [new file with mode: 0644]
tools/usb/usbip/libsrc/usbip_host_driver.c [new file with mode: 0644]
tools/usb/usbip/libsrc/usbip_host_driver.h [new file with mode: 0644]
tools/usb/usbip/libsrc/vhci_driver.c [new file with mode: 0644]
tools/usb/usbip/libsrc/vhci_driver.h [new file with mode: 0644]
tools/usb/usbip/src/Makefile.am [new file with mode: 0644]
tools/usb/usbip/src/usbip.c [new file with mode: 0644]
tools/usb/usbip/src/usbip.h [new file with mode: 0644]
tools/usb/usbip/src/usbip_attach.c [new file with mode: 0644]
tools/usb/usbip/src/usbip_bind.c [new file with mode: 0644]
tools/usb/usbip/src/usbip_detach.c [new file with mode: 0644]
tools/usb/usbip/src/usbip_list.c [new file with mode: 0644]
tools/usb/usbip/src/usbip_network.c [new file with mode: 0644]
tools/usb/usbip/src/usbip_network.h [new file with mode: 0644]
tools/usb/usbip/src/usbip_port.c [new file with mode: 0644]
tools/usb/usbip/src/usbip_unbind.c [new file with mode: 0644]
tools/usb/usbip/src/usbipd.c [new file with mode: 0644]
tools/usb/usbip/src/utils.c [new file with mode: 0644]
tools/usb/usbip/src/utils.h [new file with mode: 0644]

index 0a523c9a5ff4ec2fee6eefd5e5acef87944460a2..482c74947de02939eebfca089a344373707bf69d 100644 (file)
@@ -794,6 +794,7 @@ Greg Kroah-Hartman, "How to piss off a kernel subsystem maintainer".
   <http://www.kroah.com/log/linux/maintainer-03.html>
   <http://www.kroah.com/log/linux/maintainer-04.html>
   <http://www.kroah.com/log/linux/maintainer-05.html>
+  <http://www.kroah.com/log/linux/maintainer-06.html>
 
 NO!!!! No more huge patch bombs to linux-kernel@vger.kernel.org people!
   <https://lkml.org/lkml/2005/7/11/336>
index 9f1d750d76de9ff0d9858366e037a9635f353087..61bca509d7b99f734d1c7f054587aaa29dff8261 100644 (file)
@@ -16,9 +16,9 @@ Example:
 * DMA client
 
 Required properties:
-- dmas:                a list of <[DMA multiplexer phandle] [SRS/DRS value]> pairs,
-               where SRS/DRS values are fixed handles, specified in the SoC
-               manual as the value that would be written into the PDMACHCR.
+- dmas:                a list of <[DMA multiplexer phandle] [SRS << 8 | DRS]> pairs.
+               where SRS/DRS are specified in the SoC manual.
+               It will be written into PDMACHCR as high 16-bit parts.
 - dma-names:   a list of DMA channel names, one per "dmas" entry
 
 Example:
index baef432e83690af95ed6e3b49c1636c90f8ba135..0ac23f2ed1040c2c9f820677fdf3f5092a7c1a6d 100644 (file)
@@ -15,6 +15,17 @@ Optional properties for main touchpad device:
     keycode generated by each GPIO. Linux keycodes are defined in
     <dt-bindings/input/input.h>.
 
+- linux,gpio-keymap: When enabled, the SPT_GPIOPWN_T19 object sends messages
+    on GPIO bit changes. An array of up to 8 entries can be provided
+    indicating the Linux keycode mapped to each bit of the status byte,
+    starting at the LSB. Linux keycodes are defined in
+    <dt-bindings/input/input.h>.
+
+    Note: the numbering of the GPIOs and the bit they start at varies between
+    maXTouch devices. You must either refer to the documentation, or
+    experiment to determine which bit corresponds to which input. Use
+    KEY_RESERVED for unused padding values.
+
 Example:
 
        touch@4b {
diff --git a/Documentation/devicetree/bindings/mfd/tc3589x.txt b/Documentation/devicetree/bindings/mfd/tc3589x.txt
new file mode 100644 (file)
index 0000000..6fcedba
--- /dev/null
@@ -0,0 +1,107 @@
+* Toshiba TC3589x multi-purpose expander
+
+The Toshiba TC3589x series are I2C-based MFD devices which may expose the
+following built-in devices: gpio, keypad, rotator (vibrator), PWM (for
+e.g. LEDs or vibrators) The included models are:
+
+- TC35890
+- TC35892
+- TC35893
+- TC35894
+- TC35895
+- TC35896
+
+Required properties:
+ - compatible : must be "toshiba,tc35890", "toshiba,tc35892", "toshiba,tc35893",
+   "toshiba,tc35894", "toshiba,tc35895" or "toshiba,tc35896"
+ - reg : I2C address of the device
+ - interrupt-parent : specifies which IRQ controller we're connected to
+ - interrupts : the interrupt on the parent the controller is connected to
+ - interrupt-controller : marks the device node as an interrupt controller
+ - #interrupt-cells : should be <1>, the first cell is the IRQ offset on this
+   TC3589x interrupt controller.
+
+Optional nodes:
+
+- GPIO
+  This GPIO module inside the TC3589x has 24 (TC35890, TC35892) or 20
+  (other models) GPIO lines.
+ - compatible : must be "toshiba,tc3589x-gpio"
+ - interrupts : interrupt on the parent, which must be the tc3589x MFD device
+ - interrupt-controller : marks the device node as an interrupt controller
+ - #interrupt-cells : should be <2>, the first cell is the IRQ offset on this
+   TC3589x GPIO interrupt controller, the second cell is the interrupt flags
+   in accordance with <dt-bindings/interrupt-controller/irq.h>. The following
+   flags are valid:
+   - IRQ_TYPE_LEVEL_LOW
+   - IRQ_TYPE_LEVEL_HIGH
+   - IRQ_TYPE_EDGE_RISING
+   - IRQ_TYPE_EDGE_FALLING
+   - IRQ_TYPE_EDGE_BOTH
+ - gpio-controller : marks the device node as a GPIO controller
+ - #gpio-cells : should be <2>, the first cell is the GPIO offset on this
+   GPIO controller, the second cell is the flags.
+
+- Keypad
+  This keypad is the same on all variants, supporting up to 96 different
+  keys. The linux-specific properties are modeled on those already existing
+  in other input drivers.
+ - compatible : must be "toshiba,tc3589x-keypad"
+ - debounce-delay-ms : debounce interval in milliseconds
+ - keypad,num-rows : number of rows in the matrix, see
+   bindings/input/matrix-keymap.txt
+ - keypad,num-columns : number of columns in the matrix, see
+   bindings/input/matrix-keymap.txt
+ - linux,keymap: the definition can be found in
+   bindings/input/matrix-keymap.txt
+ - linux,no-autorepeat: do no enable autorepeat feature.
+ - linux,wakeup: use any event on keypad as wakeup event.
+
+Example:
+
+tc35893@44 {
+       compatible = "toshiba,tc35893";
+       reg = <0x44>;
+       interrupt-parent = <&gpio6>;
+       interrupts = <26 IRQ_TYPE_EDGE_RISING>;
+
+       interrupt-controller;
+       #interrupt-cells = <1>;
+
+       tc3589x_gpio {
+               compatible = "toshiba,tc3589x-gpio";
+               interrupts = <0>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+       tc3589x_keypad {
+               compatible = "toshiba,tc3589x-keypad";
+               interrupts = <6>;
+               debounce-delay-ms = <4>;
+               keypad,num-columns = <8>;
+               keypad,num-rows = <8>;
+               linux,no-autorepeat;
+               linux,wakeup;
+               linux,keymap = <0x0301006b
+                               0x04010066
+                               0x06040072
+                               0x040200d7
+                               0x0303006a
+                               0x0205000e
+                               0x0607008b
+                               0x0500001c
+                               0x0403000b
+                               0x03040034
+                               0x05020067
+                               0x0305006c
+                               0x040500e7
+                               0x0005009e
+                               0x06020073
+                               0x01030039
+                               0x07060069
+                               0x050500d9>;
+       };
+};
index 65f4f7c43136a0507ddbb23a7dc511c94cc34cdb..ee654e95d8ad55c3b53259b9f087be596b6dc99a 100644 (file)
@@ -22,7 +22,7 @@ Optional properties:
                                width of 8 is assumed.
 
  - ti,nand-ecc-opt:            A string setting the ECC layout to use. One of:
-               "sw"            <deprecated> use "ham1" instead
+               "sw"            1-bit Hamming ecc code via software
                "hw"            <deprecated> use "ham1" instead
                "hw-romcode"    <deprecated> use "ham1" instead
                "ham1"          1-bit Hamming ecc code
index 9b03c57563a49d2145fb47c2a5086ff71506fe3f..e45ac3f926b164636b73e4280cf40ddfde314203 100644 (file)
@@ -39,6 +39,10 @@ Optional properties:
   further clocks may be specified in derived bindings.
 - clock-names: One name for each entry in the clocks property, the
   first one should be "stmmaceth".
+- clk_ptp_ref: this is the PTP reference clock; in case of the PTP is
+  available this clock is used for programming the Timestamp Addend Register.
+  If not passed then the system clock will be used and this is fine on some
+  platforms.
 
 Examples:
 
index 0211c6d8a5229e17866eb90f751a015ffaf609a0..92fae82f35f2174ca64cb6de14825245870d9f5f 100644 (file)
@@ -62,7 +62,7 @@ Example:
                #gpio-cells = <2>;
                interrupt-controller;
                #interrupt-cells = <2>;
-               interrupts = <0 32 0x4>;
+               interrupts = <0 16 0x4>;
 
                pinctrl-names = "default";
                pinctrl-0 = <&gsbi5_uart_default>;
index 340980239ea9f7e1fb35f59da3ebcc0bf5b96ef8..ca69f5e3040cfa48299682dd6371f99c90b49ffa 100644 (file)
@@ -45,8 +45,8 @@ Example:
                infet5-supply = <&some_reg>;
                infet6-supply = <&some_reg>;
                infet7-supply = <&some_reg>;
-               vsys_l1-supply = <&some_reg>;
-               vsys_l2-supply = <&some_reg>;
+               vsys-l1-supply = <&some_reg>;
+               vsys-l2-supply = <&some_reg>;
 
                regulators {
                        dcdc1 {
index 46f344965313f1081dbd7894e738795a8b935815..4eb7997674a09006dfa0a991b634082ddc64974d 100644 (file)
@@ -1,7 +1,7 @@
 ADI AXI-SPDIF controller
 
 Required properties:
- - compatible : Must be "adi,axi-spdif-1.00.a"
+ - compatible : Must be "adi,axi-spdif-tx-1.00.a"
  - reg : Must contain SPDIF core's registers location and length
  - clocks : Pairs of phandle and specifier referencing the controller's clocks.
    The controller expects two clocks, the clock used for the AXI interface and
index cef181a9d8bd6506699cd98889fd36f8f6bbc306..96681c93b86df38788327df42c543738293265ea 100644 (file)
@@ -5,6 +5,7 @@ Required properties:
        * "fsl,imx23-usbphy" for imx23 and imx28
        * "fsl,imx6q-usbphy" for imx6dq and imx6dl
        * "fsl,imx6sl-usbphy" for imx6sl
+       * "fsl,imx6sx-usbphy" for imx6sx
   "fsl,imx23-usbphy" is still a fallback for other strings
 - reg: Should contain registers location and length
 - interrupts: Should contain phy interrupt
index 0218fcdc12994ea7f80ee1ce6246fde733a4b1a3..0c0970c210ab7be0c2a52ba4a977a0de8ddd0d5a 100644 (file)
@@ -2,7 +2,7 @@ Analog TV Connector
 ===================
 
 Required properties:
-- compatible: "composite-connector" or "svideo-connector"
+- compatible: "composite-video-connector" or "svideo-connector"
 
 Optional properties:
 - label: a symbolic name for the connector
@@ -14,7 +14,7 @@ Example
 -------
 
 tv: connector {
-       compatible = "composite-connector";
+       compatible = "composite-video-connector";
        label = "tv";
 
        port {
index 67a4087d53f9c731a1c0bf57e3ec48b7c1b90610..bb9753b635a3a5e8d8f794814a83584878b550e5 100644 (file)
@@ -56,10 +56,10 @@ The dma_buf buffer sharing API usage contains the following steps:
                                     size_t size, int flags,
                                     const char *exp_name)
 
-   If this succeeds, dma_buf_export allocates a dma_buf structure, and returns a
-   pointer to the same. It also associates an anonymous file with this buffer,
-   so it can be exported. On failure to allocate the dma_buf object, it returns
-   NULL.
+   If this succeeds, dma_buf_export_named allocates a dma_buf structure, and
+   returns a pointer to the same. It also associates an anonymous file with this
+   buffer, so it can be exported. On failure to allocate the dma_buf object,
+   it returns NULL.
 
    'exp_name' is the name of exporter - to facilitate information while
    debugging.
@@ -76,7 +76,7 @@ The dma_buf buffer sharing API usage contains the following steps:
    drivers and/or processes.
 
    Interface:
-      int dma_buf_fd(struct dma_buf *dmabuf)
+      int dma_buf_fd(struct dma_buf *dmabuf, int flags)
 
    This API installs an fd for the anonymous file associated with this buffer;
    returns either 'fd', or error.
@@ -157,7 +157,9 @@ to request use of buffer for allocation.
    "dma_buf->ops->" indirection from the users of this interface.
 
    In struct dma_buf_ops, unmap_dma_buf is defined as
-      void (*unmap_dma_buf)(struct dma_buf_attachment *, struct sg_table *);
+      void (*unmap_dma_buf)(struct dma_buf_attachment *,
+                            struct sg_table *,
+                            enum dma_data_direction);
 
    unmap_dma_buf signifies the end-of-DMA for the attachment provided. Like
    map_dma_buf, this API also must be implemented by the exporter.
index e386f7e4bcee1e4c8d5b0f08872c877097e6f9f9..724043858b0834f874aff57df4155f1da3dffad8 100644 (file)
@@ -138,9 +138,9 @@ Installation
   - Build, install, reboot
 
     The NFS/RDMA code will be enabled automatically if NFS and RDMA
-    are turned on. The NFS/RDMA client and server are configured via the hidden
-    SUNRPC_XPRT_RDMA config option that depends on SUNRPC and INFINIBAND. The
-    value of SUNRPC_XPRT_RDMA will be:
+    are turned on. The NFS/RDMA client and server are configured via the
+    SUNRPC_XPRT_RDMA_CLIENT and SUNRPC_XPRT_RDMA_SERVER config options that both
+    depend on SUNRPC and INFINIBAND. The default value of both options will be:
 
      - N if either SUNRPC or INFINIBAND are N, in this case the NFS/RDMA client
        and server will not be built
@@ -235,8 +235,9 @@ NFS/RDMA Setup
 
   - Start the NFS server
 
-    If the NFS/RDMA server was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in
-    kernel config), load the RDMA transport module:
+    If the NFS/RDMA server was built as a module
+    (CONFIG_SUNRPC_XPRT_RDMA_SERVER=m in kernel config), load the RDMA
+    transport module:
 
     $ modprobe svcrdma
 
@@ -255,8 +256,9 @@ NFS/RDMA Setup
 
   - On the client system
 
-    If the NFS/RDMA client was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in
-    kernel config), load the RDMA client module:
+    If the NFS/RDMA client was built as a module
+    (CONFIG_SUNRPC_XPRT_RDMA_CLIENT=m in kernel config), load the RDMA client
+    module:
 
     $ modprobe xprtrdma.ko
 
index 1fe0ccb1af553b8307999bb0a7cb997326cc44ad..8ea3e90ace07a945ef6fd512396f18ef259754a2 100644 (file)
@@ -235,6 +235,39 @@ be used for more than one file, you can store an arbitrary pointer in the
 private field of the seq_file structure; that value can then be retrieved
 by the iterator functions.
 
+There is also a wrapper function to seq_open() called seq_open_private(). It
+kmallocs a zero filled block of memory and stores a pointer to it in the
+private field of the seq_file structure, returning 0 on success. The
+block size is specified in a third parameter to the function, e.g.:
+
+       static int ct_open(struct inode *inode, struct file *file)
+       {
+               return seq_open_private(file, &ct_seq_ops,
+                                       sizeof(struct mystruct));
+       }
+
+There is also a variant function, __seq_open_private(), which is functionally
+identical except that, if successful, it returns the pointer to the allocated
+memory block, allowing further initialisation e.g.:
+
+       static int ct_open(struct inode *inode, struct file *file)
+       {
+               struct mystruct *p =
+                       __seq_open_private(file, &ct_seq_ops, sizeof(*p));
+
+               if (!p)
+                       return -ENOMEM;
+
+               p->foo = bar; /* initialize my stuff */
+                       ...
+               p->baz = true;
+
+               return 0;
+       }
+
+A corresponding close function, seq_release_private() is available which
+frees the memory allocated in the corresponding open.
+
 The other operations of interest - read(), llseek(), and release() - are
 all implemented by the seq_file code itself. So a virtual file's
 file_operations structure will look like:
index 76546324e968cf70394144beb86817c16586ceb3..6ce544191ca6b6d648cc2d66ed3df8fb7191d871 100644 (file)
@@ -53,7 +53,20 @@ with IS_ERR() (they will never return a NULL pointer). -ENOENT will be returned
 if and only if no GPIO has been assigned to the device/function/index triplet,
 other error codes are used for cases where a GPIO has been assigned but an error
 occurred while trying to acquire it. This is useful to discriminate between mere
-errors and an absence of GPIO for optional GPIO parameters.
+errors and an absence of GPIO for optional GPIO parameters. For the common
+pattern where a GPIO is optional, the gpiod_get_optional() and
+gpiod_get_index_optional() functions can be used. These functions return NULL
+instead of -ENOENT if no GPIO has been assigned to the requested function:
+
+
+       struct gpio_desc *gpiod_get_optional(struct device *dev,
+                                            const char *con_id,
+                                            enum gpiod_flags flags)
+
+       struct gpio_desc *gpiod_get_index_optional(struct device *dev,
+                                                  const char *con_id,
+                                                  unsigned int index,
+                                                  enum gpiod_flags flags)
 
 Device-managed variants of these functions are also defined:
 
@@ -65,6 +78,15 @@ Device-managed variants of these functions are also defined:
                                               unsigned int idx,
                                               enum gpiod_flags flags)
 
+       struct gpio_desc *devm_gpiod_get_optional(struct device *dev,
+                                                 const char *con_id,
+                                                 enum gpiod_flags flags)
+
+       struct gpio_desc * devm_gpiod_get_index_optional(struct device *dev,
+                                                       const char *con_id,
+                                                       unsigned int index,
+                                                       enum gpiod_flags flags)
+
 A GPIO descriptor can be disposed of using the gpiod_put() function:
 
        void gpiod_put(struct gpio_desc *desc)
index 3e742ba25536123dc4108c6eb2db860584d9b442..2ac78ae1039de5c6bf44b4b32e41de7d742be1d6 100644 (file)
@@ -57,12 +57,12 @@ Well, you are all set up now. You can now use SMBus commands or plain
 I2C to communicate with your device. SMBus commands are preferred if
 the device supports them. Both are illustrated below.
 
-  __u8 register = 0x10; /* Device register to access */
+  __u8 reg = 0x10; /* Device register to access */
   __s32 res;
   char buf[10];
 
   /* Using SMBus commands */
-  res = i2c_smbus_read_word_data(file, register);
+  res = i2c_smbus_read_word_data(file, reg);
   if (res < 0) {
     /* ERROR HANDLING: i2c transaction failed */
   } else {
@@ -70,11 +70,11 @@ the device supports them. Both are illustrated below.
   }
 
   /* Using I2C Write, equivalent of 
-     i2c_smbus_write_word_data(file, register, 0x6543) */
-  buf[0] = register;
+     i2c_smbus_write_word_data(file, reg, 0x6543) */
+  buf[0] = reg;
   buf[1] = 0x43;
   buf[2] = 0x65;
-  if (write(file, buf, 3) ! =3) {
+  if (write(file, buf, 3) !3) {
     /* ERROR HANDLING: i2c transaction failed */
   }
 
index 88d5a863712a53091dc79210f356599977dc0d9c..6c0b9f27e4652c94616ce32643a7fbe32d370eda 100644 (file)
@@ -18,7 +18,7 @@ memory image to a dump file on the local disk, or across the network to
 a remote system.
 
 Kdump and kexec are currently supported on the x86, x86_64, ppc64, ia64,
-and s390x architectures.
+s390x and arm architectures.
 
 When the system kernel boots, it reserves a small section of memory for
 the dump-capture kernel. This ensures that ongoing Direct Memory Access
@@ -112,7 +112,7 @@ There are two possible methods of using Kdump.
 2) Or use the system kernel binary itself as dump-capture kernel and there is
    no need to build a separate dump-capture kernel. This is possible
    only with the architectures which support a relocatable kernel. As
-   of today, i386, x86_64, ppc64 and ia64 architectures support relocatable
+   of today, i386, x86_64, ppc64, ia64 and arm architectures support relocatable
    kernel.
 
 Building a relocatable kernel is advantageous from the point of view that
@@ -241,6 +241,13 @@ Dump-capture kernel config options (Arch Dependent, ia64)
   kernel will be aligned to 64Mb, so if the start address is not then
   any space below the alignment point will be wasted.
 
+Dump-capture kernel config options (Arch Dependent, arm)
+----------------------------------------------------------
+
+-   To use a relocatable kernel,
+    Enable "AUTO_ZRELADDR" support under "Boot" options:
+
+    AUTO_ZRELADDR=y
 
 Extended crashkernel syntax
 ===========================
@@ -256,6 +263,10 @@ The syntax is:
     crashkernel=<range1>:<size1>[,<range2>:<size2>,...][@offset]
     range=start-[end]
 
+Please note, on arm, the offset is required.
+    crashkernel=<range1>:<size1>[,<range2>:<size2>,...]@offset
+    range=start-[end]
+
     'start' is inclusive and 'end' is exclusive.
 
 For example:
@@ -296,6 +307,12 @@ Boot into System Kernel
    on the memory consumption of the kdump system. In general this is not
    dependent on the memory size of the production system.
 
+   On arm, use "crashkernel=Y@X". Note that the start address of the kernel
+   will be aligned to 128MiB (0x08000000), so if the start address is not then
+   any space below the alignment point may be overwritten by the dump-capture kernel,
+   which means it is possible that the vmcore is not that precise as expected.
+
+
 Load the Dump-capture Kernel
 ============================
 
@@ -315,7 +332,8 @@ For ia64:
        - Use vmlinux or vmlinuz.gz
 For s390x:
        - Use image or bzImage
-
+For arm:
+       - Use zImage
 
 If you are using a uncompressed vmlinux image then use following command
 to load dump-capture kernel.
@@ -331,6 +349,15 @@ to load dump-capture kernel.
    --initrd=<initrd-for-dump-capture-kernel> \
    --append="root=<root-dev> <arch-specific-options>"
 
+If you are using a compressed zImage, then use following command
+to load dump-capture kernel.
+
+   kexec --type zImage -p <dump-capture-kernel-bzImage> \
+   --initrd=<initrd-for-dump-capture-kernel> \
+   --dtb=<dtb-for-dump-capture-kernel> \
+   --append="root=<root-dev> <arch-specific-options>"
+
+
 Please note, that --args-linux does not need to be specified for ia64.
 It is planned to make this a no-op on that architecture, but for now
 it should be omitted
@@ -347,6 +374,9 @@ For ppc64:
 For s390x:
        "1 maxcpus=1 cgroup_disable=memory"
 
+For arm:
+       "1 maxcpus=1 reset_devices"
+
 Notes on loading the dump-capture kernel:
 
 * By default, the ELF headers are stored in ELF64 format to support
index 5ae8608ca9f58a6331cae454ae7a0c84ab2f6c47..10d51c2f10d712b179f5e6f67d0b9032bb42b75c 100644 (file)
@@ -3541,6 +3541,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                                        bogus residue values);
                                s = SINGLE_LUN (the device has only one
                                        Logical Unit);
+                               u = IGNORE_UAS (don't bind to the uas driver);
                                w = NO_WP_DETECT (don't test whether the
                                        medium is write-protected).
                        Example: quirks=0419:aaf5:rl,0421:0433:rc
index af815b9ba413afc6ba3e21beac2d613e771e0bdb..f89960a0ff95e6e0c5e870f67c836be6adb9e0e6 100644 (file)
@@ -59,7 +59,7 @@ acts similar to /dev/rtc and reacts on free-fall interrupts received
 from the device. It supports blocking operations, poll/select and
 fasync operation modes. You must read 1 bytes from the device.  The
 result is number of free-fall interrupts since the last successful
-read (or 255 if number of interrupts would not fit). See the hpfall.c
+read (or 255 if number of interrupts would not fit). See the freefall.c
 file for an example on using the device.
 
 
index 81c0e2b49cd86cb9096c72c56d46935677c2d990..8afb236ca7653ed694af2b35e49eadbabd496152 100644 (file)
@@ -143,8 +143,9 @@ This will cause the core to recalculate the total load on the regulator (based
 on all its consumers) and change operating mode (if necessary and permitted)
 to best match the current operating load.
 
-The load_uA value can be determined from the consumers datasheet. e.g.most
-datasheets have tables showing the max current consumed in certain situations.
+The load_uA value can be determined from the consumer's datasheet. e.g. most
+datasheets have tables showing the maximum current consumed in certain
+situations.
 
 Most consumers will use indirect operating mode control since they have no
 knowledge of the regulator or whether the regulator is shared with other
@@ -173,7 +174,7 @@ Consumers can register interest in regulator events by calling :-
 int regulator_register_notifier(struct regulator *regulator,
                              struct notifier_block *nb);
 
-Consumers can uregister interest by calling :-
+Consumers can unregister interest by calling :-
 
 int regulator_unregister_notifier(struct regulator *regulator,
                                struct notifier_block *nb);
index f9b56b72b782f0350dc6e50f12d6fad76edd87cd..fdd919b96830b882e54c31d4c7b1f5f468624a5e 100644 (file)
@@ -9,14 +9,14 @@ Safety
 
  - Errors in regulator configuration can have very serious consequences
    for the system, potentially including lasting hardware damage.
- - It is not possible to automatically determine the power confugration
+ - It is not possible to automatically determine the power configuration
    of the system - software-equivalent variants of the same chip may
-   have different power requirments, and not all components with power
+   have different power requirements, and not all components with power
    requirements are visible to software.
 
   => The API should make no changes to the hardware state unless it has
-     specific knowledge that these changes are safe to do perform on
-     this particular system.
+     specific knowledge that these changes are safe to perform on this
+     particular system.
 
 Consumer use cases
 ------------------
index ce63af0a8e35ecab32e2f326d13a9a2b33b62909..757e3b53dc11a8acbb4d048487caab90b0ea8ebd 100644 (file)
@@ -11,7 +11,7 @@ Consider the following machine :-
                +-> [Consumer B @ 3.3V]
 
 The drivers for consumers A & B must be mapped to the correct regulator in
-order to control their power supply. This mapping can be achieved in machine
+order to control their power supplies. This mapping can be achieved in machine
 initialisation code by creating a struct regulator_consumer_supply for
 each regulator.
 
@@ -39,7 +39,7 @@ to the 'Vcc' supply for Consumer A.
 
 Constraints can now be registered by defining a struct regulator_init_data
 for each regulator power domain. This structure also maps the consumers
-to their supply regulator :-
+to their supply regulators :-
 
 static struct regulator_init_data regulator1_data = {
        .constraints = {
index 8ed17587a74bdc006b2d2922b5709f0e16ec08ad..40ca2d6e2742d182933443012aad9f6157eac361 100644 (file)
@@ -36,11 +36,11 @@ Some terms used in this document:-
                    Consumers can be classified into two types:-
 
                    Static: consumer does not change its supply voltage or
-                   current limit. It only needs to enable or disable it's
+                   current limit. It only needs to enable or disable its
                    power supply. Its supply voltage is set by the hardware,
                    bootloader, firmware or kernel board initialisation code.
 
-                   Dynamic: consumer needs to change it's supply voltage or
+                   Dynamic: consumer needs to change its supply voltage or
                    current limit to meet operation demands.
 
 
@@ -156,7 +156,7 @@ relevant to non SoC devices and is split into the following four interfaces:-
       This interface is for machine specific code and allows the creation of
       voltage/current domains (with constraints) for each regulator. It can
       provide regulator constraints that will prevent device damage through
-      overvoltage or over current caused by buggy client drivers. It also
+      overvoltage or overcurrent caused by buggy client drivers. It also
       allows the creation of a regulator tree whereby some regulators are
       supplied by others (similar to a clock tree).
 
index 13902778ae44ceb31f4f0c1c5dc173f63ffd9b8a..b17e5833ce214f963ed9af87f6f7fcf0e2c5ac18 100644 (file)
@@ -13,7 +13,7 @@ Drivers can register a regulator by calling :-
 struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
                                         const struct regulator_config *config);
 
-This will register the regulators capabilities and operations to the regulator
+This will register the regulator's capabilities and operations to the regulator
 core.
 
 Regulators can be unregistered by calling :-
@@ -23,8 +23,8 @@ void regulator_unregister(struct regulator_dev *rdev);
 
 Regulator Events
 ================
-Regulators can send events (e.g. over temp, under voltage, etc) to consumer
-drivers by calling :-
+Regulators can send events (e.g. overtemperature, undervoltage, etc) to
+consumer drivers by calling :-
 
 int regulator_notifier_call_chain(struct regulator_dev *rdev,
                                  unsigned long event, void *data);
index 1a4ce7e3e05f4836d6219838fc263440611e621d..0ec995712176ed83d4dd04ecfed81aa442848c07 100644 (file)
@@ -2,26 +2,26 @@ this_cpu operations
 -------------------
 
 this_cpu operations are a way of optimizing access to per cpu
-variables associated with the *currently* executing processor through
-the use of segment registers (or a dedicated register where the cpu
-permanently stored the beginning of the per cpu area for a specific
-processor).
+variables associated with the *currently* executing processor. This is
+done through the use of segment registers (or a dedicated register where
+the cpu permanently stored the beginning of the per cpu        area for a
+specific processor).
 
-The this_cpu operations add a per cpu variable offset to the processor
-specific percpu base and encode that operation in the instruction
+this_cpu operations add a per cpu variable offset to the processor
+specific per cpu base and encode that operation in the instruction
 operating on the per cpu variable.
 
-This means there are no atomicity issues between the calculation of
+This means that there are no atomicity issues between the calculation of
 the offset and the operation on the data. Therefore it is not
-necessary to disable preempt or interrupts to ensure that the
+necessary to disable preemption or interrupts to ensure that the
 processor is not changed between the calculation of the address and
 the operation on the data.
 
 Read-modify-write operations are of particular interest. Frequently
 processors have special lower latency instructions that can operate
-without the typical synchronization overhead but still provide some
-sort of relaxed atomicity guarantee. The x86 for example can execute
-RMV (Read Modify Write) instructions like inc/dec/cmpxchg without the
+without the typical synchronization overhead, but still provide some
+sort of relaxed atomicity guarantees. The x86, for example, can execute
+RMW (Read Modify Write) instructions like inc/dec/cmpxchg without the
 lock prefix and the associated latency penalty.
 
 Access to the variable without the lock prefix is not synchronized but
@@ -30,6 +30,38 @@ data specific to the currently executing processor. Only the current
 processor should be accessing that variable and therefore there are no
 concurrency issues with other processors in the system.
 
+Please note that accesses by remote processors to a per cpu area are
+exceptional situations and may impact performance and/or correctness
+(remote write operations) of local RMW operations via this_cpu_*.
+
+The main use of the this_cpu operations has been to optimize counter
+operations.
+
+The following this_cpu() operations with implied preemption protection
+are defined. These operations can be used without worrying about
+preemption and interrupts.
+
+       this_cpu_add()
+       this_cpu_read(pcp)
+       this_cpu_write(pcp, val)
+       this_cpu_add(pcp, val)
+       this_cpu_and(pcp, val)
+       this_cpu_or(pcp, val)
+       this_cpu_add_return(pcp, val)
+       this_cpu_xchg(pcp, nval)
+       this_cpu_cmpxchg(pcp, oval, nval)
+       this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+       this_cpu_sub(pcp, val)
+       this_cpu_inc(pcp)
+       this_cpu_dec(pcp)
+       this_cpu_sub_return(pcp, val)
+       this_cpu_inc_return(pcp)
+       this_cpu_dec_return(pcp)
+
+
+Inner working of this_cpu operations
+------------------------------------
+
 On x86 the fs: or the gs: segment registers contain the base of the
 per cpu area. It is then possible to simply use the segment override
 to relocate a per cpu relative address to the proper per cpu area for
@@ -48,22 +80,21 @@ results in a single instruction
        mov ax, gs:[x]
 
 instead of a sequence of calculation of the address and then a fetch
-from that address which occurs with the percpu operations. Before
+from that address which occurs with the per cpu operations. Before
 this_cpu_ops such sequence also required preempt disable/enable to
 prevent the kernel from moving the thread to a different processor
 while the calculation is performed.
 
-The main use of the this_cpu operations has been to optimize counter
-operations.
+Consider the following this_cpu operation:
 
        this_cpu_inc(x)
 
-results in the following single instruction (no lock prefix!)
+The above results in the following single instruction (no lock prefix!)
 
        inc gs:[x]
 
 instead of the following operations required if there is no segment
-register.
+register:
 
        int *y;
        int cpu;
@@ -73,10 +104,10 @@ register.
        (*y)++;
        put_cpu();
 
-Note that these operations can only be used on percpu data that is
+Note that these operations can only be used on per cpu data that is
 reserved for a specific processor. Without disabling preemption in the
 surrounding code this_cpu_inc() will only guarantee that one of the
-percpu counters is correctly incremented. However, there is no
+per cpu counters is correctly incremented. However, there is no
 guarantee that the OS will not move the process directly before or
 after the this_cpu instruction is executed. In general this means that
 the value of the individual counters for each processor are
@@ -86,9 +117,9 @@ that is of interest.
 Per cpu variables are used for performance reasons. Bouncing cache
 lines can be avoided if multiple processors concurrently go through
 the same code paths.  Since each processor has its own per cpu
-variables no concurrent cacheline updates take place. The price that
+variables no concurrent cache line updates take place. The price that
 has to be paid for this optimization is the need to add up the per cpu
-counters when the value of the counter is needed.
+counters when the value of a counter is needed.
 
 
 Special operations:
@@ -100,33 +131,39 @@ Takes the offset of a per cpu variable (&x !) and returns the address
 of the per cpu variable that belongs to the currently executing
 processor.  this_cpu_ptr avoids multiple steps that the common
 get_cpu/put_cpu sequence requires. No processor number is
-available. Instead the offset of the local per cpu area is simply
-added to the percpu offset.
+available. Instead, the offset of the local per cpu area is simply
+added to the per cpu offset.
 
+Note that this operation is usually used in a code segment when
+preemption has been disabled. The pointer is then used to
+access local per cpu data in a critical section. When preemption
+is re-enabled this pointer is usually no longer useful since it may
+no longer point to per cpu data of the current processor.
 
 
 Per cpu variables and offsets
 -----------------------------
 
-Per cpu variables have *offsets* to the beginning of the percpu
+Per cpu variables have *offsets* to the beginning of the per cpu
 area. They do not have addresses although they look like that in the
 code. Offsets cannot be directly dereferenced. The offset must be
-added to a base pointer of a percpu area of a processor in order to
+added to a base pointer of a per cpu area of a processor in order to
 form a valid address.
 
 Therefore the use of x or &x outside of the context of per cpu
 operations is invalid and will generally be treated like a NULL
 pointer dereference.
 
-In the context of per cpu operations
+       DEFINE_PER_CPU(int, x);
 
-       x is a per cpu variable. Most this_cpu operations take a cpu
-       variable.
+In the context of per cpu operations the above implies that x is a per
+cpu variable. Most this_cpu operations take a cpu variable.
 
-       &x is the *offset* a per cpu variable. this_cpu_ptr() takes
-       the offset of a per cpu variable which makes this look a bit
-       strange.
+       int __percpu *p = &x;
 
+&x and hence p is the *offset* of a per cpu variable. this_cpu_ptr()
+takes the offset of a per cpu variable which makes this look a bit
+strange.
 
 
 Operations on a field of a per cpu structure
@@ -152,7 +189,7 @@ If we have an offset to struct s:
 
        struct s __percpu *ps = &p;
 
-       z = this_cpu_dec(ps->m);
+       this_cpu_dec(ps->m);
 
        z = this_cpu_inc_return(ps->n);
 
@@ -172,29 +209,52 @@ if we do not make use of this_cpu ops later to manipulate fields:
 Variants of this_cpu ops
 -------------------------
 
-this_cpu ops are interrupt safe. Some architecture do not support
+this_cpu ops are interrupt safe. Some architectures do not support
 these per cpu local operations. In that case the operation must be
 replaced by code that disables interrupts, then does the operations
-that are guaranteed to be atomic and then reenable interrupts. Doing
+that are guaranteed to be atomic and then re-enable interrupts. Doing
 so is expensive. If there are other reasons why the scheduler cannot
 change the processor we are executing on then there is no reason to
-disable interrupts. For that purpose the __this_cpu operations are
-provided. For example.
-
-       __this_cpu_inc(x);
-
-Will increment x and will not fallback to code that disables
+disable interrupts. For that purpose the following __this_cpu operations
+are provided.
+
+These operations have no guarantee against concurrent interrupts or
+preemption. If a per cpu variable is not used in an interrupt context
+and the scheduler cannot preempt, then they are safe. If any interrupts
+still occur while an operation is in progress and if the interrupt too
+modifies the variable, then RMW actions can not be guaranteed to be
+safe.
+
+       __this_cpu_add()
+       __this_cpu_read(pcp)
+       __this_cpu_write(pcp, val)
+       __this_cpu_add(pcp, val)
+       __this_cpu_and(pcp, val)
+       __this_cpu_or(pcp, val)
+       __this_cpu_add_return(pcp, val)
+       __this_cpu_xchg(pcp, nval)
+       __this_cpu_cmpxchg(pcp, oval, nval)
+       __this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+       __this_cpu_sub(pcp, val)
+       __this_cpu_inc(pcp)
+       __this_cpu_dec(pcp)
+       __this_cpu_sub_return(pcp, val)
+       __this_cpu_inc_return(pcp)
+       __this_cpu_dec_return(pcp)
+
+
+Will increment x and will not fall-back to code that disables
 interrupts on platforms that cannot accomplish atomicity through
 address relocation and a Read-Modify-Write operation in the same
 instruction.
 
 
-
 &this_cpu_ptr(pp)->n vs this_cpu_ptr(&pp->n)
 --------------------------------------------
 
 The first operation takes the offset and forms an address and then
-adds the offset of the n field.
+adds the offset of the n field. This may result in two add
+instructions emitted by the compiler.
 
 The second one first adds the two offsets and then does the
 relocation.  IMHO the second form looks cleaner and has an easier time
@@ -202,4 +262,73 @@ with (). The second form also is consistent with the way
 this_cpu_read() and friends are used.
 
 
-Christoph Lameter, April 3rd, 2013
+Remote access to per cpu data
+------------------------------
+
+Per cpu data structures are designed to be used by one cpu exclusively.
+If you use the variables as intended, this_cpu_ops() are guaranteed to
+be "atomic" as no other CPU has access to these data structures.
+
+There are special cases where you might need to access per cpu data
+structures remotely. It is usually safe to do a remote read access
+and that is frequently done to summarize counters. Remote write access
+something which could be problematic because this_cpu ops do not
+have lock semantics. A remote write may interfere with a this_cpu
+RMW operation.
+
+Remote write accesses to percpu data structures are highly discouraged
+unless absolutely necessary. Please consider using an IPI to wake up
+the remote CPU and perform the update to its per cpu area.
+
+To access per-cpu data structure remotely, typically the per_cpu_ptr()
+function is used:
+
+
+       DEFINE_PER_CPU(struct data, datap);
+
+       struct data *p = per_cpu_ptr(&datap, cpu);
+
+This makes it explicit that we are getting ready to access a percpu
+area remotely.
+
+You can also do the following to convert the datap offset to an address
+
+       struct data *p = this_cpu_ptr(&datap);
+
+but, passing of pointers calculated via this_cpu_ptr to other cpus is
+unusual and should be avoided.
+
+Remote access are typically only for reading the status of another cpus
+per cpu data. Write accesses can cause unique problems due to the
+relaxed synchronization requirements for this_cpu operations.
+
+One example that illustrates some concerns with write operations is
+the following scenario that occurs because two per cpu variables
+share a cache-line but the relaxed synchronization is applied to
+only one process updating the cache-line.
+
+Consider the following example
+
+
+       struct test {
+               atomic_t a;
+               int b;
+       };
+
+       DEFINE_PER_CPU(struct test, onecacheline);
+
+There is some concern about what would happen if the field 'a' is updated
+remotely from one processor and the local processor would use this_cpu ops
+to update field b. Care should be taken that such simultaneous accesses to
+data within the same cache line are avoided. Also costly synchronization
+may be necessary. IPIs are generally recommended in such scenarios instead
+of a remote write to the per cpu area of another processor.
+
+Even in cases where the remote writes are rare, please bear in
+mind that a remote write will evict the cache line from the processor
+that most likely will access it. If the processor wakes up and finds a
+missing local cache line of a per cpu area, its performance and hence
+the wake up times will be affected.
+
+Christoph Lameter, August 4th, 2014
+Pranith Kumar, Aug 2nd, 2014
index 1ff06dee651d5da4806dfcec1ab12e8281110e58..97e92d9dc47095a953fd09c64a8f29dcebb9e2f0 100644 (file)
@@ -1279,8 +1279,13 @@ M:       Heiko Stuebner <heiko@sntech.de>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-rockchip@lists.infradead.org
 S:     Maintained
+F:     arch/arm/boot/dts/rk3*
 F:     arch/arm/mach-rockchip/
+F:     drivers/clk/rockchip/
+F:     drivers/i2c/busses/i2c-rk3x.c
 F:     drivers/*/*rockchip*
+F:     drivers/*/*/*rockchip*
+F:     sound/soc/rockchip/
 
 ARM/SAMSUNG ARM ARCHITECTURES
 M:     Ben Dooks <ben-linux@fluff.org>
@@ -7048,7 +7053,7 @@ S:        Maintained
 F:     drivers/pinctrl/sh-pfc/
 
 PIN CONTROLLER - SAMSUNG
-M:     Tomasz Figa <t.figa@samsung.com>
+M:     Tomasz Figa <tomasz.figa@gmail.com>
 M:     Thomas Abraham <thomas.abraham@linaro.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
@@ -7894,7 +7899,8 @@ S:        Supported
 F:     drivers/media/i2c/s5k5baf.c
 
 SAMSUNG SOC CLOCK DRIVERS
-M:     Tomasz Figa <t.figa@samsung.com>
+M:     Sylwester Nawrocki <s.nawrocki@samsung.com>
+M:     Tomasz Figa <tomasz.figa@gmail.com>
 S:     Supported
 L:     linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
 F:     drivers/clk/samsung/
@@ -7907,6 +7913,19 @@ S:       Supported
 L:     netdev@vger.kernel.org
 F:     drivers/net/ethernet/samsung/sxgbe/
 
+SAMSUNG USB2 PHY DRIVER
+M:     Kamil Debski <k.debski@samsung.com>
+L:     linux-kernel@vger.kernel.org
+S:     Supported
+F:     Documentation/devicetree/bindings/phy/samsung-phy.txt
+F:     Documentation/phy/samsung-usb2.txt
+F:     drivers/phy/phy-exynos4210-usb2.c
+F:     drivers/phy/phy-exynos4x12-usb2.c
+F:     drivers/phy/phy-exynos5250-usb2.c
+F:     drivers/phy/phy-s5pv210-usb2.c
+F:     drivers/phy/phy-samsung-usb2.c
+F:     drivers/phy/phy-samsung-usb2.h
+
 SERIAL DRIVERS
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:     linux-serial@vger.kernel.org
@@ -9557,6 +9576,14 @@ S:       Maintained
 F:     Documentation/usb/ohci.txt
 F:     drivers/usb/host/ohci*
 
+USB OVER IP DRIVER
+M:     Valentina Manea <valentina.manea.m@gmail.com>
+M:     Shuah Khan <shuah.kh@samsung.com>
+L:     linux-usb@vger.kernel.org
+S:     Maintained
+F:     drivers/usb/usbip/
+F:     tools/usb/usbip/
+
 USB PEGASUS DRIVER
 M:     Petko Manolov <petkan@nucleusys.com>
 L:     linux-usb@vger.kernel.org
@@ -10057,9 +10084,9 @@ F:      Documentation/x86/
 F:     arch/x86/
 
 X86 PLATFORM DRIVERS
-M:     Matthew Garrett <matthew.garrett@nebula.com>
+M:     Darren Hart <dvhart@infradead.org>
 L:     platform-driver-x86@vger.kernel.org
-T:     git git://cavan.codon.org.uk/platform-drivers-x86.git
+T:     git git://git.infradead.org/users/dvhart/linux-platform-drivers-x86.git
 S:     Maintained
 F:     drivers/platform/x86/
 
index f64fc7804a031a54ba82e9a4629680cfec6dd7ae..1a60bdd05c9a1611f3cee75f1073354d5a6297d0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 17
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc4
 NAME = Shuffling Zombie Juror
 
 # *DOCUMENTATION*
index 5ebab5895edb7991e660104d8288514d77fdf2c3..f05bdb4b1cb97ee8f0d3bbec58fbc7285522c852 100644 (file)
@@ -500,10 +500,14 @@ extern inline void writeq(u64 b, volatile void __iomem *addr)
 #define outb_p         outb
 #define outw_p         outw
 #define outl_p         outl
-#define readb_relaxed(addr) __raw_readb(addr)
-#define readw_relaxed(addr) __raw_readw(addr)
-#define readl_relaxed(addr) __raw_readl(addr)
-#define readq_relaxed(addr) __raw_readq(addr)
+#define readb_relaxed(addr)    __raw_readb(addr)
+#define readw_relaxed(addr)    __raw_readw(addr)
+#define readl_relaxed(addr)    __raw_readl(addr)
+#define readq_relaxed(addr)    __raw_readq(addr)
+#define writeb_relaxed(b, addr)        __raw_writeb(b, addr)
+#define writew_relaxed(b, addr)        __raw_writew(b, addr)
+#define writel_relaxed(b, addr)        __raw_writel(b, addr)
+#define writeq_relaxed(b, addr)        __raw_writeq(b, addr)
 
 #define mmiowb()
 
index f2c94402e2c8b95028bace631c3cbf6f2aeca5b1..c509d306db4561ea65a40703b42e7f9bd078d352 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <uapi/asm/unistd.h>
 
-#define NR_SYSCALLS                    508
+#define NR_SYSCALLS                    511
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_STAT64
index 53ae7bb1bfd1b3841572ae69587b80dddd9c0657..d214a0358100b6ad82a63fce68bc6016eb9ddaa4 100644 (file)
 #define __NR_process_vm_writev         505
 #define __NR_kcmp                      506
 #define __NR_finit_module              507
+#define __NR_sched_setattr             508
+#define __NR_sched_getattr             509
+#define __NR_renameat2                 510
 
 #endif /* _UAPI_ALPHA_UNISTD_H */
index dca9b3fb0071d8c24c1c5e1048a0da8461e12d8e..24789713f1eafb4757ec1084c32225ce88bf4ad4 100644 (file)
@@ -526,6 +526,9 @@ sys_call_table:
        .quad sys_process_vm_writev             /* 505 */
        .quad sys_kcmp
        .quad sys_finit_module
+       .quad sys_sched_setattr
+       .quad sys_sched_getattr
+       .quad sys_renameat2                     /* 510 */
 
        .size sys_call_table, . - sys_call_table
        .type sys_call_table, @object
index 4670afc3b971374886c923efc762ed2684b9aa49..9e1142729fd14c003c4f302a8305de1d735ab7a2 100644 (file)
@@ -427,7 +427,7 @@ struct ic_inv_args {
 
 static void __ic_line_inv_vaddr_helper(void *info)
 {
-        struct ic_inv *ic_inv_args = (struct ic_inv_args *) info;
+        struct ic_inv_args *ic_inv = info;
 
         __ic_line_inv_vaddr_local(ic_inv->paddr, ic_inv->vaddr, ic_inv->sz);
 }
@@ -581,6 +581,7 @@ void flush_icache_range(unsigned long kstart, unsigned long kend)
                tot_sz -= sz;
        }
 }
+EXPORT_SYMBOL(flush_icache_range);
 
 /*
  * General purpose helper to make I and D cache lines consistent.
index c49a775937db39912411a33be3d63a5d31eacfba..32cbbd5659023cffe04faf6c97eb7ee5be196585 100644 (file)
@@ -1983,8 +1983,6 @@ config XIP_PHYS_ADDR
 config KEXEC
        bool "Kexec system call (EXPERIMENTAL)"
        depends on (!SMP || PM_SLEEP_SMP)
-       select CRYPTO
-       select CRYPTO_SHA256
        help
          kexec is a system call that implements the ability to shutdown your
          current kernel, and to start another kernel.  It is like a reboot
index 9b3d2ba82f13a1b6aaf725c0e529255310726052..8689949bdba3f7fad944beaf77ce9b5efa6dbe59 100644 (file)
 
                        usb1: usb@48390000 {
                                compatible = "synopsys,dwc3";
-                               reg = <0x48390000 0x17000>;
+                               reg = <0x48390000 0x10000>;
                                interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
                                phys = <&usb2_phy1>;
                                phy-names = "usb2-phy";
 
                        usb2: usb@483d0000 {
                                compatible = "synopsys,dwc3";
-                               reg = <0x483d0000 0x17000>;
+                               reg = <0x483d0000 0x10000>;
                                interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
                                phys = <&usb2_phy2>;
                                phy-names = "usb2-phy";
index 646a6eade788f0114847bfa254f9bb7fcff272be..e7ac47fa6615e33ee52e3ef58025721f49c7eb08 100644 (file)
        status = "okay";
        pinctrl-names = "default";
        pinctrl-0 = <&i2c0_pins>;
-       clock-frequency = <400000>;
+       clock-frequency = <100000>;
 
        tps65218: tps65218@24 {
                reg = <0x24>;
        ranges = <0 0 0 0x01000000>;    /* minimum GPMC partition = 16MB */
        nand@0,0 {
                reg = <0 0 4>;          /* device IO registers */
-               ti,nand-ecc-opt = "bch8";
+               ti,nand-ecc-opt = "bch16";
                ti,elm-id = <&elm>;
                nand-bus-width = <8>;
                gpmc,device-width = <1>;
                gpmc,rd-cycle-ns = <40>;
                gpmc,wr-cycle-ns = <40>;
                gpmc,wait-pin = <0>;
-               gpmc,wait-on-read;
-               gpmc,wait-on-write;
                gpmc,bus-turnaround-ns = <0>;
                gpmc,cycle2cycle-delay-ns = <0>;
                gpmc,clk-activation-ns = <0>;
index ed7dd23959155598aba377c27d727e8dc481c551..ac3e4859935f1ad31da67107eda970eec6f526ba 100644 (file)
 };
 
 &gpmc {
-       status = "okay";
+       status = "okay";        /* Disable QSPI when enabling GPMC (NAND) */
        pinctrl-names = "default";
        pinctrl-0 = <&nand_flash_x8>;
        ranges = <0 0 0x08000000 0x10000000>;   /* CS0: NAND */
        nand@0,0 {
                reg = <0 0 0>; /* CS0, offset 0 */
-               ti,nand-ecc-opt = "bch8";
+               ti,nand-ecc-opt = "bch16";
                ti,elm-id = <&elm>;
                nand-bus-width = <8>;
                gpmc,device-width = <1>;
                gpmc,access-ns = <30>; /* tCEA + 4*/
                gpmc,rd-cycle-ns = <40>;
                gpmc,wr-cycle-ns = <40>;
-               gpmc,wait-on-read = "true";
-               gpmc,wait-on-write = "true";
+               gpmc,wait-pin = <0>;
                gpmc,bus-turnaround-ns = <0>;
                gpmc,cycle2cycle-delay-ns = <0>;
                gpmc,clk-activation-ns = <0>;
 };
 
 &qspi {
-       status = "okay";
+       status = "disabled";    /* Disable GPMC (NAND) when enabling QSPI */
        pinctrl-names = "default";
        pinctrl-0 = <&qspi1_default>;
 
index 65ccf564b9a5636eabb7af6cf2697d5c28dccd74..6c97d4af61eec9e36da60ab3257c508e0ef3ba7e 100644 (file)
                                usb: usbck {
                                        compatible = "atmel,at91rm9200-clk-usb";
                                        #clock-cells = <0>;
-                                       atmel,clk-divisors = <1 2>;
+                                       atmel,clk-divisors = <1 2 0 0>;
                                        clocks = <&pllb>;
                                };
 
index 31f7652612fc8f2f1e284b74eb6f9bef7e8e7986..4e0abbd9d6553e71d6881b074196d62dea4ac04b 100644 (file)
@@ -40,6 +40,7 @@
                                };
 
                                pllb: pllbck {
+                                       compatible = "atmel,at91sam9g20-clk-pllb";
                                        atmel,clk-input-range = <2000000 32000000>;
                                        atmel,pll-clk-output-ranges = <30000000 100000000 0 0>;
                                };
index 50f8022905a1f36e415f93f8638055993d5f4b5d..e03fbf3c6889120e9fce89d0fdb39fb70fe7b222 100644 (file)
@@ -8,6 +8,7 @@
 /dts-v1/;
 
 #include "dra74x.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 
 / {
        model = "TI DRA742";
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
        };
+
+       vtt_fixed: fixedregulator-vtt {
+               compatible = "regulator-fixed";
+               regulator-name = "vtt_fixed";
+               regulator-min-microvolt = <1350000>;
+               regulator-max-microvolt = <1350000>;
+               regulator-always-on;
+               regulator-boot-on;
+               enable-active-high;
+               gpio = <&gpio7 11 GPIO_ACTIVE_HIGH>;
+       };
 };
 
 &dra7_pmx_core {
+       pinctrl-names = "default";
+       pinctrl-0 = <&vtt_pin>;
+
+       vtt_pin: pinmux_vtt_pin {
+               pinctrl-single,pins = <
+                       0x3b4 (PIN_OUTPUT | MUX_MODE14) /* spi1_cs1.gpio7_11 */
+               >;
+       };
+
        i2c1_pins: pinmux_i2c1_pins {
                pinctrl-single,pins = <
                        0x400 (PIN_INPUT | MUX_MODE0) /* i2c1_sda */
 
        i2c3_pins: pinmux_i2c3_pins {
                pinctrl-single,pins = <
-                       0x410 (PIN_INPUT | MUX_MODE0) /* i2c3_sda */
-                       0x414 (PIN_INPUT | MUX_MODE0) /* i2c3_scl */
+                       0x288 (PIN_INPUT | MUX_MODE9) /* gpio6_14.i2c3_sda */
+                       0x28c (PIN_INPUT | MUX_MODE9) /* gpio6_15.i2c3_scl */
                >;
        };
 
        mcspi1_pins: pinmux_mcspi1_pins {
                pinctrl-single,pins = <
-                       0x3a4 (PIN_INPUT | MUX_MODE0) /* spi2_clk */
-                       0x3a8 (PIN_INPUT | MUX_MODE0) /* spi2_d1 */
-                       0x3ac (PIN_INPUT | MUX_MODE0) /* spi2_d0 */
-                       0x3b0 (PIN_INPUT_SLEW | MUX_MODE0) /* spi2_cs0 */
-                       0x3b4 (PIN_INPUT_SLEW | MUX_MODE0) /* spi2_cs1 */
-                       0x3b8 (PIN_INPUT_SLEW | MUX_MODE6) /* spi2_cs2 */
-                       0x3bc (PIN_INPUT_SLEW | MUX_MODE6) /* spi2_cs3 */
+                       0x3a4 (PIN_INPUT | MUX_MODE0) /* spi1_sclk */
+                       0x3a8 (PIN_INPUT | MUX_MODE0) /* spi1_d1 */
+                       0x3ac (PIN_INPUT | MUX_MODE0) /* spi1_d0 */
+                       0x3b0 (PIN_INPUT_SLEW | MUX_MODE0) /* spi1_cs0 */
+                       0x3b8 (PIN_INPUT_SLEW | MUX_MODE6) /* spi1_cs2.hdmi1_hpd */
+                       0x3bc (PIN_INPUT_SLEW | MUX_MODE6) /* spi1_cs3.hdmi1_cec */
                >;
        };
 
        status = "okay";
        pinctrl-names = "default";
        pinctrl-0 = <&i2c3_pins>;
-       clock-frequency = <3400000>;
+       clock-frequency = <400000>;
 };
 
 &mcspi1 {
                        reg = <0x001c0000 0x00020000>;
                };
                partition@7 {
-                       label = "NAND.u-boot-env";
+                       label = "NAND.u-boot-env.backup1";
                        reg = <0x001e0000 0x00020000>;
                };
                partition@8 {
 &usb2_phy2 {
        phy-supply = <&ldousb_reg>;
 };
+
+&gpio7 {
+       ti,no-reset-on-init;
+       ti,no-idle-on-init;
+};
index 97f603c4483d6a46032f06f7961d801091d1b3a4..d678152db4cb39036f7e05a6494737006714e81b 100644 (file)
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
-                       #interrupt-cells = <1>;
+                       #interrupt-cells = <2>;
                };
 
                gpio2: gpio@48055000 {
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
-                       #interrupt-cells = <1>;
+                       #interrupt-cells = <2>;
                };
 
                gpio3: gpio@48057000 {
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
-                       #interrupt-cells = <1>;
+                       #interrupt-cells = <2>;
                };
 
                gpio4: gpio@48059000 {
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
-                       #interrupt-cells = <1>;
+                       #interrupt-cells = <2>;
                };
 
                gpio5: gpio@4805b000 {
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
-                       #interrupt-cells = <1>;
+                       #interrupt-cells = <2>;
                };
 
                gpio6: gpio@4805d000 {
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
-                       #interrupt-cells = <1>;
+                       #interrupt-cells = <2>;
                };
 
                gpio7: gpio@48051000 {
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
-                       #interrupt-cells = <1>;
+                       #interrupt-cells = <2>;
                };
 
                gpio8: gpio@48053000 {
                        gpio-controller;
                        #gpio-cells = <2>;
                        interrupt-controller;
-                       #interrupt-cells = <1>;
+                       #interrupt-cells = <2>;
                };
 
                uart1: serial@4806a000 {
index f1bbf9a32991dd0b35dc9ee5c72cc9eef0d9246c..82d623d05915813761ecaf8c908dbdafac6af42c 100644 (file)
                                MX53_PAD_CSI0_DAT9__I2C1_SCL      0x400001ec
                        >;
                };
+
+               pinctrl_pmic: pmicgrp {
+                       fsl,pins = <
+                               MX53_PAD_CSI0_DAT5__GPIO5_23    0x1e4 /* IRQ */
+                       >;
+               };
        };
 };
 
@@ -38,6 +44,8 @@
 
        pmic: mc34708@8 {
                compatible = "fsl,mc34708";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_pmic>;
                reg = <0x08>;
                interrupt-parent = <&gpio5>;
                interrupts = <23 0x8>;
index c8e51dd41b8f2e9f729e852ee68140ae896b3ad6..71598546087f366c19baf0faf55b63ceee1ae3ec 100644 (file)
@@ -58,7 +58,7 @@
 
        sound-spdif {
                compatible = "fsl,imx-audio-spdif";
-               model = "imx-spdif";
+               model = "On-board SPDIF";
                /* IMX6 doesn't implement this yet */
                spdif-controller = <&spdif>;
                spdif-out;
 };
 
 &usbh1 {
+       disable-over-current;
        vbus-supply = <&reg_usbh1_vbus>;
        status = "okay";
 };
 
 &usbotg {
+       disable-over-current;
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_hummingboard_usbotg_id>;
        vbus-supply = <&reg_usbotg_vbus>;
index e8e781656b3f5ec422800d731768eefb70a88ed7..6a524ca011e70df048939fbc5ef0659c88a660e9 100644 (file)
@@ -61,7 +61,7 @@
 
        sound-spdif {
                compatible = "fsl,imx-audio-spdif";
-               model = "imx-spdif";
+               model = "Integrated SPDIF";
                /* IMX6 doesn't implement this yet */
                spdif-controller = <&spdif>;
                spdif-out;
                        fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
                };
 
+               pinctrl_cubox_i_usbh1: cubox-i-usbh1 {
+                       fsl,pins = <MX6QDL_PAD_GPIO_3__USB_H1_OC 0x1b0b0>;
+               };
+
                pinctrl_cubox_i_usbh1_vbus: cubox-i-usbh1-vbus {
                        fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x4001b0b0>;
                };
 
-               pinctrl_cubox_i_usbotg_id: cubox-i-usbotg-id {
+               pinctrl_cubox_i_usbotg: cubox-i-usbotg {
                        /*
-                        * The Cubox-i pulls this low, but as it's pointless
+                        * The Cubox-i pulls ID low, but as it's pointless
                         * leaving it as a pull-up, even if it is just 10uA.
                         */
-                       fsl,pins = <MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059>;
+                       fsl,pins = <
+                               MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059
+                               MX6QDL_PAD_KEY_COL4__USB_OTG_OC 0x1b0b0
+                       >;
                };
 
                pinctrl_cubox_i_usbotg_vbus: cubox-i-usbotg-vbus {
 };
 
 &usbh1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_cubox_i_usbh1>;
        vbus-supply = <&reg_usbh1_vbus>;
        status = "okay";
 };
 
 &usbotg {
        pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_cubox_i_usbotg_id>;
+       pinctrl-0 = <&pinctrl_cubox_i_usbotg>;
        vbus-supply = <&reg_usbotg_vbus>;
        status = "okay";
 };
index d16066608e21ae3716bc52a58597dc51f6ed9241..db9f45b2c57304603a78db4c20ca50a0f133c247 100644 (file)
@@ -17,7 +17,7 @@
        enet {
                pinctrl_microsom_enet_ar8035: microsom-enet-ar8035 {
                        fsl,pins = <
-                               MX6QDL_PAD_ENET_MDIO__ENET_MDIO         0x1b0b0
+                               MX6QDL_PAD_ENET_MDIO__ENET_MDIO         0x1b8b0
                                MX6QDL_PAD_ENET_MDC__ENET_MDC           0x1b0b0
                                /* AR8035 reset */
                                MX6QDL_PAD_KEY_ROW4__GPIO4_IO15         0x130b0
index 3c3e6da1deacdaddd2ec75cfa2aa3ba8837b929e..a9aae88b74f52687bf896795c83071571dacef73 100644 (file)
 &uart3 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart3_pins>;
+       interrupts-extended = <&intc 74 &omap3_pmx_core OMAP3_UART3_RX>;
 };
 
 &gpio1 {
index b15f1a77d684eac5bad3ea9f0defbf8d549a686a..4361777a08d81090cca597271a5f7a6d3b22ea25 100644 (file)
@@ -93,7 +93,7 @@
        };
 
        tv: connector {
-               compatible = "composite-connector";
+               compatible = "composite-video-connector";
                label = "tv";
 
                port {
        };
 
        twl_power: power {
-               compatible = "ti,twl4030-power-n900";
+               compatible = "ti,twl4030-power-n900", "ti,twl4030-power-idle-osc-off";
                ti,use_poweroff;
        };
 };
index 02f69f4a8fd37739cf12139861760196ed183079..9bad94efe1c81c65a56f9d8fbb6d8fcc53bcd2af 100644 (file)
                #address-cells = <1>;
                #size-cells = <1>;
                reg = <1 0 0x08000000>;
-               ti,nand-ecc-opt = "ham1";
+               ti,nand-ecc-opt = "sw";
                nand-bus-width = <8>;
                gpmc,cs-on-ns = <0>;
                gpmc,cs-rd-off-ns = <36>;
index e47ff69dcf7053e7bb22d3f5d40e7cd09628687c..5c375003bad106216109b5626264300433dabd1d 100644 (file)
                ti,bit-shift = <0x1e>;
                reg = <0x0d00>;
                ti,set-bit-to-disable;
+               ti,set-rate-parent;
        };
 
        dpll4_m6_ck: dpll4_m6_ck {
index e67a23b5d7884725290b6348a54a97f3427ccbc3..58c27466f01262a6f9ecee2058fb11dff9b5df3f 100644 (file)
 
        l3_iclk_div: l3_iclk_div {
                #clock-cells = <0>;
-               compatible = "fixed-factor-clock";
+               compatible = "ti,divider-clock";
+               ti,max-div = <2>;
+               ti,bit-shift = <4>;
+               reg = <0x100>;
                clocks = <&dpll_core_h12x2_ck>;
-               clock-mult = <1>;
-               clock-div = <1>;
+               ti,index-power-of-two;
        };
 
        gpu_l3_iclk: gpu_l3_iclk {
 
        l4_root_clk_div: l4_root_clk_div {
                #clock-cells = <0>;
-               compatible = "fixed-factor-clock";
+               compatible = "ti,divider-clock";
+               ti,max-div = <2>;
+               ti,bit-shift = <8>;
+               reg = <0x100>;
                clocks = <&l3_iclk_div>;
-               clock-mult = <1>;
-               clock-div = <1>;
+               ti,index-power-of-two;
        };
 
        slimbus1_slimbus_clk: slimbus1_slimbus_clk {
index 4a2000c620ad7a6a77f3b7aec18efc9a79e3a94e..3e97a669f15ef484107cdef76dbac8051d97202d 100644 (file)
                msp2: msp@80117000 {
                        pinctrl-names = "default";
                        pinctrl-0 = <&msp2_default_mode>;
-                       status = "okay";
                };
 
                msp3: msp@80125000 {
index 2e3bd3172b2366227a78f8404f191e4d0e6e8be6..55eb35f068fb6f9b760d36fd8be2a6f811359754 100644 (file)
                regulator-always-on;
        };
 
-       clk32kg: regulator-clk32kg {
-               compatible = "ti,twl6030-clk32kg";
-       };
-
        twl_usb_comparator: usb-comparator {
                compatible = "ti,twl6030-usb";
                interrupts = <4>, <10>;
index 88099175fc56c64be13c5a31e5cf05ed18b60e50..d86771abbf57a3760e65c4718a4fbfc6bad8359b 100644 (file)
@@ -1443,14 +1443,14 @@ void edma_assign_channel_eventq(unsigned channel, enum dma_event_q eventq_no)
 EXPORT_SYMBOL(edma_assign_channel_eventq);
 
 static int edma_setup_from_hw(struct device *dev, struct edma_soc_info *pdata,
-                             struct edma *edma_cc)
+                             struct edma *edma_cc, int cc_id)
 {
        int i;
        u32 value, cccfg;
        s8 (*queue_priority_map)[2];
 
        /* Decode the eDMA3 configuration from CCCFG register */
-       cccfg = edma_read(0, EDMA_CCCFG);
+       cccfg = edma_read(cc_id, EDMA_CCCFG);
 
        value = GET_NUM_REGN(cccfg);
        edma_cc->num_region = BIT(value);
@@ -1464,7 +1464,8 @@ static int edma_setup_from_hw(struct device *dev, struct edma_soc_info *pdata,
        value = GET_NUM_EVQUE(cccfg);
        edma_cc->num_tc = value + 1;
 
-       dev_dbg(dev, "eDMA3 HW configuration (cccfg: 0x%08x):\n", cccfg);
+       dev_dbg(dev, "eDMA3 CC%d HW configuration (cccfg: 0x%08x):\n", cc_id,
+               cccfg);
        dev_dbg(dev, "num_region: %u\n", edma_cc->num_region);
        dev_dbg(dev, "num_channel: %u\n", edma_cc->num_channels);
        dev_dbg(dev, "num_slot: %u\n", edma_cc->num_slots);
@@ -1684,7 +1685,7 @@ static int edma_probe(struct platform_device *pdev)
                        return -ENOMEM;
 
                /* Get eDMA3 configuration from IP */
-               ret = edma_setup_from_hw(dev, info[j], edma_cc[j]);
+               ret = edma_setup_from_hw(dev, info[j], edma_cc[j], j);
                if (ret)
                        return ret;
 
index fd43f7f55b701f95393af71be7ef2259139f2586..79ecb4f34ffb34f25037f829a6227ea69b7a9fc8 100644 (file)
@@ -472,7 +472,6 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size)
        "mcr    p15, 0, r0, c1, c0, 0   @ set SCTLR \n\t" \
        "isb    \n\t" \
        "bl     v7_flush_dcache_"__stringify(level)" \n\t" \
-       "clrex  \n\t" \
        "mrc    p15, 0, r0, c1, c0, 1   @ get ACTLR \n\t" \
        "bic    r0, r0, #(1 << 6)       @ disable local coherency \n\t" \
        "mcr    p15, 0, r0, c1, c0, 1   @ set ACTLR \n\t" \
index 963a2515906dce2a2c42e7b924edb6106652497c..819777d0e91f92cb91ff8c1933c480cb1bb80b91 100644 (file)
@@ -74,6 +74,7 @@
 #define ARM_CPU_PART_CORTEX_A12                0x4100c0d0
 #define ARM_CPU_PART_CORTEX_A17                0x4100c0e0
 #define ARM_CPU_PART_CORTEX_A15                0x4100c0f0
+#define ARM_CPU_PART_MASK              0xff00fff0
 
 #define ARM_CPU_XSCALE_ARCH_MASK       0xe000
 #define ARM_CPU_XSCALE_ARCH_V1         0x2000
@@ -179,7 +180,7 @@ static inline unsigned int __attribute_const__ read_cpuid_implementor(void)
  */
 static inline unsigned int __attribute_const__ read_cpuid_part(void)
 {
-       return read_cpuid_id() & 0xff00fff0;
+       return read_cpuid_id() & ARM_CPU_PART_MASK;
 }
 
 static inline unsigned int __attribute_const__ __deprecated read_cpuid_part_number(void)
index f4b46d39b9cfb12756050a992262367ce575f90b..afb9cafd378618fef0d39a7bcae64e9950afdb1c 100644 (file)
@@ -50,6 +50,7 @@ typedef struct user_fp elf_fpregset_t;
 #define R_ARM_ABS32            2
 #define R_ARM_CALL             28
 #define R_ARM_JUMP24           29
+#define R_ARM_TARGET1          38
 #define R_ARM_V4BX             40
 #define R_ARM_PREL31           42
 #define R_ARM_MOVW_ABS_NC      43
index a252c0bfacf50e5adb09d339e42ed0bedfd1ac08..0ad7d490ee6f2657b1504359d362ad8d886bee91 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/cpumask.h>
 #include <linux/err.h>
 
+#include <asm/cpu.h>
 #include <asm/cputype.h>
 
 /*
@@ -25,6 +26,20 @@ static inline bool is_smp(void)
 #endif
 }
 
+/**
+ * smp_cpuid_part() - return part id for a given cpu
+ * @cpu:       logical cpu id.
+ *
+ * Return: part id of logical cpu passed as argument.
+ */
+static inline unsigned int smp_cpuid_part(int cpu)
+{
+       struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpu);
+
+       return is_smp() ? cpu_info->cpuid & ARM_CPU_PART_MASK :
+                         read_cpuid_part();
+}
+
 /* all SMP configurations have the extended CPUID registers */
 #ifndef CONFIG_MMU
 #define tlb_ops_need_broadcast()       0
index 1109017499e52f05e92ca7056831323f4ed330e9..e8275ea88e8806d79b784deef60b57c6cf76a8ad 100644 (file)
@@ -26,25 +26,14 @@ static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
        __generic_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
 }
 
-static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
+void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
                size_t size, enum dma_data_direction dir,
-               struct dma_attrs *attrs)
-{
-       if (__generic_dma_ops(hwdev)->unmap_page)
-               __generic_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs);
-}
+               struct dma_attrs *attrs);
 
-static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
-               dma_addr_t handle, size_t size, enum dma_data_direction dir)
-{
-       if (__generic_dma_ops(hwdev)->sync_single_for_cpu)
-               __generic_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir);
-}
+void xen_dma_sync_single_for_cpu(struct device *hwdev,
+               dma_addr_t handle, size_t size, enum dma_data_direction dir);
+
+void xen_dma_sync_single_for_device(struct device *hwdev,
+               dma_addr_t handle, size_t size, enum dma_data_direction dir);
 
-static inline void xen_dma_sync_single_for_device(struct device *hwdev,
-               dma_addr_t handle, size_t size, enum dma_data_direction dir)
-{
-       if (__generic_dma_ops(hwdev)->sync_single_for_device)
-               __generic_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir);
-}
 #endif /* _ASM_ARM_XEN_PAGE_COHERENT_H */
index ded062f9b358038c05fa074816706c40619e6408..135c24a5ba262b76529fa1c3dbe088d098de84a5 100644 (file)
@@ -33,7 +33,6 @@ typedef struct xpaddr {
 #define INVALID_P2M_ENTRY      (~0UL)
 
 unsigned long __pfn_to_mfn(unsigned long pfn);
-unsigned long __mfn_to_pfn(unsigned long mfn);
 extern struct rb_root phys_to_mach;
 
 static inline unsigned long pfn_to_mfn(unsigned long pfn)
@@ -51,14 +50,6 @@ static inline unsigned long pfn_to_mfn(unsigned long pfn)
 
 static inline unsigned long mfn_to_pfn(unsigned long mfn)
 {
-       unsigned long pfn;
-
-       if (phys_to_mach.rb_node != NULL) {
-               pfn = __mfn_to_pfn(mfn);
-               if (pfn != INVALID_P2M_ENTRY)
-                       return pfn;
-       }
-
        return mfn;
 }
 
index 8db307d0954bb03ee95550471dcc0e6f86ae560f..2fdf8679b46e19d1d9e9b0b9c3d196b7c0edbccb 100644 (file)
 #endif
        .endif
        msr     spsr_cxsf, \rpsr
-#if defined(CONFIG_CPU_V6)
-       ldr     r0, [sp]
-       strex   r1, r2, [sp]                    @ clear the exclusive monitor
-       ldmib   sp, {r1 - pc}^                  @ load r1 - pc, cpsr
-#elif defined(CONFIG_CPU_32v6K)
-       clrex                                   @ clear the exclusive monitor
-       ldmia   sp, {r0 - pc}^                  @ load r0 - pc, cpsr
-#else
-       ldmia   sp, {r0 - pc}^                  @ load r0 - pc, cpsr
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K)
+       @ We must avoid clrex due to Cortex-A15 erratum #830321
+       sub     r0, sp, #4                      @ uninhabited address
+       strex   r1, r2, [r0]                    @ clear the exclusive monitor
 #endif
+       ldmia   sp, {r0 - pc}^                  @ load r0 - pc, cpsr
        .endm
 
        .macro  restore_user_regs, fast = 0, offset = 0
        ldr     r1, [sp, #\offset + S_PSR]      @ get calling cpsr
        ldr     lr, [sp, #\offset + S_PC]!      @ get pc
        msr     spsr_cxsf, r1                   @ save in spsr_svc
-#if defined(CONFIG_CPU_V6)
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K)
+       @ We must avoid clrex due to Cortex-A15 erratum #830321
        strex   r1, r2, [sp]                    @ clear the exclusive monitor
-#elif defined(CONFIG_CPU_32v6K)
-       clrex                                   @ clear the exclusive monitor
 #endif
        .if     \fast
        ldmdb   sp, {r1 - lr}^                  @ get calling r1 - lr
        .endif
        ldr     lr, [sp, #S_SP]                 @ top of the stack
        ldrd    r0, r1, [sp, #S_LR]             @ calling lr and pc
-       clrex                                   @ clear the exclusive monitor
+
+       @ We must avoid clrex due to Cortex-A15 erratum #830321
+       strex   r2, r1, [sp, #S_LR]             @ clear the exclusive monitor
+
        stmdb   lr!, {r0, r1, \rpsr}            @ calling lr and rfe context
        ldmia   sp, {r0 - r12}
        mov     sp, lr
        .endm
 #else  /* ifdef CONFIG_CPU_V7M */
        .macro  restore_user_regs, fast = 0, offset = 0
-       clrex                                   @ clear the exclusive monitor
        mov     r2, sp
        load_user_sp_lr r2, r3, \offset + S_SP  @ calling sp, lr
        ldr     r1, [sp, #\offset + S_PSR]      @ get calling cpsr
        ldr     lr, [sp, #\offset + S_PC]       @ get pc
        add     sp, sp, #\offset + S_SP
        msr     spsr_cxsf, r1                   @ save in spsr_svc
+
+       @ We must avoid clrex due to Cortex-A15 erratum #830321
+       strex   r1, r2, [sp]                    @ clear the exclusive monitor
+
        .if     \fast
        ldmdb   sp, {r1 - r12}                  @ get calling r1 - r12
        .else
index 45e478157278e331ac6474ca5dbac859415b0fff..6a4dffefd3579994e3d9f1e0b9b02ab3422b738a 100644 (file)
@@ -91,6 +91,7 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
                        break;
 
                case R_ARM_ABS32:
+               case R_ARM_TARGET1:
                        *(u32 *)loc += sym->st_value;
                        break;
 
index 4c979d466cc1681c4b3efc70623345eee5974b78..a96a8043277c3de69cc460a5b2a3f83a36fc30ed 100644 (file)
@@ -93,6 +93,8 @@ static int kvm_handle_wfx(struct kvm_vcpu *vcpu, struct kvm_run *run)
        else
                kvm_vcpu_block(vcpu);
 
+       kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
+
        return 1;
 }
 
index 991415d978b6020a958ac44a886103ee83aa764c..3988e72d16ff9f20efdad72c51dab74b01f559b2 100644 (file)
@@ -99,6 +99,10 @@ __do_hyp_init:
        mrc     p15, 0, r0, c10, c2, 1
        mcr     p15, 4, r0, c10, c2, 1
 
+       @ Invalidate the stale TLBs from Bootloader
+       mcr     p15, 4, r0, c8, c7, 0   @ TLBIALLH
+       dsb     ish
+
        @ Set the HSCTLR to:
        @  - ARM/THUMB exceptions: Kernel config (Thumb-2 kernel)
        @  - Endianness: Kernel config
index 3a185faee795b589725bffd222e2299eac5cffc3..f4b6e91843e44565257982eb7297101bbdbcd4bb 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/gpio.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
+#include <linux/clk-provider.h>
 
 #include <asm/setup.h>
 #include <asm/irq.h>
@@ -35,13 +36,21 @@ static void __init at91rm9200_dt_init_irq(void)
        of_irq_init(irq_of_match);
 }
 
+static void __init at91rm9200_dt_timer_init(void)
+{
+#if defined(CONFIG_COMMON_CLK)
+       of_clk_init(NULL);
+#endif
+       at91rm9200_timer_init();
+}
+
 static const char *at91rm9200_dt_board_compat[] __initdata = {
        "atmel,at91rm9200",
        NULL
 };
 
 DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200 (Device Tree)")
-       .init_time      = at91rm9200_timer_init,
+       .init_time      = at91rm9200_dt_timer_init,
        .map_io         = at91_map_io,
        .handle_irq     = at91_aic_handle_irq,
        .init_early     = at91rm9200_dt_initialize,
index 67c492aabf4d5ebd3769ff01e304e9371acafafc..b19a39652545daf3ca46243e29c7e7780fb27a91 100644 (file)
@@ -36,5 +36,4 @@ obj-$(CONFIG_ARCH_BCM_5301X)  += bcm_5301x.o
 
 ifeq ($(CONFIG_ARCH_BRCMSTB),y)
 obj-y                          += brcmstb.o
-obj-$(CONFIG_SMP)              += headsmp-brcmstb.o platsmp-brcmstb.o
 endif
diff --git a/arch/arm/mach-bcm/brcmstb.h b/arch/arm/mach-bcm/brcmstb.h
deleted file mode 100644 (file)
index ec0c3d1..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (C) 2013-2014 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef __BRCMSTB_H__
-#define __BRCMSTB_H__
-
-void brcmstb_secondary_startup(void);
-
-#endif /* __BRCMSTB_H__ */
diff --git a/arch/arm/mach-bcm/headsmp-brcmstb.S b/arch/arm/mach-bcm/headsmp-brcmstb.S
deleted file mode 100644 (file)
index 199c1ea..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * SMP boot code for secondary CPUs
- * Based on arch/arm/mach-tegra/headsmp.S
- *
- * Copyright (C) 2010 NVIDIA, Inc.
- * Copyright (C) 2013-2014 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <asm/assembler.h>
-#include <linux/linkage.h>
-#include <linux/init.h>
-
-        .section ".text.head", "ax"
-
-ENTRY(brcmstb_secondary_startup)
-        /*
-         * Ensure CPU is in a sane state by disabling all IRQs and switching
-         * into SVC mode.
-         */
-        setmode        PSR_I_BIT | PSR_F_BIT | SVC_MODE, r0
-
-        bl      v7_invalidate_l1
-        b       secondary_startup
-ENDPROC(brcmstb_secondary_startup)
diff --git a/arch/arm/mach-bcm/platsmp-brcmstb.c b/arch/arm/mach-bcm/platsmp-brcmstb.c
deleted file mode 100644 (file)
index af780e9..0000000
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * Broadcom STB CPU SMP and hotplug support for ARM
- *
- * Copyright (C) 2013-2014 Broadcom Corporation
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation version 2.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/printk.h>
-#include <linux/regmap.h>
-#include <linux/smp.h>
-#include <linux/mfd/syscon.h>
-#include <linux/spinlock.h>
-
-#include <asm/cacheflush.h>
-#include <asm/cp15.h>
-#include <asm/mach-types.h>
-#include <asm/smp_plat.h>
-
-#include "brcmstb.h"
-
-enum {
-       ZONE_MAN_CLKEN_MASK             = BIT(0),
-       ZONE_MAN_RESET_CNTL_MASK        = BIT(1),
-       ZONE_MAN_MEM_PWR_MASK           = BIT(4),
-       ZONE_RESERVED_1_MASK            = BIT(5),
-       ZONE_MAN_ISO_CNTL_MASK          = BIT(6),
-       ZONE_MANUAL_CONTROL_MASK        = BIT(7),
-       ZONE_PWR_DN_REQ_MASK            = BIT(9),
-       ZONE_PWR_UP_REQ_MASK            = BIT(10),
-       ZONE_BLK_RST_ASSERT_MASK        = BIT(12),
-       ZONE_PWR_OFF_STATE_MASK         = BIT(25),
-       ZONE_PWR_ON_STATE_MASK          = BIT(26),
-       ZONE_DPG_PWR_STATE_MASK         = BIT(28),
-       ZONE_MEM_PWR_STATE_MASK         = BIT(29),
-       ZONE_RESET_STATE_MASK           = BIT(31),
-       CPU0_PWR_ZONE_CTRL_REG          = 1,
-       CPU_RESET_CONFIG_REG            = 2,
-};
-
-static void __iomem *cpubiuctrl_block;
-static void __iomem *hif_cont_block;
-static u32 cpu0_pwr_zone_ctrl_reg;
-static u32 cpu_rst_cfg_reg;
-static u32 hif_cont_reg;
-
-#ifdef CONFIG_HOTPLUG_CPU
-static DEFINE_PER_CPU_ALIGNED(int, per_cpu_sw_state);
-
-static int per_cpu_sw_state_rd(u32 cpu)
-{
-       sync_cache_r(SHIFT_PERCPU_PTR(&per_cpu_sw_state, per_cpu_offset(cpu)));
-       return per_cpu(per_cpu_sw_state, cpu);
-}
-
-static void per_cpu_sw_state_wr(u32 cpu, int val)
-{
-       per_cpu(per_cpu_sw_state, cpu) = val;
-       dmb();
-       sync_cache_w(SHIFT_PERCPU_PTR(&per_cpu_sw_state, per_cpu_offset(cpu)));
-       dsb_sev();
-}
-#else
-static inline void per_cpu_sw_state_wr(u32 cpu, int val) { }
-#endif
-
-static void __iomem *pwr_ctrl_get_base(u32 cpu)
-{
-       void __iomem *base = cpubiuctrl_block + cpu0_pwr_zone_ctrl_reg;
-       base += (cpu_logical_map(cpu) * 4);
-       return base;
-}
-
-static u32 pwr_ctrl_rd(u32 cpu)
-{
-       void __iomem *base = pwr_ctrl_get_base(cpu);
-       return readl_relaxed(base);
-}
-
-static void pwr_ctrl_wr(u32 cpu, u32 val)
-{
-       void __iomem *base = pwr_ctrl_get_base(cpu);
-       writel(val, base);
-}
-
-static void cpu_rst_cfg_set(u32 cpu, int set)
-{
-       u32 val;
-       val = readl_relaxed(cpubiuctrl_block + cpu_rst_cfg_reg);
-       if (set)
-               val |= BIT(cpu_logical_map(cpu));
-       else
-               val &= ~BIT(cpu_logical_map(cpu));
-       writel_relaxed(val, cpubiuctrl_block + cpu_rst_cfg_reg);
-}
-
-static void cpu_set_boot_addr(u32 cpu, unsigned long boot_addr)
-{
-       const int reg_ofs = cpu_logical_map(cpu) * 8;
-       writel_relaxed(0, hif_cont_block + hif_cont_reg + reg_ofs);
-       writel_relaxed(boot_addr, hif_cont_block + hif_cont_reg + 4 + reg_ofs);
-}
-
-static void brcmstb_cpu_boot(u32 cpu)
-{
-       pr_info("SMP: Booting CPU%d...\n", cpu);
-
-       /*
-        * set the reset vector to point to the secondary_startup
-        * routine
-        */
-       cpu_set_boot_addr(cpu, virt_to_phys(brcmstb_secondary_startup));
-
-       /* unhalt the cpu */
-       cpu_rst_cfg_set(cpu, 0);
-}
-
-static void brcmstb_cpu_power_on(u32 cpu)
-{
-       /*
-        * The secondary cores power was cut, so we must go through
-        * power-on initialization.
-        */
-       u32 tmp;
-
-       pr_info("SMP: Powering up CPU%d...\n", cpu);
-
-       /* Request zone power up */
-       pwr_ctrl_wr(cpu, ZONE_PWR_UP_REQ_MASK);
-
-       /* Wait for the power up FSM to complete */
-       do {
-               tmp = pwr_ctrl_rd(cpu);
-       } while (!(tmp & ZONE_PWR_ON_STATE_MASK));
-
-       per_cpu_sw_state_wr(cpu, 1);
-}
-
-static int brcmstb_cpu_get_power_state(u32 cpu)
-{
-       int tmp = pwr_ctrl_rd(cpu);
-       return (tmp & ZONE_RESET_STATE_MASK) ? 0 : 1;
-}
-
-#ifdef CONFIG_HOTPLUG_CPU
-
-static void brcmstb_cpu_die(u32 cpu)
-{
-       v7_exit_coherency_flush(all);
-
-       /* Prevent all interrupts from reaching this CPU. */
-       arch_local_irq_disable();
-
-       /*
-        * Final full barrier to ensure everything before this instruction has
-        * quiesced.
-        */
-       isb();
-       dsb();
-
-       per_cpu_sw_state_wr(cpu, 0);
-
-       /* Sit and wait to die */
-       wfi();
-
-       /* We should never get here... */
-       panic("Spurious interrupt on CPU %d received!\n", cpu);
-}
-
-static int brcmstb_cpu_kill(u32 cpu)
-{
-       u32 tmp;
-
-       pr_info("SMP: Powering down CPU%d...\n", cpu);
-
-       while (per_cpu_sw_state_rd(cpu))
-               ;
-
-       /* Program zone reset */
-       pwr_ctrl_wr(cpu, ZONE_RESET_STATE_MASK | ZONE_BLK_RST_ASSERT_MASK |
-                             ZONE_PWR_DN_REQ_MASK);
-
-       /* Verify zone reset */
-       tmp = pwr_ctrl_rd(cpu);
-       if (!(tmp & ZONE_RESET_STATE_MASK))
-               pr_err("%s: Zone reset bit for CPU %d not asserted!\n",
-                       __func__, cpu);
-
-       /* Wait for power down */
-       do {
-               tmp = pwr_ctrl_rd(cpu);
-       } while (!(tmp & ZONE_PWR_OFF_STATE_MASK));
-
-       /* Settle-time from Broadcom-internal DVT reference code */
-       udelay(7);
-
-       /* Assert reset on the CPU */
-       cpu_rst_cfg_set(cpu, 1);
-
-       return 1;
-}
-
-#endif /* CONFIG_HOTPLUG_CPU */
-
-static int __init setup_hifcpubiuctrl_regs(struct device_node *np)
-{
-       int rc = 0;
-       char *name;
-       struct device_node *syscon_np = NULL;
-
-       name = "syscon-cpu";
-
-       syscon_np = of_parse_phandle(np, name, 0);
-       if (!syscon_np) {
-               pr_err("can't find phandle %s\n", name);
-               rc = -EINVAL;
-               goto cleanup;
-       }
-
-       cpubiuctrl_block = of_iomap(syscon_np, 0);
-       if (!cpubiuctrl_block) {
-               pr_err("iomap failed for cpubiuctrl_block\n");
-               rc = -EINVAL;
-               goto cleanup;
-       }
-
-       rc = of_property_read_u32_index(np, name, CPU0_PWR_ZONE_CTRL_REG,
-                                       &cpu0_pwr_zone_ctrl_reg);
-       if (rc) {
-               pr_err("failed to read 1st entry from %s property (%d)\n", name,
-                       rc);
-               rc = -EINVAL;
-               goto cleanup;
-       }
-
-       rc = of_property_read_u32_index(np, name, CPU_RESET_CONFIG_REG,
-                                       &cpu_rst_cfg_reg);
-       if (rc) {
-               pr_err("failed to read 2nd entry from %s property (%d)\n", name,
-                       rc);
-               rc = -EINVAL;
-               goto cleanup;
-       }
-
-cleanup:
-       if (syscon_np)
-               of_node_put(syscon_np);
-
-       return rc;
-}
-
-static int __init setup_hifcont_regs(struct device_node *np)
-{
-       int rc = 0;
-       char *name;
-       struct device_node *syscon_np = NULL;
-
-       name = "syscon-cont";
-
-       syscon_np = of_parse_phandle(np, name, 0);
-       if (!syscon_np) {
-               pr_err("can't find phandle %s\n", name);
-               rc = -EINVAL;
-               goto cleanup;
-       }
-
-       hif_cont_block = of_iomap(syscon_np, 0);
-       if (!hif_cont_block) {
-               pr_err("iomap failed for hif_cont_block\n");
-               rc = -EINVAL;
-               goto cleanup;
-       }
-
-       /* offset is at top of hif_cont_block */
-       hif_cont_reg = 0;
-
-cleanup:
-       if (syscon_np)
-               of_node_put(syscon_np);
-
-       return rc;
-}
-
-static void __init brcmstb_cpu_ctrl_setup(unsigned int max_cpus)
-{
-       int rc;
-       struct device_node *np;
-       char *name;
-
-       name = "brcm,brcmstb-smpboot";
-       np = of_find_compatible_node(NULL, NULL, name);
-       if (!np) {
-               pr_err("can't find compatible node %s\n", name);
-               return;
-       }
-
-       rc = setup_hifcpubiuctrl_regs(np);
-       if (rc)
-               return;
-
-       rc = setup_hifcont_regs(np);
-       if (rc)
-               return;
-}
-
-static DEFINE_SPINLOCK(boot_lock);
-
-static void brcmstb_secondary_init(unsigned int cpu)
-{
-       /*
-        * Synchronise with the boot thread.
-        */
-       spin_lock(&boot_lock);
-       spin_unlock(&boot_lock);
-}
-
-static int brcmstb_boot_secondary(unsigned int cpu, struct task_struct *idle)
-{
-       /*
-        * set synchronisation state between this boot processor
-        * and the secondary one
-        */
-       spin_lock(&boot_lock);
-
-       /* Bring up power to the core if necessary */
-       if (brcmstb_cpu_get_power_state(cpu) == 0)
-               brcmstb_cpu_power_on(cpu);
-
-       brcmstb_cpu_boot(cpu);
-
-       /*
-        * now the secondary core is starting up let it run its
-        * calibrations, then wait for it to finish
-        */
-       spin_unlock(&boot_lock);
-
-       return 0;
-}
-
-static struct smp_operations brcmstb_smp_ops __initdata = {
-       .smp_prepare_cpus       = brcmstb_cpu_ctrl_setup,
-       .smp_secondary_init     = brcmstb_secondary_init,
-       .smp_boot_secondary     = brcmstb_boot_secondary,
-#ifdef CONFIG_HOTPLUG_CPU
-       .cpu_kill               = brcmstb_cpu_kill,
-       .cpu_die                = brcmstb_cpu_die,
-#endif
-};
-
-CPU_METHOD_OF_DECLARE(brcmstb_smp, "brcm,brahma-b15", &brcmstb_smp_ops);
index b2f8b60cf0e9035c0b8eabb4ef6fae098c8bcbf7..dc9a764a7c371d9b1ad5f27e14038cdbeca8690f 100644 (file)
@@ -43,7 +43,6 @@
        "mcr    p15, 0, r0, c1, c0, 0   @ set SCTLR\n\t" \
        "isb\n\t"\
        "bl     v7_flush_dcache_"__stringify(level)"\n\t" \
-       "clrex\n\t"\
        "mrc    p15, 0, r0, c1, c0, 1   @ get ACTLR\n\t" \
        "bic    r0, r0, #(1 << 6)       @ disable local coherency\n\t" \
        /* Dummy Load of a device register to avoid Erratum 799270 */ \
index e87f2a83d6bfccf809fe6d5c1cf16cbd474a8f70..2d245c2e641cd9314378def624b45093951a59cc 100644 (file)
@@ -142,7 +142,7 @@ __init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs,
        board_nand_data.nr_parts        = nr_parts;
        board_nand_data.devsize         = nand_type;
 
-       board_nand_data.ecc_opt = OMAP_ECC_HAM1_CODE_HW;
+       board_nand_data.ecc_opt = OMAP_ECC_HAM1_CODE_SW;
        gpmc_nand_init(&board_nand_data, gpmc_t);
 }
 #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
index 8897ad7035fd448bf8021a9aea06c3684639fb3f..cb7764314f1736206c9dba849e2e777c76cbb1e7 100644 (file)
@@ -49,7 +49,8 @@ static bool gpmc_hwecc_bch_capable(enum omap_ecc ecc_opt)
                return 0;
 
        /* legacy platforms support only HAM1 (1-bit Hamming) ECC scheme */
-       if (ecc_opt == OMAP_ECC_HAM1_CODE_HW)
+       if (ecc_opt == OMAP_ECC_HAM1_CODE_HW ||
+           ecc_opt == OMAP_ECC_HAM1_CODE_SW)
                return 1;
        else
                return 0;
index 8bc13380f0a06ec14859b8c274883142a14ef968..2f97228f188aa3a835146d81bb7bffc2edcb039d 100644 (file)
@@ -1207,8 +1207,7 @@ int gpmc_cs_program_settings(int cs, struct gpmc_settings *p)
                }
        }
 
-       if ((p->wait_on_read || p->wait_on_write) &&
-           (p->wait_pin > gpmc_nr_waitpins)) {
+       if (p->wait_pin > gpmc_nr_waitpins) {
                pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin);
                return -EINVAL;
        }
@@ -1288,8 +1287,8 @@ void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p)
                p->wait_on_write = of_property_read_bool(np,
                                                         "gpmc,wait-on-write");
                if (!p->wait_on_read && !p->wait_on_write)
-                       pr_warn("%s: read/write wait monitoring not enabled!\n",
-                               __func__);
+                       pr_debug("%s: rd/wr wait monitoring not enabled!\n",
+                                __func__);
        }
 }
 
@@ -1403,8 +1402,11 @@ static int gpmc_probe_nand_child(struct platform_device *pdev,
                pr_err("%s: ti,nand-ecc-opt not found\n", __func__);
                return -ENODEV;
        }
-       if (!strcmp(s, "ham1") || !strcmp(s, "sw") ||
-               !strcmp(s, "hw") || !strcmp(s, "hw-romcode"))
+
+       if (!strcmp(s, "sw"))
+               gpmc_nand_data->ecc_opt = OMAP_ECC_HAM1_CODE_SW;
+       else if (!strcmp(s, "ham1") ||
+                !strcmp(s, "hw") || !strcmp(s, "hw-romcode"))
                gpmc_nand_data->ecc_opt =
                                OMAP_ECC_HAM1_CODE_HW;
        else if (!strcmp(s, "bch4"))
index d42022f2a71e67c6588fda9b02294625940bb3bf..53841dea80ea5c2eaf040c8180922c95ccff18b1 100644 (file)
@@ -663,7 +663,7 @@ void __init dra7xxx_check_revision(void)
 
        default:
                /* Unknown default to latest silicon rev as default*/
-               pr_warn("%s: unknown idcode=0x%08x (hawkeye=0x%08x,rev=0x%d)\n",
+               pr_warn("%s: unknown idcode=0x%08x (hawkeye=0x%08x,rev=0x%x)\n",
                        __func__, idcode, hawkeye, rev);
                omap_revision = DRA752_REV_ES1_1;
        }
index 01ef59def44b86e84a5a1afc1b84d34f0caa17e4..d22c30d3ccfa0809d2662cbd5390c20f40b24a55 100644 (file)
@@ -56,7 +56,7 @@ static void _add_clkdev(struct omap_device *od, const char *clk_alias,
 
        r = clk_get_sys(dev_name(&od->pdev->dev), clk_alias);
        if (!IS_ERR(r)) {
-               dev_warn(&od->pdev->dev,
+               dev_dbg(&od->pdev->dev,
                         "alias %s already exists\n", clk_alias);
                clk_put(r);
                return;
index 6c074f37cdd2ac57aa6a1ba2673b5e9fbcb3c3ca..8fd87a3055bf6c4a084a25a51f19e4263567add7 100644 (file)
@@ -2185,6 +2185,8 @@ static int _enable(struct omap_hwmod *oh)
                         oh->mux->pads_dynamic))) {
                omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
                _reconfigure_io_chain();
+       } else if (oh->flags & HWMOD_FORCE_MSTANDBY) {
+               _reconfigure_io_chain();
        }
 
        _add_initiator_dep(oh, mpu_oh);
@@ -2291,6 +2293,8 @@ static int _idle(struct omap_hwmod *oh)
        if (oh->mux && oh->mux->pads_dynamic) {
                omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
                _reconfigure_io_chain();
+       } else if (oh->flags & HWMOD_FORCE_MSTANDBY) {
+               _reconfigure_io_chain();
        }
 
        oh->_state = _HWMOD_STATE_IDLE;
@@ -3345,6 +3349,9 @@ int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois)
        if (!ois)
                return 0;
 
+       if (ois[0] == NULL) /* Empty list */
+               return 0;
+
        if (!linkspace) {
                if (_alloc_linkspace(ois)) {
                        pr_err("omap_hwmod: could not allocate link space\n");
index 2757abf87fbc5216662daa5ae87e06c991940756..5684f112654bb9dc6688f43fc2defa58dcbf7d65 100644 (file)
@@ -35,6 +35,7 @@
 #include "i2c.h"
 #include "mmc.h"
 #include "wd_timer.h"
+#include "soc.h"
 
 /* Base offset for all DRA7XX interrupts external to MPUSS */
 #define DRA7XX_IRQ_GIC_START   32
@@ -3261,7 +3262,6 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
        &dra7xx_l4_per3__usb_otg_ss1,
        &dra7xx_l4_per3__usb_otg_ss2,
        &dra7xx_l4_per3__usb_otg_ss3,
-       &dra7xx_l4_per3__usb_otg_ss4,
        &dra7xx_l3_main_1__vcp1,
        &dra7xx_l4_per2__vcp1,
        &dra7xx_l3_main_1__vcp2,
@@ -3270,8 +3270,26 @@ static struct omap_hwmod_ocp_if *dra7xx_hwmod_ocp_ifs[] __initdata = {
        NULL,
 };
 
+static struct omap_hwmod_ocp_if *dra74x_hwmod_ocp_ifs[] __initdata = {
+       &dra7xx_l4_per3__usb_otg_ss4,
+       NULL,
+};
+
+static struct omap_hwmod_ocp_if *dra72x_hwmod_ocp_ifs[] __initdata = {
+       NULL,
+};
+
 int __init dra7xx_hwmod_init(void)
 {
+       int ret;
+
        omap_hwmod_init();
-       return omap_hwmod_register_links(dra7xx_hwmod_ocp_ifs);
+       ret = omap_hwmod_register_links(dra7xx_hwmod_ocp_ifs);
+
+       if (!ret && soc_is_dra74x())
+               return omap_hwmod_register_links(dra74x_hwmod_ocp_ifs);
+       else if (!ret && soc_is_dra72x())
+               return omap_hwmod_register_links(dra72x_hwmod_ocp_ifs);
+
+       return ret;
 }
index 01ca8086fb6c734a984b973fb4bfab30eff152e6..4376f59626d1fd5b1117eb4de8d1c33ba6e5ef01 100644 (file)
@@ -245,6 +245,8 @@ IS_AM_SUBCLASS(437x, 0x437)
 #define soc_is_omap54xx()              0
 #define soc_is_omap543x()              0
 #define soc_is_dra7xx()                        0
+#define soc_is_dra74x()                        0
+#define soc_is_dra72x()                        0
 
 #if defined(MULTI_OMAP2)
 # if defined(CONFIG_ARCH_OMAP2)
@@ -393,7 +395,11 @@ IS_OMAP_TYPE(3430, 0x3430)
 
 #if defined(CONFIG_SOC_DRA7XX)
 #undef soc_is_dra7xx
+#undef soc_is_dra74x
+#undef soc_is_dra72x
 #define soc_is_dra7xx()        (of_machine_is_compatible("ti,dra7"))
+#define soc_is_dra74x()        (of_machine_is_compatible("ti,dra74"))
+#define soc_is_dra72x()        (of_machine_is_compatible("ti,dra72"))
 #endif
 
 /* Various silicon revisions for omap2 */
index 17435c1aa2fe318ceeb4692632bd986ce5484655..126ddafad5265dc62793fd6e7f25aea16b7c42e1 100644 (file)
@@ -183,8 +183,8 @@ enum {
 
 static struct clk div4_clks[DIV4_NR] = {
        [DIV4_SDH] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 8, 0x0dff, CLK_ENABLE_ON_INIT),
-       [DIV4_SD0] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 4, 0x1de0, CLK_ENABLE_ON_INIT),
-       [DIV4_SD1] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 0, 0x1de0, CLK_ENABLE_ON_INIT),
+       [DIV4_SD0] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 4, 0x1df0, CLK_ENABLE_ON_INIT),
+       [DIV4_SD1] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 0, 0x1df0, CLK_ENABLE_ON_INIT),
 };
 
 /* DIV6 clocks */
index 10e193d707f531216776695b5da2cf0c65de418a..453b23129cfa0cd3903e7ebdc3aaef8009bb3542 100644 (file)
@@ -152,7 +152,7 @@ enum {
 
 static struct clk div4_clks[DIV4_NR] = {
        [DIV4_SDH] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 8, 0x0dff, CLK_ENABLE_ON_INIT),
-       [DIV4_SD0] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 4, 0x1de0, CLK_ENABLE_ON_INIT),
+       [DIV4_SD0] = SH_CLK_DIV4(&pll1_clk, SDCKCR, 4, 0x1df0, CLK_ENABLE_ON_INIT),
 };
 
 /* DIV6 clocks */
index d8c4048b9e338d345bb5e5ceb682e3ded7df09ce..02a6f45a0b9e1c832d5c5d6bfcb79395a42363a2 100644 (file)
@@ -644,7 +644,7 @@ static struct clk_lookup lookups[] = {
        CLKDEV_DEV_ID("sh-sci.5", &mstp_clks[MSTP207]), /* SCIFA5 */
        CLKDEV_DEV_ID("e6cb0000.serial", &mstp_clks[MSTP207]), /* SCIFA5 */
        CLKDEV_DEV_ID("sh-sci.8", &mstp_clks[MSTP206]), /* SCIFB */
-       CLKDEV_DEV_ID("0xe6c3000.serial", &mstp_clks[MSTP206]), /* SCIFB */
+       CLKDEV_DEV_ID("e6c3000.serial", &mstp_clks[MSTP206]), /* SCIFB */
        CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[MSTP204]), /* SCIFA0 */
        CLKDEV_DEV_ID("e6c40000.serial", &mstp_clks[MSTP204]), /* SCIFA0 */
        CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[MSTP203]), /* SCIFA1 */
index 2c2754e79cb37d3fbcd9aff04ca086e4ba6f5274..f61158c6ce7185a3b30ef396116a7fc2d74b3c72 100644 (file)
@@ -426,9 +426,15 @@ static int ve_spc_populate_opps(uint32_t cluster)
 
 static int ve_init_opp_table(struct device *cpu_dev)
 {
-       int cluster = topology_physical_package_id(cpu_dev->id);
-       int idx, ret = 0, max_opp = info->num_opps[cluster];
-       struct ve_spc_opp *opps = info->opps[cluster];
+       int cluster;
+       int idx, ret = 0, max_opp;
+       struct ve_spc_opp *opps;
+
+       cluster = topology_physical_package_id(cpu_dev->id);
+       cluster = cluster < 0 ? 0 : cluster;
+
+       max_opp = info->num_opps[cluster];
+       opps = info->opps[cluster];
 
        for (idx = 0; idx < max_opp; idx++, opps++) {
                ret = dev_pm_opp_add(cpu_dev, opps->freq * 1000, opps->u_volt);
@@ -537,6 +543,8 @@ static struct clk *ve_spc_clk_register(struct device *cpu_dev)
        spc->hw.init = &init;
        spc->cluster = topology_physical_package_id(cpu_dev->id);
 
+       spc->cluster = spc->cluster < 0 ? 0 : spc->cluster;
+
        init.name = dev_name(cpu_dev);
        init.ops = &clk_spc_ops;
        init.flags = CLK_IS_ROOT | CLK_GET_RATE_NOCACHE;
index 3815a8262af070b98f33d61ac31908961ee06eb2..8c48c5c22a331aac8f547335d6990c598457ef0b 100644 (file)
  */
        .align  5
 ENTRY(v6_early_abort)
-#ifdef CONFIG_CPU_V6
-       sub     r1, sp, #4                      @ Get unused stack location
-       strex   r0, r1, [r1]                    @ Clear the exclusive monitor
-#elif defined(CONFIG_CPU_32v6K)
-       clrex
-#endif
        mrc     p15, 0, r1, c5, c0, 0           @ get FSR
        mrc     p15, 0, r0, c6, c0, 0           @ get FAR
 /*
index 703375277ba6d3dcdae7f93404d2d19e531aad68..4812ad054214572ba6e7198247e2c190e469897d 100644 (file)
  */
        .align  5
 ENTRY(v7_early_abort)
-       /*
-        * The effect of data aborts on on the exclusive access monitor are
-        * UNPREDICTABLE. Do a CLREX to clear the state
-        */
-       clrex
-
        mrc     p15, 0, r1, c5, c0, 0           @ get FSR
        mrc     p15, 0, r0, c6, c0, 0           @ get FAR
 
index 12969523414cf2d0b972bdfb8b3ff50b9c781c8f..1f85bfe6b4704d97e999b748f46a61a362f20d66 100644 (file)
@@ -1 +1 @@
-obj-y          := enlighten.o hypercall.o grant-table.o p2m.o mm.o
+obj-y          := enlighten.o hypercall.o grant-table.o p2m.o mm.o mm32.o
index 98544c5f86e99710a7845e7a55648cdf73c14599..0e15f011f9c86895db17d57e0e1e999164d0312c 100644 (file)
@@ -260,6 +260,12 @@ static int __init xen_guest_init(void)
        xen_domain_type = XEN_HVM_DOMAIN;
 
        xen_setup_features();
+
+       if (!xen_feature(XENFEAT_grant_map_identity)) {
+               pr_warn("Please upgrade your Xen.\n"
+                               "If your platform has any non-coherent DMA devices, they won't work properly.\n");
+       }
+
        if (xen_feature(XENFEAT_dom0))
                xen_start_info->flags |= SIF_INITDOMAIN|SIF_PRIVILEGED;
        else
diff --git a/arch/arm/xen/mm32.c b/arch/arm/xen/mm32.c
new file mode 100644 (file)
index 0000000..3b99860
--- /dev/null
@@ -0,0 +1,202 @@
+#include <linux/cpu.h>
+#include <linux/dma-mapping.h>
+#include <linux/gfp.h>
+#include <linux/highmem.h>
+
+#include <xen/features.h>
+
+static DEFINE_PER_CPU(unsigned long, xen_mm32_scratch_virt);
+static DEFINE_PER_CPU(pte_t *, xen_mm32_scratch_ptep);
+
+static int alloc_xen_mm32_scratch_page(int cpu)
+{
+       struct page *page;
+       unsigned long virt;
+       pmd_t *pmdp;
+       pte_t *ptep;
+
+       if (per_cpu(xen_mm32_scratch_ptep, cpu) != NULL)
+               return 0;
+
+       page = alloc_page(GFP_KERNEL);
+       if (page == NULL) {
+               pr_warn("Failed to allocate xen_mm32_scratch_page for cpu %d\n", cpu);
+               return -ENOMEM;
+       }
+
+       virt = (unsigned long)__va(page_to_phys(page));
+       pmdp = pmd_offset(pud_offset(pgd_offset_k(virt), virt), virt);
+       ptep = pte_offset_kernel(pmdp, virt);
+
+       per_cpu(xen_mm32_scratch_virt, cpu) = virt;
+       per_cpu(xen_mm32_scratch_ptep, cpu) = ptep;
+
+       return 0;
+}
+
+static int xen_mm32_cpu_notify(struct notifier_block *self,
+                                   unsigned long action, void *hcpu)
+{
+       int cpu = (long)hcpu;
+       switch (action) {
+       case CPU_UP_PREPARE:
+               if (alloc_xen_mm32_scratch_page(cpu))
+                       return NOTIFY_BAD;
+               break;
+       default:
+               break;
+       }
+       return NOTIFY_OK;
+}
+
+static struct notifier_block xen_mm32_cpu_notifier = {
+       .notifier_call  = xen_mm32_cpu_notify,
+};
+
+static void* xen_mm32_remap_page(dma_addr_t handle)
+{
+       unsigned long virt = get_cpu_var(xen_mm32_scratch_virt);
+       pte_t *ptep = __get_cpu_var(xen_mm32_scratch_ptep);
+
+       *ptep = pfn_pte(handle >> PAGE_SHIFT, PAGE_KERNEL);
+       local_flush_tlb_kernel_page(virt);
+
+       return (void*)virt;
+}
+
+static void xen_mm32_unmap(void *vaddr)
+{
+       put_cpu_var(xen_mm32_scratch_virt);
+}
+
+
+/* functions called by SWIOTLB */
+
+static void dma_cache_maint(dma_addr_t handle, unsigned long offset,
+       size_t size, enum dma_data_direction dir,
+       void (*op)(const void *, size_t, int))
+{
+       unsigned long pfn;
+       size_t left = size;
+
+       pfn = (handle >> PAGE_SHIFT) + offset / PAGE_SIZE;
+       offset %= PAGE_SIZE;
+
+       do {
+               size_t len = left;
+               void *vaddr;
+       
+               if (!pfn_valid(pfn))
+               {
+                       /* Cannot map the page, we don't know its physical address.
+                        * Return and hope for the best */
+                       if (!xen_feature(XENFEAT_grant_map_identity))
+                               return;
+                       vaddr = xen_mm32_remap_page(handle) + offset;
+                       op(vaddr, len, dir);
+                       xen_mm32_unmap(vaddr - offset);
+               } else {
+                       struct page *page = pfn_to_page(pfn);
+
+                       if (PageHighMem(page)) {
+                               if (len + offset > PAGE_SIZE)
+                                       len = PAGE_SIZE - offset;
+
+                               if (cache_is_vipt_nonaliasing()) {
+                                       vaddr = kmap_atomic(page);
+                                       op(vaddr + offset, len, dir);
+                                       kunmap_atomic(vaddr);
+                               } else {
+                                       vaddr = kmap_high_get(page);
+                                       if (vaddr) {
+                                               op(vaddr + offset, len, dir);
+                                               kunmap_high(page);
+                                       }
+                               }
+                       } else {
+                               vaddr = page_address(page) + offset;
+                               op(vaddr, len, dir);
+                       }
+               }
+
+               offset = 0;
+               pfn++;
+               left -= len;
+       } while (left);
+}
+
+static void __xen_dma_page_dev_to_cpu(struct device *hwdev, dma_addr_t handle,
+               size_t size, enum dma_data_direction dir)
+{
+       /* Cannot use __dma_page_dev_to_cpu because we don't have a
+        * struct page for handle */
+
+       if (dir != DMA_TO_DEVICE)
+               outer_inv_range(handle, handle + size);
+
+       dma_cache_maint(handle & PAGE_MASK, handle & ~PAGE_MASK, size, dir, dmac_unmap_area);
+}
+
+static void __xen_dma_page_cpu_to_dev(struct device *hwdev, dma_addr_t handle,
+               size_t size, enum dma_data_direction dir)
+{
+
+       dma_cache_maint(handle & PAGE_MASK, handle & ~PAGE_MASK, size, dir, dmac_map_area);
+
+       if (dir == DMA_FROM_DEVICE) {
+               outer_inv_range(handle, handle + size);
+       } else {
+               outer_clean_range(handle, handle + size);
+       }
+}
+
+void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
+               size_t size, enum dma_data_direction dir,
+               struct dma_attrs *attrs)
+
+{
+       if (!__generic_dma_ops(hwdev)->unmap_page)
+               return;
+       if (dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
+               return;
+
+       __xen_dma_page_dev_to_cpu(hwdev, handle, size, dir);
+}
+
+void xen_dma_sync_single_for_cpu(struct device *hwdev,
+               dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+       if (!__generic_dma_ops(hwdev)->sync_single_for_cpu)
+               return;
+       __xen_dma_page_dev_to_cpu(hwdev, handle, size, dir);
+}
+
+void xen_dma_sync_single_for_device(struct device *hwdev,
+               dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+       if (!__generic_dma_ops(hwdev)->sync_single_for_device)
+               return;
+       __xen_dma_page_cpu_to_dev(hwdev, handle, size, dir);
+}
+
+int __init xen_mm32_init(void)
+{
+       int cpu;
+
+       if (!xen_initial_domain())
+               return 0;
+
+       register_cpu_notifier(&xen_mm32_cpu_notifier);
+       get_online_cpus();
+       for_each_online_cpu(cpu) {
+               if (alloc_xen_mm32_scratch_page(cpu)) {
+                       put_online_cpus();
+                       unregister_cpu_notifier(&xen_mm32_cpu_notifier);
+                       return -ENOMEM;
+               }
+       }
+       put_online_cpus();
+
+       return 0;
+}
+arch_initcall(xen_mm32_init);
index 97baf44278171680a0932f949c22e8e26c54926f..05485777625474e835fc41a5d57fb494ca778552 100644 (file)
@@ -21,14 +21,12 @@ struct xen_p2m_entry {
        unsigned long pfn;
        unsigned long mfn;
        unsigned long nr_pages;
-       struct rb_node rbnode_mach;
        struct rb_node rbnode_phys;
 };
 
 static rwlock_t p2m_lock;
 struct rb_root phys_to_mach = RB_ROOT;
 EXPORT_SYMBOL_GPL(phys_to_mach);
-static struct rb_root mach_to_phys = RB_ROOT;
 
 static int xen_add_phys_to_mach_entry(struct xen_p2m_entry *new)
 {
@@ -41,8 +39,6 @@ static int xen_add_phys_to_mach_entry(struct xen_p2m_entry *new)
                parent = *link;
                entry = rb_entry(parent, struct xen_p2m_entry, rbnode_phys);
 
-               if (new->mfn == entry->mfn)
-                       goto err_out;
                if (new->pfn == entry->pfn)
                        goto err_out;
 
@@ -88,64 +84,6 @@ unsigned long __pfn_to_mfn(unsigned long pfn)
 }
 EXPORT_SYMBOL_GPL(__pfn_to_mfn);
 
-static int xen_add_mach_to_phys_entry(struct xen_p2m_entry *new)
-{
-       struct rb_node **link = &mach_to_phys.rb_node;
-       struct rb_node *parent = NULL;
-       struct xen_p2m_entry *entry;
-       int rc = 0;
-
-       while (*link) {
-               parent = *link;
-               entry = rb_entry(parent, struct xen_p2m_entry, rbnode_mach);
-
-               if (new->mfn == entry->mfn)
-                       goto err_out;
-               if (new->pfn == entry->pfn)
-                       goto err_out;
-
-               if (new->mfn < entry->mfn)
-                       link = &(*link)->rb_left;
-               else
-                       link = &(*link)->rb_right;
-       }
-       rb_link_node(&new->rbnode_mach, parent, link);
-       rb_insert_color(&new->rbnode_mach, &mach_to_phys);
-       goto out;
-
-err_out:
-       rc = -EINVAL;
-       pr_warn("%s: cannot add pfn=%pa -> mfn=%pa: pfn=%pa -> mfn=%pa already exists\n",
-                       __func__, &new->pfn, &new->mfn, &entry->pfn, &entry->mfn);
-out:
-       return rc;
-}
-
-unsigned long __mfn_to_pfn(unsigned long mfn)
-{
-       struct rb_node *n = mach_to_phys.rb_node;
-       struct xen_p2m_entry *entry;
-       unsigned long irqflags;
-
-       read_lock_irqsave(&p2m_lock, irqflags);
-       while (n) {
-               entry = rb_entry(n, struct xen_p2m_entry, rbnode_mach);
-               if (entry->mfn <= mfn &&
-                               entry->mfn + entry->nr_pages > mfn) {
-                       read_unlock_irqrestore(&p2m_lock, irqflags);
-                       return entry->pfn + (mfn - entry->mfn);
-               }
-               if (mfn < entry->mfn)
-                       n = n->rb_left;
-               else
-                       n = n->rb_right;
-       }
-       read_unlock_irqrestore(&p2m_lock, irqflags);
-
-       return INVALID_P2M_ENTRY;
-}
-EXPORT_SYMBOL_GPL(__mfn_to_pfn);
-
 int set_foreign_p2m_mapping(struct gnttab_map_grant_ref *map_ops,
                            struct gnttab_map_grant_ref *kmap_ops,
                            struct page **pages, unsigned int count)
@@ -192,7 +130,6 @@ bool __set_phys_to_machine_multi(unsigned long pfn,
                        p2m_entry = rb_entry(n, struct xen_p2m_entry, rbnode_phys);
                        if (p2m_entry->pfn <= pfn &&
                                        p2m_entry->pfn + p2m_entry->nr_pages > pfn) {
-                               rb_erase(&p2m_entry->rbnode_mach, &mach_to_phys);
                                rb_erase(&p2m_entry->rbnode_phys, &phys_to_mach);
                                write_unlock_irqrestore(&p2m_lock, irqflags);
                                kfree(p2m_entry);
@@ -217,8 +154,7 @@ bool __set_phys_to_machine_multi(unsigned long pfn,
        p2m_entry->mfn = mfn;
 
        write_lock_irqsave(&p2m_lock, irqflags);
-       if ((rc = xen_add_phys_to_mach_entry(p2m_entry) < 0) ||
-               (rc = xen_add_mach_to_phys_entry(p2m_entry) < 0)) {
+       if ((rc = xen_add_phys_to_mach_entry(p2m_entry)) < 0) {
                write_unlock_irqrestore(&p2m_lock, irqflags);
                return false;
        }
index c294e67d3925e13401526b4b57ce9637bdb92092..ae67e88c28b99497b4ae394bc849bdb20cacdd02 100644 (file)
@@ -150,7 +150,6 @@ static void sha2_finup(struct shash_desc *desc, const u8 *data,
        kernel_neon_begin_partial(28);
        sha2_ce_transform(blocks, data, sctx->state, NULL, len);
        kernel_neon_end();
-       data += blocks * SHA256_BLOCK_SIZE;
 }
 
 static int sha224_finup(struct shash_desc *desc, const u8 *data,
index d064047612b12acb2668927c4b3cedf504d22c11..52b484b6aa1a7fec251a72b028f655523c74236a 100644 (file)
@@ -79,7 +79,6 @@ static inline void decode_ctrl_reg(u32 reg,
  */
 #define ARM_MAX_BRP            16
 #define ARM_MAX_WRP            16
-#define ARM_MAX_HBP_SLOTS      (ARM_MAX_BRP + ARM_MAX_WRP)
 
 /* Virtual debug register bases. */
 #define AARCH64_DBG_REG_BVR    0
index 3df21feeabddfca221e3a65063634ca339e4c0d9..286b1bec547ce2a060d01cf816893b2b4aef9d12 100644 (file)
@@ -139,7 +139,7 @@ extern struct task_struct *cpu_switch_to(struct task_struct *prev,
        ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
 
 #define KSTK_EIP(tsk)  ((unsigned long)task_pt_regs(tsk)->pc)
-#define KSTK_ESP(tsk)  ((unsigned long)task_pt_regs(tsk)->sp)
+#define KSTK_ESP(tsk)  user_stack_pointer(task_pt_regs(tsk))
 
 /*
  * Prefetching support
index 501000fadb6fde2249096d3dc6ee027cba427e14..41ed9e13795e59411b701f7590d3a5386f52ba01 100644 (file)
@@ -137,7 +137,7 @@ struct pt_regs {
        (!((regs)->pstate & PSR_F_BIT))
 
 #define user_stack_pointer(regs) \
-       (!compat_user_mode(regs)) ? ((regs)->sp) : ((regs)->compat_sp)
+       (!compat_user_mode(regs) ? (regs)->sp : (regs)->compat_sp)
 
 static inline unsigned long regs_return_value(struct pt_regs *regs)
 {
index ad8aebb1cdef7d289d609015bc22d51498cddc08..3dca15634e69c6b1b34db6e00b3564089129326b 100644 (file)
@@ -270,6 +270,7 @@ static int fpsimd_cpu_pm_notifier(struct notifier_block *self,
        case CPU_PM_ENTER:
                if (current->mm && !test_thread_flag(TIF_FOREIGN_FPSTATE))
                        fpsimd_save_state(&current->thread.fpsimd_state);
+               this_cpu_write(fpsimd_last_state, NULL);
                break;
        case CPU_PM_EXIT:
                if (current->mm)
index bed028364a93235006b467c20daeb8725b9a4615..873069056229a89c4808b49f73e60d196ff53634 100644 (file)
@@ -373,10 +373,6 @@ ENTRY(__boot_cpu_mode)
        .long   0
        .popsection
 
-       .align  3
-2:     .quad   .
-       .quad   PAGE_OFFSET
-
 #ifdef CONFIG_SMP
        .align  3
 1:     .quad   .
index 0f08dfd69ebc73ea99b7b7f6d68c4b2f320eb2d1..dfa6e3e74fddec289649c1baba921378f521f611 100644 (file)
@@ -97,19 +97,15 @@ static bool migrate_one_irq(struct irq_desc *desc)
        if (irqd_is_per_cpu(d) || !cpumask_test_cpu(smp_processor_id(), affinity))
                return false;
 
-       if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids)
+       if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
+               affinity = cpu_online_mask;
                ret = true;
+       }
 
-       /*
-        * when using forced irq_set_affinity we must ensure that the cpu
-        * being offlined is not present in the affinity mask, it may be
-        * selected as the target CPU otherwise
-        */
-       affinity = cpu_online_mask;
        c = irq_data_get_irq_chip(d);
        if (!c->irq_set_affinity)
                pr_debug("IRQ%u: unable to set affinity\n", d->irq);
-       else if (c->irq_set_affinity(d, affinity, true) == IRQ_SET_MASK_OK && ret)
+       else if (c->irq_set_affinity(d, affinity, false) == IRQ_SET_MASK_OK && ret)
                cpumask_copy(d->affinity, affinity);
 
        return ret;
index 422ebd63b619253d23c7a82d5fb14b322dc47fe1..6762ad705587fa34fff0281546273a6930ddbcbf 100644 (file)
@@ -24,6 +24,12 @@ u64 perf_reg_value(struct pt_regs *regs, int idx)
                        return regs->compat_lr;
        }
 
+       if ((u32)idx == PERF_REG_ARM64_SP)
+               return regs->sp;
+
+       if ((u32)idx == PERF_REG_ARM64_PC)
+               return regs->pc;
+
        return regs->regs[idx];
 }
 
index 1309d64aa9268f755504c37ada95c4bb44010cc6..29d48690f2ac59ef56d5384d1fde5db92f0624e7 100644 (file)
@@ -230,9 +230,27 @@ void exit_thread(void)
 {
 }
 
+static void tls_thread_flush(void)
+{
+       asm ("msr tpidr_el0, xzr");
+
+       if (is_compat_task()) {
+               current->thread.tp_value = 0;
+
+               /*
+                * We need to ensure ordering between the shadow state and the
+                * hardware state, so that we don't corrupt the hardware state
+                * with a stale shadow state during context switch.
+                */
+               barrier();
+               asm ("msr tpidrro_el0, xzr");
+       }
+}
+
 void flush_thread(void)
 {
        fpsimd_flush_thread();
+       tls_thread_flush();
        flush_ptrace_hw_breakpoint(current);
 }
 
index 70526cfda056e7216ef7f773b059d31b6ca4f88a..fe63ac5e9bf5582cb4e494262a9d714d4b6758a7 100644 (file)
@@ -87,7 +87,8 @@ static void ptrace_hbptriggered(struct perf_event *bp,
                        break;
                }
        }
-       for (i = ARM_MAX_BRP; i < ARM_MAX_HBP_SLOTS && !bp; ++i) {
+
+       for (i = 0; i < ARM_MAX_WRP; ++i) {
                if (current->thread.debug.hbp_watch[i] == bp) {
                        info.si_errno = -((i << 1) + 1);
                        break;
@@ -662,8 +663,10 @@ static int compat_gpr_get(struct task_struct *target,
                        kbuf += sizeof(reg);
                } else {
                        ret = copy_to_user(ubuf, &reg, sizeof(reg));
-                       if (ret)
+                       if (ret) {
+                               ret = -EFAULT;
                                break;
+                       }
 
                        ubuf += sizeof(reg);
                }
@@ -701,8 +704,10 @@ static int compat_gpr_set(struct task_struct *target,
                        kbuf += sizeof(reg);
                } else {
                        ret = copy_from_user(&reg, ubuf, sizeof(reg));
-                       if (ret)
-                               return ret;
+                       if (ret) {
+                               ret = -EFAULT;
+                               break;
+                       }
 
                        ubuf += sizeof(reg);
                }
index f6f0ccf35ae67110c030d72c6c7648e04168c6e9..edb146d0185740b18de7d7cd365ae5d01ea1cbdc 100644 (file)
@@ -78,6 +78,7 @@ unsigned int compat_elf_hwcap2 __read_mostly;
 #endif
 
 static const char *cpu_name;
+static const char *machine_name;
 phys_addr_t __fdt_pointer __initdata;
 
 /*
@@ -309,6 +310,8 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys)
                while (true)
                        cpu_relax();
        }
+
+       machine_name = of_flat_dt_get_machine_name();
 }
 
 /*
@@ -447,21 +450,10 @@ static int c_show(struct seq_file *m, void *v)
 {
        int i;
 
-       /*
-        * Dump out the common processor features in a single line. Userspace
-        * should read the hwcaps with getauxval(AT_HWCAP) rather than
-        * attempting to parse this.
-        */
-       seq_puts(m, "features\t:");
-       for (i = 0; hwcap_str[i]; i++)
-               if (elf_hwcap & (1 << i))
-                       seq_printf(m, " %s", hwcap_str[i]);
-       seq_puts(m, "\n\n");
+       seq_printf(m, "Processor\t: %s rev %d (%s)\n",
+                  cpu_name, read_cpuid_id() & 15, ELF_PLATFORM);
 
        for_each_online_cpu(i) {
-               struct cpuinfo_arm64 *cpuinfo = &per_cpu(cpu_data, i);
-               u32 midr = cpuinfo->reg_midr;
-
                /*
                 * glibc reads /proc/cpuinfo to determine the number of
                 * online processors, looking for lines beginning with
@@ -470,13 +462,25 @@ static int c_show(struct seq_file *m, void *v)
 #ifdef CONFIG_SMP
                seq_printf(m, "processor\t: %d\n", i);
 #endif
-               seq_printf(m, "implementer\t: 0x%02x\n",
-                          MIDR_IMPLEMENTOR(midr));
-               seq_printf(m, "variant\t\t: 0x%x\n", MIDR_VARIANT(midr));
-               seq_printf(m, "partnum\t\t: 0x%03x\n", MIDR_PARTNUM(midr));
-               seq_printf(m, "revision\t: 0x%x\n\n", MIDR_REVISION(midr));
        }
 
+       /* dump out the processor features */
+       seq_puts(m, "Features\t: ");
+
+       for (i = 0; hwcap_str[i]; i++)
+               if (elf_hwcap & (1 << i))
+                       seq_printf(m, "%s ", hwcap_str[i]);
+
+       seq_printf(m, "\nCPU implementer\t: 0x%02x\n", read_cpuid_id() >> 24);
+       seq_printf(m, "CPU architecture: AArch64\n");
+       seq_printf(m, "CPU variant\t: 0x%x\n", (read_cpuid_id() >> 20) & 15);
+       seq_printf(m, "CPU part\t: 0x%03x\n", (read_cpuid_id() >> 4) & 0xfff);
+       seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
+
+       seq_puts(m, "\n");
+
+       seq_printf(m, "Hardware\t: %s\n", machine_name);
+
        return 0;
 }
 
index de2b0226e06df34fd7aaa4bb55e014fc33f9cddf..dc47e53e9e28c15da99e62976a9ca29f71da8bc4 100644 (file)
@@ -79,6 +79,12 @@ long compat_arm_syscall(struct pt_regs *regs)
 
        case __ARM_NR_compat_set_tls:
                current->thread.tp_value = regs->regs[0];
+
+               /*
+                * Protect against register corruption from context switch.
+                * See comment in tls_thread_flush.
+                */
+               barrier();
                asm ("msr tpidrro_el0, %0" : : "r" (regs->regs[0]));
                return 0;
 
index e28be510380ca758f8cdb76a5da57892cb02e3bf..34b8bd0711e94295b3b8d629e2e032db8d8bce33 100644 (file)
@@ -66,6 +66,8 @@ static int kvm_handle_wfx(struct kvm_vcpu *vcpu, struct kvm_run *run)
        else
                kvm_vcpu_block(vcpu);
 
+       kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
+
        return 1;
 }
 
index d968796f4b2d7a88dda3605f0f16b9777879052b..c3191168a994fba06b6f5ddc807dbc8eceec224b 100644 (file)
@@ -80,6 +80,10 @@ __do_hyp_init:
        msr     mair_el2, x4
        isb
 
+       /* Invalidate the stale TLBs from Bootloader */
+       tlbi    alle2
+       dsb     sy
+
        mrs     x4, sctlr_el2
        and     x4, x4, #SCTLR_EL2_EE   // preserve endianness of EL2
        ldr     x5, =SCTLR_EL2_FLAGS
index fe14ccf285613c39f8801a8ca29389c5df6afa44..0c76c802e31ce864a0374f3a397a7c403077fec0 100644 (file)
@@ -68,6 +68,7 @@ void flush_icache_range(unsigned long start, unsigned long end)
        );
        local_irq_restore(flags);
 }
+EXPORT_SYMBOL(flush_icache_range);
 
 void hexagon_clean_dcache_range(unsigned long start, unsigned long end)
 {
index 64aefb76bd69054a2f5d9f7627a950347a959d82..c84c88bbbbd79abd66d7cd919bdd7507b0c26b07 100644 (file)
@@ -549,8 +549,6 @@ source "drivers/sn/Kconfig"
 config KEXEC
        bool "kexec system call"
        depends on !IA64_HP_SIM && (!SMP || HOTPLUG_CPU)
-       select CRYPTO
-       select CRYPTO_SHA256
        help
          kexec is a system call that implements the ability to shutdown your
          current kernel, and to start another kernel.  It is like a reboot
index 3ff8c9a25335b20eb4d3f7dfab3513fe584abf39..87b7c7581b1dd5777642a3b87dd9002b7e68dc50 100644 (file)
@@ -91,8 +91,6 @@ config MMU_SUN3
 config KEXEC
        bool "kexec system call"
        depends on M68KCLASSIC
-       select CRYPTO
-       select CRYPTO_SHA256
        help
          kexec is a system call that implements the ability to shutdown your
          current kernel, and to start another kernel.  It is like a reboot
index 1fcdd344c7ad5797605ddbb9ee98bcde3461c295..4ef7a54813e6b72d88a0d40109a26347b91aa7c6 100644 (file)
@@ -4,7 +4,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define NR_syscalls            352
+#define NR_syscalls            354
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
index 9cd82fbc7817f716d589368bda3c1d274687a607..b419c6b7ac3739b150000dfd13aff28d3dcc372a 100644 (file)
 #define __NR_sched_setattr     349
 #define __NR_sched_getattr     350
 #define __NR_renameat2         351
+#define __NR_getrandom         352
+#define __NR_memfd_create      353
 
 #endif /* _UAPI_ASM_M68K_UNISTD_H_ */
index 501e102127899c6afaa893bd99d4d555f5bab8ec..05b46c2b08b8d8d4be26c56e8be4d245cef3dab6 100644 (file)
@@ -372,4 +372,6 @@ ENTRY(sys_call_table)
        .long sys_sched_setattr
        .long sys_sched_getattr         /* 350 */
        .long sys_renameat2
+       .long sys_getrandom
+       .long sys_memfd_create
 
index 40e1c1dd0e24a47d38f142ce0c5543d629a0fd50..6feded3b0c4c1eb6d1414082a9f9318041129a39 100644 (file)
@@ -127,7 +127,7 @@ config SECCOMP
 
 endmenu
 
-menu "Advanced setup"
+menu "Kernel features"
 
 config ADVANCED_OPTIONS
        bool "Prompt for advanced kernel configuration options"
@@ -248,10 +248,10 @@ config MICROBLAZE_64K_PAGES
 
 endchoice
 
-endmenu
-
 source "mm/Kconfig"
 
+endmenu
+
 menu "Executable file formats"
 
 source "fs/Kconfig.binfmt"
index b4a4cb150aa998af14d3d359db7c2b73f26397db..596e485ae7074df3b8cf5abba5d390153c1166c7 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <asm/percpu.h>
 #include <asm/ptrace.h>
+#include <linux/linkage.h>
 
 /*
  * These are per-cpu variables required in entry.S, among other
index 0aa005703a0b5f348848afb5936f650d18f28322..59a89a64a8656b01436f4aaf38ec270f5d8b2a7a 100644 (file)
@@ -98,13 +98,13 @@ static inline int access_ok(int type, const void __user *addr,
 
        if ((get_fs().seg < ((unsigned long)addr)) ||
                        (get_fs().seg < ((unsigned long)addr + size - 1))) {
-               pr_debug("ACCESS fail: %s at 0x%08x (size 0x%x), seg 0x%08x\n",
+               pr_devel("ACCESS fail: %s at 0x%08x (size 0x%x), seg 0x%08x\n",
                        type ? "WRITE" : "READ ", (__force u32)addr, (u32)size,
                        (u32)get_fs().seg);
                return 0;
        }
 ok:
-       pr_debug("ACCESS OK: %s at 0x%08x (size 0x%x), seg 0x%08x\n",
+       pr_devel("ACCESS OK: %s at 0x%08x (size 0x%x), seg 0x%08x\n",
                        type ? "WRITE" : "READ ", (__force u32)addr, (u32)size,
                        (u32)get_fs().seg);
        return 1;
index fd56a8f66489dc68264ac8f70cc70863c6f25380..ea4b233647c1aa32d23562e7abba7dab72d404db 100644 (file)
@@ -38,6 +38,6 @@
 
 #endif /* __ASSEMBLY__ */
 
-#define __NR_syscalls         381
+#define __NR_syscalls         387
 
 #endif /* _ASM_MICROBLAZE_UNISTD_H */
index df51e78a72cc1b045e5f2e3146be63a5a3ad1790..900c7e5333b650666c374a8e378129b1c7eb43f1 100644 (file)
@@ -2396,8 +2396,6 @@ source "kernel/Kconfig.preempt"
 
 config KEXEC
        bool "Kexec system call"
-       select CRYPTO
-       select CRYPTO_SHA256
        help
          kexec is a system call that implements the ability to shutdown your
          current kernel, and to start another kernel.  It is like a reboot
index a577609f8ed60229ed4d3fc26931bc23f955c599..4bc7b62fb4b68761341619d7bd8300dbb8786d76 100644 (file)
@@ -399,8 +399,6 @@ config PPC64_SUPPORTS_MEMORY_FAILURE
 config KEXEC
        bool "kexec system call"
        depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP))
-       select CRYPTO
-       select CRYPTO_SHA256
        help
          kexec is a system call that implements the ability to shutdown your
          current kernel, and to start another kernel.  It is like a reboot
index 4bee1a6d41d04d0694ee6ad45ab98e9ebfd70b44..45fd06cdc3e86639d3ddc829c4d44c8db0069bd0 100644 (file)
@@ -5,6 +5,7 @@ CONFIG_SMP=y
 CONFIG_NR_CPUS=4
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=15
index 6d7b22f41b5077a6d0f614fceb58c596856a209d..77d7bf3ca2acb014def979d68d21c7f94401ed10 100644 (file)
@@ -5,6 +5,7 @@ CONFIG_SMP=y
 CONFIG_NR_CPUS=4
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=15
index 4b07bade1ba99942e88ea9cd4dd251996cbede70..269d6e47c67d2a998272f27545ec238766c68dc8 100644 (file)
@@ -4,6 +4,7 @@ CONFIG_ALTIVEC=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=24
 CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
 CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
index 3c72fa615bd9e29e135df83b7944fa48c922db8f..7594c5ac64818f6b01537bb0c0be3519c73bd455 100644 (file)
@@ -5,6 +5,7 @@ CONFIG_NR_CPUS=4
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_BLK_DEV_INITRD=y
index 95e545d9f25c94935c1cee35a9e2b45e7c0169cf..c8b6a9ddb21bf813c448dfc4f847a3f611c23dd1 100644 (file)
@@ -4,6 +4,7 @@ CONFIG_NR_CPUS=4
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_COMPAT_BRK is not set
index cec044a3ff69dd6c05dcfec122fcb53653b412f8..e5e7838af0088f04b8faf5f40d8204962bd0bb6f 100644 (file)
@@ -3,6 +3,7 @@ CONFIG_ALTIVEC=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_SYSVIPC=y
+CONFIG_FHANDLE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BLK_DEV_INITRD=y
index f26b267eb71fa947db544f202e6cd55b581b1821..f6c02f8cdc62bd6f92a231e2afad8985074b7351 100644 (file)
@@ -4,6 +4,7 @@ CONFIG_VSX=y
 CONFIG_SMP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
index 438e813dc9cb1c18cf4605f5d937135100d39530..587f5514f9b1c4ad20a019c13596cb191bc308a7 100644 (file)
@@ -3,6 +3,7 @@ CONFIG_PPC_BOOK3E_64=y
 CONFIG_SMP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_TASKSTATS=y
index fdee37fab81c5aa1f70263e7c4979fc0df7e9956..2e637c881d2b44be41b9db66145ac7863cbe1be1 100644 (file)
@@ -5,6 +5,7 @@ CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_RD_LZMA=y
index a905063281cc329b376605fa583d1e3282ce36c2..50375f1f59e7a509641dcfd45036f328f7a267ee 100644 (file)
@@ -5,6 +5,7 @@ CONFIG_SMP=y
 CONFIG_NR_CPUS=2048
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_AUDIT=y
 CONFIG_AUDITSYSCALL=y
 CONFIG_IRQ_DOMAIN_DEBUG=y
index 58e3dbf43ca419f6877c7f87ac856e4ace764560..4428ee428f4ea992f11a85ff233e93cbf3825488 100644 (file)
@@ -6,6 +6,7 @@ CONFIG_NR_CPUS=2048
 CONFIG_CPU_LITTLE_ENDIAN=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_FHANDLE=y
 CONFIG_AUDIT=y
 CONFIG_AUDITSYSCALL=y
 CONFIG_IRQ_DOMAIN_DEBUG=y
index 279b80f3bb293d0bceceecb9eb38ff344e26b8fb..c0c61fa9cd9e4d3440798c9c1c0f93cb9276fcfa 100644 (file)
                                 STACK_FRAME_OVERHEAD + KERNEL_REDZONE_SIZE)
 #define STACK_FRAME_MARKER     12
 
+#if defined(_CALL_ELF) && _CALL_ELF == 2
+#define STACK_FRAME_MIN_SIZE   32
+#else
+#define STACK_FRAME_MIN_SIZE   STACK_FRAME_OVERHEAD
+#endif
+
 /* Size of dummy stack frame allocated when calling signal handler. */
 #define __SIGNAL_FRAMESIZE     128
 #define __SIGNAL_FRAMESIZE32   64
@@ -60,6 +66,7 @@
 #define STACK_FRAME_REGS_MARKER        ASM_CONST(0x72656773)
 #define STACK_INT_FRAME_SIZE   (sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD)
 #define STACK_FRAME_MARKER     2
+#define STACK_FRAME_MIN_SIZE   STACK_FRAME_OVERHEAD
 
 /* Size of stack frame allocated when calling signal handler. */
 #define __SIGNAL_FRAMESIZE     64
index 542bc0f0673fc8e792d984b8215511cf4b4566b4..7d8a600688058ec5025cfd3688b6eb369cdadea5 100644 (file)
@@ -362,3 +362,6 @@ SYSCALL(ni_syscall) /* sys_kcmp */
 SYSCALL_SPU(sched_setattr)
 SYSCALL_SPU(sched_getattr)
 SYSCALL_SPU(renameat2)
+SYSCALL_SPU(seccomp)
+SYSCALL_SPU(getrandom)
+SYSCALL_SPU(memfd_create)
index 5ce5552ab9f5ca24fe479bfd81ea4a915a478a90..4e9af3fd43e7d062755255d932c2123ea5f54c8a 100644 (file)
@@ -12,7 +12,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define __NR_syscalls          358
+#define __NR_syscalls          361
 
 #define __NR__exit __NR_exit
 #define NR_syscalls    __NR_syscalls
index 2d526f7b48da121f60b2c3c7c069b07199a76ff6..0688fc06e18394268002ae2b7e419f183e6a7dc4 100644 (file)
 #define __NR_sched_setattr     355
 #define __NR_sched_getattr     356
 #define __NR_renameat2         357
+#define __NR_seccomp           358
+#define __NR_getrandom         359
+#define __NR_memfd_create      360
 
 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
index 72c20bb16d266b4ed0aa2160382414f161ad0663..79294c4c5015ea83771e4ebc849a561bd376144d 100644 (file)
@@ -62,10 +62,10 @@ long kvmppc_alloc_hpt(struct kvm *kvm, u32 *htab_orderp)
        }
 
        kvm->arch.hpt_cma_alloc = 0;
-       page = kvm_alloc_hpt(1 << (order - PAGE_SHIFT));
+       page = kvm_alloc_hpt(1ul << (order - PAGE_SHIFT));
        if (page) {
                hpt = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
-               memset((void *)hpt, 0, (1 << order));
+               memset((void *)hpt, 0, (1ul << order));
                kvm->arch.hpt_cma_alloc = 1;
        }
 
index 74d1e780748b58f17f8987218a6184c87aae63da..2396dda282cdef0ed5c11c6ab7c3f4f479d0ac04 100644 (file)
@@ -35,7 +35,7 @@ static int valid_next_sp(unsigned long sp, unsigned long prev_sp)
                return 0;               /* must be 16-byte aligned */
        if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD))
                return 0;
-       if (sp >= prev_sp + STACK_FRAME_OVERHEAD)
+       if (sp >= prev_sp + STACK_FRAME_MIN_SIZE)
                return 1;
        /*
         * sp could decrease when we jump off an interrupt stack
index 97ac8dc33667f1319802fd08a8c1d9d56b8905b5..5e1ed1575aabe23c245edcdff06433cfb0a62327 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <asm/opal.h>
 #include <asm/cputable.h>
+#include <asm/machdep.h>
 
 static int opal_hmi_handler_nb_init;
 struct OpalHmiEvtNode {
@@ -185,4 +186,4 @@ static int __init opal_hmi_handler_init(void)
        }
        return 0;
 }
-subsys_initcall(opal_hmi_handler_init);
+machine_subsys_initcall(powernv, opal_hmi_handler_init);
index c904583baf4b94d46e5a0ae3b4f5dca134a4bc87..17ee193960a09aab4e5e4502525f4b55788bdcce 100644 (file)
@@ -113,7 +113,7 @@ out:
 static int pseries_remove_mem_node(struct device_node *np)
 {
        const char *type;
-       const unsigned int *regs;
+       const __be32 *regs;
        unsigned long base;
        unsigned int lmb_size;
        int ret = -EINVAL;
@@ -132,8 +132,8 @@ static int pseries_remove_mem_node(struct device_node *np)
        if (!regs)
                return ret;
 
-       base = *(unsigned long *)regs;
-       lmb_size = regs[3];
+       base = be64_to_cpu(*(unsigned long *)regs);
+       lmb_size = be32_to_cpu(regs[3]);
 
        pseries_remove_memblock(base, lmb_size);
        return 0;
@@ -153,7 +153,7 @@ static inline int pseries_remove_mem_node(struct device_node *np)
 static int pseries_add_mem_node(struct device_node *np)
 {
        const char *type;
-       const unsigned int *regs;
+       const __be32 *regs;
        unsigned long base;
        unsigned int lmb_size;
        int ret = -EINVAL;
@@ -172,8 +172,8 @@ static int pseries_add_mem_node(struct device_node *np)
        if (!regs)
                return ret;
 
-       base = *(unsigned long *)regs;
-       lmb_size = regs[3];
+       base = be64_to_cpu(*(unsigned long *)regs);
+       lmb_size = be32_to_cpu(regs[3]);
 
        /*
         * Update memory region to represent the memory add
@@ -187,14 +187,14 @@ static int pseries_update_drconf_memory(struct of_prop_reconfig *pr)
        struct of_drconf_cell *new_drmem, *old_drmem;
        unsigned long memblock_size;
        u32 entries;
-       u32 *p;
+       __be32 *p;
        int i, rc = -EINVAL;
 
        memblock_size = pseries_memory_block_size();
        if (!memblock_size)
                return -EINVAL;
 
-       p = (u32 *) pr->old_prop->value;
+       p = (__be32 *) pr->old_prop->value;
        if (!p)
                return -EINVAL;
 
@@ -203,28 +203,30 @@ static int pseries_update_drconf_memory(struct of_prop_reconfig *pr)
         * entries. Get the niumber of entries and skip to the array of
         * of_drconf_cell's.
         */
-       entries = *p++;
+       entries = be32_to_cpu(*p++);
        old_drmem = (struct of_drconf_cell *)p;
 
-       p = (u32 *)pr->prop->value;
+       p = (__be32 *)pr->prop->value;
        p++;
        new_drmem = (struct of_drconf_cell *)p;
 
        for (i = 0; i < entries; i++) {
-               if ((old_drmem[i].flags & DRCONF_MEM_ASSIGNED) &&
-                   (!(new_drmem[i].flags & DRCONF_MEM_ASSIGNED))) {
-                       rc = pseries_remove_memblock(old_drmem[i].base_addr,
+               if ((be32_to_cpu(old_drmem[i].flags) & DRCONF_MEM_ASSIGNED) &&
+                   (!(be32_to_cpu(new_drmem[i].flags) & DRCONF_MEM_ASSIGNED))) {
+                       rc = pseries_remove_memblock(
+                               be64_to_cpu(old_drmem[i].base_addr),
                                                     memblock_size);
                        break;
-               } else if ((!(old_drmem[i].flags & DRCONF_MEM_ASSIGNED)) &&
-                          (new_drmem[i].flags & DRCONF_MEM_ASSIGNED)) {
-                       rc = memblock_add(old_drmem[i].base_addr,
+               } else if ((!(be32_to_cpu(old_drmem[i].flags) &
+                           DRCONF_MEM_ASSIGNED)) &&
+                           (be32_to_cpu(new_drmem[i].flags) &
+                           DRCONF_MEM_ASSIGNED)) {
+                       rc = memblock_add(be64_to_cpu(old_drmem[i].base_addr),
                                          memblock_size);
                        rc = (rc < 0) ? -EINVAL : 0;
                        break;
                }
        }
-
        return rc;
 }
 
index ab39ceb89ecfa3e4b8e1b3eb34e3787aedbefeaa..05c78bb5f57024bf220e778af99888a1df6e6bbc 100644 (file)
@@ -48,8 +48,6 @@ config ARCH_SUPPORTS_DEBUG_PAGEALLOC
 
 config KEXEC
        def_bool y
-       select CRYPTO
-       select CRYPTO_SHA256
 
 config AUDIT_ARCH
        def_bool y
index 2fcccc0c997cc3102dcb67e5ea2f60fc4f4200b2..c81661e756a0396bb8e90dee214492b154081d91 100644 (file)
 #define IPL_PARM_BLK_FCP_LEN (sizeof(struct ipl_list_hdr) + \
                              sizeof(struct ipl_block_fcp))
 
-#define IPL_PARM_BLK0_FCP_LEN (sizeof(struct ipl_block_fcp) + 8)
+#define IPL_PARM_BLK0_FCP_LEN (sizeof(struct ipl_block_fcp) + 16)
 
 #define IPL_PARM_BLK_CCW_LEN (sizeof(struct ipl_list_hdr) + \
                              sizeof(struct ipl_block_ccw))
 
-#define IPL_PARM_BLK0_CCW_LEN (sizeof(struct ipl_block_ccw) + 8)
+#define IPL_PARM_BLK0_CCW_LEN (sizeof(struct ipl_block_ccw) + 16)
 
 #define IPL_MAX_SUPPORTED_VERSION (0)
 
@@ -38,10 +38,11 @@ struct ipl_list_hdr {
        u8  pbt;
        u8  flags;
        u16 reserved2;
+       u8  loadparm[8];
 } __attribute__((packed));
 
 struct ipl_block_fcp {
-       u8  reserved1[313-1];
+       u8  reserved1[305-1];
        u8  opt;
        u8  reserved2[3];
        u16 reserved3;
@@ -62,7 +63,6 @@ struct ipl_block_fcp {
                                 offsetof(struct ipl_block_fcp, scp_data)))
 
 struct ipl_block_ccw {
-       u8  load_parm[8];
        u8  reserved1[84];
        u8  reserved2[2];
        u16 devno;
index b76317c1f3eb5b542d3ee628326da48910866770..5efb2fe186e78275faa6ecc223b94a8c96c86a70 100644 (file)
@@ -1127,7 +1127,7 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
                                            unsigned long addr, pte_t *ptep)
 {
        pgste_t pgste;
-       pte_t pte;
+       pte_t pte, oldpte;
        int young;
 
        if (mm_has_pgste(vma->vm_mm)) {
@@ -1135,12 +1135,13 @@ static inline int ptep_test_and_clear_young(struct vm_area_struct *vma,
                pgste = pgste_ipte_notify(vma->vm_mm, ptep, pgste);
        }
 
-       pte = *ptep;
+       oldpte = pte = *ptep;
        ptep_flush_direct(vma->vm_mm, addr, ptep);
        young = pte_young(pte);
        pte = pte_mkold(pte);
 
        if (mm_has_pgste(vma->vm_mm)) {
+               pgste = pgste_update_all(&oldpte, pgste, vma->vm_mm);
                pgste = pgste_set_pte(ptep, pgste, pte);
                pgste_set_unlock(ptep, pgste);
        } else
@@ -1330,6 +1331,7 @@ static inline int ptep_set_access_flags(struct vm_area_struct *vma,
        ptep_flush_direct(vma->vm_mm, address, ptep);
 
        if (mm_has_pgste(vma->vm_mm)) {
+               pgste_set_key(ptep, pgste, entry, vma->vm_mm);
                pgste = pgste_set_pte(ptep, pgste, entry);
                pgste_set_unlock(ptep, pgste);
        } else
index 3802d2d3a18d7cf4abf5604d6f66e01b6e34424d..940ac49198db1dd406b99944f51183df869cd420 100644 (file)
 #define __NR_sched_setattr     345
 #define __NR_sched_getattr     346
 #define __NR_renameat2         347
-#define NR_syscalls 348
+#define __NR_seccomp           348
+#define __NR_getrandom         349
+#define __NR_memfd_create      350
+#define NR_syscalls 351
 
 /* 
  * There are some system calls that are not present on 64 bit, some
index 45cdb37aa6f812813c69d08102e4e1f521e5df1f..faf6caa510dcedb862ad65be7108e1042a754939 100644 (file)
@@ -214,3 +214,6 @@ COMPAT_SYSCALL_WRAP3(finit_module, int, fd, const char __user *, uargs, int, fla
 COMPAT_SYSCALL_WRAP3(sched_setattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, flags);
 COMPAT_SYSCALL_WRAP4(sched_getattr, pid_t, pid, struct sched_attr __user *, attr, unsigned int, size, unsigned int, flags);
 COMPAT_SYSCALL_WRAP5(renameat2, int, olddfd, const char __user *, oldname, int, newdfd, const char __user *, newname, unsigned int, flags);
+COMPAT_SYSCALL_WRAP3(seccomp, unsigned int, op, unsigned int, flags, const char __user *, uargs)
+COMPAT_SYSCALL_WRAP3(getrandom, char __user *, buf, size_t, count, unsigned int, flags)
+COMPAT_SYSCALL_WRAP2(memfd_create, const char __user *, uname, unsigned int, flags)
index 633ca7504536c10a517667b5f582653f763390e3..39badb9ca0b30c6b7b32ce720165e85c3c33319a 100644 (file)
@@ -455,22 +455,6 @@ DEFINE_IPL_ATTR_RO(ipl_fcp, bootprog, "%lld\n", (unsigned long long)
 DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n", (unsigned long long)
                   IPL_PARMBLOCK_START->ipl_info.fcp.br_lba);
 
-static struct attribute *ipl_fcp_attrs[] = {
-       &sys_ipl_type_attr.attr,
-       &sys_ipl_device_attr.attr,
-       &sys_ipl_fcp_wwpn_attr.attr,
-       &sys_ipl_fcp_lun_attr.attr,
-       &sys_ipl_fcp_bootprog_attr.attr,
-       &sys_ipl_fcp_br_lba_attr.attr,
-       NULL,
-};
-
-static struct attribute_group ipl_fcp_attr_group = {
-       .attrs = ipl_fcp_attrs,
-};
-
-/* CCW ipl device attributes */
-
 static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
                                     struct kobj_attribute *attr, char *page)
 {
@@ -487,6 +471,23 @@ static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
 static struct kobj_attribute sys_ipl_ccw_loadparm_attr =
        __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
 
+static struct attribute *ipl_fcp_attrs[] = {
+       &sys_ipl_type_attr.attr,
+       &sys_ipl_device_attr.attr,
+       &sys_ipl_fcp_wwpn_attr.attr,
+       &sys_ipl_fcp_lun_attr.attr,
+       &sys_ipl_fcp_bootprog_attr.attr,
+       &sys_ipl_fcp_br_lba_attr.attr,
+       &sys_ipl_ccw_loadparm_attr.attr,
+       NULL,
+};
+
+static struct attribute_group ipl_fcp_attr_group = {
+       .attrs = ipl_fcp_attrs,
+};
+
+/* CCW ipl device attributes */
+
 static struct attribute *ipl_ccw_attrs_vm[] = {
        &sys_ipl_type_attr.attr,
        &sys_ipl_device_attr.attr,
@@ -765,28 +766,10 @@ DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%lld\n", "%lld\n",
 DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
                   reipl_block_fcp->ipl_info.fcp.devno);
 
-static struct attribute *reipl_fcp_attrs[] = {
-       &sys_reipl_fcp_device_attr.attr,
-       &sys_reipl_fcp_wwpn_attr.attr,
-       &sys_reipl_fcp_lun_attr.attr,
-       &sys_reipl_fcp_bootprog_attr.attr,
-       &sys_reipl_fcp_br_lba_attr.attr,
-       NULL,
-};
-
-static struct attribute_group reipl_fcp_attr_group = {
-       .attrs = reipl_fcp_attrs,
-};
-
-/* CCW reipl device attributes */
-
-DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
-       reipl_block_ccw->ipl_info.ccw.devno);
-
 static void reipl_get_ascii_loadparm(char *loadparm,
                                     struct ipl_parameter_block *ibp)
 {
-       memcpy(loadparm, ibp->ipl_info.ccw.load_parm, LOADPARM_LEN);
+       memcpy(loadparm, ibp->hdr.loadparm, LOADPARM_LEN);
        EBCASC(loadparm, LOADPARM_LEN);
        loadparm[LOADPARM_LEN] = 0;
        strim(loadparm);
@@ -821,13 +804,50 @@ static ssize_t reipl_generic_loadparm_store(struct ipl_parameter_block *ipb,
                return -EINVAL;
        }
        /* initialize loadparm with blanks */
-       memset(ipb->ipl_info.ccw.load_parm, ' ', LOADPARM_LEN);
+       memset(ipb->hdr.loadparm, ' ', LOADPARM_LEN);
        /* copy and convert to ebcdic */
-       memcpy(ipb->ipl_info.ccw.load_parm, buf, lp_len);
-       ASCEBC(ipb->ipl_info.ccw.load_parm, LOADPARM_LEN);
+       memcpy(ipb->hdr.loadparm, buf, lp_len);
+       ASCEBC(ipb->hdr.loadparm, LOADPARM_LEN);
        return len;
 }
 
+/* FCP wrapper */
+static ssize_t reipl_fcp_loadparm_show(struct kobject *kobj,
+                                      struct kobj_attribute *attr, char *page)
+{
+       return reipl_generic_loadparm_show(reipl_block_fcp, page);
+}
+
+static ssize_t reipl_fcp_loadparm_store(struct kobject *kobj,
+                                       struct kobj_attribute *attr,
+                                       const char *buf, size_t len)
+{
+       return reipl_generic_loadparm_store(reipl_block_fcp, buf, len);
+}
+
+static struct kobj_attribute sys_reipl_fcp_loadparm_attr =
+       __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_fcp_loadparm_show,
+                                           reipl_fcp_loadparm_store);
+
+static struct attribute *reipl_fcp_attrs[] = {
+       &sys_reipl_fcp_device_attr.attr,
+       &sys_reipl_fcp_wwpn_attr.attr,
+       &sys_reipl_fcp_lun_attr.attr,
+       &sys_reipl_fcp_bootprog_attr.attr,
+       &sys_reipl_fcp_br_lba_attr.attr,
+       &sys_reipl_fcp_loadparm_attr.attr,
+       NULL,
+};
+
+static struct attribute_group reipl_fcp_attr_group = {
+       .attrs = reipl_fcp_attrs,
+};
+
+/* CCW reipl device attributes */
+
+DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
+       reipl_block_ccw->ipl_info.ccw.devno);
+
 /* NSS wrapper */
 static ssize_t reipl_nss_loadparm_show(struct kobject *kobj,
                                       struct kobj_attribute *attr, char *page)
@@ -1125,11 +1145,10 @@ static void reipl_block_ccw_fill_parms(struct ipl_parameter_block *ipb)
        /* LOADPARM */
        /* check if read scp info worked and set loadparm */
        if (sclp_ipl_info.is_valid)
-               memcpy(ipb->ipl_info.ccw.load_parm,
-                               &sclp_ipl_info.loadparm, LOADPARM_LEN);
+               memcpy(ipb->hdr.loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
        else
                /* read scp info failed: set empty loadparm (EBCDIC blanks) */
-               memset(ipb->ipl_info.ccw.load_parm, 0x40, LOADPARM_LEN);
+               memset(ipb->hdr.loadparm, 0x40, LOADPARM_LEN);
        ipb->hdr.flags = DIAG308_FLAGS_LP_VALID;
 
        /* VM PARM */
@@ -1251,9 +1270,16 @@ static int __init reipl_fcp_init(void)
                return rc;
        }
 
-       if (ipl_info.type == IPL_TYPE_FCP)
+       if (ipl_info.type == IPL_TYPE_FCP) {
                memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE);
-       else {
+               /*
+                * Fix loadparm: There are systems where the (SCSI) LOADPARM
+                * is invalid in the SCSI IPL parameter block, so take it
+                * always from sclp_ipl_info.
+                */
+               memcpy(reipl_block_fcp->hdr.loadparm, sclp_ipl_info.loadparm,
+                      LOADPARM_LEN);
+       } else {
                reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
                reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
                reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
@@ -1864,7 +1890,23 @@ static void __init shutdown_actions_init(void)
 
 static int __init s390_ipl_init(void)
 {
+       char str[8] = {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40};
+
        sclp_get_ipl_info(&sclp_ipl_info);
+       /*
+        * Fix loadparm: There are systems where the (SCSI) LOADPARM
+        * returned by read SCP info is invalid (contains EBCDIC blanks)
+        * when the system has been booted via diag308. In that case we use
+        * the value from diag308, if available.
+        *
+        * There are also systems where diag308 store does not work in
+        * case the system is booted from HMC. Fortunately in this case
+        * READ SCP info provides the correct value.
+        */
+       if (memcmp(sclp_ipl_info.loadparm, str, sizeof(str)) == 0 &&
+           diag308_set_works)
+               memcpy(sclp_ipl_info.loadparm, ipl_block.hdr.loadparm,
+                      LOADPARM_LEN);
        shutdown_actions_init();
        shutdown_triggers_init();
        return 0;
@@ -2060,6 +2102,13 @@ void s390_reset_system(void (*func)(void *), void *data)
        S390_lowcore.program_new_psw.addr =
                PSW_ADDR_AMODE | (unsigned long) s390_base_pgm_handler;
 
+       /*
+        * Clear subchannel ID and number to signal new kernel that no CCW or
+        * SCSI IPL has been done (for kexec and kdump)
+        */
+       S390_lowcore.subchannel_id = 0;
+       S390_lowcore.subchannel_nr = 0;
+
        /* Store status at absolute zero */
        store_status();
 
index ae1d5be7dd885d4d20f7b1f37d56ebbab9f92526..82bc113e8c1dd3718cf663a88d7bc9a2c9c97fb4 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
+#include <linux/random.h>
 #include <linux/user.h>
 #include <linux/tty.h>
 #include <linux/ioport.h>
@@ -61,6 +62,7 @@
 #include <asm/diag.h>
 #include <asm/os_info.h>
 #include <asm/sclp.h>
+#include <asm/sysinfo.h>
 #include "entry.h"
 
 /*
@@ -766,6 +768,7 @@ static void __init setup_hwcaps(void)
 #endif
 
        get_cpu_id(&cpu_id);
+       add_device_randomness(&cpu_id, sizeof(cpu_id));
        switch (cpu_id.machine) {
        case 0x9672:
 #if !defined(CONFIG_64BIT)
@@ -803,6 +806,19 @@ static void __init setup_hwcaps(void)
        }
 }
 
+/*
+ * Add system information as device randomness
+ */
+static void __init setup_randomness(void)
+{
+       struct sysinfo_3_2_2 *vmms;
+
+       vmms = (struct sysinfo_3_2_2 *) alloc_page(GFP_KERNEL);
+       if (vmms && stsi(vmms, 3, 2, 2) == 0 && vmms->count)
+               add_device_randomness(&vmms, vmms->count);
+       free_page((unsigned long) vmms);
+}
+
 /*
  * Setup function called from init/main.c just after the banner
  * was printed.
@@ -901,6 +917,9 @@ void __init setup_arch(char **cmdline_p)
 
        /* Setup zfcpdump support */
        setup_zfcpdump();
+
+       /* Add system specific data to the random pool */
+       setup_randomness();
 }
 
 #ifdef CONFIG_32BIT
index fe5cdf29a001be0e52fd0436bbbabd3603d37f66..6fe886ac2db596a81f67a80e69e4f5f54609c45f 100644 (file)
@@ -356,3 +356,6 @@ SYSCALL(sys_finit_module,sys_finit_module,compat_sys_finit_module)
 SYSCALL(sys_sched_setattr,sys_sched_setattr,compat_sys_sched_setattr) /* 345 */
 SYSCALL(sys_sched_getattr,sys_sched_getattr,compat_sys_sched_getattr)
 SYSCALL(sys_renameat2,sys_renameat2,compat_sys_renameat2)
+SYSCALL(sys_seccomp,sys_seccomp,compat_sys_seccomp)
+SYSCALL(sys_getrandom,sys_getrandom,compat_sys_getrandom)
+SYSCALL(sys_memfd_create,sys_memfd_create,compat_sys_memfd_create) /* 350 */
index 65fc3979c2f11bb037fd7f646c18a1188b4c4553..7cf18f8d4cb4fc9d281169ed8dee675f4c68b6be 100644 (file)
@@ -22,13 +22,11 @@ __kernel_clock_gettime:
        basr    %r5,0
 0:     al      %r5,21f-0b(%r5)                 /* get &_vdso_data */
        chi     %r2,__CLOCK_REALTIME
-       je      10f
+       je      11f
        chi     %r2,__CLOCK_MONOTONIC
        jne     19f
 
        /* CLOCK_MONOTONIC */
-       ltr     %r3,%r3
-       jz      9f                              /* tp == NULL */
 1:     l       %r4,__VDSO_UPD_COUNT+4(%r5)     /* load update counter */
        tml     %r4,0x0001                      /* pending update ? loop */
        jnz     1b
@@ -67,12 +65,10 @@ __kernel_clock_gettime:
        j       6b
 8:     st      %r2,0(%r3)                      /* store tp->tv_sec */
        st      %r1,4(%r3)                      /* store tp->tv_nsec */
-9:     lhi     %r2,0
+       lhi     %r2,0
        br      %r14
 
        /* CLOCK_REALTIME */
-10:    ltr     %r3,%r3                         /* tp == NULL */
-       jz      18f
 11:    l       %r4,__VDSO_UPD_COUNT+4(%r5)     /* load update counter */
        tml     %r4,0x0001                      /* pending update ? loop */
        jnz     11b
@@ -111,7 +107,7 @@ __kernel_clock_gettime:
        j       15b
 17:    st      %r2,0(%r3)                      /* store tp->tv_sec */
        st      %r1,4(%r3)                      /* store tp->tv_nsec */
-18:    lhi     %r2,0
+       lhi     %r2,0
        br      %r14
 
        /* Fallback to system call */
index 91940ed33a4ab21686f890481545cbfdd9404468..3f34e09db5f4d4d0e5f7a12b9e3acb89a72a6773 100644 (file)
@@ -21,7 +21,7 @@ __kernel_clock_gettime:
        .cfi_startproc
        larl    %r5,_vdso_data
        cghi    %r2,__CLOCK_REALTIME
-       je      4f
+       je      5f
        cghi    %r2,__CLOCK_THREAD_CPUTIME_ID
        je      9f
        cghi    %r2,-2          /* Per-thread CPUCLOCK with PID=0, VIRT=1 */
@@ -30,8 +30,6 @@ __kernel_clock_gettime:
        jne     12f
 
        /* CLOCK_MONOTONIC */
-       ltgr    %r3,%r3
-       jz      3f                              /* tp == NULL */
 0:     lg      %r4,__VDSO_UPD_COUNT(%r5)       /* load update counter */
        tmll    %r4,0x0001                      /* pending update ? loop */
        jnz     0b
@@ -53,12 +51,10 @@ __kernel_clock_gettime:
        j       1b
 2:     stg     %r0,0(%r3)                      /* store tp->tv_sec */
        stg     %r1,8(%r3)                      /* store tp->tv_nsec */
-3:     lghi    %r2,0
+       lghi    %r2,0
        br      %r14
 
        /* CLOCK_REALTIME */
-4:     ltr     %r3,%r3                         /* tp == NULL */
-       jz      8f
 5:     lg      %r4,__VDSO_UPD_COUNT(%r5)       /* load update counter */
        tmll    %r4,0x0001                      /* pending update ? loop */
        jnz     5b
@@ -80,7 +76,7 @@ __kernel_clock_gettime:
        j       6b
 7:     stg     %r0,0(%r3)                      /* store tp->tv_sec */
        stg     %r1,8(%r3)                      /* store tp->tv_nsec */
-8:     lghi    %r2,0
+       lghi    %r2,0
        br      %r14
 
        /* CLOCK_THREAD_CPUTIME_ID for this thread */
index ce81eb2ab76a207128069119acaac4e92918fa99..81b0e11521e444501ff5b1fc723965374ea3bd7e 100644 (file)
@@ -1317,19 +1317,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                return -EINVAL;
        }
 
-       switch (kvm_run->exit_reason) {
-       case KVM_EXIT_S390_SIEIC:
-       case KVM_EXIT_UNKNOWN:
-       case KVM_EXIT_INTR:
-       case KVM_EXIT_S390_RESET:
-       case KVM_EXIT_S390_UCONTROL:
-       case KVM_EXIT_S390_TSCH:
-       case KVM_EXIT_DEBUG:
-               break;
-       default:
-               BUG();
-       }
-
        vcpu->arch.sie_block->gpsw.mask = kvm_run->psw_mask;
        vcpu->arch.sie_block->gpsw.addr = kvm_run->psw_addr;
        if (kvm_run->kvm_dirty_regs & KVM_SYNC_PREFIX) {
index 19daa53a3da4a739f8f1b89cb7b88bf4dc0e5606..5404a6261db91a4fa204a9e2ad839b97530604c7 100644 (file)
@@ -986,11 +986,21 @@ int set_guest_storage_key(struct mm_struct *mm, unsigned long addr,
        pte_t *ptep;
 
        down_read(&mm->mmap_sem);
+retry:
        ptep = get_locked_pte(current->mm, addr, &ptl);
        if (unlikely(!ptep)) {
                up_read(&mm->mmap_sem);
                return -EFAULT;
        }
+       if (!(pte_val(*ptep) & _PAGE_INVALID) &&
+            (pte_val(*ptep) & _PAGE_PROTECT)) {
+                       pte_unmap_unlock(*ptep, ptl);
+                       if (fixup_user_fault(current, mm, addr, FAULT_FLAG_WRITE)) {
+                               up_read(&mm->mmap_sem);
+                               return -EFAULT;
+                       }
+                       goto retry;
+               }
 
        new = old = pgste_get_lock(ptep);
        pgste_val(new) &= ~(PGSTE_GR_BIT | PGSTE_GC_BIT |
index b319846ad97f340465bf6231720acd8445f1e781..244fb4c81e2525d0cbc62dceab964722bff5b5c5 100644 (file)
@@ -598,8 +598,6 @@ source kernel/Kconfig.hz
 config KEXEC
        bool "kexec system call (EXPERIMENTAL)"
        depends on SUPERH32 && MMU
-       select CRYPTO
-       select CRYPTO_SHA256
        help
          kexec is a system call that implements the ability to shutdown your
          current kernel, and to start another kernel.  It is like a reboot
index 097c2cdd117f53c543fb919ba6740210b1471a4a..f770e3992620e8a1673ee1a2bd47280be55cccd4 100644 (file)
@@ -229,6 +229,7 @@ void flush_icache_range(unsigned long start, unsigned long end)
 
        cacheop_on_each_cpu(local_flush_icache_range, (void *)&data, 1);
 }
+EXPORT_SYMBOL(flush_icache_range);
 
 void flush_icache_page(struct vm_area_struct *vma, struct page *page)
 {
index bf8daf9d9c9b9b02b2c7e7a97e2a1f958b38708f..37458f38b22093d9bf1b6468577fb39de3f54013 100644 (file)
@@ -105,6 +105,8 @@ static noinline int gup_pte_range(pmd_t pmd, unsigned long addr,
                VM_BUG_ON(!pfn_valid(pte_pfn(pte)));
                page = pte_page(pte);
                get_page(page);
+               __flush_anon_page(page, addr);
+               flush_dcache_page(page);
                pages[*nr] = page;
                (*nr)++;
 
index a3ffe2dd4832b18ff60e2716e770e1dfb7324d44..7fcd492adbfcfb030a34c2f4d34558fc9a20ad81 100644 (file)
@@ -191,8 +191,6 @@ source "kernel/Kconfig.hz"
 
 config KEXEC
        bool "kexec system call"
-       select CRYPTO
-       select CRYPTO_SHA256
        ---help---
          kexec is a system call that implements the ability to shutdown your
          current kernel, and to start another kernel.  It is like a reboot
index 01e8ab29f43a8bac34f3d0f98ea6e8c2b69cd2df..19eaa62d456a7c0635c9ec407dc3b998b7027bd4 100644 (file)
@@ -183,6 +183,7 @@ void flush_icache_range(unsigned long start, unsigned long end)
                preempt_enable();
        }
 }
+EXPORT_SYMBOL(flush_icache_range);
 
 
 /* Called when smp_send_reschedule() triggers IRQ_RESCHEDULE. */
index 780d77388dec507d7e11bb6f9d8595fe4f64c93d..7c8fb7018dc6bf728a5a70ef9bde100d94f3b565 100644 (file)
@@ -254,7 +254,8 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set,
 
        err |= setup_sigframe(frame, regs, set);
        if (err == 0)
-               err |= setup_return(regs, &ksig->ka, frame->retcode, frame, usig);
+               err |= setup_return(regs, &ksig->ka, frame->retcode, frame,
+                                   ksig->sig);
 
        return err;
 }
@@ -276,7 +277,8 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
        err |= __save_altstack(&frame->sig.uc.uc_stack, regs->UCreg_sp);
        err |= setup_sigframe(&frame->sig, regs, set);
        if (err == 0)
-               err |= setup_return(regs, &ksig->ka, frame->sig.retcode, frame, usig);
+               err |= setup_return(regs, &ksig->ka, frame->sig.retcode, frame,
+                                   ksig->sig);
 
        if (err == 0) {
                /*
@@ -303,7 +305,6 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs,
                          int syscall)
 {
        struct thread_info *thread = current_thread_info();
-       struct task_struct *tsk = current;
        sigset_t *oldset = sigmask_to_save();
        int usig = ksig->sig;
        int ret;
@@ -373,7 +374,7 @@ static void do_signal(struct pt_regs *regs, int syscall)
        if (!user_mode(regs))
                return;
 
-       if (get_signsl(&ksig)) {
+       if (get_signal(&ksig)) {
                handle_signal(&ksig, regs, syscall);
                return;
        }
index 61b6d51866f8680353044f5d7f5a3ea5cb19b7ac..3942f74c92d7d338ee0c8a858ad2e5a81774686d 100644 (file)
@@ -17,6 +17,4 @@ obj-$(CONFIG_IA32_EMULATION) += ia32/
 obj-y += platform/
 obj-y += net/
 
-ifeq ($(CONFIG_X86_64),y)
-obj-$(CONFIG_KEXEC) += purgatory/
-endif
+obj-$(CONFIG_KEXEC_FILE) += purgatory/
index 5d0bf1aa9dcb6d68fd39f395dcbef9f89954cbc0..778178f4c7d132c15f4f7700b0ad31a20ea7d24b 100644 (file)
@@ -1585,9 +1585,6 @@ source kernel/Kconfig.hz
 
 config KEXEC
        bool "kexec system call"
-       select BUILD_BIN2C
-       select CRYPTO
-       select CRYPTO_SHA256
        ---help---
          kexec is a system call that implements the ability to shutdown your
          current kernel, and to start another kernel.  It is like a reboot
@@ -1602,9 +1599,22 @@ config KEXEC
          interface is strongly in flux, so no good recommendation can be
          made.
 
+config KEXEC_FILE
+       bool "kexec file based system call"
+       select BUILD_BIN2C
+       depends on KEXEC
+       depends on X86_64
+       depends on CRYPTO=y
+       depends on CRYPTO_SHA256=y
+       ---help---
+         This is new version of kexec system call. This system call is
+         file based and takes file descriptors as system call argument
+         for kernel and initramfs as opposed to list of segments as
+         accepted by previous system call.
+
 config KEXEC_VERIFY_SIG
        bool "Verify kernel signature during kexec_file_load() syscall"
-       depends on KEXEC
+       depends on KEXEC_FILE
        ---help---
          This option makes kernel signature verification mandatory for
          kexec_file_load() syscall. If kernel is signature can not be
index c1aa368878431fe0b551cb4704b6587fd8826145..60087ca37679ccfad7c0417b8e3b32852524ba7c 100644 (file)
@@ -184,11 +184,8 @@ archheaders:
        $(Q)$(MAKE) $(build)=arch/x86/syscalls all
 
 archprepare:
-ifeq ($(CONFIG_KEXEC),y)
-# Build only for 64bit. No loaders for 32bit yet.
- ifeq ($(CONFIG_X86_64),y)
+ifeq ($(CONFIG_KEXEC_FILE),y)
        $(Q)$(MAKE) $(build)=arch/x86/purgatory arch/x86/purgatory/kexec-purgatory.c
- endif
 endif
 
 ###
@@ -254,6 +251,7 @@ archclean:
        $(Q)rm -rf $(objtree)/arch/x86_64
        $(Q)$(MAKE) $(clean)=$(boot)
        $(Q)$(MAKE) $(clean)=arch/x86/tools
+       $(Q)$(MAKE) $(clean)=arch/x86/purgatory
 
 PHONY += kvmconfig
 kvmconfig:
index 0aeed5ca356ec04bdbc4705fb6bbf5010cb65354..478c490f36547930e7101c4ad051292810fb04db 100644 (file)
@@ -227,6 +227,8 @@ static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned
 
 extern void io_apic_eoi(unsigned int apic, unsigned int vector);
 
+extern bool mp_should_keep_irq(struct device *dev);
+
 #else  /* !CONFIG_X86_IO_APIC */
 
 #define io_apic_assign_pci_irqs 0
index 0ec0560126180a152372ac3fc908752ea6e9ce87..aa97a070f09fbb6d31876b005a1dc86444897c10 100644 (file)
@@ -131,8 +131,13 @@ static inline int pte_exec(pte_t pte)
 
 static inline int pte_special(pte_t pte)
 {
-       return (pte_flags(pte) & (_PAGE_PRESENT|_PAGE_SPECIAL)) ==
-                                (_PAGE_PRESENT|_PAGE_SPECIAL);
+       /*
+        * See CONFIG_NUMA_BALANCING pte_numa in include/asm-generic/pgtable.h.
+        * On x86 we have _PAGE_BIT_NUMA == _PAGE_BIT_GLOBAL+1 ==
+        * __PAGE_BIT_SOFTW1 == _PAGE_BIT_SPECIAL.
+        */
+       return (pte_flags(pte) & _PAGE_SPECIAL) &&
+               (pte_flags(pte) & (_PAGE_PRESENT|_PAGE_PROTNONE));
 }
 
 static inline unsigned long pte_pfn(pte_t pte)
index 5be9063545d278bd978d8c14e67fb7be08cc937b..3874693c0e53adc3593a21374154e99941944703 100644 (file)
@@ -19,6 +19,7 @@ extern pud_t level3_ident_pgt[512];
 extern pmd_t level2_kernel_pgt[512];
 extern pmd_t level2_fixmap_pgt[512];
 extern pmd_t level2_ident_pgt[512];
+extern pte_t level1_fixmap_pgt[512];
 extern pgd_t init_level4_pgt[];
 
 #define swapper_pg_dir init_level4_pgt
index b5ea75c4a4b411d14ae2bf810eb7d40bde9f8716..ada2e2d6be3e01335734016a2aae5dc677ab69af 100644 (file)
@@ -71,6 +71,7 @@ obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o
 obj-$(CONFIG_X86_TSC)          += trace_clock.o
 obj-$(CONFIG_KEXEC)            += machine_kexec_$(BITS).o
 obj-$(CONFIG_KEXEC)            += relocate_kernel_$(BITS).o crash.o
+obj-$(CONFIG_KEXEC_FILE)       += kexec-bzimage64.o
 obj-$(CONFIG_CRASH_DUMP)       += crash_dump_$(BITS).o
 obj-y                          += kprobes/
 obj-$(CONFIG_MODULES)          += module.o
@@ -118,5 +119,4 @@ ifeq ($(CONFIG_X86_64),y)
 
        obj-$(CONFIG_PCI_MMCONFIG)      += mmconf-fam10h_64.o
        obj-y                           += vsmp_64.o
-       obj-$(CONFIG_KEXEC)             += kexec-bzimage64.o
 endif
index 29290f554e7963fc104cd385921692a6bbc41470..337ce5a9b15c86bb7e9ea7747749fed1aee0d2d7 100644 (file)
@@ -1070,6 +1070,11 @@ static int mp_map_pin_to_irq(u32 gsi, int idx, int ioapic, int pin,
        }
 
        if (flags & IOAPIC_MAP_ALLOC) {
+               /* special handling for legacy IRQs */
+               if (irq < nr_legacy_irqs() && info->count == 1 &&
+                   mp_irqdomain_map(domain, irq, pin) != 0)
+                       irq = -1;
+
                if (irq > 0)
                        info->count++;
                else if (info->count == 0)
@@ -3896,7 +3901,15 @@ int mp_irqdomain_map(struct irq_domain *domain, unsigned int virq,
                        info->polarity = 1;
                }
                info->node = NUMA_NO_NODE;
-               info->set = 1;
+
+               /*
+                * setup_IO_APIC_irqs() programs all legacy IRQs with default
+                * trigger and polarity attributes. Don't set the flag for that
+                * case so the first legacy IRQ user could reprogram the pin
+                * with real trigger and polarity attributes.
+                */
+               if (virq >= nr_legacy_irqs() || info->count)
+                       info->set = 1;
        }
        set_io_apic_irq_attr(&attr, ioapic, hwirq, info->trigger,
                             info->polarity);
@@ -3946,6 +3959,18 @@ int mp_set_gsi_attr(u32 gsi, int trigger, int polarity, int node)
        return ret;
 }
 
+bool mp_should_keep_irq(struct device *dev)
+{
+       if (dev->power.is_prepared)
+               return true;
+#ifdef CONFIG_PM_RUNTIME
+       if (dev->power.runtime_status == RPM_SUSPENDING)
+               return true;
+#endif
+
+       return false;
+}
+
 /* Enable IOAPIC early just for system timer */
 void __init pre_init_apic_IRQ0(void)
 {
index 0553a34fa0df9eacf9336ee9076b28802531240b..a618fcd2c07d3d54062a8558a7f9941b16859203 100644 (file)
@@ -182,8 +182,7 @@ void native_machine_crash_shutdown(struct pt_regs *regs)
        crash_save_cpu(regs, safe_smp_processor_id());
 }
 
-#ifdef CONFIG_X86_64
-
+#ifdef CONFIG_KEXEC_FILE
 static int get_nr_ram_ranges_callback(unsigned long start_pfn,
                                unsigned long nr_pfn, void *arg)
 {
@@ -696,5 +695,4 @@ int crash_load_segments(struct kimage *image)
 
        return ret;
 }
-
-#endif /* CONFIG_X86_64 */
+#endif /* CONFIG_KEXEC_FILE */
index 1e6cff5814fa62ea0aefdc9d87fc1dec532d16e6..44f1ed42fdf2136c0b2654256745d20edca1a28d 100644 (file)
@@ -203,7 +203,7 @@ void __init native_init_IRQ(void)
                set_intr_gate(i, interrupt[i - FIRST_EXTERNAL_VECTOR]);
        }
 
-       if (!acpi_ioapic && !of_ioapic)
+       if (!acpi_ioapic && !of_ioapic && nr_legacy_irqs())
                setup_irq(2, &irq2);
 
 #ifdef CONFIG_X86_32
index 8b04018e5d1f0732f1d1c3cf3ad092352d1409d6..485981059a40e703e7be8debd49a14e45dde0e54 100644 (file)
 #include <asm/debugreg.h>
 #include <asm/kexec-bzimage64.h>
 
+#ifdef CONFIG_KEXEC_FILE
 static struct kexec_file_ops *kexec_file_loaders[] = {
                &kexec_bzImage64_ops,
 };
+#endif
 
 static void free_transition_pgtable(struct kimage *image)
 {
@@ -178,6 +180,7 @@ static void load_segments(void)
                );
 }
 
+#ifdef CONFIG_KEXEC_FILE
 /* Update purgatory as needed after various image segments have been prepared */
 static int arch_update_purgatory(struct kimage *image)
 {
@@ -209,6 +212,12 @@ static int arch_update_purgatory(struct kimage *image)
 
        return ret;
 }
+#else /* !CONFIG_KEXEC_FILE */
+static inline int arch_update_purgatory(struct kimage *image)
+{
+       return 0;
+}
+#endif /* CONFIG_KEXEC_FILE */
 
 int machine_kexec_prepare(struct kimage *image)
 {
@@ -329,6 +338,7 @@ void arch_crash_save_vmcoreinfo(void)
 
 /* arch-dependent functionality related to kexec file-based syscall */
 
+#ifdef CONFIG_KEXEC_FILE
 int arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
                                  unsigned long buf_len)
 {
@@ -522,3 +532,4 @@ overflow:
               (int)ELF64_R_TYPE(rel[i].r_info), value);
        return -ENOEXEC;
 }
+#endif /* CONFIG_KEXEC_FILE */
index bf7ef5ce29dff7f89d8e93fb8bee4119f445379b..0fa29609b2c42236c7cd5bd913533cf18b895cc3 100644 (file)
@@ -68,6 +68,8 @@ static struct irqaction irq0  = {
 
 void __init setup_default_timer_irq(void)
 {
+       if (!nr_legacy_irqs())
+               return;
        setup_irq(0, &irq0);
 }
 
index 3865116c51fbf583a923d4131882c653b5fc3c24..b9958c364075e949620001cc9d8f02a2715d0128 100644 (file)
@@ -229,7 +229,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 
 static void intel_mid_pci_irq_disable(struct pci_dev *dev)
 {
-       if (!dev->dev.power.is_prepared && dev->irq > 0)
+       if (!mp_should_keep_irq(&dev->dev) && dev->irq > 0)
                mp_unmap_irq(dev->irq);
 }
 
index bc1a2c341891034d04c86b834c5d132e7f954e33..eb500c2592ad8ab4ced728f676d9102411fa3782 100644 (file)
@@ -1256,7 +1256,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
 
 static void pirq_disable_irq(struct pci_dev *dev)
 {
-       if (io_apic_assign_pci_irqs && !dev->dev.power.is_prepared &&
+       if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) &&
            dev->irq) {
                mp_unmap_irq(dev->irq);
                dev->irq = 0;
index 7fde9ee438a43b0e1f55b4c2db3fb90b83c3f1ce..899dd24542568de85e815e4b9f206d66286bca8c 100644 (file)
@@ -11,6 +11,7 @@ targets += purgatory.ro
 # sure how to relocate those. Like kexec-tools, use custom flags.
 
 KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes -fno-zero-initialized-in-bss -fno-builtin -ffreestanding -c -MD -Os -mcmodel=large
+KBUILD_CFLAGS += -m$(BITS)
 
 $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
                $(call if_changed,ld)
@@ -24,7 +25,4 @@ $(obj)/kexec-purgatory.c: $(obj)/purgatory.ro FORCE
        $(call if_changed,bin2c)
 
 
-# No loaders for 32bits yet.
-ifeq ($(CONFIG_X86_64),y)
- obj-$(CONFIG_KEXEC)           += kexec-purgatory.o
-endif
+obj-$(CONFIG_KEXEC_FILE)       += kexec-purgatory.o
index e8a1201c3293bf074bedfaa7243f0e670064d457..16fb0099b7f295ed40c206e25478037f0b2ff651 100644 (file)
@@ -1866,12 +1866,11 @@ static void __init check_pt_base(unsigned long *pt_base, unsigned long *pt_end,
  *
  * We can construct this by grafting the Xen provided pagetable into
  * head_64.S's preconstructed pagetables.  We copy the Xen L2's into
- * level2_ident_pgt, level2_kernel_pgt and level2_fixmap_pgt.  This
- * means that only the kernel has a physical mapping to start with -
- * but that's enough to get __va working.  We need to fill in the rest
- * of the physical mapping once some sort of allocator has been set
- * up.
- * NOTE: for PVH, the page tables are native.
+ * level2_ident_pgt, and level2_kernel_pgt.  This means that only the
+ * kernel has a physical mapping to start with - but that's enough to
+ * get __va working.  We need to fill in the rest of the physical
+ * mapping once some sort of allocator has been set up.  NOTE: for
+ * PVH, the page tables are native.
  */
 void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
 {
@@ -1902,8 +1901,11 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
                /* L3_i[0] -> level2_ident_pgt */
                convert_pfn_mfn(level3_ident_pgt);
                /* L3_k[510] -> level2_kernel_pgt
-                * L3_i[511] -> level2_fixmap_pgt */
+                * L3_k[511] -> level2_fixmap_pgt */
                convert_pfn_mfn(level3_kernel_pgt);
+
+               /* L3_k[511][506] -> level1_fixmap_pgt */
+               convert_pfn_mfn(level2_fixmap_pgt);
        }
        /* We get [511][511] and have Xen's version of level2_kernel_pgt */
        l3 = m2v(pgd[pgd_index(__START_KERNEL_map)].pgd);
@@ -1913,21 +1915,15 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
        addr[1] = (unsigned long)l3;
        addr[2] = (unsigned long)l2;
        /* Graft it onto L4[272][0]. Note that we creating an aliasing problem:
-        * Both L4[272][0] and L4[511][511] have entries that point to the same
+        * Both L4[272][0] and L4[511][510] have entries that point to the same
         * L2 (PMD) tables. Meaning that if you modify it in __va space
         * it will be also modified in the __ka space! (But if you just
         * modify the PMD table to point to other PTE's or none, then you
         * are OK - which is what cleanup_highmap does) */
        copy_page(level2_ident_pgt, l2);
-       /* Graft it onto L4[511][511] */
+       /* Graft it onto L4[511][510] */
        copy_page(level2_kernel_pgt, l2);
 
-       /* Get [511][510] and graft that in level2_fixmap_pgt */
-       l3 = m2v(pgd[pgd_index(__START_KERNEL_map + PMD_SIZE)].pgd);
-       l2 = m2v(l3[pud_index(__START_KERNEL_map + PMD_SIZE)].pud);
-       copy_page(level2_fixmap_pgt, l2);
-       /* Note that we don't do anything with level1_fixmap_pgt which
-        * we don't need. */
        if (!xen_feature(XENFEAT_auto_translated_physmap)) {
                /* Make pagetable pieces RO */
                set_page_prot(init_level4_pgt, PAGE_KERNEL_RO);
@@ -1937,6 +1933,7 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
                set_page_prot(level2_ident_pgt, PAGE_KERNEL_RO);
                set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO);
                set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO);
+               set_page_prot(level1_fixmap_pgt, PAGE_KERNEL_RO);
 
                /* Pin down new L4 */
                pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE,
index 3a617af60d465196bb894cebdc4042ccd4e4a92f..49c6c3d9444916e0dc727d51c96349e92c424d6a 100644 (file)
@@ -4,24 +4,23 @@ config ZONE_DMA
 config XTENSA
        def_bool y
        select ARCH_WANT_FRAME_POINTERS
-       select HAVE_IDE
-       select GENERIC_ATOMIC64
-       select GENERIC_CLOCKEVENTS
-       select VIRT_TO_BUS
-       select GENERIC_IRQ_SHOW
-       select GENERIC_SCHED_CLOCK
-       select MODULES_USE_ELF_RELA
-       select GENERIC_PCI_IOMAP
        select ARCH_WANT_IPC_PARSE_VERSION
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select BUILDTIME_EXTABLE_SORT
        select CLONE_BACKWARDS
-       select IRQ_DOMAIN
-       select HAVE_OPROFILE
+       select COMMON_CLK
+       select GENERIC_ATOMIC64
+       select GENERIC_CLOCKEVENTS
+       select GENERIC_IRQ_SHOW
+       select GENERIC_PCI_IOMAP
+       select GENERIC_SCHED_CLOCK
        select HAVE_FUNCTION_TRACER
        select HAVE_IRQ_TIME_ACCOUNTING
+       select HAVE_OPROFILE
        select HAVE_PERF_EVENTS
-       select COMMON_CLK
+       select IRQ_DOMAIN
+       select MODULES_USE_ELF_RELA
+       select VIRT_TO_BUS
        help
          Xtensa processors are 32-bit RISC machines designed by Tensilica
          primarily for embedded systems.  These processors are both
@@ -62,7 +61,9 @@ config TRACE_IRQFLAGS_SUPPORT
        def_bool y
 
 config MMU
-       def_bool n
+       bool
+       default n if !XTENSA_VARIANT_CUSTOM
+       default XTENSA_VARIANT_MMU if XTENSA_VARIANT_CUSTOM
 
 config VARIANT_IRQ_SWITCH
        def_bool n
@@ -102,8 +103,40 @@ config XTENSA_VARIANT_S6000
        select VARIANT_IRQ_SWITCH
        select ARCH_REQUIRE_GPIOLIB
        select XTENSA_CALIBRATE_CCOUNT
+
+config XTENSA_VARIANT_CUSTOM
+       bool "Custom Xtensa processor configuration"
+       select MAY_HAVE_SMP
+       select HAVE_XTENSA_GPIO32
+       help
+         Select this variant to use a custom Xtensa processor configuration.
+         You will be prompted for a processor variant CORENAME.
 endchoice
 
+config XTENSA_VARIANT_CUSTOM_NAME
+       string "Xtensa Processor Custom Core Variant Name"
+       depends on XTENSA_VARIANT_CUSTOM
+       help
+         Provide the name of a custom Xtensa processor variant.
+         This CORENAME selects arch/xtensa/variant/CORENAME.
+         Dont forget you have to select MMU if you have one.
+
+config XTENSA_VARIANT_NAME
+       string
+       default "dc232b"                        if XTENSA_VARIANT_DC232B
+       default "dc233c"                        if XTENSA_VARIANT_DC233C
+       default "fsf"                           if XTENSA_VARIANT_FSF
+       default "s6000"                         if XTENSA_VARIANT_S6000
+       default XTENSA_VARIANT_CUSTOM_NAME      if XTENSA_VARIANT_CUSTOM
+
+config XTENSA_VARIANT_MMU
+       bool "Core variant has a Full MMU (TLB, Pages, Protection, etc)"
+       depends on XTENSA_VARIANT_CUSTOM
+       default y
+       help
+         Build a Conventional Kernel with full MMU support,
+         ie: it supports a TLB with auto-loading, page protection.
+
 config XTENSA_UNALIGNED_USER
        bool "Unaligned memory access in use space"
        help
@@ -156,13 +189,9 @@ config HOTPLUG_CPU
 
          Say N if you want to disable CPU hotplug.
 
-config MATH_EMULATION
-       bool "Math emulation"
-       help
-       Can we use information of configuration file?
-
 config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
        bool "Initialize Xtensa MMU inside the Linux kernel code"
+       depends on MMU
        default y
        help
          Earlier version initialized the MMU in the exception vector
@@ -192,6 +221,7 @@ config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX
 
 config HIGHMEM
        bool "High Memory Support"
+       depends on MMU
        help
          Linux can use the full amount of RAM in the system by
          default. However, the default MMUv2 setup only maps the
@@ -208,6 +238,32 @@ config HIGHMEM
 
          If unsure, say Y.
 
+config FAST_SYSCALL_XTENSA
+       bool "Enable fast atomic syscalls"
+       default n
+       help
+         fast_syscall_xtensa is a syscall that can make atomic operations
+         on UP kernel when processor has no s32c1i support.
+
+         This syscall is deprecated. It may have issues when called with
+         invalid arguments. It is provided only for backwards compatibility.
+         Only enable it if your userspace software requires it.
+
+         If unsure, say N.
+
+config FAST_SYSCALL_SPILL_REGISTERS
+       bool "Enable spill registers syscall"
+       default n
+       help
+         fast_syscall_spill_registers is a syscall that spills all active
+         register windows of a calling userspace task onto its stack.
+
+         This syscall is deprecated. It may have issues when called with
+         invalid arguments. It is provided only for backwards compatibility.
+         Only enable it if your userspace software requires it.
+
+         If unsure, say N.
+
 endmenu
 
 config XTENSA_CALIBRATE_CCOUNT
@@ -250,12 +306,14 @@ config XTENSA_PLATFORM_ISS
 
 config XTENSA_PLATFORM_XT2000
        bool "XT2000"
+       select HAVE_IDE
        help
          XT2000 is the name of Tensilica's feature-rich emulation platform.
          This hardware is capable of running a full Linux distribution.
 
 config XTENSA_PLATFORM_S6105
        bool "S6105"
+       select HAVE_IDE
        select SERIAL_CONSOLE
        select NO_IOPORT_MAP
 
index 81250ece3062ae914628d8b49f777ac7de580263..472533064b465d126ab95434a6b285050fa4890f 100644 (file)
@@ -4,6 +4,7 @@
 # for more details.
 #
 # Copyright (C) 2001 - 2005  Tensilica Inc.
+# Copyright (C) 2014 Cadence Design Systems Inc.
 #
 # This file is included by the global makefile so that you can add your own
 # architecture-specific flags and dependencies. Remember to do have actions
 # Core configuration.
 # (Use VAR=<xtensa_config> to use another default compiler.)
 
-variant-$(CONFIG_XTENSA_VARIANT_FSF)           := fsf
-variant-$(CONFIG_XTENSA_VARIANT_DC232B)                := dc232b
-variant-$(CONFIG_XTENSA_VARIANT_DC233C)                := dc233c
-variant-$(CONFIG_XTENSA_VARIANT_S6000)         := s6000
-variant-$(CONFIG_XTENSA_VARIANT_LINUX_CUSTOM)  := custom
+variant-y := $(patsubst "%",%,$(CONFIG_XTENSA_VARIANT_NAME))
 
 VARIANT = $(variant-y)
 export VARIANT
index 742a347be67a3ef7651615435f7d41711f8c139e..c4d17a34ab86ca3d61ca85f398cf0fd80b753f41 100644 (file)
@@ -4,8 +4,11 @@
 
 / {
        compatible = "cdns,xtensa-kc705";
+       chosen {
+               bootargs = "earlycon=uart8250,mmio32,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=0x38000000";
+       };
        memory@0 {
                device_type = "memory";
-               reg = <0x00000000 0x08000000>;
+               reg = <0x00000000 0x38000000>;
        };
 };
index f6000fe05119a1a9ad5f79cff94c4516b106809d..721df1214bc3bff9026f5f593a7453b2a8341a68 100644 (file)
@@ -66,7 +66,6 @@ CONFIG_XTENSA_ARCH_LINUX_BE=y
 CONFIG_MMU=y
 # CONFIG_XTENSA_UNALIGNED_USER is not set
 # CONFIG_PREEMPT is not set
-# CONFIG_MATH_EMULATION is not set
 # CONFIG_HIGHMEM is not set
 
 #
index 1493c68352d11454a50a7fdfb5f11f49ab54de88..b966baf82cae8af3f52e6500414af80326937b6d 100644 (file)
@@ -146,7 +146,6 @@ CONFIG_XTENSA_VARIANT_FSF=y
 # CONFIG_XTENSA_VARIANT_S6000 is not set
 # CONFIG_XTENSA_UNALIGNED_USER is not set
 # CONFIG_PREEMPT is not set
-# CONFIG_MATH_EMULATION is not set
 CONFIG_XTENSA_CALIBRATE_CCOUNT=y
 CONFIG_SERIAL_CONSOLE=y
 CONFIG_XTENSA_ISS_NETWORK=y
@@ -308,7 +307,7 @@ CONFIG_MISC_DEVICES=y
 # EEPROM support
 #
 # CONFIG_EEPROM_93CX6 is not set
-CONFIG_HAVE_IDE=y
+# CONFIG_HAVE_IDE is not set
 # CONFIG_IDE is not set
 
 #
index 12a492ab6d17f9fbf74dedd1a9723a269ee7cbef..9471265b8ca69e1a4bce9dcc531dae2d8d03e271 100644 (file)
@@ -109,7 +109,6 @@ CONFIG_VARIANT_IRQ_SWITCH=y
 CONFIG_XTENSA_VARIANT_S6000=y
 # CONFIG_XTENSA_UNALIGNED_USER is not set
 CONFIG_PREEMPT=y
-# CONFIG_MATH_EMULATION is not set
 # CONFIG_HIGHMEM is not set
 CONFIG_XTENSA_CALIBRATE_CCOUNT=y
 CONFIG_SERIAL_CONSOLE=y
index 555a98a1845363588ced5fd3ec26a2269846e3d8..e72aaca7a77fc112161cc22133b6c1305cc5c3ae 100644 (file)
@@ -37,6 +37,7 @@
  * specials for cache aliasing:
  *
  * __flush_invalidate_dcache_page_alias(vaddr,paddr)
+ * __invalidate_dcache_page_alias(vaddr,paddr)
  * __invalidate_icache_page_alias(vaddr,paddr)
  */
 
@@ -62,6 +63,7 @@ extern void __flush_invalidate_dcache_range(unsigned long, unsigned long);
 
 #if defined(CONFIG_MMU) && (DCACHE_WAY_SIZE > PAGE_SIZE)
 extern void __flush_invalidate_dcache_page_alias(unsigned long, unsigned long);
+extern void __invalidate_dcache_page_alias(unsigned long, unsigned long);
 #else
 static inline void __flush_invalidate_dcache_page_alias(unsigned long virt,
                                                        unsigned long phys) { }
index 9f6c33d0428a73d6b59f601992aede5a956dc3da..62b507deea9da136cc26cf32388a5a3358efa251 100644 (file)
@@ -23,8 +23,8 @@
  * Here we define all the compile-time 'special' virtual
  * addresses. The point is to have a constant address at
  * compile time, but to set the physical address only
- * in the boot process. We allocate these special  addresses
- * from the end of the consistent memory region backwards.
+ * in the boot process. We allocate these special addresses
+ * from the start of the consistent memory region upwards.
  * Also this lets us do fail-safe vmalloc(), we
  * can guarantee that these special addresses and
  * vmalloc()-ed addresses never overlap.
@@ -38,7 +38,8 @@ enum fixed_addresses {
 #ifdef CONFIG_HIGHMEM
        /* reserved pte's for temporary kernel mappings */
        FIX_KMAP_BEGIN,
-       FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1,
+       FIX_KMAP_END = FIX_KMAP_BEGIN +
+               (KM_TYPE_NR * NR_CPUS * DCACHE_N_COLORS) - 1,
 #endif
        __end_of_fixed_addresses
 };
@@ -47,7 +48,28 @@ enum fixed_addresses {
 #define FIXADDR_SIZE   (__end_of_fixed_addresses << PAGE_SHIFT)
 #define FIXADDR_START  ((FIXADDR_TOP - FIXADDR_SIZE) & PMD_MASK)
 
-#include <asm-generic/fixmap.h>
+#define __fix_to_virt(x)       (FIXADDR_START + ((x) << PAGE_SHIFT))
+#define __virt_to_fix(x)       (((x) - FIXADDR_START) >> PAGE_SHIFT)
+
+#ifndef __ASSEMBLY__
+/*
+ * 'index to address' translation. If anyone tries to use the idx
+ * directly without translation, we catch the bug with a NULL-deference
+ * kernel oops. Illegal ranges of incoming indices are caught too.
+ */
+static __always_inline unsigned long fix_to_virt(const unsigned int idx)
+{
+       BUILD_BUG_ON(idx >= __end_of_fixed_addresses);
+       return __fix_to_virt(idx);
+}
+
+static inline unsigned long virt_to_fix(const unsigned long vaddr)
+{
+       BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
+       return __virt_to_fix(vaddr);
+}
+
+#endif
 
 #define kmap_get_fixmap_pte(vaddr) \
        pte_offset_kernel( \
index 2653ef5d55f1c9ed92d35d50f91136732334ec1b..2c7901edffaf3a6b38714386294c633a8aa7d8c3 100644 (file)
 #ifndef _XTENSA_HIGHMEM_H
 #define _XTENSA_HIGHMEM_H
 
+#include <linux/wait.h>
 #include <asm/cacheflush.h>
 #include <asm/fixmap.h>
 #include <asm/kmap_types.h>
 #include <asm/pgtable.h>
 
-#define PKMAP_BASE             (FIXADDR_START - PMD_SIZE)
-#define LAST_PKMAP             PTRS_PER_PTE
+#define PKMAP_BASE             ((FIXADDR_START - \
+                                 (LAST_PKMAP + 1) * PAGE_SIZE) & PMD_MASK)
+#define LAST_PKMAP             (PTRS_PER_PTE * DCACHE_N_COLORS)
 #define LAST_PKMAP_MASK                (LAST_PKMAP - 1)
 #define PKMAP_NR(virt)         (((virt) - PKMAP_BASE) >> PAGE_SHIFT)
 #define PKMAP_ADDR(nr)         (PKMAP_BASE + ((nr) << PAGE_SHIFT))
 
 #define kmap_prot              PAGE_KERNEL
 
+#if DCACHE_WAY_SIZE > PAGE_SIZE
+#define get_pkmap_color get_pkmap_color
+static inline int get_pkmap_color(struct page *page)
+{
+       return DCACHE_ALIAS(page_to_phys(page));
+}
+
+extern unsigned int last_pkmap_nr_arr[];
+
+static inline unsigned int get_next_pkmap_nr(unsigned int color)
+{
+       last_pkmap_nr_arr[color] =
+               (last_pkmap_nr_arr[color] + DCACHE_N_COLORS) & LAST_PKMAP_MASK;
+       return last_pkmap_nr_arr[color] + color;
+}
+
+static inline int no_more_pkmaps(unsigned int pkmap_nr, unsigned int color)
+{
+       return pkmap_nr < DCACHE_N_COLORS;
+}
+
+static inline int get_pkmap_entries_count(unsigned int color)
+{
+       return LAST_PKMAP / DCACHE_N_COLORS;
+}
+
+extern wait_queue_head_t pkmap_map_wait_arr[];
+
+static inline wait_queue_head_t *get_pkmap_wait_queue_head(unsigned int color)
+{
+       return pkmap_map_wait_arr + color;
+}
+#endif
+
 extern pte_t *pkmap_page_table;
 
 void *kmap_high(struct page *page);
index 47f582333f6b799b246a39577e96bf1dced7cee3..abe24c6f8b2f06f112f9e9933306bcdd5a924d4d 100644 (file)
@@ -78,7 +78,9 @@
 # define DCACHE_ALIAS_EQ(a,b)  ((((a) ^ (b)) & DCACHE_ALIAS_MASK) == 0)
 #else
 # define DCACHE_ALIAS_ORDER    0
+# define DCACHE_ALIAS(a)       ((void)(a), 0)
 #endif
+#define DCACHE_N_COLORS                (1 << DCACHE_ALIAS_ORDER)
 
 #if ICACHE_WAY_SIZE > PAGE_SIZE
 # define ICACHE_ALIAS_ORDER    (ICACHE_WAY_SHIFT - PAGE_SHIFT)
@@ -134,6 +136,7 @@ static inline __attribute_const__ int get_order(unsigned long size)
 #endif
 
 struct page;
+struct vm_area_struct;
 extern void clear_page(void *page);
 extern void copy_page(void *to, void *from);
 
@@ -143,8 +146,15 @@ extern void copy_page(void *to, void *from);
  */
 
 #if DCACHE_WAY_SIZE > PAGE_SIZE
-extern void clear_user_page(void*, unsigned long, struct page*);
-extern void copy_user_page(void*, void*, unsigned long, struct page*);
+extern void clear_page_alias(void *vaddr, unsigned long paddr);
+extern void copy_page_alias(void *to, void *from,
+                           unsigned long to_paddr, unsigned long from_paddr);
+
+#define clear_user_highpage clear_user_highpage
+void clear_user_highpage(struct page *page, unsigned long vaddr);
+#define __HAVE_ARCH_COPY_USER_HIGHPAGE
+void copy_user_highpage(struct page *to, struct page *from,
+                       unsigned long vaddr, struct vm_area_struct *vma);
 #else
 # define clear_user_page(page, vaddr, pg)      clear_page(page)
 # define copy_user_page(to, from, vaddr, pg)   copy_page(to, from)
index 4b0ca35a93b1a731bf0ce2c1db32f9fabb890fef..b2173e5da601cbe57303f9060faacb0dde0310cf 100644 (file)
 #define VMALLOC_START          0xC0000000
 #define VMALLOC_END            0xC7FEFFFF
 #define TLBTEMP_BASE_1         0xC7FF0000
-#define TLBTEMP_BASE_2         0xC7FF8000
+#define TLBTEMP_BASE_2         (TLBTEMP_BASE_1 + DCACHE_WAY_SIZE)
+#if 2 * DCACHE_WAY_SIZE > ICACHE_WAY_SIZE
+#define TLBTEMP_SIZE           (2 * DCACHE_WAY_SIZE)
+#else
+#define TLBTEMP_SIZE           ICACHE_WAY_SIZE
+#endif
 
 /*
  * For the Xtensa architecture, the PTE layout is as follows:
index fd686dc45d1a95b5016de15341c6d3fe173837fe..c7211e7e182d56cd85e3ec923ee89f81748b26af 100644 (file)
  */
        .macro  get_fs  ad, sp
        GET_CURRENT(\ad,\sp)
+#if THREAD_CURRENT_DS > 1020
+       addi    \ad, \ad, TASK_THREAD
+       l32i    \ad, \ad, THREAD_CURRENT_DS - TASK_THREAD
+#else
        l32i    \ad, \ad, THREAD_CURRENT_DS
+#endif
        .endm
 
 /*
index b4cb1100c0fb01f6ca178ef5c3f0e4adc02b8f9a..a47909f0c34b4892848d06b9f55ebe4a37563d90 100644 (file)
 #define TCSETSW                0x5403
 #define TCSETSF                0x5404
 
-#define TCGETA         _IOR('t', 23, struct termio)
-#define TCSETA         _IOW('t', 24, struct termio)
-#define TCSETAW                _IOW('t', 25, struct termio)
-#define TCSETAF                _IOW('t', 28, struct termio)
+#define TCGETA         0x80127417      /* _IOR('t', 23, struct termio) */
+#define TCSETA         0x40127418      /* _IOW('t', 24, struct termio) */
+#define TCSETAW                0x40127419      /* _IOW('t', 25, struct termio) */
+#define TCSETAF                0x4012741C      /* _IOW('t', 28, struct termio) */
 
 #define TCSBRK         _IO('t', 29)
 #define TCXONC         _IO('t', 30)
 #define TCFLSH         _IO('t', 31)
 
-#define TIOCSWINSZ     _IOW('t', 103, struct winsize)
-#define TIOCGWINSZ     _IOR('t', 104, struct winsize)
+#define TIOCSWINSZ     0x40087467      /* _IOW('t', 103, struct winsize) */
+#define TIOCGWINSZ     0x80087468      /* _IOR('t', 104, struct winsize) */
 #define        TIOCSTART       _IO('t', 110)           /* start output, like ^Q */
 #define        TIOCSTOP        _IO('t', 111)           /* stop output, like ^S */
 #define TIOCOUTQ        _IOR('t', 115, int)     /* output queue size */
@@ -88,7 +88,6 @@
 #define TIOCSETD       _IOW('T', 35, int)
 #define TIOCGETD       _IOR('T', 36, int)
 #define TCSBRKP                _IOW('T', 37, int)   /* Needed for POSIX tcsendbreak()*/
-#define TIOCTTYGSTRUCT _IOR('T', 38, struct tty_struct) /* For debugging only*/
 #define TIOCSBRK       _IO('T', 39)         /* BSD compatibility */
 #define TIOCCBRK       _IO('T', 40)         /* BSD compatibility */
 #define TIOCGSID       _IOR('T', 41, pid_t) /* Return the session ID of FD*/
 #define TIOCSERGETLSR   _IOR('T', 89, unsigned int) /* Get line status reg. */
   /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
 # define TIOCSER_TEMT    0x01               /* Transmitter physically empty */
-#define TIOCSERGETMULTI _IOR('T', 90, struct serial_multiport_struct) /* Get multiport config  */
-#define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* Set multiport config */
+#define TIOCSERGETMULTI 0x80a8545a /* Get multiport config  */
+                       /* _IOR('T', 90, struct serial_multiport_struct) */
+#define TIOCSERSETMULTI 0x40a8545b /* Set multiport config */
+                       /* _IOW('T', 91, struct serial_multiport_struct) */
 
 #define TIOCMIWAIT     _IO('T', 92) /* wait for a change on serial input line(s) */
 #define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
index b9395529f02d465643091d71c4d6b6ca9650ff4b..8883fc877c5c93334cacfd29ffe6a12300bb0961 100644 (file)
@@ -739,7 +739,10 @@ __SYSCALL(334, sys_sched_setattr, 2)
 #define __NR_sched_getattr                     335
 __SYSCALL(335, sys_sched_getattr, 3)
 
-#define __NR_syscall_count                     336
+#define __NR_renameat2                         336
+__SYSCALL(336, sys_renameat2, 5)
+
+#define __NR_syscall_count                     337
 
 /*
  * sysxtensa syscall handler
index d4cef6039a5c1ab785d4dead614ad7c9f92d0d6d..890004af03a927fb8768a4d3e7878ccd3c6a1ddf 100644 (file)
@@ -8,6 +8,7 @@
  * this archive for more details.
  *
  * Copyright (C) 2001 - 2005 Tensilica, Inc.
+ * Copyright (C) 2014 Cadence Design Systems Inc.
  *
  * Rewritten by Chris Zankel <chris@zankel.net>
  *
@@ -174,6 +175,10 @@ ENTRY(fast_unaligned)
        s32i    a0, a2, PT_AREG2
        s32i    a3, a2, PT_AREG3
 
+       rsr     a3, excsave1
+       movi    a4, fast_unaligned_fixup
+       s32i    a4, a3, EXC_TABLE_FIXUP
+
        /* Keep value of SAR in a0 */
 
        rsr     a0, sar
@@ -225,10 +230,6 @@ ENTRY(fast_unaligned)
        addx8   a5, a6, a5
        jx      a5                      # jump into table
 
-       /* Invalid instruction, CRITICAL! */
-.Linvalid_instruction_load:
-       j       .Linvalid_instruction
-
        /* Load: Load memory address. */
 
 .Lload: movi   a3, ~3
@@ -272,18 +273,6 @@ ENTRY(fast_unaligned)
        /* Set target register. */
 
 1:
-
-#if XCHAL_HAVE_LOOPS
-       rsr     a5, lend                # check if we reached LEND
-       bne     a7, a5, 1f
-       rsr     a5, lcount              # and LCOUNT != 0
-       beqz    a5, 1f
-       addi    a5, a5, -1              # decrement LCOUNT and set
-       rsr     a7, lbeg                # set PC to LBEGIN
-       wsr     a5, lcount
-#endif
-
-1:     wsr     a7, epc1                # skip load instruction
        extui   a4, a4, INSN_T, 4       # extract target register
        movi    a5, .Lload_table
        addx8   a4, a4, a5
@@ -326,6 +315,35 @@ ENTRY(fast_unaligned)
        mov     a3, a14         ;       _j 1f;  .align 8
        mov     a3, a15         ;       _j 1f;  .align 8
 
+       /* We cannot handle this exception. */
+
+       .extern _kernel_exception
+.Linvalid_instruction_load:
+.Linvalid_instruction_store:
+
+       movi    a4, 0
+       rsr     a3, excsave1
+       s32i    a4, a3, EXC_TABLE_FIXUP
+
+       /* Restore a4...a8 and SAR, set SP, and jump to default exception. */
+
+       l32i    a8, a2, PT_AREG8
+       l32i    a7, a2, PT_AREG7
+       l32i    a6, a2, PT_AREG6
+       l32i    a5, a2, PT_AREG5
+       l32i    a4, a2, PT_AREG4
+       wsr     a0, sar
+       mov     a1, a2
+
+       rsr     a0, ps
+       bbsi.l  a0, PS_UM_BIT, 2f     # jump if user mode
+
+       movi    a0, _kernel_exception
+       jx      a0
+
+2:     movi    a0, _user_exception
+       jx      a0
+
 1:     # a7: instruction pointer, a4: instruction, a3: value
 
        movi    a6, 0                   # mask: ffffffff:00000000
@@ -353,17 +371,6 @@ ENTRY(fast_unaligned)
        /* Get memory address */
 
 1:
-#if XCHAL_HAVE_LOOPS
-       rsr     a4, lend                # check if we reached LEND
-       bne     a7, a4, 1f
-       rsr     a4, lcount              # and LCOUNT != 0
-       beqz    a4, 1f
-       addi    a4, a4, -1              # decrement LCOUNT and set
-       rsr     a7, lbeg                # set PC to LBEGIN
-       wsr     a4, lcount
-#endif
-
-1:     wsr     a7, epc1                # skip store instruction
        movi    a4, ~3
        and     a4, a4, a8              # align memory address
 
@@ -375,25 +382,25 @@ ENTRY(fast_unaligned)
 #endif
 
        __ssa8r a8
-       __src_b a7, a5, a6              # lo-mask  F..F0..0 (BE) 0..0F..F (LE)
+       __src_b a8, a5, a6              # lo-mask  F..F0..0 (BE) 0..0F..F (LE)
        __src_b a6, a6, a5              # hi-mask  0..0F..F (BE) F..F0..0 (LE)
 #ifdef UNALIGNED_USER_EXCEPTION
        l32e    a5, a4, -8
 #else
        l32i    a5, a4, 0               # load lower address word
 #endif
-       and     a5, a5, a7              # mask
-       __sh    a7, a3                  # shift value
-       or      a5, a5, a7              # or with original value
+       and     a5, a5, a8              # mask
+       __sh    a8, a3                  # shift value
+       or      a5, a5, a8              # or with original value
 #ifdef UNALIGNED_USER_EXCEPTION
        s32e    a5, a4, -8
-       l32e    a7, a4, -4
+       l32e    a8, a4, -4
 #else
        s32i    a5, a4, 0               # store
-       l32i    a7, a4, 4               # same for upper address word
+       l32i    a8, a4, 4               # same for upper address word
 #endif
        __sl    a5, a3
-       and     a6, a7, a6
+       and     a6, a8, a6
        or      a6, a6, a5
 #ifdef UNALIGNED_USER_EXCEPTION
        s32e    a6, a4, -4
@@ -401,9 +408,27 @@ ENTRY(fast_unaligned)
        s32i    a6, a4, 4
 #endif
 
-       /* Done. restore stack and return */
-
 .Lexit:
+#if XCHAL_HAVE_LOOPS
+       rsr     a4, lend                # check if we reached LEND
+       bne     a7, a4, 1f
+       rsr     a4, lcount              # and LCOUNT != 0
+       beqz    a4, 1f
+       addi    a4, a4, -1              # decrement LCOUNT and set
+       rsr     a7, lbeg                # set PC to LBEGIN
+       wsr     a4, lcount
+#endif
+
+1:     wsr     a7, epc1                # skip emulated instruction
+
+       /* Update icount if we're single-stepping in userspace. */
+       rsr     a4, icountlevel
+       beqz    a4, 1f
+       bgeui   a4, LOCKLEVEL + 1, 1f
+       rsr     a4, icount
+       addi    a4, a4, 1
+       wsr     a4, icount
+1:
        movi    a4, 0
        rsr     a3, excsave1
        s32i    a4, a3, EXC_TABLE_FIXUP
@@ -424,31 +449,40 @@ ENTRY(fast_unaligned)
        l32i    a2, a2, PT_AREG2
        rfe
 
-       /* We cannot handle this exception. */
+ENDPROC(fast_unaligned)
 
-       .extern _kernel_exception
-.Linvalid_instruction_store:
-.Linvalid_instruction:
+ENTRY(fast_unaligned_fixup)
 
-       /* Restore a4...a8 and SAR, set SP, and jump to default exception. */
+       l32i    a2, a3, EXC_TABLE_DOUBLE_SAVE
+       wsr     a3, excsave1
 
        l32i    a8, a2, PT_AREG8
        l32i    a7, a2, PT_AREG7
        l32i    a6, a2, PT_AREG6
        l32i    a5, a2, PT_AREG5
        l32i    a4, a2, PT_AREG4
+       l32i    a0, a2, PT_AREG2
+       xsr     a0, depc                        # restore depc and a0
        wsr     a0, sar
-       mov     a1, a2
+
+       rsr     a0, exccause
+       s32i    a0, a2, PT_DEPC                 # mark as a regular exception
 
        rsr     a0, ps
-       bbsi.l  a2, PS_UM_BIT, 1f     # jump if user mode
+       bbsi.l  a0, PS_UM_BIT, 1f               # jump if user mode
 
-       movi    a0, _kernel_exception
+       rsr     a0, exccause
+       addx4   a0, a0, a3                      # find entry in table
+       l32i    a0, a0, EXC_TABLE_FAST_KERNEL   # load handler
+       l32i    a3, a2, PT_AREG3
        jx      a0
-
-1:     movi    a0, _user_exception
+1:
+       rsr     a0, exccause
+       addx4   a0, a0, a3                      # find entry in table
+       l32i    a0, a0, EXC_TABLE_FAST_USER     # load handler
+       l32i    a3, a2, PT_AREG3
        jx      a0
 
-ENDPROC(fast_unaligned)
+ENDPROC(fast_unaligned_fixup)
 
 #endif /* XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION */
index ef7f4990722b4fde3a175a0d524f82c3b2ce8b7b..82bbfa5a05b34389c0947b2846bc68d49282c2a7 100644 (file)
@@ -986,6 +986,8 @@ ENDPROC(fast_syscall_unrecoverable)
  *             j done
  */
 
+#ifdef CONFIG_FAST_SYSCALL_XTENSA
+
 #define TRY                                                            \
        .section __ex_table, "a";                                       \
        .word   66f, 67f;                                               \
@@ -1001,9 +1003,8 @@ ENTRY(fast_syscall_xtensa)
        movi    a7, 4                   # sizeof(unsigned int)
        access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp
 
-       addi    a6, a6, -1              # assuming SYS_XTENSA_ATOMIC_SET = 1
-       _bgeui  a6, SYS_XTENSA_COUNT - 1, .Lill
-       _bnei   a6, SYS_XTENSA_ATOMIC_CMP_SWP - 1, .Lnswp
+       _bgeui  a6, SYS_XTENSA_COUNT, .Lill
+       _bnei   a6, SYS_XTENSA_ATOMIC_CMP_SWP, .Lnswp
 
        /* Fall through for ATOMIC_CMP_SWP. */
 
@@ -1015,27 +1016,26 @@ TRY     s32i    a5, a3, 0               # different, modify value
        l32i    a7, a2, PT_AREG7        # restore a7
        l32i    a0, a2, PT_AREG0        # restore a0
        movi    a2, 1                   # and return 1
-       addi    a6, a6, 1               # restore a6 (really necessary?)
        rfe
 
 1:     l32i    a7, a2, PT_AREG7        # restore a7
        l32i    a0, a2, PT_AREG0        # restore a0
        movi    a2, 0                   # return 0 (note that we cannot set
-       addi    a6, a6, 1               # restore a6 (really necessary?)
        rfe
 
 .Lnswp:        /* Atomic set, add, and exg_add. */
 
 TRY    l32i    a7, a3, 0               # orig
+       addi    a6, a6, -SYS_XTENSA_ATOMIC_SET
        add     a0, a4, a7              # + arg
        moveqz  a0, a4, a6              # set
+       addi    a6, a6, SYS_XTENSA_ATOMIC_SET
 TRY    s32i    a0, a3, 0               # write new value
 
        mov     a0, a2
        mov     a2, a7
        l32i    a7, a0, PT_AREG7        # restore a7
        l32i    a0, a0, PT_AREG0        # restore a0
-       addi    a6, a6, 1               # restore a6 (really necessary?)
        rfe
 
 CATCH
@@ -1044,13 +1044,25 @@ CATCH
        movi    a2, -EFAULT
        rfe
 
-.Lill: l32i    a7, a2, PT_AREG0        # restore a7
+.Lill: l32i    a7, a2, PT_AREG7        # restore a7
        l32i    a0, a2, PT_AREG0        # restore a0
        movi    a2, -EINVAL
        rfe
 
 ENDPROC(fast_syscall_xtensa)
 
+#else /* CONFIG_FAST_SYSCALL_XTENSA */
+
+ENTRY(fast_syscall_xtensa)
+
+       l32i    a0, a2, PT_AREG0        # restore a0
+       movi    a2, -ENOSYS
+       rfe
+
+ENDPROC(fast_syscall_xtensa)
+
+#endif /* CONFIG_FAST_SYSCALL_XTENSA */
+
 
 /* fast_syscall_spill_registers.
  *
@@ -1066,6 +1078,8 @@ ENDPROC(fast_syscall_xtensa)
  * Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler.
  */
 
+#ifdef CONFIG_FAST_SYSCALL_SPILL_REGISTERS
+
 ENTRY(fast_syscall_spill_registers)
 
        /* Register a FIXUP handler (pass current wb as a parameter) */
@@ -1400,6 +1414,18 @@ ENTRY(fast_syscall_spill_registers_fixup_return)
 
 ENDPROC(fast_syscall_spill_registers_fixup_return)
 
+#else /* CONFIG_FAST_SYSCALL_SPILL_REGISTERS */
+
+ENTRY(fast_syscall_spill_registers)
+
+       l32i    a0, a2, PT_AREG0        # restore a0
+       movi    a2, -ENOSYS
+       rfe
+
+ENDPROC(fast_syscall_spill_registers)
+
+#endif /* CONFIG_FAST_SYSCALL_SPILL_REGISTERS */
+
 #ifdef CONFIG_MMU
 /*
  * We should never get here. Bail out!
@@ -1565,7 +1591,7 @@ ENTRY(fast_second_level_miss)
        rsr     a0, excvaddr
        bltu    a0, a3, 2f
 
-       addi    a1, a0, -(2 << (DCACHE_ALIAS_ORDER + PAGE_SHIFT))
+       addi    a1, a0, -TLBTEMP_SIZE
        bgeu    a1, a3, 2f
 
        /* Check if we have to restore an ITLB mapping. */
@@ -1820,7 +1846,6 @@ ENTRY(_switch_to)
 
        entry   a1, 16
 
-       mov     a10, a2                 # preserve 'prev' (a2)
        mov     a11, a3                 # and 'next' (a3)
 
        l32i    a4, a2, TASK_THREAD_INFO
@@ -1828,8 +1853,14 @@ ENTRY(_switch_to)
 
        save_xtregs_user a4 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
 
-       s32i    a0, a10, THREAD_RA      # save return address
-       s32i    a1, a10, THREAD_SP      # save stack pointer
+#if THREAD_RA > 1020 || THREAD_SP > 1020
+       addi    a10, a2, TASK_THREAD
+       s32i    a0, a10, THREAD_RA - TASK_THREAD        # save return address
+       s32i    a1, a10, THREAD_SP - TASK_THREAD        # save stack pointer
+#else
+       s32i    a0, a2, THREAD_RA       # save return address
+       s32i    a1, a2, THREAD_SP       # save stack pointer
+#endif
 
        /* Disable ints while we manipulate the stack pointer. */
 
@@ -1870,7 +1901,6 @@ ENTRY(_switch_to)
        load_xtregs_user a5 a6 a8 a9 a12 a13 THREAD_XTREGS_USER
 
        wsr     a14, ps
-       mov     a2, a10                 # return 'prev'
        rsync
 
        retw
index 2d9cc6dbfd78acacd5bc63dbc140e02dbe0a4dc3..e8b76b8e4b2910a17435fd971da65138b97cbfde 100644 (file)
@@ -49,9 +49,8 @@ dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *handle,gfp_t flag)
 
        /* We currently don't support coherent memory outside KSEG */
 
-       if (ret < XCHAL_KSEG_CACHED_VADDR
-           || ret >= XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE)
-               BUG();
+       BUG_ON(ret < XCHAL_KSEG_CACHED_VADDR ||
+              ret > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1);
 
 
        if (ret != 0) {
@@ -68,10 +67,11 @@ EXPORT_SYMBOL(dma_alloc_coherent);
 void dma_free_coherent(struct device *hwdev, size_t size,
                         void *vaddr, dma_addr_t dma_handle)
 {
-       long addr=(long)vaddr+XCHAL_KSEG_CACHED_VADDR-XCHAL_KSEG_BYPASS_VADDR;
+       unsigned long addr = (unsigned long)vaddr +
+               XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR;
 
-       if (addr < 0 || addr >= XCHAL_KSEG_SIZE)
-               BUG();
+       BUG_ON(addr < XCHAL_KSEG_CACHED_VADDR ||
+              addr > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1);
 
        free_pages(addr, get_order(size));
 }
index 40b5a3771fb063fb02ffaa7fe07a426a3a684677..4d02e38514f5460cc9c3a65d7b4d390be1c9e3aa 100644 (file)
@@ -571,6 +571,7 @@ void flush_icache_range(unsigned long start, unsigned long end)
        };
        on_each_cpu(ipi_flush_icache_range, &fd, 1);
 }
+EXPORT_SYMBOL(flush_icache_range);
 
 /* ------------------------------------------------------------------------- */
 
index eebbfd8c26fc25121bced6cb18c074a55c6cb5f5..9d2f45f010ef7e9448e3837e873b617f0a493b23 100644 (file)
@@ -101,9 +101,8 @@ static dispatch_init_table_t __initdata dispatch_init_table[] = {
 #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
 #ifdef CONFIG_XTENSA_UNALIGNED_USER
 { EXCCAUSE_UNALIGNED,          USER,      fast_unaligned },
-#else
-{ EXCCAUSE_UNALIGNED,          0,         do_unaligned_user },
 #endif
+{ EXCCAUSE_UNALIGNED,          0,         do_unaligned_user },
 { EXCCAUSE_UNALIGNED,          KRNL,      fast_unaligned },
 #endif
 #ifdef CONFIG_MMU
@@ -264,7 +263,6 @@ do_illegal_instruction(struct pt_regs *regs)
  */
 
 #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
-#ifndef CONFIG_XTENSA_UNALIGNED_USER
 void
 do_unaligned_user (struct pt_regs *regs)
 {
@@ -286,7 +284,6 @@ do_unaligned_user (struct pt_regs *regs)
 
 }
 #endif
-#endif
 
 void
 do_debug(struct pt_regs *regs)
index 8453e6e398951b0d1864b6e570c8d7d63e45d356..1b397a902292f8224f27856f6ff14471fad1e6ff 100644 (file)
@@ -454,8 +454,14 @@ _DoubleExceptionVector_WindowOverflow:
        s32i    a0, a2, PT_DEPC
 
 _DoubleExceptionVector_handle_exception:
+       addi    a0, a0, -EXCCAUSE_UNALIGNED
+       beqz    a0, 2f
        addx4   a0, a0, a3
-       l32i    a0, a0, EXC_TABLE_FAST_USER
+       l32i    a0, a0, EXC_TABLE_FAST_USER + 4 * EXCCAUSE_UNALIGNED
+       xsr     a3, excsave1
+       jx      a0
+2:
+       movi    a0, user_exception
        xsr     a3, excsave1
        jx      a0
 
index d16db6df86f8e3d823ac2f189816d9889249323e..fc1bc2ba8d5deb34348e783d82f6e0a0b919828a 100644 (file)
@@ -269,13 +269,13 @@ SECTIONS
                  .UserExceptionVector.literal)
   SECTION_VECTOR (_DoubleExceptionVector_literal,
                  .DoubleExceptionVector.literal,
-                 DOUBLEEXC_VECTOR_VADDR - 40,
+                 DOUBLEEXC_VECTOR_VADDR - 48,
                  SIZEOF(.UserExceptionVector.text),
                  .UserExceptionVector.text)
   SECTION_VECTOR (_DoubleExceptionVector_text,
                  .DoubleExceptionVector.text,
                  DOUBLEEXC_VECTOR_VADDR,
-                 40,
+                 48,
                  .DoubleExceptionVector.literal)
 
   . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3;
index 63cbb867dadd64d8907176f1bd60420f8a41217a..d75aa1476da7595d224c02576a8ee5fcb3fe716e 100644 (file)
  *
  */
 
-#if (DCACHE_WAY_SIZE > PAGE_SIZE) && defined(CONFIG_HIGHMEM)
-#error "HIGHMEM is not supported on cores with aliasing cache."
-#endif
+#if (DCACHE_WAY_SIZE > PAGE_SIZE)
+static inline void kmap_invalidate_coherent(struct page *page,
+                                           unsigned long vaddr)
+{
+       if (!DCACHE_ALIAS_EQ(page_to_phys(page), vaddr)) {
+               unsigned long kvaddr;
+
+               if (!PageHighMem(page)) {
+                       kvaddr = (unsigned long)page_to_virt(page);
+
+                       __invalidate_dcache_page(kvaddr);
+               } else {
+                       kvaddr = TLBTEMP_BASE_1 +
+                               (page_to_phys(page) & DCACHE_ALIAS_MASK);
+
+                       __invalidate_dcache_page_alias(kvaddr,
+                                                      page_to_phys(page));
+               }
+       }
+}
+
+static inline void *coherent_kvaddr(struct page *page, unsigned long base,
+                                   unsigned long vaddr, unsigned long *paddr)
+{
+       if (PageHighMem(page) || !DCACHE_ALIAS_EQ(page_to_phys(page), vaddr)) {
+               *paddr = page_to_phys(page);
+               return (void *)(base + (vaddr & DCACHE_ALIAS_MASK));
+       } else {
+               *paddr = 0;
+               return page_to_virt(page);
+       }
+}
+
+void clear_user_highpage(struct page *page, unsigned long vaddr)
+{
+       unsigned long paddr;
+       void *kvaddr = coherent_kvaddr(page, TLBTEMP_BASE_1, vaddr, &paddr);
+
+       pagefault_disable();
+       kmap_invalidate_coherent(page, vaddr);
+       set_bit(PG_arch_1, &page->flags);
+       clear_page_alias(kvaddr, paddr);
+       pagefault_enable();
+}
+
+void copy_user_highpage(struct page *dst, struct page *src,
+                       unsigned long vaddr, struct vm_area_struct *vma)
+{
+       unsigned long dst_paddr, src_paddr;
+       void *dst_vaddr = coherent_kvaddr(dst, TLBTEMP_BASE_1, vaddr,
+                                         &dst_paddr);
+       void *src_vaddr = coherent_kvaddr(src, TLBTEMP_BASE_2, vaddr,
+                                         &src_paddr);
+
+       pagefault_disable();
+       kmap_invalidate_coherent(dst, vaddr);
+       set_bit(PG_arch_1, &dst->flags);
+       copy_page_alias(dst_vaddr, src_vaddr, dst_paddr, src_paddr);
+       pagefault_enable();
+}
+
+#endif /* DCACHE_WAY_SIZE > PAGE_SIZE */
 
 #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
 
@@ -103,7 +162,8 @@ void flush_dcache_page(struct page *page)
                if (!alias && !mapping)
                        return;
 
-               __flush_invalidate_dcache_page((long)page_address(page));
+               virt = TLBTEMP_BASE_1 + (phys & DCACHE_ALIAS_MASK);
+               __flush_invalidate_dcache_page_alias(virt, phys);
 
                virt = TLBTEMP_BASE_1 + (temp & DCACHE_ALIAS_MASK);
 
@@ -168,13 +228,12 @@ update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t *ptep)
 #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
 
        if (!PageReserved(page) && test_bit(PG_arch_1, &page->flags)) {
-
-               unsigned long paddr = (unsigned long) page_address(page);
                unsigned long phys = page_to_phys(page);
-               unsigned long tmp = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK);
-
-               __flush_invalidate_dcache_page(paddr);
+               unsigned long tmp;
 
+               tmp = TLBTEMP_BASE_1 + (phys & DCACHE_ALIAS_MASK);
+               __flush_invalidate_dcache_page_alias(tmp, phys);
+               tmp = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK);
                __flush_invalidate_dcache_page_alias(tmp, phys);
                __invalidate_icache_page_alias(tmp, phys);
 
index 17a8c0d6fd17e525d448e7e577e5fbcdd6a91f76..8cfb71ec0937369a8adf79a3d6e754f589cbba5f 100644 (file)
 
 static pte_t *kmap_pte;
 
+#if DCACHE_WAY_SIZE > PAGE_SIZE
+unsigned int last_pkmap_nr_arr[DCACHE_N_COLORS];
+wait_queue_head_t pkmap_map_wait_arr[DCACHE_N_COLORS];
+
+static void __init kmap_waitqueues_init(void)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(pkmap_map_wait_arr); ++i)
+               init_waitqueue_head(pkmap_map_wait_arr + i);
+}
+#else
+static inline void kmap_waitqueues_init(void)
+{
+}
+#endif
+
+static inline enum fixed_addresses kmap_idx(int type, unsigned long color)
+{
+       return (type + KM_TYPE_NR * smp_processor_id()) * DCACHE_N_COLORS +
+               color;
+}
+
 void *kmap_atomic(struct page *page)
 {
        enum fixed_addresses idx;
        unsigned long vaddr;
-       int type;
 
        pagefault_disable();
        if (!PageHighMem(page))
                return page_address(page);
 
-       type = kmap_atomic_idx_push();
-       idx = type + KM_TYPE_NR * smp_processor_id();
+       idx = kmap_idx(kmap_atomic_idx_push(),
+                      DCACHE_ALIAS(page_to_phys(page)));
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 #ifdef CONFIG_DEBUG_HIGHMEM
-       BUG_ON(!pte_none(*(kmap_pte - idx)));
+       BUG_ON(!pte_none(*(kmap_pte + idx)));
 #endif
-       set_pte(kmap_pte - idx, mk_pte(page, PAGE_KERNEL_EXEC));
+       set_pte(kmap_pte + idx, mk_pte(page, PAGE_KERNEL_EXEC));
 
        return (void *)vaddr;
 }
@@ -38,12 +60,10 @@ EXPORT_SYMBOL(kmap_atomic);
 
 void __kunmap_atomic(void *kvaddr)
 {
-       int idx, type;
-
        if (kvaddr >= (void *)FIXADDR_START &&
            kvaddr < (void *)FIXADDR_TOP) {
-               type = kmap_atomic_idx();
-               idx = type + KM_TYPE_NR * smp_processor_id();
+               int idx = kmap_idx(kmap_atomic_idx(),
+                                  DCACHE_ALIAS((unsigned long)kvaddr));
 
                /*
                 * Force other mappings to Oops if they'll try to access this
@@ -51,7 +71,7 @@ void __kunmap_atomic(void *kvaddr)
                 * is a bad idea also, in case the page changes cacheability
                 * attributes or becomes a protected page in a hypervisor.
                 */
-               pte_clear(&init_mm, kvaddr, kmap_pte - idx);
+               pte_clear(&init_mm, kvaddr, kmap_pte + idx);
                local_flush_tlb_kernel_range((unsigned long)kvaddr,
                                             (unsigned long)kvaddr + PAGE_SIZE);
 
@@ -69,4 +89,5 @@ void __init kmap_init(void)
        /* cache the first kmap pte */
        kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
        kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
+       kmap_waitqueues_init();
 }
index 1f68558dbcc2264f99f917fcb18659d90f46a8cb..11a01c3e9cea91ece949e93c0c7776bdb4826170 100644 (file)
@@ -110,41 +110,24 @@ ENTRY(__tlbtemp_mapping_start)
 #if (DCACHE_WAY_SIZE > PAGE_SIZE)
 
 /*
- * clear_user_page (void *addr, unsigned long vaddr, struct page *page)
- *                     a2              a3                 a4
+ * clear_page_alias(void *addr, unsigned long paddr)
+ *                     a2              a3
  */
 
-ENTRY(clear_user_page)
+ENTRY(clear_page_alias)
 
        entry   a1, 32
 
-       /* Mark page dirty and determine alias. */
+       /* Skip setting up a temporary DTLB if not aliased low page. */
 
-       movi    a7, (1 << PG_ARCH_1)
-       l32i    a5, a4, PAGE_FLAGS
-       xor     a6, a2, a3
-       extui   a3, a3, PAGE_SHIFT, DCACHE_ALIAS_ORDER
-       extui   a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
-       or      a5, a5, a7
-       slli    a3, a3, PAGE_SHIFT
-       s32i    a5, a4, PAGE_FLAGS
+       movi    a5, PAGE_OFFSET
+       movi    a6, 0
+       beqz    a3, 1f
 
-       /* Skip setting up a temporary DTLB if not aliased. */
-
-       beqz    a6, 1f
-
-       /* Invalidate kernel page. */
-
-       mov     a10, a2
-       call8   __invalidate_dcache_page
-
-       /* Setup a temporary DTLB with the color of the VPN */
-
-       movi    a4, ((PAGE_KERNEL | _PAGE_HW_WRITE) - PAGE_OFFSET) & 0xffffffff
-       movi    a5, TLBTEMP_BASE_1                      # virt
-       add     a6, a2, a4                              # ppn
-       add     a2, a5, a3                              # add 'color'
+       /* Setup a temporary DTLB for the addr. */
 
+       addi    a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
+       mov     a4, a2
        wdtlb   a6, a2
        dsync
 
@@ -165,62 +148,43 @@ ENTRY(clear_user_page)
 
        /* We need to invalidate the temporary idtlb entry, if any. */
 
-1:     addi    a2, a2, -PAGE_SIZE
-       idtlb   a2
+1:     idtlb   a4
        dsync
 
        retw
 
-ENDPROC(clear_user_page)
+ENDPROC(clear_page_alias)
 
 /*
- * copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page)
- *                    a2          a3           a4                  a5
+ * copy_page_alias(void *to, void *from,
+ *                     a2        a3
+ *                 unsigned long to_paddr, unsigned long from_paddr)
+ *                              a4                      a5
  */
 
-ENTRY(copy_user_page)
+ENTRY(copy_page_alias)
 
        entry   a1, 32
 
-       /* Mark page dirty and determine alias for destination. */
-
-       movi    a8, (1 << PG_ARCH_1)
-       l32i    a9, a5, PAGE_FLAGS
-       xor     a6, a2, a4
-       xor     a7, a3, a4
-       extui   a4, a4, PAGE_SHIFT, DCACHE_ALIAS_ORDER
-       extui   a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER
-       extui   a7, a7, PAGE_SHIFT, DCACHE_ALIAS_ORDER
-       or      a9, a9, a8
-       slli    a4, a4, PAGE_SHIFT
-       s32i    a9, a5, PAGE_FLAGS
-       movi    a5, ((PAGE_KERNEL | _PAGE_HW_WRITE) - PAGE_OFFSET) & 0xffffffff
-
-       beqz    a6, 1f
-
-       /* Invalidate dcache */
-
-       mov     a10, a2
-       call8   __invalidate_dcache_page
+       /* Skip setting up a temporary DTLB for destination if not aliased. */
 
-       /* Setup a temporary DTLB with a matching color. */
+       movi    a6, 0
+       movi    a7, 0
+       beqz    a4, 1f
 
-       movi    a8, TLBTEMP_BASE_1                      # base
-       add     a6, a2, a5                              # ppn
-       add     a2, a8, a4                              # add 'color'
+       /* Setup a temporary DTLB for destination. */
 
+       addi    a6, a4, (PAGE_KERNEL | _PAGE_HW_WRITE)
        wdtlb   a6, a2
        dsync
 
-       /* Skip setting up a temporary DTLB for destination if not aliased. */
+       /* Skip setting up a temporary DTLB for source if not aliased. */
 
-1:     beqz    a7, 1f
+1:     beqz    a5, 1f
 
-       /* Setup a temporary DTLB with a matching color. */
+       /* Setup a temporary DTLB for source. */
 
-       movi    a8, TLBTEMP_BASE_2                      # base
-       add     a7, a3, a5                              # ppn
-       add     a3, a8, a4
+       addi    a7, a5, PAGE_KERNEL
        addi    a8, a3, 1                               # way1
 
        wdtlb   a7, a8
@@ -271,7 +235,7 @@ ENTRY(copy_user_page)
 
        retw
 
-ENDPROC(copy_user_page)
+ENDPROC(copy_page_alias)
 
 #endif
 
@@ -300,6 +264,30 @@ ENTRY(__flush_invalidate_dcache_page_alias)
        retw
 
 ENDPROC(__flush_invalidate_dcache_page_alias)
+
+/*
+ * void __invalidate_dcache_page_alias (addr, phys)
+ *                                       a2    a3
+ */
+
+ENTRY(__invalidate_dcache_page_alias)
+
+       entry   sp, 16
+
+       movi    a7, 0                   # required for exception handler
+       addi    a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE)
+       mov     a4, a2
+       wdtlb   a6, a2
+       dsync
+
+       ___invalidate_dcache_page a2 a3
+
+       idtlb   a4
+       dsync
+
+       retw
+
+ENDPROC(__invalidate_dcache_page_alias)
 #endif
 
 ENTRY(__tlbtemp_mapping_itlb)
index 3429b483d9f85cd2495e01c8c0a11d05bc22e16c..abe4513eb0ddf072f628406eb8af2d13b2774678 100644 (file)
 #include <asm/io.h>
 
 #if defined(CONFIG_HIGHMEM)
-static void * __init init_pmd(unsigned long vaddr)
+static void * __init init_pmd(unsigned long vaddr, unsigned long n_pages)
 {
        pgd_t *pgd = pgd_offset_k(vaddr);
        pmd_t *pmd = pmd_offset(pgd, vaddr);
+       pte_t *pte;
+       unsigned long i;
 
-       if (pmd_none(*pmd)) {
-               unsigned i;
-               pte_t *pte = alloc_bootmem_low_pages(PAGE_SIZE);
+       n_pages = ALIGN(n_pages, PTRS_PER_PTE);
 
-               for (i = 0; i < 1024; i++)
-                       pte_clear(NULL, 0, pte + i);
+       pr_debug("%s: vaddr: 0x%08lx, n_pages: %ld\n",
+                __func__, vaddr, n_pages);
 
-               set_pmd(pmd, __pmd(((unsigned long)pte) & PAGE_MASK));
-               BUG_ON(pte != pte_offset_kernel(pmd, 0));
-               pr_debug("%s: vaddr: 0x%08lx, pmd: 0x%p, pte: 0x%p\n",
-                        __func__, vaddr, pmd, pte);
-               return pte;
-       } else {
-               return pte_offset_kernel(pmd, 0);
+       pte = alloc_bootmem_low_pages(n_pages * sizeof(pte_t));
+
+       for (i = 0; i < n_pages; ++i)
+               pte_clear(NULL, 0, pte + i);
+
+       for (i = 0; i < n_pages; i += PTRS_PER_PTE, ++pmd) {
+               pte_t *cur_pte = pte + i;
+
+               BUG_ON(!pmd_none(*pmd));
+               set_pmd(pmd, __pmd(((unsigned long)cur_pte) & PAGE_MASK));
+               BUG_ON(cur_pte != pte_offset_kernel(pmd, 0));
+               pr_debug("%s: pmd: 0x%p, pte: 0x%p\n",
+                        __func__, pmd, cur_pte);
        }
+       return pte;
 }
 
 static void __init fixedrange_init(void)
 {
-       BUILD_BUG_ON(FIXADDR_SIZE > PMD_SIZE);
-       init_pmd(__fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK);
+       init_pmd(__fix_to_virt(0), __end_of_fixed_addresses);
 }
 #endif
 
@@ -52,7 +58,7 @@ void __init paging_init(void)
        memset(swapper_pg_dir, 0, PAGE_SIZE);
 #ifdef CONFIG_HIGHMEM
        fixedrange_init();
-       pkmap_page_table = init_pmd(PKMAP_BASE);
+       pkmap_page_table = init_pmd(PKMAP_BASE, LAST_PKMAP);
        kmap_init();
 #endif
 }
index bc423f7b02da856a6987089b6750322c9b7cbfe4..f14b4abbebd89a0b812a67b06e3a9bb2dffb707b 100644 (file)
@@ -520,7 +520,7 @@ void bio_integrity_endio(struct bio *bio, int error)
         */
        if (error) {
                bio->bi_end_io = bip->bip_end_io;
-               bio_endio(bio, error);
+               bio_endio_nodec(bio, error);
 
                return;
        }
index c359d72e9d76f24a44b7c4b6b8c36c6677436191..bf930f481d437ac1b1731d32d453280309773445 100644 (file)
@@ -1252,7 +1252,6 @@ void blk_rq_set_block_pc(struct request *rq)
        rq->__sector = (sector_t) -1;
        rq->bio = rq->biotail = NULL;
        memset(rq->__cmd, 0, sizeof(rq->__cmd));
-       rq->cmd = rq->__cmd;
 }
 EXPORT_SYMBOL(blk_rq_set_block_pc);
 
index 54535831f1e197a6a6c56a5cc8a4b08e90d4020b..77881798f7930bd4c1df4ea3cc4a0ab3f30ddc80 100644 (file)
 #include "blk.h"
 
 static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
-                                            struct bio *bio)
+                                            struct bio *bio,
+                                            bool no_sg_merge)
 {
        struct bio_vec bv, bvprv = { NULL };
-       int cluster, high, highprv = 1, no_sg_merge;
+       int cluster, high, highprv = 1;
        unsigned int seg_size, nr_phys_segs;
        struct bio *fbio, *bbio;
        struct bvec_iter iter;
@@ -35,7 +36,6 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
        cluster = blk_queue_cluster(q);
        seg_size = 0;
        nr_phys_segs = 0;
-       no_sg_merge = test_bit(QUEUE_FLAG_NO_SG_MERGE, &q->queue_flags);
        high = 0;
        for_each_bio(bio) {
                bio_for_each_segment(bv, bio, iter) {
@@ -88,18 +88,23 @@ new_segment:
 
 void blk_recalc_rq_segments(struct request *rq)
 {
-       rq->nr_phys_segments = __blk_recalc_rq_segments(rq->q, rq->bio);
+       bool no_sg_merge = !!test_bit(QUEUE_FLAG_NO_SG_MERGE,
+                       &rq->q->queue_flags);
+
+       rq->nr_phys_segments = __blk_recalc_rq_segments(rq->q, rq->bio,
+                       no_sg_merge);
 }
 
 void blk_recount_segments(struct request_queue *q, struct bio *bio)
 {
-       if (test_bit(QUEUE_FLAG_NO_SG_MERGE, &q->queue_flags))
+       if (test_bit(QUEUE_FLAG_NO_SG_MERGE, &q->queue_flags) &&
+                       bio->bi_vcnt < queue_max_segments(q))
                bio->bi_phys_segments = bio->bi_vcnt;
        else {
                struct bio *nxt = bio->bi_next;
 
                bio->bi_next = NULL;
-               bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio);
+               bio->bi_phys_segments = __blk_recalc_rq_segments(q, bio, false);
                bio->bi_next = nxt;
        }
 
index 5189cb1e478a6b283609006364c01f9f8e31d082..383ea0cb1f0a295463789d956aae820b334f4a55 100644 (file)
@@ -112,18 +112,22 @@ static void blk_mq_usage_counter_release(struct percpu_ref *ref)
  */
 void blk_mq_freeze_queue(struct request_queue *q)
 {
+       bool freeze;
+
        spin_lock_irq(q->queue_lock);
-       q->mq_freeze_depth++;
+       freeze = !q->mq_freeze_depth++;
        spin_unlock_irq(q->queue_lock);
 
-       percpu_ref_kill(&q->mq_usage_counter);
-       blk_mq_run_queues(q, false);
+       if (freeze) {
+               percpu_ref_kill(&q->mq_usage_counter);
+               blk_mq_run_queues(q, false);
+       }
        wait_event(q->mq_freeze_wq, percpu_ref_is_zero(&q->mq_usage_counter));
 }
 
 static void blk_mq_unfreeze_queue(struct request_queue *q)
 {
-       bool wake = false;
+       bool wake;
 
        spin_lock_irq(q->queue_lock);
        wake = !--q->mq_freeze_depth;
@@ -172,6 +176,8 @@ static void blk_mq_rq_ctx_init(struct request_queue *q, struct blk_mq_ctx *ctx,
        /* tag was already set */
        rq->errors = 0;
 
+       rq->cmd = rq->__cmd;
+
        rq->extra_len = 0;
        rq->sense_len = 0;
        rq->resid_len = 0;
@@ -1068,13 +1074,17 @@ static void blk_mq_bio_to_request(struct request *rq, struct bio *bio)
                blk_account_io_start(rq, 1);
 }
 
+static inline bool hctx_allow_merges(struct blk_mq_hw_ctx *hctx)
+{
+       return (hctx->flags & BLK_MQ_F_SHOULD_MERGE) &&
+               !blk_queue_nomerges(hctx->queue);
+}
+
 static inline bool blk_mq_merge_queue_io(struct blk_mq_hw_ctx *hctx,
                                         struct blk_mq_ctx *ctx,
                                         struct request *rq, struct bio *bio)
 {
-       struct request_queue *q = hctx->queue;
-
-       if (!(hctx->flags & BLK_MQ_F_SHOULD_MERGE)) {
+       if (!hctx_allow_merges(hctx)) {
                blk_mq_bio_to_request(rq, bio);
                spin_lock(&ctx->lock);
 insert_rq:
@@ -1082,6 +1092,8 @@ insert_rq:
                spin_unlock(&ctx->lock);
                return false;
        } else {
+               struct request_queue *q = hctx->queue;
+
                spin_lock(&ctx->lock);
                if (!blk_mq_attempt_merge(q, ctx, bio)) {
                        blk_mq_bio_to_request(rq, bio);
@@ -1309,6 +1321,7 @@ static void blk_mq_free_rq_map(struct blk_mq_tag_set *set,
                                continue;
                        set->ops->exit_request(set->driver_data, tags->rqs[i],
                                                hctx_idx, i);
+                       tags->rqs[i] = NULL;
                }
        }
 
@@ -1342,8 +1355,9 @@ static struct blk_mq_tags *blk_mq_init_rq_map(struct blk_mq_tag_set *set,
 
        INIT_LIST_HEAD(&tags->page_list);
 
-       tags->rqs = kmalloc_node(set->queue_depth * sizeof(struct request *),
-                                       GFP_KERNEL, set->numa_node);
+       tags->rqs = kzalloc_node(set->queue_depth * sizeof(struct request *),
+                                GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY,
+                                set->numa_node);
        if (!tags->rqs) {
                blk_mq_free_tags(tags);
                return NULL;
@@ -1367,8 +1381,9 @@ static struct blk_mq_tags *blk_mq_init_rq_map(struct blk_mq_tag_set *set,
                        this_order--;
 
                do {
-                       page = alloc_pages_node(set->numa_node, GFP_KERNEL,
-                                               this_order);
+                       page = alloc_pages_node(set->numa_node,
+                               GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY,
+                               this_order);
                        if (page)
                                break;
                        if (!this_order--)
@@ -1392,8 +1407,10 @@ static struct blk_mq_tags *blk_mq_init_rq_map(struct blk_mq_tag_set *set,
                        if (set->ops->init_request) {
                                if (set->ops->init_request(set->driver_data,
                                                tags->rqs[i], hctx_idx, i,
-                                               set->numa_node))
+                                               set->numa_node)) {
+                                       tags->rqs[i] = NULL;
                                        goto fail;
+                               }
                        }
 
                        p += rq_size;
@@ -1404,7 +1421,6 @@ static struct blk_mq_tags *blk_mq_init_rq_map(struct blk_mq_tag_set *set,
        return tags;
 
 fail:
-       pr_warn("%s: failed to allocate requests\n", __func__);
        blk_mq_free_rq_map(set, tags, hctx_idx);
        return NULL;
 }
@@ -1574,7 +1590,7 @@ static int blk_mq_init_hw_queues(struct request_queue *q,
                hctx->tags = set->tags[i];
 
                /*
-                * Allocate space for all possible cpus to avoid allocation in
+                * Allocate space for all possible cpus to avoid allocation at
                 * runtime
                 */
                hctx->ctxs = kmalloc_node(nr_cpu_ids * sizeof(void *),
@@ -1662,8 +1678,8 @@ static void blk_mq_map_swqueue(struct request_queue *q)
 
        queue_for_each_hw_ctx(q, hctx, i) {
                /*
-                * If not software queues are mapped to this hardware queue,
-                * disable it and free the request entries
+                * If no software queues are mapped to this hardware queue,
+                * disable it and free the request entries.
                 */
                if (!hctx->nr_ctx) {
                        struct blk_mq_tag_set *set = q->tag_set;
@@ -1713,14 +1729,10 @@ static void blk_mq_del_queue_tag_set(struct request_queue *q)
 {
        struct blk_mq_tag_set *set = q->tag_set;
 
-       blk_mq_freeze_queue(q);
-
        mutex_lock(&set->tag_list_lock);
        list_del_init(&q->tag_set_list);
        blk_mq_update_tag_set_depth(set);
        mutex_unlock(&set->tag_list_lock);
-
-       blk_mq_unfreeze_queue(q);
 }
 
 static void blk_mq_add_queue_tag_set(struct blk_mq_tag_set *set,
@@ -1928,6 +1940,61 @@ static int blk_mq_queue_reinit_notify(struct notifier_block *nb,
        return NOTIFY_OK;
 }
 
+static int __blk_mq_alloc_rq_maps(struct blk_mq_tag_set *set)
+{
+       int i;
+
+       for (i = 0; i < set->nr_hw_queues; i++) {
+               set->tags[i] = blk_mq_init_rq_map(set, i);
+               if (!set->tags[i])
+                       goto out_unwind;
+       }
+
+       return 0;
+
+out_unwind:
+       while (--i >= 0)
+               blk_mq_free_rq_map(set, set->tags[i], i);
+
+       set->tags = NULL;
+       return -ENOMEM;
+}
+
+/*
+ * Allocate the request maps associated with this tag_set. Note that this
+ * may reduce the depth asked for, if memory is tight. set->queue_depth
+ * will be updated to reflect the allocated depth.
+ */
+static int blk_mq_alloc_rq_maps(struct blk_mq_tag_set *set)
+{
+       unsigned int depth;
+       int err;
+
+       depth = set->queue_depth;
+       do {
+               err = __blk_mq_alloc_rq_maps(set);
+               if (!err)
+                       break;
+
+               set->queue_depth >>= 1;
+               if (set->queue_depth < set->reserved_tags + BLK_MQ_TAG_MIN) {
+                       err = -ENOMEM;
+                       break;
+               }
+       } while (set->queue_depth);
+
+       if (!set->queue_depth || err) {
+               pr_err("blk-mq: failed to allocate request map\n");
+               return -ENOMEM;
+       }
+
+       if (depth != set->queue_depth)
+               pr_info("blk-mq: reduced tag depth (%u -> %u)\n",
+                                               depth, set->queue_depth);
+
+       return 0;
+}
+
 /*
  * Alloc a tag set to be associated with one or more request queues.
  * May fail with EINVAL for various error conditions. May adjust the
@@ -1936,8 +2003,6 @@ static int blk_mq_queue_reinit_notify(struct notifier_block *nb,
  */
 int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set)
 {
-       int i;
-
        if (!set->nr_hw_queues)
                return -EINVAL;
        if (!set->queue_depth)
@@ -1958,23 +2023,18 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set)
                                 sizeof(struct blk_mq_tags *),
                                 GFP_KERNEL, set->numa_node);
        if (!set->tags)
-               goto out;
+               return -ENOMEM;
 
-       for (i = 0; i < set->nr_hw_queues; i++) {
-               set->tags[i] = blk_mq_init_rq_map(set, i);
-               if (!set->tags[i])
-                       goto out_unwind;
-       }
+       if (blk_mq_alloc_rq_maps(set))
+               goto enomem;
 
        mutex_init(&set->tag_list_lock);
        INIT_LIST_HEAD(&set->tag_list);
 
        return 0;
-
-out_unwind:
-       while (--i >= 0)
-               blk_mq_free_rq_map(set, set->tags[i], i);
-out:
+enomem:
+       kfree(set->tags);
+       set->tags = NULL;
        return -ENOMEM;
 }
 EXPORT_SYMBOL(blk_mq_alloc_tag_set);
@@ -1989,6 +2049,7 @@ void blk_mq_free_tag_set(struct blk_mq_tag_set *set)
        }
 
        kfree(set->tags);
+       set->tags = NULL;
 }
 EXPORT_SYMBOL(blk_mq_free_tag_set);
 
index 4db5abf96b9ec1595a822efebfb9df9776af6477..17f5c84ce7bfb588a5a34bc244a7ac38067b4391 100644 (file)
@@ -554,8 +554,10 @@ int blk_register_queue(struct gendisk *disk)
         * Initialization must be complete by now.  Finish the initial
         * bypass from queue allocation.
         */
-       queue_flag_set_unlocked(QUEUE_FLAG_INIT_DONE, q);
-       blk_queue_bypass_end(q);
+       if (!blk_queue_init_done(q)) {
+               queue_flag_set_unlocked(QUEUE_FLAG_INIT_DONE, q);
+               blk_queue_bypass_end(q);
+       }
 
        ret = blk_trace_init_sysfs(dev);
        if (ret)
index cadc37841744ddb1ed0b481e97f82319ee47aefc..3f31cf9508e6204c144c2b665fb90aa67df3c9a2 100644 (file)
@@ -1272,15 +1272,22 @@ __cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg)
        rb_insert_color(&cfqg->rb_node, &st->rb);
 }
 
+/*
+ * This has to be called only on activation of cfqg
+ */
 static void
 cfq_update_group_weight(struct cfq_group *cfqg)
 {
-       BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
-
        if (cfqg->new_weight) {
                cfqg->weight = cfqg->new_weight;
                cfqg->new_weight = 0;
        }
+}
+
+static void
+cfq_update_group_leaf_weight(struct cfq_group *cfqg)
+{
+       BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
 
        if (cfqg->new_leaf_weight) {
                cfqg->leaf_weight = cfqg->new_leaf_weight;
@@ -1299,7 +1306,12 @@ cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg)
        /* add to the service tree */
        BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
 
-       cfq_update_group_weight(cfqg);
+       /*
+        * Update leaf_weight.  We cannot update weight at this point
+        * because cfqg might already have been activated and is
+        * contributing its current weight to the parent's child_weight.
+        */
+       cfq_update_group_leaf_weight(cfqg);
        __cfq_group_service_tree_add(st, cfqg);
 
        /*
@@ -1323,6 +1335,7 @@ cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg)
         */
        while ((parent = cfqg_parent(pos))) {
                if (propagate) {
+                       cfq_update_group_weight(pos);
                        propagate = !parent->nr_active++;
                        parent->children_weight += pos->weight;
                }
index 791f419431322882a915f88995df7b72552d5507..09da5e4a8e03bb77e33de4b9822ba26bbff8973f 100644 (file)
@@ -28,10 +28,10 @@ struct kobject *block_depr;
 /* for extended dynamic devt allocation, currently only one major is used */
 #define NR_EXT_DEVT            (1 << MINORBITS)
 
-/* For extended devt allocation.  ext_devt_mutex prevents look up
+/* For extended devt allocation.  ext_devt_lock prevents look up
  * results from going away underneath its user.
  */
-static DEFINE_MUTEX(ext_devt_mutex);
+static DEFINE_SPINLOCK(ext_devt_lock);
 static DEFINE_IDR(ext_devt_idr);
 
 static struct device_type disk_type;
@@ -420,9 +420,13 @@ int blk_alloc_devt(struct hd_struct *part, dev_t *devt)
        }
 
        /* allocate ext devt */
-       mutex_lock(&ext_devt_mutex);
-       idx = idr_alloc(&ext_devt_idr, part, 0, NR_EXT_DEVT, GFP_KERNEL);
-       mutex_unlock(&ext_devt_mutex);
+       idr_preload(GFP_KERNEL);
+
+       spin_lock(&ext_devt_lock);
+       idx = idr_alloc(&ext_devt_idr, part, 0, NR_EXT_DEVT, GFP_NOWAIT);
+       spin_unlock(&ext_devt_lock);
+
+       idr_preload_end();
        if (idx < 0)
                return idx == -ENOSPC ? -EBUSY : idx;
 
@@ -447,9 +451,9 @@ void blk_free_devt(dev_t devt)
                return;
 
        if (MAJOR(devt) == BLOCK_EXT_MAJOR) {
-               mutex_lock(&ext_devt_mutex);
+               spin_lock(&ext_devt_lock);
                idr_remove(&ext_devt_idr, blk_mangle_minor(MINOR(devt)));
-               mutex_unlock(&ext_devt_mutex);
+               spin_unlock(&ext_devt_lock);
        }
 }
 
@@ -665,7 +669,6 @@ void del_gendisk(struct gendisk *disk)
                sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
        pm_runtime_set_memalloc_noio(disk_to_dev(disk), false);
        device_del(disk_to_dev(disk));
-       blk_free_devt(disk_to_dev(disk)->devt);
 }
 EXPORT_SYMBOL(del_gendisk);
 
@@ -690,13 +693,13 @@ struct gendisk *get_gendisk(dev_t devt, int *partno)
        } else {
                struct hd_struct *part;
 
-               mutex_lock(&ext_devt_mutex);
+               spin_lock(&ext_devt_lock);
                part = idr_find(&ext_devt_idr, blk_mangle_minor(MINOR(devt)));
                if (part && get_disk(part_to_disk(part))) {
                        *partno = part->partno;
                        disk = part_to_disk(part);
                }
-               mutex_unlock(&ext_devt_mutex);
+               spin_unlock(&ext_devt_lock);
        }
 
        return disk;
@@ -1098,6 +1101,7 @@ static void disk_release(struct device *dev)
 {
        struct gendisk *disk = dev_to_disk(dev);
 
+       blk_free_devt(dev->devt);
        disk_release_events(disk);
        kfree(disk->random);
        disk_replace_part_tbl(disk, NULL);
index 789cdea05893bb8e3420ede5d1aa65e7af408e1b..0d9e5f97f0a8afaa397530a77684bacc7b22ab26 100644 (file)
@@ -211,6 +211,7 @@ static const struct attribute_group *part_attr_groups[] = {
 static void part_release(struct device *dev)
 {
        struct hd_struct *p = dev_to_part(dev);
+       blk_free_devt(dev->devt);
        free_part_stats(p);
        free_part_info(p);
        kfree(p);
@@ -253,7 +254,6 @@ void delete_partition(struct gendisk *disk, int partno)
        rcu_assign_pointer(ptbl->last_lookup, NULL);
        kobject_put(part->holder_dir);
        device_del(part_to_dev(part));
-       blk_free_devt(part_devt(part));
 
        hd_struct_put(part);
 }
index 51bf5155ee756a4ac479e9c49fcf88824b0aeedc..9b8eaeca6a794b5be8e732567aceffbe6ab6ebdb 100644 (file)
@@ -279,7 +279,6 @@ static int blk_complete_sghdr_rq(struct request *rq, struct sg_io_hdr *hdr,
        r = blk_rq_unmap_user(bio);
        if (!ret)
                ret = r;
-       blk_put_request(rq);
 
        return ret;
 }
@@ -297,8 +296,6 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
 
        if (hdr->interface_id != 'S')
                return -EINVAL;
-       if (hdr->cmd_len > BLK_MAX_CDB)
-               return -EINVAL;
 
        if (hdr->dxfer_len > (queue_max_hw_sectors(q) << 9))
                return -EIO;
@@ -317,16 +314,23 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
        if (hdr->flags & SG_FLAG_Q_AT_HEAD)
                at_head = 1;
 
+       ret = -ENOMEM;
        rq = blk_get_request(q, writing ? WRITE : READ, GFP_KERNEL);
        if (!rq)
-               return -ENOMEM;
+               goto out;
        blk_rq_set_block_pc(rq);
 
-       if (blk_fill_sghdr_rq(q, rq, hdr, mode)) {
-               blk_put_request(rq);
-               return -EFAULT;
+       if (hdr->cmd_len > BLK_MAX_CDB) {
+               rq->cmd = kzalloc(hdr->cmd_len, GFP_KERNEL);
+               if (!rq->cmd)
+                       goto out_put_request;
        }
 
+       ret = -EFAULT;
+       if (blk_fill_sghdr_rq(q, rq, hdr, mode))
+               goto out_free_cdb;
+
+       ret = 0;
        if (hdr->iovec_count) {
                size_t iov_data_len;
                struct iovec *iov = NULL;
@@ -335,7 +339,7 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
                                            0, NULL, &iov);
                if (ret < 0) {
                        kfree(iov);
-                       goto out;
+                       goto out_free_cdb;
                }
 
                iov_data_len = ret;
@@ -358,7 +362,7 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
                                      GFP_KERNEL);
 
        if (ret)
-               goto out;
+               goto out_free_cdb;
 
        bio = rq->bio;
        memset(sense, 0, sizeof(sense));
@@ -376,9 +380,14 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
 
        hdr->duration = jiffies_to_msecs(jiffies - start_time);
 
-       return blk_complete_sghdr_rq(rq, hdr, bio);
-out:
+       ret = blk_complete_sghdr_rq(rq, hdr, bio);
+
+out_free_cdb:
+       if (rq->cmd != rq->__cmd)
+               kfree(rq->cmd);
+out_put_request:
        blk_put_request(rq);
+out:
        return ret;
 }
 
@@ -448,6 +457,11 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
        }
 
        rq = blk_get_request(q, in_len ? WRITE : READ, __GFP_WAIT);
+       if (!rq) {
+               err = -ENOMEM;
+               goto error;
+       }
+       blk_rq_set_block_pc(rq);
 
        cmdlen = COMMAND_SIZE(opcode);
 
@@ -501,7 +515,6 @@ int sg_scsi_ioctl(struct request_queue *q, struct gendisk *disk, fmode_t mode,
        memset(sense, 0, sizeof(sense));
        rq->sense = sense;
        rq->sense_len = 0;
-       blk_rq_set_block_pc(rq);
 
        blk_execute_rq(q, disk, rq, 0);
 
@@ -521,7 +534,8 @@ out:
        
 error:
        kfree(buffer);
-       blk_put_request(rq);
+       if (rq)
+               blk_put_request(rq);
        return err;
 }
 EXPORT_SYMBOL_GPL(sg_scsi_ioctl);
index 97eb001960b97774e89643f65711d2a68e6a3a8f..2f6e4fb1a1ea14c4a1bcba18618b0bdaf6e1cd9c 100644 (file)
@@ -121,6 +121,7 @@ static int public_key_verify_signature_2(const struct key *key,
 struct asymmetric_key_subtype public_key_subtype = {
        .owner                  = THIS_MODULE,
        .name                   = "public_key",
+       .name_len               = sizeof("public_key") - 1,
        .describe               = public_key_describe,
        .destroy                = public_key_destroy,
        .verify_signature       = public_key_verify_signature_2,
index 79175e6ea0b28493f26079d5a17926e0aab63984..2421f46184ce873076fe3cfc0f195a2d7bf4f902 100644 (file)
@@ -128,6 +128,7 @@ static int pefile_strip_sig_wrapper(const void *pebuf,
 {
        struct win_certificate wrapper;
        const u8 *pkcs7;
+       unsigned len;
 
        if (ctx->sig_len < sizeof(wrapper)) {
                pr_debug("Signature wrapper too short\n");
@@ -154,33 +155,49 @@ static int pefile_strip_sig_wrapper(const void *pebuf,
                return -ENOTSUPP;
        }
 
-       /* Looks like actual pkcs signature length is in wrapper->length.
-        * size obtained from data dir entries lists the total size of
-        * certificate table which is also aligned to octawrod boundary.
-        *
-        * So set signature length field appropriately.
+       /* It looks like the pkcs signature length in wrapper->length and the
+        * size obtained from the data dir entries, which lists the total size
+        * of certificate table, are both aligned to an octaword boundary, so
+        * we may have to deal with some padding.
         */
        ctx->sig_len = wrapper.length;
        ctx->sig_offset += sizeof(wrapper);
        ctx->sig_len -= sizeof(wrapper);
-       if (ctx->sig_len == 0) {
+       if (ctx->sig_len < 4) {
                pr_debug("Signature data missing\n");
                return -EKEYREJECTED;
        }
 
-       /* What's left should a PKCS#7 cert */
+       /* What's left should be a PKCS#7 cert */
        pkcs7 = pebuf + ctx->sig_offset;
-       if (pkcs7[0] == (ASN1_CONS_BIT | ASN1_SEQ)) {
-               if (pkcs7[1] == 0x82 &&
-                   pkcs7[2] == (((ctx->sig_len - 4) >> 8) & 0xff) &&
-                   pkcs7[3] ==  ((ctx->sig_len - 4)       & 0xff))
-                       return 0;
-               if (pkcs7[1] == 0x80)
-                       return 0;
-               if (pkcs7[1] > 0x82)
-                       return -EMSGSIZE;
+       if (pkcs7[0] != (ASN1_CONS_BIT | ASN1_SEQ))
+               goto not_pkcs7;
+
+       switch (pkcs7[1]) {
+       case 0 ... 0x7f:
+               len = pkcs7[1] + 2;
+               goto check_len;
+       case ASN1_INDEFINITE_LENGTH:
+               return 0;
+       case 0x81:
+               len = pkcs7[2] + 3;
+               goto check_len;
+       case 0x82:
+               len = ((pkcs7[2] << 8) | pkcs7[3]) + 4;
+               goto check_len;
+       case 0x83 ... 0xff:
+               return -EMSGSIZE;
+       default:
+               goto not_pkcs7;
        }
 
+check_len:
+       if (len <= ctx->sig_len) {
+               /* There may be padding */
+               ctx->sig_len = len;
+               return 0;
+       }
+not_pkcs7:
        pr_debug("Signature data not PKCS#7\n");
        return -ELIBBAD;
 }
index 2da8660262e5ccefa00e7608958adaf8c7328e9a..81dc75033f1590111d488216302f475c42b42137 100644 (file)
@@ -33,7 +33,7 @@ acpi_cmos_rtc_space_handler(u32 function, acpi_physical_address address,
                      void *handler_context, void *region_context)
 {
        int i;
-       u8 *value = (u8 *)&value64;
+       u8 *value = (u8 *)value64;
 
        if (address > 0xff || !value64)
                return AE_BAD_PARAMETER;
index ce06149088c5b5366cd4c87b67dfffdb793fc7a6..fddc1e86f9d0e73648a26de5cdc1fd82ec9f9b03 100644 (file)
@@ -196,6 +196,17 @@ static struct lpss_device_desc byt_i2c_dev_desc = {
        .setup = lpss_i2c_setup,
 };
 
+static struct lpss_shared_clock bsw_pwm_clock = {
+       .name = "pwm_clk",
+       .rate = 19200000,
+};
+
+static struct lpss_device_desc bsw_pwm_dev_desc = {
+       .clk_required = true,
+       .save_ctx = true,
+       .shared_clock = &bsw_pwm_clock,
+};
+
 #else
 
 #define LPSS_ADDR(desc) (0UL)
@@ -225,6 +236,12 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
        { "INT33B2", },
        { "INT33FC", },
 
+       /* Braswell LPSS devices */
+       { "80862288", LPSS_ADDR(bsw_pwm_dev_desc) },
+       { "8086228A", LPSS_ADDR(byt_uart_dev_desc) },
+       { "8086228E", LPSS_ADDR(byt_spi_dev_desc) },
+       { "808622C1", LPSS_ADDR(byt_i2c_dev_desc) },
+
        { "INT3430", LPSS_ADDR(lpt_dev_desc) },
        { "INT3431", LPSS_ADDR(lpt_dev_desc) },
        { "INT3432", LPSS_ADDR(lpt_i2c_dev_desc) },
@@ -593,7 +610,7 @@ static int acpi_lpss_suspend_late(struct device *dev)
        return acpi_dev_suspend_late(dev);
 }
 
-static int acpi_lpss_restore_early(struct device *dev)
+static int acpi_lpss_resume_early(struct device *dev)
 {
        int ret = acpi_dev_resume_early(dev);
 
@@ -633,15 +650,15 @@ static int acpi_lpss_runtime_resume(struct device *dev)
 static struct dev_pm_domain acpi_lpss_pm_domain = {
        .ops = {
 #ifdef CONFIG_PM_SLEEP
-               .suspend_late = acpi_lpss_suspend_late,
-               .restore_early = acpi_lpss_restore_early,
                .prepare = acpi_subsys_prepare,
                .complete = acpi_subsys_complete,
                .suspend = acpi_subsys_suspend,
-               .resume_early = acpi_subsys_resume_early,
+               .suspend_late = acpi_lpss_suspend_late,
+               .resume_early = acpi_lpss_resume_early,
                .freeze = acpi_subsys_freeze,
                .poweroff = acpi_subsys_suspend,
-               .poweroff_late = acpi_subsys_suspend_late,
+               .poweroff_late = acpi_lpss_suspend_late,
+               .restore_early = acpi_lpss_resume_early,
 #endif
 #ifdef CONFIG_PM_RUNTIME
                .runtime_suspend = acpi_lpss_runtime_suspend,
index 68f725839eb6d61bf129664922b1b22d7bdb0d05..1b13b921dda933e373b3e237886e55269df94aa7 100644 (file)
@@ -316,6 +316,45 @@ acpi_ns_check_package(struct acpi_evaluate_info *info,
                    acpi_ns_check_package_list(info, package, elements, count);
                break;
 
+       case ACPI_PTYPE2_UUID_PAIR:
+
+               /* The package must contain pairs of (UUID + type) */
+
+               if (count & 1) {
+                       expected_count = count + 1;
+                       goto package_too_small;
+               }
+
+               while (count > 0) {
+                       status = acpi_ns_check_object_type(info, elements,
+                                                          package->ret_info.
+                                                          object_type1, 0);
+                       if (ACPI_FAILURE(status)) {
+                               return (status);
+                       }
+
+                       /* Validate length of the UUID buffer */
+
+                       if ((*elements)->buffer.length != 16) {
+                               ACPI_WARN_PREDEFINED((AE_INFO,
+                                                     info->full_pathname,
+                                                     info->node_flags,
+                                                     "Invalid length for UUID Buffer"));
+                               return (AE_AML_OPERAND_VALUE);
+                       }
+
+                       status = acpi_ns_check_object_type(info, elements + 1,
+                                                          package->ret_info.
+                                                          object_type2, 0);
+                       if (ACPI_FAILURE(status)) {
+                               return (status);
+                       }
+
+                       elements += 2;
+                       count -= 2;
+               }
+               break;
+
        default:
 
                /* Should not get here if predefined info table is correct */
index 1c162e7be045405f267ef8d8140795508f8ea1c0..5fdfe65fe165d0a95b72e258a6c4584682f7019a 100644 (file)
@@ -534,20 +534,6 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
                        " invalid.\n");
        }
 
-       /*
-        * When fully charged, some batteries wrongly report
-        * capacity_now = design_capacity instead of = full_charge_capacity
-        */
-       if (battery->capacity_now > battery->full_charge_capacity
-           && battery->full_charge_capacity != ACPI_BATTERY_VALUE_UNKNOWN) {
-               if (battery->capacity_now != battery->design_capacity)
-                       printk_once(KERN_WARNING FW_BUG
-                               "battery: reported current charge level (%d) "
-                               "is higher than reported maximum charge level (%d).\n",
-                               battery->capacity_now, battery->full_charge_capacity);
-               battery->capacity_now = battery->full_charge_capacity;
-       }
-
        if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
            && battery->capacity_now >= 0 && battery->capacity_now <= 100)
                battery->capacity_now = (battery->capacity_now *
index a66ab658abbc6d69af9ef07fb7e79209531df376..cb6066c809ea03dddec42b0871e22a67ef242726 100644 (file)
@@ -197,6 +197,8 @@ static bool advance_transaction(struct acpi_ec *ec)
                                t->rdata[t->ri++] = acpi_ec_read_data(ec);
                                if (t->rlen == t->ri) {
                                        t->flags |= ACPI_EC_COMMAND_COMPLETE;
+                                       if (t->command == ACPI_EC_COMMAND_QUERY)
+                                               pr_debug("hardware QR_EC completion\n");
                                        wakeup = true;
                                }
                        } else
@@ -208,7 +210,20 @@ static bool advance_transaction(struct acpi_ec *ec)
                }
                return wakeup;
        } else {
-               if ((status & ACPI_EC_FLAG_IBF) == 0) {
+               /*
+                * There is firmware refusing to respond QR_EC when SCI_EVT
+                * is not set, for which case, we complete the QR_EC
+                * without issuing it to the firmware.
+                * https://bugzilla.kernel.org/show_bug.cgi?id=86211
+                */
+               if (!(status & ACPI_EC_FLAG_SCI) &&
+                   (t->command == ACPI_EC_COMMAND_QUERY)) {
+                       t->flags |= ACPI_EC_COMMAND_POLL;
+                       t->rdata[t->ri++] = 0x00;
+                       t->flags |= ACPI_EC_COMMAND_COMPLETE;
+                       pr_debug("software QR_EC completion\n");
+                       wakeup = true;
+               } else if ((status & ACPI_EC_FLAG_IBF) == 0) {
                        acpi_ec_write_cmd(ec, t->command);
                        t->flags |= ACPI_EC_COMMAND_POLL;
                } else
@@ -288,11 +303,11 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
        /* following two actions should be kept atomic */
        ec->curr = t;
        start_transaction(ec);
-       if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
-               clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
        spin_unlock_irqrestore(&ec->lock, tmp);
        ret = ec_poll(ec);
        spin_lock_irqsave(&ec->lock, tmp);
+       if (ec->curr->command == ACPI_EC_COMMAND_QUERY)
+               clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
        ec->curr = NULL;
        spin_unlock_irqrestore(&ec->lock, tmp);
        return ret;
@@ -1015,6 +1030,10 @@ static struct dmi_system_id ec_dmi_table[] __initdata = {
        DMI_MATCH(DMI_SYS_VENDOR, "Quanta"),
        DMI_MATCH(DMI_PRODUCT_NAME, "TW9/SW9"),}, NULL},
        {
+       ec_flag_msi, "Clevo W350etq", {
+       DMI_MATCH(DMI_SYS_VENDOR, "CLEVO CO."),
+       DMI_MATCH(DMI_PRODUCT_NAME, "W35_37ET"),}, NULL},
+       {
        ec_validate_ecdt, "ASUS hardware", {
        DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL},
        {
index c96887d5289eaed997e29eaab738f8bb4bb488ee..6e6b80eb0bba1e369d36308d5779ec3cc184c4a0 100644 (file)
@@ -484,6 +484,10 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
        /* Keep IOAPIC pin configuration when suspending */
        if (dev->dev.power.is_prepared)
                return;
+#ifdef CONFIG_PM_RUNTIME
+       if (dev->dev.power.runtime_status == RPM_SUSPENDING)
+               return;
+#endif
 
        entry = acpi_pci_irq_lookup(dev, pin);
        if (!entry)
index 3dca36d4ad26ef22d6ecea66e166ae22cde9ab33..17f9ec501972ef208b505ed881173e2dac0cc2ea 100644 (file)
@@ -1071,9 +1071,9 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
 
        if (pr->id == 0 && cpuidle_get_driver() == &acpi_idle_driver) {
 
-               cpuidle_pause_and_lock();
                /* Protect against cpu-hotplug */
                get_online_cpus();
+               cpuidle_pause_and_lock();
 
                /* Disable all cpuidle devices */
                for_each_online_cpu(cpu) {
@@ -1100,8 +1100,8 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr)
                                cpuidle_enable_device(dev);
                        }
                }
-               put_online_cpus();
                cpuidle_resume_and_unlock();
+               put_online_cpus();
        }
 
        return 0;
index 0a817ad24f16f75853d34e11deb1a226ef3d9ed0..3bf7764659a4f5643557eb2aee4b5b327da4f88f 100644 (file)
@@ -667,8 +667,14 @@ static ssize_t
 acpi_device_sun_show(struct device *dev, struct device_attribute *attr,
                     char *buf) {
        struct acpi_device *acpi_dev = to_acpi_device(dev);
+       acpi_status status;
+       unsigned long long sun;
+
+       status = acpi_evaluate_integer(acpi_dev->handle, "_SUN", NULL, &sun);
+       if (ACPI_FAILURE(status))
+               return -ENODEV;
 
-       return sprintf(buf, "%lu\n", acpi_dev->pnp.sun);
+       return sprintf(buf, "%llu\n", sun);
 }
 static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL);
 
@@ -690,7 +696,6 @@ static int acpi_device_setup_files(struct acpi_device *dev)
 {
        struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
        acpi_status status;
-       unsigned long long sun;
        int result = 0;
 
        /*
@@ -731,14 +736,10 @@ static int acpi_device_setup_files(struct acpi_device *dev)
        if (dev->pnp.unique_id)
                result = device_create_file(&dev->dev, &dev_attr_uid);
 
-       status = acpi_evaluate_integer(dev->handle, "_SUN", NULL, &sun);
-       if (ACPI_SUCCESS(status)) {
-               dev->pnp.sun = (unsigned long)sun;
+       if (acpi_has_method(dev->handle, "_SUN")) {
                result = device_create_file(&dev->dev, &dev_attr_sun);
                if (result)
                        goto end;
-       } else {
-               dev->pnp.sun = (unsigned long)-1;
        }
 
        if (acpi_has_method(dev->handle, "_STA")) {
@@ -922,12 +923,17 @@ static void acpi_device_notify(acpi_handle handle, u32 event, void *data)
        device->driver->ops.notify(device, event);
 }
 
-static acpi_status acpi_device_notify_fixed(void *data)
+static void acpi_device_notify_fixed(void *data)
 {
        struct acpi_device *device = data;
 
        /* Fixed hardware devices have no handles */
        acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device);
+}
+
+static acpi_status acpi_device_fixed_event(void *data)
+{
+       acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_device_notify_fixed, data);
        return AE_OK;
 }
 
@@ -938,12 +944,12 @@ static int acpi_device_install_notify_handler(struct acpi_device *device)
        if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
                status =
                    acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
-                                                    acpi_device_notify_fixed,
+                                                    acpi_device_fixed_event,
                                                     device);
        else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
                status =
                    acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
-                                                    acpi_device_notify_fixed,
+                                                    acpi_device_fixed_event,
                                                     device);
        else
                status = acpi_install_notify_handler(device->handle,
@@ -960,10 +966,10 @@ static void acpi_device_remove_notify_handler(struct acpi_device *device)
 {
        if (device->device_type == ACPI_BUS_TYPE_POWER_BUTTON)
                acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
-                                               acpi_device_notify_fixed);
+                                               acpi_device_fixed_event);
        else if (device->device_type == ACPI_BUS_TYPE_SLEEP_BUTTON)
                acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
-                                               acpi_device_notify_fixed);
+                                               acpi_device_fixed_event);
        else
                acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
                                           acpi_device_notify);
@@ -975,7 +981,7 @@ static int acpi_device_probe(struct device *dev)
        struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver);
        int ret;
 
-       if (acpi_dev->handler)
+       if (acpi_dev->handler && !acpi_is_pnp_device(acpi_dev))
                return -EINVAL;
 
        if (!acpi_drv->ops.add)
index 826884392e6b4b9df067623cfad758c29ea954a7..fcbda105616eb703b87e50ee88650cd4dde72d78 100644 (file)
@@ -82,9 +82,9 @@ module_param(allow_duplicates, bool, 0644);
  * For Windows 8 systems: used to decide if video module
  * should skip registering backlight interface of its own.
  */
-static int use_native_backlight_param = 1;
+static int use_native_backlight_param = -1;
 module_param_named(use_native_backlight, use_native_backlight_param, int, 0444);
-static bool use_native_backlight_dmi = false;
+static bool use_native_backlight_dmi = true;
 
 static int register_count;
 static struct mutex video_list_lock;
@@ -417,6 +417,12 @@ static int __init video_set_use_native_backlight(const struct dmi_system_id *d)
        return 0;
 }
 
+static int __init video_disable_native_backlight(const struct dmi_system_id *d)
+{
+       use_native_backlight_dmi = false;
+       return 0;
+}
+
 static struct dmi_system_id video_dmi_table[] __initdata = {
        /*
         * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121
@@ -720,6 +726,41 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
                DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 8780w"),
                },
        },
+
+       /*
+        * These models have a working acpi_video backlight control, and using
+        * native backlight causes a regression where backlight does not work
+        * when userspace is not handling brightness key events. Disable
+        * native_backlight on these to fix this:
+        * https://bugzilla.kernel.org/show_bug.cgi?id=81691
+        */
+       {
+        .callback = video_disable_native_backlight,
+        .ident = "ThinkPad T420",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T420"),
+               },
+       },
+       {
+        .callback = video_disable_native_backlight,
+        .ident = "ThinkPad T520",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+               DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T520"),
+               },
+       },
+
+       /* The native backlight controls do not work on some older machines */
+       {
+        /* https://bugs.freedesktop.org/show_bug.cgi?id=81515 */
+        .callback = video_disable_native_backlight,
+        .ident = "HP ENVY 15 Notebook",
+        .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "HP ENVY 15 Notebook PC"),
+               },
+       },
        {}
 };
 
index a29f8012fb08483cfb67e47b9d104db1e7db4954..a0cc0edafc78e27a9b1cee2031d1a74e523425d2 100644 (file)
@@ -305,6 +305,14 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x9c85), board_ahci }, /* Wildcat Point-LP RAID */
        { PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */
        { PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */
+       { PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */
+       { PCI_VDEVICE(INTEL, 0x8c83), board_ahci }, /* 9 Series AHCI */
+       { PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */
+       { PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series RAID */
+       { PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */
+       { PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */
+       { PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */
+       { PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */
 
        /* JMicron 360/1/3/5/6, match class to avoid IDE function */
        { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
@@ -442,6 +450,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a),
          .driver_data = board_ahci_yes_fbs },                  /* 88se9172 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9172),
+         .driver_data = board_ahci_yes_fbs },                  /* 88se9182 */
+       { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9182),
          .driver_data = board_ahci_yes_fbs },                  /* 88se9172 */
        { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192),
          .driver_data = board_ahci_yes_fbs },                  /* 88se9172 on some Gigabyte */
@@ -1329,6 +1339,18 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000)
                ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS;
 
+       /*
+        * The JMicron chip 361/363 contains one SATA controller and one
+        * PATA controller,for powering on these both controllers, we must
+        * follow the sequence one by one, otherwise one of them can not be
+        * powered on successfully, so here we disable the async suspend
+        * method for these chips.
+        */
+       if (pdev->vendor == PCI_VENDOR_ID_JMICRON &&
+               (pdev->device == PCI_DEVICE_ID_JMICRON_JMB363 ||
+               pdev->device == PCI_DEVICE_ID_JMICRON_JMB361))
+               device_disable_async_suspend(&pdev->dev);
+
        /* acquire resources */
        rc = pcim_enable_device(pdev);
        if (rc)
index f1fef74e503cd94716dfe090ab397d83118065f5..032904402c9509af14eafdc36993e8d6eb39ac88 100644 (file)
  */
 
 #include <linux/ahci_platform.h>
-#include <linux/reset.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+
+#include <soc/tegra/fuse.h>
 #include <soc/tegra/pmc.h>
+
 #include "ahci.h"
 
 #define SATA_CONFIGURATION_0                           0x180
@@ -180,9 +183,12 @@ static int tegra_ahci_controller_init(struct ahci_host_priv *hpriv)
 
        /* Pad calibration */
 
-       /* FIXME Always use calibration 0. Change this to read the calibration
-        * fuse once the fuse driver has landed. */
-       val = 0;
+       ret = tegra_fuse_readl(FUSE_SATA_CALIB, &val);
+       if (ret) {
+               dev_err(&tegra->pdev->dev,
+                       "failed to read calibration fuse: %d\n", ret);
+               return ret;
+       }
 
        calib = tegra124_pad_calibration[val & FUSE_SATA_CALIB_MASK];
 
index c6962300b93c7c6292ed91d62611db6678af1f49..f03aab187f4da1cf16d3f2cb34642f4fcaad7434 100644 (file)
@@ -78,6 +78,9 @@
 #define CFG_MEM_RAM_SHUTDOWN           0x00000070
 #define BLOCK_MEM_RDY                  0x00000074
 
+/* Max retry for link down */
+#define MAX_LINK_DOWN_RETRY 3
+
 struct xgene_ahci_context {
        struct ahci_host_priv *hpriv;
        struct device *dev;
@@ -145,6 +148,14 @@ static unsigned int xgene_ahci_qc_issue(struct ata_queued_cmd *qc)
        return rc;
 }
 
+static bool xgene_ahci_is_memram_inited(struct xgene_ahci_context *ctx)
+{
+       void __iomem *diagcsr = ctx->csr_diag;
+
+       return (readl(diagcsr + CFG_MEM_RAM_SHUTDOWN) == 0 &&
+               readl(diagcsr + BLOCK_MEM_RDY) == 0xFFFFFFFF);
+}
+
 /**
  * xgene_ahci_read_id - Read ID data from the specified device
  * @dev: device
@@ -229,8 +240,11 @@ static void xgene_ahci_set_phy_cfg(struct xgene_ahci_context *ctx, int channel)
  * and Gen1 (1.5Gbps). Otherwise during long IO stress test, the PHY will
  * report disparity error and etc. In addition, during COMRESET, there can
  * be error reported in the register PORT_SCR_ERR. For SERR_DISPARITY and
- * SERR_10B_8B_ERR, the PHY receiver line must be reseted. The following
- * algorithm is followed to proper configure the hardware PHY during COMRESET:
+ * SERR_10B_8B_ERR, the PHY receiver line must be reseted. Also during long
+ * reboot cycle regression, sometimes the PHY reports link down even if the
+ * device is present because of speed negotiation failure. so need to retry
+ * the COMRESET to get the link up. The following algorithm is followed to
+ * proper configure the hardware PHY during COMRESET:
  *
  * Alg Part 1:
  * 1. Start the PHY at Gen3 speed (default setting)
@@ -246,9 +260,15 @@ static void xgene_ahci_set_phy_cfg(struct xgene_ahci_context *ctx, int channel)
  * Alg Part 2:
  * 1. On link up, if there are any SERR_DISPARITY and SERR_10B_8B_ERR error
  *    reported in the register PORT_SCR_ERR, then reset the PHY receiver line
- * 2. Go to Alg Part 3
+ * 2. Go to Alg Part 4
  *
  * Alg Part 3:
+ * 1. Check the PORT_SCR_STAT to see whether device presence detected but PHY
+ *    communication establishment failed and maximum link down attempts are
+ *    less than Max attempts 3 then goto Alg Part 1.
+ * 2. Go to Alg Part 4.
+ *
+ * Alg Part 4:
  * 1. Clear any pending from register PORT_SCR_ERR.
  *
  * NOTE: For the initial version, we will NOT support Gen1/Gen2. In addition
@@ -267,19 +287,27 @@ static int xgene_ahci_do_hardreset(struct ata_link *link,
        u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
        void __iomem *port_mmio = ahci_port_base(ap);
        struct ata_taskfile tf;
+       int link_down_retry = 0;
        int rc;
-       u32 val;
-
-       /* clear D2H reception area to properly wait for D2H FIS */
-       ata_tf_init(link->device, &tf);
-       tf.command = ATA_BUSY;
-       ata_tf_to_fis(&tf, 0, 0, d2h_fis);
-       rc = sata_link_hardreset(link, timing, deadline, online,
+       u32 val, sstatus;
+
+       do {
+               /* clear D2H reception area to properly wait for D2H FIS */
+               ata_tf_init(link->device, &tf);
+               tf.command = ATA_BUSY;
+               ata_tf_to_fis(&tf, 0, 0, d2h_fis);
+               rc = sata_link_hardreset(link, timing, deadline, online,
                                 ahci_check_ready);
+               if (*online) {
+                       val = readl(port_mmio + PORT_SCR_ERR);
+                       if (val & (SERR_DISPARITY | SERR_10B_8B_ERR))
+                               dev_warn(ctx->dev, "link has error\n");
+                       break;
+               }
 
-       val = readl(port_mmio + PORT_SCR_ERR);
-       if (val & (SERR_DISPARITY | SERR_10B_8B_ERR))
-               dev_warn(ctx->dev, "link has error\n");
+               sata_scr_read(link, SCR_STATUS, &sstatus);
+       } while (link_down_retry++ < MAX_LINK_DOWN_RETRY &&
+                (sstatus & 0xff) == 0x1);
 
        /* clear all errors if any pending */
        val = readl(port_mmio + PORT_SCR_ERR);
@@ -467,6 +495,11 @@ static int xgene_ahci_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
+       if (xgene_ahci_is_memram_inited(ctx)) {
+               dev_info(dev, "skip clock and PHY initialization\n");
+               goto skip_clk_phy;
+       }
+
        /* Due to errata, HW requires full toggle transition */
        rc = ahci_platform_enable_clks(hpriv);
        if (rc)
@@ -479,7 +512,7 @@ static int xgene_ahci_probe(struct platform_device *pdev)
 
        /* Configure the host controller */
        xgene_ahci_hw_init(hpriv);
-
+skip_clk_phy:
        hpriv->flags = AHCI_HFLAG_NO_PMP | AHCI_HFLAG_NO_NCQ;
 
        rc = ahci_platform_init_host(pdev, hpriv, &xgene_ahci_port_info);
index 893e30e9a9efab5662d5361e83051f9ac1c650c0..ffbe625e6fd2738726e77d42313aa9a09866ec4b 100644 (file)
@@ -340,6 +340,14 @@ static const struct pci_device_id piix_pci_tbl[] = {
        { 0x8086, 0x0F21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_byt },
        /* SATA Controller IDE (Coleto Creek) */
        { 0x8086, 0x23a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+       /* SATA Controller IDE (9 Series) */
+       { 0x8086, 0x8c88, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb },
+       /* SATA Controller IDE (9 Series) */
+       { 0x8086, 0x8c89, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb },
+       /* SATA Controller IDE (9 Series) */
+       { 0x8086, 0x8c80, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
+       /* SATA Controller IDE (9 Series) */
+       { 0x8086, 0x8c81, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
 
        { }     /* terminate list */
 };
index 4d1a5d2c4287f2979c34a2913c0cb4018f573776..47e418b8c8baa0eee13b0a2843c25371a83bd338 100644 (file)
@@ -143,6 +143,18 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i
        };
        const struct ata_port_info *ppi[] = { &info, NULL };
 
+       /*
+        * The JMicron chip 361/363 contains one SATA controller and one
+        * PATA controller,for powering on these both controllers, we must
+        * follow the sequence one by one, otherwise one of them can not be
+        * powered on successfully, so here we disable the async suspend
+        * method for these chips.
+        */
+       if (pdev->vendor == PCI_VENDOR_ID_JMICRON &&
+               (pdev->device == PCI_DEVICE_ID_JMICRON_JMB363 ||
+               pdev->device == PCI_DEVICE_ID_JMICRON_JMB361))
+               device_disable_async_suspend(&pdev->dev);
+
        return ata_pci_bmdma_init_one(pdev, ppi, &jmicron_sht, NULL, 0);
 }
 
index 7d1326985bee8b4d3e9dcb326bf795622901bf49..bfc90b8547f23f1c243a4f1c6d7c00fc95f632a6 100644 (file)
@@ -146,6 +146,9 @@ struct regcache_ops {
        enum regcache_type type;
        int (*init)(struct regmap *map);
        int (*exit)(struct regmap *map);
+#ifdef CONFIG_DEBUG_FS
+       void (*debugfs_init)(struct regmap *map);
+#endif
        int (*read)(struct regmap *map, unsigned int reg, unsigned int *value);
        int (*write)(struct regmap *map, unsigned int reg, unsigned int value);
        int (*sync)(struct regmap *map, unsigned int min, unsigned int max);
index 6a7e4fa12854c8ac365edbe6dbf918c04d2ccd59..f3e8fe0cc65030a8fea51c00994a343df8220659 100644 (file)
@@ -194,10 +194,6 @@ static void rbtree_debugfs_init(struct regmap *map)
 {
        debugfs_create_file("rbtree", 0400, map->debugfs, map, &rbtree_fops);
 }
-#else
-static void rbtree_debugfs_init(struct regmap *map)
-{
-}
 #endif
 
 static int regcache_rbtree_init(struct regmap *map)
@@ -222,8 +218,6 @@ static int regcache_rbtree_init(struct regmap *map)
                        goto err;
        }
 
-       rbtree_debugfs_init(map);
-
        return 0;
 
 err:
@@ -532,6 +526,9 @@ struct regcache_ops regcache_rbtree_ops = {
        .name = "rbtree",
        .init = regcache_rbtree_init,
        .exit = regcache_rbtree_exit,
+#ifdef CONFIG_DEBUG_FS
+       .debugfs_init = rbtree_debugfs_init,
+#endif
        .read = regcache_rbtree_read,
        .write = regcache_rbtree_write,
        .sync = regcache_rbtree_sync,
index 29b4128da0b08ce6b8eda048557ed9093b07efa0..5617da6dc898b3edeff6f8b6cdca38fbab849900 100644 (file)
@@ -698,7 +698,7 @@ int regcache_sync_block(struct regmap *map, void *block,
                        unsigned int block_base, unsigned int start,
                        unsigned int end)
 {
-       if (regmap_can_raw_write(map))
+       if (regmap_can_raw_write(map) && !map->use_single_rw)
                return regcache_sync_block_raw(map, block, cache_present,
                                               block_base, start, end);
        else
index 45d812c0ea7751868d3d14d7691da6f74493b54a..65ea7b256b3eab603100bfe451383bb1fa339ae8 100644 (file)
@@ -538,6 +538,9 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
 
                next = rb_next(&range_node->node);
        }
+
+       if (map->cache_ops && map->cache_ops->debugfs_init)
+               map->cache_ops->debugfs_init(map);
 }
 
 void regmap_debugfs_exit(struct regmap *map)
index 78f43fb2fe84647d5e97d5c9f6468cf6c8704187..1cf427bc0d4a8f0ddd9571b69f5dcc14a2167bdb 100644 (file)
@@ -109,7 +109,7 @@ bool regmap_readable(struct regmap *map, unsigned int reg)
 
 bool regmap_volatile(struct regmap *map, unsigned int reg)
 {
-       if (!regmap_readable(map, reg))
+       if (!map->format.format_write && !regmap_readable(map, reg))
                return false;
 
        if (map->volatile_reg)
index 294a7dd2519028a21260579f6c25b5a9aff011f7..f032ed6dd459564ece3a6cf119070c72ca2991cc 100644 (file)
@@ -282,6 +282,7 @@ static const struct pci_device_id bcma_pci_bridge_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
+       { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) },  /* 0xA8DB */
        { 0, },
 };
 MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl);
index c7d138eca731b638c324eaf30ae60007625c0f80..3598110d2cefcff5cc1b69319b8d1891f7f46a2f 100644 (file)
@@ -442,12 +442,15 @@ static int rd_nr;
 int rd_size = CONFIG_BLK_DEV_RAM_SIZE;
 static int max_part;
 static int part_shift;
+static int part_show = 0;
 module_param(rd_nr, int, S_IRUGO);
 MODULE_PARM_DESC(rd_nr, "Maximum number of brd devices");
 module_param(rd_size, int, S_IRUGO);
 MODULE_PARM_DESC(rd_size, "Size of each RAM disk in kbytes.");
 module_param(max_part, int, S_IRUGO);
 MODULE_PARM_DESC(max_part, "Maximum number of partitions per RAM disk");
+module_param(part_show, int, S_IRUGO);
+MODULE_PARM_DESC(part_show, "Control RAM disk visibility in /proc/partitions");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_BLOCKDEV_MAJOR(RAMDISK_MAJOR);
 MODULE_ALIAS("rd");
@@ -501,7 +504,8 @@ static struct brd_device *brd_alloc(int i)
        disk->fops              = &brd_fops;
        disk->private_data      = brd;
        disk->queue             = brd->brd_queue;
-       disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;
+       if (!part_show)
+               disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;
        sprintf(disk->disk_name, "ram%d", i);
        set_capacity(disk, rd_size * 2);
 
index db1e9560d8a721c5165955651462c11d5b306f0a..5c8e7fe077458f31e83b0bcf65137b255e4a8336 100644 (file)
@@ -3918,7 +3918,6 @@ skip_create_disk:
        if (rv) {
                dev_err(&dd->pdev->dev,
                        "Unable to allocate request queue\n");
-               rv = -ENOMEM;
                goto block_queue_alloc_init_error;
        }
 
index a3b042c4d448dcb4ad0a21272dd8ff83527f3b9d..00d469c7f9f79742c659011088b144d5bf4b6bef 100644 (file)
@@ -462,17 +462,21 @@ static int null_add_dev(void)
        struct gendisk *disk;
        struct nullb *nullb;
        sector_t size;
+       int rv;
 
        nullb = kzalloc_node(sizeof(*nullb), GFP_KERNEL, home_node);
-       if (!nullb)
+       if (!nullb) {
+               rv = -ENOMEM;
                goto out;
+       }
 
        spin_lock_init(&nullb->lock);
 
        if (queue_mode == NULL_Q_MQ && use_per_node_hctx)
                submit_queues = nr_online_nodes;
 
-       if (setup_queues(nullb))
+       rv = setup_queues(nullb);
+       if (rv)
                goto out_free_nullb;
 
        if (queue_mode == NULL_Q_MQ) {
@@ -484,22 +488,29 @@ static int null_add_dev(void)
                nullb->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
                nullb->tag_set.driver_data = nullb;
 
-               if (blk_mq_alloc_tag_set(&nullb->tag_set))
+               rv = blk_mq_alloc_tag_set(&nullb->tag_set);
+               if (rv)
                        goto out_cleanup_queues;
 
                nullb->q = blk_mq_init_queue(&nullb->tag_set);
-               if (!nullb->q)
+               if (!nullb->q) {
+                       rv = -ENOMEM;
                        goto out_cleanup_tags;
+               }
        } else if (queue_mode == NULL_Q_BIO) {
                nullb->q = blk_alloc_queue_node(GFP_KERNEL, home_node);
-               if (!nullb->q)
+               if (!nullb->q) {
+                       rv = -ENOMEM;
                        goto out_cleanup_queues;
+               }
                blk_queue_make_request(nullb->q, null_queue_bio);
                init_driver_queues(nullb);
        } else {
                nullb->q = blk_init_queue_node(null_request_fn, &nullb->lock, home_node);
-               if (!nullb->q)
+               if (!nullb->q) {
+                       rv = -ENOMEM;
                        goto out_cleanup_queues;
+               }
                blk_queue_prep_rq(nullb->q, null_rq_prep_fn);
                blk_queue_softirq_done(nullb->q, null_softirq_done_fn);
                init_driver_queues(nullb);
@@ -509,8 +520,10 @@ static int null_add_dev(void)
        queue_flag_set_unlocked(QUEUE_FLAG_NONROT, nullb->q);
 
        disk = nullb->disk = alloc_disk_node(1, home_node);
-       if (!disk)
+       if (!disk) {
+               rv = -ENOMEM;
                goto out_cleanup_blk_queue;
+       }
 
        mutex_lock(&lock);
        list_add_tail(&nullb->list, &nullb_list);
@@ -544,7 +557,7 @@ out_cleanup_queues:
 out_free_nullb:
        kfree(nullb);
 out:
-       return -ENOMEM;
+       return rv;
 }
 
 static int __init null_init(void)
index 623c84145b792b9ddaa852e45c2cdbf80b1f08d5..4b97baf8afa317347ca7ff531f2d8828394084a2 100644 (file)
@@ -5087,9 +5087,11 @@ static int rbd_dev_device_setup(struct rbd_device *rbd_dev)
        set_capacity(rbd_dev->disk, rbd_dev->mapping.size / SECTOR_SIZE);
        set_disk_ro(rbd_dev->disk, rbd_dev->mapping.read_only);
 
-       rbd_dev->rq_wq = alloc_workqueue(rbd_dev->disk->disk_name, 0, 0);
-       if (!rbd_dev->rq_wq)
+       rbd_dev->rq_wq = alloc_workqueue("%s", 0, 0, rbd_dev->disk->disk_name);
+       if (!rbd_dev->rq_wq) {
+               ret = -ENOMEM;
                goto err_out_mapping;
+       }
 
        ret = rbd_bus_add_dev(rbd_dev);
        if (ret)
index ab3ea62e5dfc70dc0e62488290688f468d69cbcc..c4328d9d9981ed18c8d5c5decc5af9efe00338ee 100644 (file)
@@ -1203,7 +1203,6 @@ static struct platform_driver ace_platform_driver = {
        .probe = ace_probe,
        .remove = ace_remove,
        .driver = {
-               .owner = THIS_MODULE,
                .name = "xsysace",
                .of_match_table = ace_of_match,
        },
index dfa4024c448a6222d8d12ffb2f05e1976652fca0..d00831c3d73136dc06df360445e0d9590c752eed 100644 (file)
@@ -378,7 +378,6 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index)
        /* Should NEVER happen. Return bio error if it does. */
        if (unlikely(ret)) {
                pr_err("Decompression failed! err=%d, page=%u\n", ret, index);
-               atomic64_inc(&zram->stats.failed_reads);
                return ret;
        }
 
@@ -547,8 +546,6 @@ out:
                zcomp_strm_release(zram->comp, zstrm);
        if (is_partial_io(bvec))
                kfree(uncmem);
-       if (ret)
-               atomic64_inc(&zram->stats.failed_writes);
        return ret;
 }
 
@@ -566,6 +563,13 @@ static int zram_bvec_rw(struct zram *zram, struct bio_vec *bvec, u32 index,
                ret = zram_bvec_write(zram, bvec, index, offset);
        }
 
+       if (unlikely(ret)) {
+               if (rw == READ)
+                       atomic64_inc(&zram->stats.failed_reads);
+               else
+                       atomic64_inc(&zram->stats.failed_writes);
+       }
+
        return ret;
 }
 
index 5b0afde729cd885286f48d31991f7bc98f44328b..e0f725c87cc617b4ade4c7574c18fa6ce15ca828 100644 (file)
@@ -84,7 +84,7 @@ struct zram_stats {
        atomic64_t compr_data_size;     /* compressed size of pages stored */
        atomic64_t num_reads;   /* failed + successful */
        atomic64_t num_writes;  /* --do-- */
-       atomic64_t failed_reads;        /* should NEVER! happen */
+       atomic64_t failed_reads;        /* can happen when memory is too low */
        atomic64_t failed_writes;       /* can happen when memory is too low */
        atomic64_t invalid_io;  /* non-page-aligned I/O requests */
        atomic64_t notify_free; /* no. of swap slot free notifications */
index 6f550d9e7a2dbd1258a2ba833bcda6fb97a003a2..a60f26400705e11aae4ef6abcb8c840e94a33806 100644 (file)
@@ -586,6 +586,30 @@ static int arm_ccn_pmu_type_eq(u32 a, u32 b)
        return 0;
 }
 
+static void arm_ccn_pmu_event_destroy(struct perf_event *event)
+{
+       struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
+       struct hw_perf_event *hw = &event->hw;
+
+       if (hw->idx == CCN_IDX_PMU_CYCLE_COUNTER) {
+               clear_bit(CCN_IDX_PMU_CYCLE_COUNTER, ccn->dt.pmu_counters_mask);
+       } else {
+               struct arm_ccn_component *source =
+                               ccn->dt.pmu_counters[hw->idx].source;
+
+               if (CCN_CONFIG_TYPE(event->attr.config) == CCN_TYPE_XP &&
+                               CCN_CONFIG_EVENT(event->attr.config) ==
+                               CCN_EVENT_WATCHPOINT)
+                       clear_bit(hw->config_base, source->xp.dt_cmp_mask);
+               else
+                       clear_bit(hw->config_base, source->pmu_events_mask);
+               clear_bit(hw->idx, ccn->dt.pmu_counters_mask);
+       }
+
+       ccn->dt.pmu_counters[hw->idx].source = NULL;
+       ccn->dt.pmu_counters[hw->idx].event = NULL;
+}
+
 static int arm_ccn_pmu_event_init(struct perf_event *event)
 {
        struct arm_ccn *ccn;
@@ -599,6 +623,7 @@ static int arm_ccn_pmu_event_init(struct perf_event *event)
                return -ENOENT;
 
        ccn = pmu_to_arm_ccn(event->pmu);
+       event->destroy = arm_ccn_pmu_event_destroy;
 
        if (hw->sample_period) {
                dev_warn(ccn->dev, "Sampling not supported!\n");
@@ -731,30 +756,6 @@ static int arm_ccn_pmu_event_init(struct perf_event *event)
        return 0;
 }
 
-static void arm_ccn_pmu_event_free(struct perf_event *event)
-{
-       struct arm_ccn *ccn = pmu_to_arm_ccn(event->pmu);
-       struct hw_perf_event *hw = &event->hw;
-
-       if (hw->idx == CCN_IDX_PMU_CYCLE_COUNTER) {
-               clear_bit(CCN_IDX_PMU_CYCLE_COUNTER, ccn->dt.pmu_counters_mask);
-       } else {
-               struct arm_ccn_component *source =
-                               ccn->dt.pmu_counters[hw->idx].source;
-
-               if (CCN_CONFIG_TYPE(event->attr.config) == CCN_TYPE_XP &&
-                               CCN_CONFIG_EVENT(event->attr.config) ==
-                               CCN_EVENT_WATCHPOINT)
-                       clear_bit(hw->config_base, source->xp.dt_cmp_mask);
-               else
-                       clear_bit(hw->config_base, source->pmu_events_mask);
-               clear_bit(hw->idx, ccn->dt.pmu_counters_mask);
-       }
-
-       ccn->dt.pmu_counters[hw->idx].source = NULL;
-       ccn->dt.pmu_counters[hw->idx].event = NULL;
-}
-
 static u64 arm_ccn_pmu_read_counter(struct arm_ccn *ccn, int idx)
 {
        u64 res;
@@ -1027,8 +1028,6 @@ static int arm_ccn_pmu_event_add(struct perf_event *event, int flags)
 static void arm_ccn_pmu_event_del(struct perf_event *event, int flags)
 {
        arm_ccn_pmu_event_stop(event, PERF_EF_UPDATE);
-
-       arm_ccn_pmu_event_free(event);
 }
 
 static void arm_ccn_pmu_event_read(struct perf_event *event)
index f7a32d2326c6428f4f4e8b1000381b7dc4301e5f..773bcde893c0472b3ecf8f2e9e3a5356d532a402 100644 (file)
@@ -60,7 +60,7 @@ int dev_pm_opp_init_cpufreq_table(struct device *dev,
                goto out;
        }
 
-       freq_table = kcalloc(sizeof(*freq_table), (max_opps + 1), GFP_ATOMIC);
+       freq_table = kcalloc((max_opps + 1), sizeof(*freq_table), GFP_ATOMIC);
        if (!freq_table) {
                ret = -ENOMEM;
                goto out;
index c5eac949760de99ab8345fa1933657278afe7092..0668b389c5165cae8d02e4bedb270b32b8372bde 100644 (file)
@@ -660,6 +660,7 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
        ICPU(0x3f, core_params),
        ICPU(0x45, core_params),
        ICPU(0x46, core_params),
+       ICPU(0x4c, byt_params),
        ICPU(0x4f, core_params),
        ICPU(0x56, core_params),
        {}
@@ -688,7 +689,7 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
 
        add_timer_on(&cpu->timer, cpunum);
 
-       pr_info("Intel pstate controlling: cpu %d\n", cpunum);
+       pr_debug("Intel pstate controlling: cpu %d\n", cpunum);
 
        return 0;
 }
@@ -707,10 +708,6 @@ static unsigned int intel_pstate_get(unsigned int cpu_num)
 
 static int intel_pstate_set_policy(struct cpufreq_policy *policy)
 {
-       struct cpudata *cpu;
-
-       cpu = all_cpu_data[policy->cpu];
-
        if (!policy->cpuinfo.max_freq)
                return -ENODEV;
 
index 9a68225a757e44edd2554f9672197ee64363a5ad..3f9791f07b8ea05f745a2bcbce6b738379443087 100644 (file)
@@ -501,7 +501,7 @@ static int check_mem_type(void __iomem *dmc_reg)
        return val >> 8;
 }
 
-static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)
+static int s5pv210_cpu_init(struct cpufreq_policy *policy)
 {
        unsigned long mem_type;
        int ret;
index 344d79fa34078166694d1301b4c93e939a94e76b..ef94c3b81f18048c6feee67368d2fd24da416424 100644 (file)
@@ -138,25 +138,18 @@ static int bl_enter_powerdown(struct cpuidle_device *dev,
        return idx;
 }
 
-static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int cpu_id)
+static int __init bl_idle_driver_init(struct cpuidle_driver *drv, int part_id)
 {
-       struct cpuinfo_arm *cpu_info;
        struct cpumask *cpumask;
-       unsigned long cpuid;
        int cpu;
 
        cpumask = kzalloc(cpumask_size(), GFP_KERNEL);
        if (!cpumask)
                return -ENOMEM;
 
-       for_each_possible_cpu(cpu) {
-               cpu_info = &per_cpu(cpu_data, cpu);
-               cpuid = is_smp() ? cpu_info->cpuid : read_cpuid_id();
-
-               /* read cpu id part number */
-               if ((cpuid & 0xFFF0) == cpu_id)
+       for_each_possible_cpu(cpu)
+               if (smp_cpuid_part(cpu) == part_id)
                        cpumask_set_cpu(cpu, cpumask);
-       }
 
        drv->cpumask = cpumask;
 
index 4222cb2aa96aa18e66a75f76d0d56b3feb346982..7bb9d65d9a2c9c99f12314c537fa8cf00c0929ef 100644 (file)
@@ -29,7 +29,7 @@
 EXPORT_TRACEPOINT_SYMBOL(fence_annotate_wait_on);
 EXPORT_TRACEPOINT_SYMBOL(fence_emit);
 
-/**
+/*
  * fence context counter: each execution context should have its own
  * fence context, this allows checking if fences belong to the same
  * context or not. One device can have multiple separate contexts,
index 6a9d89c93b1fdd0f7dfb4f8a68dee807efc5f29a..ae2ab14e64b30e5edf9119569d379766eba24b94 100644 (file)
@@ -362,8 +362,9 @@ static void jz4740_dma_chan_irq(struct jz4740_dmaengine_chan *chan)
                        vchan_cyclic_callback(&chan->desc->vdesc);
                } else {
                        if (chan->next_sg == chan->desc->num_sgs) {
-                               chan->desc = NULL;
+                               list_del(&chan->desc->vdesc.node);
                                vchan_cookie_complete(&chan->desc->vdesc);
+                               chan->desc = NULL;
                        }
                }
        }
index 6557147d9331e252d38c566a07b61ada3b7a7f71..7e4c43c189600cc042248f21e8796c86acf79755 100644 (file)
@@ -241,9 +241,6 @@ static void bt8xxgpio_remove(struct pci_dev *pdev)
        bgwrite(~0x0, BT848_INT_STAT);
        bgwrite(0x0, BT848_GPIO_OUT_EN);
 
-       iounmap(bg->mmio);
-       release_mem_region(pci_resource_start(pdev, 0),
-                          pci_resource_len(pdev, 0));
        pci_disable_device(pdev);
 }
 
index a2cc6be97983fe327cd4f67a4c3204cd4985691c..b792194e0d9ceb6320457c99f270a67680a2d6d8 100644 (file)
@@ -67,6 +67,7 @@ static int ast_detect_chip(struct drm_device *dev)
 {
        struct ast_private *ast = dev->dev_private;
        uint32_t data, jreg;
+       ast_open_key(ast);
 
        if (dev->pdev->device == PCI_CHIP_AST1180) {
                ast->chip = AST1100;
@@ -104,7 +105,7 @@ static int ast_detect_chip(struct drm_device *dev)
                        }
                        ast->vga2_clone = false;
                } else {
-                       ast->chip = 2000;
+                       ast->chip = AST2000;
                        DRM_INFO("AST 2000 detected\n");
                }
        }
index 4c761dcea97217e9495ed16a6403250ac04a7ff3..05c01ea8529487c9d37f32cd31237291728c82c9 100644 (file)
@@ -99,6 +99,7 @@ static struct ast_vbios_dclk_info dclk_table[] = {
        {0x25, 0x65, 0x80},                                     /* 16: VCLK88.75    */
        {0x77, 0x58, 0x80},                                     /* 17: VCLK119      */
        {0x32, 0x67, 0x80},                                 /* 18: VCLK85_5     */
+       {0x6a, 0x6d, 0x80},                                     /* 19: VCLK97_75        */
 };
 
 static struct ast_vbios_stdtable vbios_stdtable[] = {
index fa2be249999c70711e1b19cbe0df92fd5e081631..90e773019eac78f0a247f840eb5ada047a0b5573 100644 (file)
@@ -4696,8 +4696,9 @@ int drm_mode_create_dumb_ioctl(struct drm_device *dev,
                return -EINVAL;
 
        /* overflow checks for 32bit size calculations */
+       /* NOTE: DIV_ROUND_UP() can overflow */
        cpp = DIV_ROUND_UP(args->bpp, 8);
-       if (cpp > 0xffffffffU / args->width)
+       if (!cpp || cpp > 0xffffffffU / args->width)
                return -EINVAL;
        stride = cpp * args->width;
        if (args->height > 0xffffffffU / stride)
index 2e7f03ad5ee2e9e84e9de0588ce78d8ad67f86f2..9933c26017edae26a2bab5879e8be0543735c027 100644 (file)
@@ -1336,12 +1336,17 @@ static int i915_load_modeset_init(struct drm_device *dev)
 
        intel_power_domains_init_hw(dev_priv);
 
+       /*
+        * We enable some interrupt sources in our postinstall hooks, so mark
+        * interrupts as enabled _before_ actually enabling them to avoid
+        * special cases in our ordering checks.
+        */
+       dev_priv->pm._irqs_disabled = false;
+
        ret = drm_irq_install(dev, dev->pdev->irq);
        if (ret)
                goto cleanup_gem_stolen;
 
-       dev_priv->pm._irqs_disabled = false;
-
        /* Important: The output setup functions called by modeset_init need
         * working irqs for e.g. gmbus and dp aux transfers. */
        intel_modeset_init(dev);
index 7a830eac5ba30a7859eb65313d9ee567c5d324eb..3524306d8cfbf7b9d7e93b2bd076774eb69b36bc 100644 (file)
@@ -184,6 +184,7 @@ enum hpd_pin {
                if ((1 << (domain)) & (mask))
 
 struct drm_i915_private;
+struct i915_mm_struct;
 struct i915_mmu_object;
 
 enum intel_dpll_id {
@@ -1506,9 +1507,8 @@ struct drm_i915_private {
        struct i915_gtt gtt; /* VM representing the global address space */
 
        struct i915_gem_mm mm;
-#if defined(CONFIG_MMU_NOTIFIER)
-       DECLARE_HASHTABLE(mmu_notifiers, 7);
-#endif
+       DECLARE_HASHTABLE(mm_structs, 7);
+       struct mutex mm_lock;
 
        /* Kernel Modesetting */
 
@@ -1814,8 +1814,8 @@ struct drm_i915_gem_object {
                        unsigned workers :4;
 #define I915_GEM_USERPTR_MAX_WORKERS 15
 
-                       struct mm_struct *mm;
-                       struct i915_mmu_object *mn;
+                       struct i915_mm_struct *mm;
+                       struct i915_mmu_object *mmu_object;
                        struct work_struct *work;
                } userptr;
        };
index ba7f5c6bb50d1f7e5b886ea20e74ed58a9ae5247..ad55b06a3cb1c69754fe60947a183e0af6604e46 100644 (file)
@@ -1590,10 +1590,13 @@ unlock:
 out:
        switch (ret) {
        case -EIO:
-               /* If this -EIO is due to a gpu hang, give the reset code a
-                * chance to clean up the mess. Otherwise return the proper
-                * SIGBUS. */
-               if (i915_terminally_wedged(&dev_priv->gpu_error)) {
+               /*
+                * We eat errors when the gpu is terminally wedged to avoid
+                * userspace unduly crashing (gl has no provisions for mmaps to
+                * fail). But any other -EIO isn't ours (e.g. swap in failure)
+                * and so needs to be reported.
+                */
+               if (!i915_terminally_wedged(&dev_priv->gpu_error)) {
                        ret = VM_FAULT_SIGBUS;
                        break;
                }
index fe69fc837d9ee25f33b3dbd15664c2c33b9ca721..d384139973790e09d2da3583861c7224b1596f44 100644 (file)
 #include <linux/mempolicy.h>
 #include <linux/swap.h>
 
+struct i915_mm_struct {
+       struct mm_struct *mm;
+       struct drm_device *dev;
+       struct i915_mmu_notifier *mn;
+       struct hlist_node node;
+       struct kref kref;
+       struct work_struct work;
+};
+
 #if defined(CONFIG_MMU_NOTIFIER)
 #include <linux/interval_tree.h>
 
@@ -41,16 +50,12 @@ struct i915_mmu_notifier {
        struct mmu_notifier mn;
        struct rb_root objects;
        struct list_head linear;
-       struct drm_device *dev;
-       struct mm_struct *mm;
-       struct work_struct work;
-       unsigned long count;
        unsigned long serial;
        bool has_linear;
 };
 
 struct i915_mmu_object {
-       struct i915_mmu_notifier *mmu;
+       struct i915_mmu_notifier *mn;
        struct interval_tree_node it;
        struct list_head link;
        struct drm_i915_gem_object *obj;
@@ -96,18 +101,18 @@ static void *invalidate_range__linear(struct i915_mmu_notifier *mn,
                                      unsigned long start,
                                      unsigned long end)
 {
-       struct i915_mmu_object *mmu;
+       struct i915_mmu_object *mo;
        unsigned long serial;
 
 restart:
        serial = mn->serial;
-       list_for_each_entry(mmu, &mn->linear, link) {
+       list_for_each_entry(mo, &mn->linear, link) {
                struct drm_i915_gem_object *obj;
 
-               if (mmu->it.last < start || mmu->it.start > end)
+               if (mo->it.last < start || mo->it.start > end)
                        continue;
 
-               obj = mmu->obj;
+               obj = mo->obj;
                drm_gem_object_reference(&obj->base);
                spin_unlock(&mn->lock);
 
@@ -160,130 +165,47 @@ static const struct mmu_notifier_ops i915_gem_userptr_notifier = {
 };
 
 static struct i915_mmu_notifier *
-__i915_mmu_notifier_lookup(struct drm_device *dev, struct mm_struct *mm)
-{
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct i915_mmu_notifier *mmu;
-
-       /* Protected by dev->struct_mutex */
-       hash_for_each_possible(dev_priv->mmu_notifiers, mmu, node, (unsigned long)mm)
-               if (mmu->mm == mm)
-                       return mmu;
-
-       return NULL;
-}
-
-static struct i915_mmu_notifier *
-i915_mmu_notifier_get(struct drm_device *dev, struct mm_struct *mm)
+i915_mmu_notifier_create(struct mm_struct *mm)
 {
-       struct drm_i915_private *dev_priv = to_i915(dev);
-       struct i915_mmu_notifier *mmu;
+       struct i915_mmu_notifier *mn;
        int ret;
 
-       lockdep_assert_held(&dev->struct_mutex);
-
-       mmu = __i915_mmu_notifier_lookup(dev, mm);
-       if (mmu)
-               return mmu;
-
-       mmu = kmalloc(sizeof(*mmu), GFP_KERNEL);
-       if (mmu == NULL)
+       mn = kmalloc(sizeof(*mn), GFP_KERNEL);
+       if (mn == NULL)
                return ERR_PTR(-ENOMEM);
 
-       spin_lock_init(&mmu->lock);
-       mmu->dev = dev;
-       mmu->mn.ops = &i915_gem_userptr_notifier;
-       mmu->mm = mm;
-       mmu->objects = RB_ROOT;
-       mmu->count = 0;
-       mmu->serial = 1;
-       INIT_LIST_HEAD(&mmu->linear);
-       mmu->has_linear = false;
-
-       /* Protected by mmap_sem (write-lock) */
-       ret = __mmu_notifier_register(&mmu->mn, mm);
+       spin_lock_init(&mn->lock);
+       mn->mn.ops = &i915_gem_userptr_notifier;
+       mn->objects = RB_ROOT;
+       mn->serial = 1;
+       INIT_LIST_HEAD(&mn->linear);
+       mn->has_linear = false;
+
+        /* Protected by mmap_sem (write-lock) */
+       ret = __mmu_notifier_register(&mn->mn, mm);
        if (ret) {
-               kfree(mmu);
+               kfree(mn);
                return ERR_PTR(ret);
        }
 
-       /* Protected by dev->struct_mutex */
-       hash_add(dev_priv->mmu_notifiers, &mmu->node, (unsigned long)mm);
-       return mmu;
+       return mn;
 }
 
-static void
-__i915_mmu_notifier_destroy_worker(struct work_struct *work)
+static void __i915_mmu_notifier_update_serial(struct i915_mmu_notifier *mn)
 {
-       struct i915_mmu_notifier *mmu = container_of(work, typeof(*mmu), work);
-       mmu_notifier_unregister(&mmu->mn, mmu->mm);
-       kfree(mmu);
-}
-
-static void
-__i915_mmu_notifier_destroy(struct i915_mmu_notifier *mmu)
-{
-       lockdep_assert_held(&mmu->dev->struct_mutex);
-
-       /* Protected by dev->struct_mutex */
-       hash_del(&mmu->node);
-
-       /* Our lock ordering is: mmap_sem, mmu_notifier_scru, struct_mutex.
-        * We enter the function holding struct_mutex, therefore we need
-        * to drop our mutex prior to calling mmu_notifier_unregister in
-        * order to prevent lock inversion (and system-wide deadlock)
-        * between the mmap_sem and struct-mutex. Hence we defer the
-        * unregistration to a workqueue where we hold no locks.
-        */
-       INIT_WORK(&mmu->work, __i915_mmu_notifier_destroy_worker);
-       schedule_work(&mmu->work);
-}
-
-static void __i915_mmu_notifier_update_serial(struct i915_mmu_notifier *mmu)
-{
-       if (++mmu->serial == 0)
-               mmu->serial = 1;
-}
-
-static bool i915_mmu_notifier_has_linear(struct i915_mmu_notifier *mmu)
-{
-       struct i915_mmu_object *mn;
-
-       list_for_each_entry(mn, &mmu->linear, link)
-               if (mn->is_linear)
-                       return true;
-
-       return false;
-}
-
-static void
-i915_mmu_notifier_del(struct i915_mmu_notifier *mmu,
-                     struct i915_mmu_object *mn)
-{
-       lockdep_assert_held(&mmu->dev->struct_mutex);
-
-       spin_lock(&mmu->lock);
-       list_del(&mn->link);
-       if (mn->is_linear)
-               mmu->has_linear = i915_mmu_notifier_has_linear(mmu);
-       else
-               interval_tree_remove(&mn->it, &mmu->objects);
-       __i915_mmu_notifier_update_serial(mmu);
-       spin_unlock(&mmu->lock);
-
-       /* Protected against _add() by dev->struct_mutex */
-       if (--mmu->count == 0)
-               __i915_mmu_notifier_destroy(mmu);
+       if (++mn->serial == 0)
+               mn->serial = 1;
 }
 
 static int
-i915_mmu_notifier_add(struct i915_mmu_notifier *mmu,
-                     struct i915_mmu_object *mn)
+i915_mmu_notifier_add(struct drm_device *dev,
+                     struct i915_mmu_notifier *mn,
+                     struct i915_mmu_object *mo)
 {
        struct interval_tree_node *it;
        int ret;
 
-       ret = i915_mutex_lock_interruptible(mmu->dev);
+       ret = i915_mutex_lock_interruptible(dev);
        if (ret)
                return ret;
 
@@ -291,11 +213,11 @@ i915_mmu_notifier_add(struct i915_mmu_notifier *mmu,
         * remove the objects from the interval tree) before we do
         * the check for overlapping objects.
         */
-       i915_gem_retire_requests(mmu->dev);
+       i915_gem_retire_requests(dev);
 
-       spin_lock(&mmu->lock);
-       it = interval_tree_iter_first(&mmu->objects,
-                                     mn->it.start, mn->it.last);
+       spin_lock(&mn->lock);
+       it = interval_tree_iter_first(&mn->objects,
+                                     mo->it.start, mo->it.last);
        if (it) {
                struct drm_i915_gem_object *obj;
 
@@ -312,86 +234,122 @@ i915_mmu_notifier_add(struct i915_mmu_notifier *mmu,
 
                obj = container_of(it, struct i915_mmu_object, it)->obj;
                if (!obj->userptr.workers)
-                       mmu->has_linear = mn->is_linear = true;
+                       mn->has_linear = mo->is_linear = true;
                else
                        ret = -EAGAIN;
        } else
-               interval_tree_insert(&mn->it, &mmu->objects);
+               interval_tree_insert(&mo->it, &mn->objects);
 
        if (ret == 0) {
-               list_add(&mn->link, &mmu->linear);
-               __i915_mmu_notifier_update_serial(mmu);
+               list_add(&mo->link, &mn->linear);
+               __i915_mmu_notifier_update_serial(mn);
        }
-       spin_unlock(&mmu->lock);
-       mutex_unlock(&mmu->dev->struct_mutex);
+       spin_unlock(&mn->lock);
+       mutex_unlock(&dev->struct_mutex);
 
        return ret;
 }
 
+static bool i915_mmu_notifier_has_linear(struct i915_mmu_notifier *mn)
+{
+       struct i915_mmu_object *mo;
+
+       list_for_each_entry(mo, &mn->linear, link)
+               if (mo->is_linear)
+                       return true;
+
+       return false;
+}
+
+static void
+i915_mmu_notifier_del(struct i915_mmu_notifier *mn,
+                     struct i915_mmu_object *mo)
+{
+       spin_lock(&mn->lock);
+       list_del(&mo->link);
+       if (mo->is_linear)
+               mn->has_linear = i915_mmu_notifier_has_linear(mn);
+       else
+               interval_tree_remove(&mo->it, &mn->objects);
+       __i915_mmu_notifier_update_serial(mn);
+       spin_unlock(&mn->lock);
+}
+
 static void
 i915_gem_userptr_release__mmu_notifier(struct drm_i915_gem_object *obj)
 {
-       struct i915_mmu_object *mn;
+       struct i915_mmu_object *mo;
 
-       mn = obj->userptr.mn;
-       if (mn == NULL)
+       mo = obj->userptr.mmu_object;
+       if (mo == NULL)
                return;
 
-       i915_mmu_notifier_del(mn->mmu, mn);
-       obj->userptr.mn = NULL;
+       i915_mmu_notifier_del(mo->mn, mo);
+       kfree(mo);
+
+       obj->userptr.mmu_object = NULL;
+}
+
+static struct i915_mmu_notifier *
+i915_mmu_notifier_find(struct i915_mm_struct *mm)
+{
+       if (mm->mn == NULL) {
+               down_write(&mm->mm->mmap_sem);
+               mutex_lock(&to_i915(mm->dev)->mm_lock);
+               if (mm->mn == NULL)
+                       mm->mn = i915_mmu_notifier_create(mm->mm);
+               mutex_unlock(&to_i915(mm->dev)->mm_lock);
+               up_write(&mm->mm->mmap_sem);
+       }
+       return mm->mn;
 }
 
 static int
 i915_gem_userptr_init__mmu_notifier(struct drm_i915_gem_object *obj,
                                    unsigned flags)
 {
-       struct i915_mmu_notifier *mmu;
-       struct i915_mmu_object *mn;
+       struct i915_mmu_notifier *mn;
+       struct i915_mmu_object *mo;
        int ret;
 
        if (flags & I915_USERPTR_UNSYNCHRONIZED)
                return capable(CAP_SYS_ADMIN) ? 0 : -EPERM;
 
-       down_write(&obj->userptr.mm->mmap_sem);
-       ret = i915_mutex_lock_interruptible(obj->base.dev);
-       if (ret == 0) {
-               mmu = i915_mmu_notifier_get(obj->base.dev, obj->userptr.mm);
-               if (!IS_ERR(mmu))
-                       mmu->count++; /* preemptive add to act as a refcount */
-               else
-                       ret = PTR_ERR(mmu);
-               mutex_unlock(&obj->base.dev->struct_mutex);
-       }
-       up_write(&obj->userptr.mm->mmap_sem);
-       if (ret)
-               return ret;
+       if (WARN_ON(obj->userptr.mm == NULL))
+               return -EINVAL;
 
-       mn = kzalloc(sizeof(*mn), GFP_KERNEL);
-       if (mn == NULL) {
-               ret = -ENOMEM;
-               goto destroy_mmu;
-       }
+       mn = i915_mmu_notifier_find(obj->userptr.mm);
+       if (IS_ERR(mn))
+               return PTR_ERR(mn);
 
-       mn->mmu = mmu;
-       mn->it.start = obj->userptr.ptr;
-       mn->it.last = mn->it.start + obj->base.size - 1;
-       mn->obj = obj;
+       mo = kzalloc(sizeof(*mo), GFP_KERNEL);
+       if (mo == NULL)
+               return -ENOMEM;
 
-       ret = i915_mmu_notifier_add(mmu, mn);
-       if (ret)
-               goto free_mn;
+       mo->mn = mn;
+       mo->it.start = obj->userptr.ptr;
+       mo->it.last = mo->it.start + obj->base.size - 1;
+       mo->obj = obj;
 
-       obj->userptr.mn = mn;
+       ret = i915_mmu_notifier_add(obj->base.dev, mn, mo);
+       if (ret) {
+               kfree(mo);
+               return ret;
+       }
+
+       obj->userptr.mmu_object = mo;
        return 0;
+}
+
+static void
+i915_mmu_notifier_free(struct i915_mmu_notifier *mn,
+                      struct mm_struct *mm)
+{
+       if (mn == NULL)
+               return;
 
-free_mn:
+       mmu_notifier_unregister(&mn->mn, mm);
        kfree(mn);
-destroy_mmu:
-       mutex_lock(&obj->base.dev->struct_mutex);
-       if (--mmu->count == 0)
-               __i915_mmu_notifier_destroy(mmu);
-       mutex_unlock(&obj->base.dev->struct_mutex);
-       return ret;
 }
 
 #else
@@ -413,15 +371,114 @@ i915_gem_userptr_init__mmu_notifier(struct drm_i915_gem_object *obj,
 
        return 0;
 }
+
+static void
+i915_mmu_notifier_free(struct i915_mmu_notifier *mn,
+                      struct mm_struct *mm)
+{
+}
+
 #endif
 
+static struct i915_mm_struct *
+__i915_mm_struct_find(struct drm_i915_private *dev_priv, struct mm_struct *real)
+{
+       struct i915_mm_struct *mm;
+
+       /* Protected by dev_priv->mm_lock */
+       hash_for_each_possible(dev_priv->mm_structs, mm, node, (unsigned long)real)
+               if (mm->mm == real)
+                       return mm;
+
+       return NULL;
+}
+
+static int
+i915_gem_userptr_init__mm_struct(struct drm_i915_gem_object *obj)
+{
+       struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
+       struct i915_mm_struct *mm;
+       int ret = 0;
+
+       /* During release of the GEM object we hold the struct_mutex. This
+        * precludes us from calling mmput() at that time as that may be
+        * the last reference and so call exit_mmap(). exit_mmap() will
+        * attempt to reap the vma, and if we were holding a GTT mmap
+        * would then call drm_gem_vm_close() and attempt to reacquire
+        * the struct mutex. So in order to avoid that recursion, we have
+        * to defer releasing the mm reference until after we drop the
+        * struct_mutex, i.e. we need to schedule a worker to do the clean
+        * up.
+        */
+       mutex_lock(&dev_priv->mm_lock);
+       mm = __i915_mm_struct_find(dev_priv, current->mm);
+       if (mm == NULL) {
+               mm = kmalloc(sizeof(*mm), GFP_KERNEL);
+               if (mm == NULL) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+               kref_init(&mm->kref);
+               mm->dev = obj->base.dev;
+
+               mm->mm = current->mm;
+               atomic_inc(&current->mm->mm_count);
+
+               mm->mn = NULL;
+
+               /* Protected by dev_priv->mm_lock */
+               hash_add(dev_priv->mm_structs,
+                        &mm->node, (unsigned long)mm->mm);
+       } else
+               kref_get(&mm->kref);
+
+       obj->userptr.mm = mm;
+out:
+       mutex_unlock(&dev_priv->mm_lock);
+       return ret;
+}
+
+static void
+__i915_mm_struct_free__worker(struct work_struct *work)
+{
+       struct i915_mm_struct *mm = container_of(work, typeof(*mm), work);
+       i915_mmu_notifier_free(mm->mn, mm->mm);
+       mmdrop(mm->mm);
+       kfree(mm);
+}
+
+static void
+__i915_mm_struct_free(struct kref *kref)
+{
+       struct i915_mm_struct *mm = container_of(kref, typeof(*mm), kref);
+
+       /* Protected by dev_priv->mm_lock */
+       hash_del(&mm->node);
+       mutex_unlock(&to_i915(mm->dev)->mm_lock);
+
+       INIT_WORK(&mm->work, __i915_mm_struct_free__worker);
+       schedule_work(&mm->work);
+}
+
+static void
+i915_gem_userptr_release__mm_struct(struct drm_i915_gem_object *obj)
+{
+       if (obj->userptr.mm == NULL)
+               return;
+
+       kref_put_mutex(&obj->userptr.mm->kref,
+                      __i915_mm_struct_free,
+                      &to_i915(obj->base.dev)->mm_lock);
+       obj->userptr.mm = NULL;
+}
+
 struct get_pages_work {
        struct work_struct work;
        struct drm_i915_gem_object *obj;
        struct task_struct *task;
 };
 
-
 #if IS_ENABLED(CONFIG_SWIOTLB)
 #define swiotlb_active() swiotlb_nr_tbl()
 #else
@@ -479,7 +536,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
        if (pvec == NULL)
                pvec = drm_malloc_ab(num_pages, sizeof(struct page *));
        if (pvec != NULL) {
-               struct mm_struct *mm = obj->userptr.mm;
+               struct mm_struct *mm = obj->userptr.mm->mm;
 
                down_read(&mm->mmap_sem);
                while (pinned < num_pages) {
@@ -545,7 +602,7 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
 
        pvec = NULL;
        pinned = 0;
-       if (obj->userptr.mm == current->mm) {
+       if (obj->userptr.mm->mm == current->mm) {
                pvec = kmalloc(num_pages*sizeof(struct page *),
                               GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
                if (pvec == NULL) {
@@ -651,17 +708,13 @@ static void
 i915_gem_userptr_release(struct drm_i915_gem_object *obj)
 {
        i915_gem_userptr_release__mmu_notifier(obj);
-
-       if (obj->userptr.mm) {
-               mmput(obj->userptr.mm);
-               obj->userptr.mm = NULL;
-       }
+       i915_gem_userptr_release__mm_struct(obj);
 }
 
 static int
 i915_gem_userptr_dmabuf_export(struct drm_i915_gem_object *obj)
 {
-       if (obj->userptr.mn)
+       if (obj->userptr.mmu_object)
                return 0;
 
        return i915_gem_userptr_init__mmu_notifier(obj, 0);
@@ -736,7 +789,6 @@ i915_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file
                return -ENODEV;
        }
 
-       /* Allocate the new object */
        obj = i915_gem_object_alloc(dev);
        if (obj == NULL)
                return -ENOMEM;
@@ -754,8 +806,8 @@ i915_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file
         * at binding. This means that we need to hook into the mmu_notifier
         * in order to detect if the mmu is destroyed.
         */
-       ret = -ENOMEM;
-       if ((obj->userptr.mm = get_task_mm(current)))
+       ret = i915_gem_userptr_init__mm_struct(obj);
+       if (ret == 0)
                ret = i915_gem_userptr_init__mmu_notifier(obj, args->flags);
        if (ret == 0)
                ret = drm_gem_handle_create(file, &obj->base, &handle);
@@ -772,9 +824,8 @@ i915_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *file
 int
 i915_gem_init_userptr(struct drm_device *dev)
 {
-#if defined(CONFIG_MMU_NOTIFIER)
        struct drm_i915_private *dev_priv = to_i915(dev);
-       hash_init(dev_priv->mmu_notifiers);
-#endif
+       mutex_init(&dev_priv->mm_lock);
+       hash_init(dev_priv->mm_structs);
        return 0;
 }
index e4d7607da2c482ee6e31576e746de5ca71b6e28a..f29b44c86a2f7354c29dd0ce3ca3a5cfc7ae723c 100644 (file)
 #define GFX_OP_DESTBUFFER_INFO  ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
 #define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
 #define GFX_OP_DRAWRECT_INFO_I965  ((0x7900<<16)|0x2)
-#define SRC_COPY_BLT_CMD                ((2<<29)|(0x43<<22)|4)
+
+#define COLOR_BLT_CMD                  (2<<29 | 0x40<<22 | (5-2))
+#define SRC_COPY_BLT_CMD               ((2<<29)|(0x43<<22)|4)
 #define XY_SRC_COPY_BLT_CMD            ((2<<29)|(0x53<<22)|6)
 #define XY_MONO_SRC_COPY_IMM_BLT       ((2<<29)|(0x71<<22)|5)
-#define XY_SRC_COPY_BLT_WRITE_ALPHA    (1<<21)
-#define XY_SRC_COPY_BLT_WRITE_RGB      (1<<20)
+#define   BLT_WRITE_A                  (2<<20)
+#define   BLT_WRITE_RGB                        (1<<20)
+#define   BLT_WRITE_RGBA               (BLT_WRITE_RGB | BLT_WRITE_A)
 #define   BLT_DEPTH_8                  (0<<24)
 #define   BLT_DEPTH_16_565             (1<<24)
 #define   BLT_DEPTH_16_1555            (2<<24)
 #define   BLT_DEPTH_32                 (3<<24)
-#define   BLT_ROP_GXCOPY               (0xcc<<16)
+#define   BLT_ROP_SRC_COPY             (0xcc<<16)
+#define   BLT_ROP_COLOR_COPY           (0xf0<<16)
 #define XY_SRC_COPY_BLT_SRC_TILED      (1<<15) /* 965+ only */
 #define XY_SRC_COPY_BLT_DST_TILED      (1<<11) /* 965+ only */
 #define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
index a66955037e4e2f30bb9662fed0be12a02d5deaf2..eee79e1c322253165a4c58cff448fa401119abcd 100644 (file)
@@ -1123,7 +1123,7 @@ init_vbt_defaults(struct drm_i915_private *dev_priv)
        }
 }
 
-static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
+static int intel_no_opregion_vbt_callback(const struct dmi_system_id *id)
 {
        DRM_DEBUG_KMS("Falling back to manually reading VBT from "
                      "VBIOS ROM for %s\n",
index e8abfce40976c74a2f9cff93c4d93c897eda112e..9212e6504e0f1a2867ae7913d01cf019107d77b0 100644 (file)
@@ -804,7 +804,7 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = {
        .destroy = intel_encoder_destroy,
 };
 
-static int __init intel_no_crt_dmi_callback(const struct dmi_system_id *id)
+static int intel_no_crt_dmi_callback(const struct dmi_system_id *id)
 {
        DRM_INFO("Skipping CRT initialization for %s\n", id->ident);
        return 1;
index d074d704f458f3b8f81774391d2a6459e416f360..d8324c69fa868de2364cf1b272426f5a634c5c31 100644 (file)
@@ -2233,6 +2233,15 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
        if (need_vtd_wa(dev) && alignment < 256 * 1024)
                alignment = 256 * 1024;
 
+       /*
+        * Global gtt pte registers are special registers which actually forward
+        * writes to a chunk of system memory. Which means that there is no risk
+        * that the register values disappear as soon as we call
+        * intel_runtime_pm_put(), so it is correct to wrap only the
+        * pin/unpin/fence and not more.
+        */
+       intel_runtime_pm_get(dev_priv);
+
        dev_priv->mm.interruptible = false;
        ret = i915_gem_object_pin_to_display_plane(obj, alignment, pipelined);
        if (ret)
@@ -2250,12 +2259,14 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,
        i915_gem_object_pin_fence(obj);
 
        dev_priv->mm.interruptible = true;
+       intel_runtime_pm_put(dev_priv);
        return 0;
 
 err_unpin:
        i915_gem_object_unpin_from_display_plane(obj);
 err_interruptible:
        dev_priv->mm.interruptible = true;
+       intel_runtime_pm_put(dev_priv);
        return ret;
 }
 
@@ -4188,10 +4199,6 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
                intel_set_pch_fifo_underrun_reporting(dev, pipe, false);
 
        intel_disable_pipe(dev_priv, pipe);
-
-       if (intel_crtc->config.dp_encoder_is_mst)
-               intel_ddi_set_vc_payload_alloc(crtc, false);
-
        ironlake_pfit_disable(intel_crtc);
 
        for_each_encoder_on_crtc(dev, crtc, encoder)
@@ -4256,6 +4263,9 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
                intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, false);
        intel_disable_pipe(dev_priv, pipe);
 
+       if (intel_crtc->config.dp_encoder_is_mst)
+               intel_ddi_set_vc_payload_alloc(crtc, false);
+
        intel_ddi_disable_transcoder_func(dev_priv, cpu_transcoder);
 
        ironlake_pfit_disable(intel_crtc);
@@ -8240,6 +8250,15 @@ static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc,
                        goto fail_locked;
                }
 
+               /*
+                * Global gtt pte registers are special registers which actually
+                * forward writes to a chunk of system memory. Which means that
+                * there is no risk that the register values disappear as soon
+                * as we call intel_runtime_pm_put(), so it is correct to wrap
+                * only the pin/unpin/fence and not more.
+                */
+               intel_runtime_pm_get(dev_priv);
+
                /* Note that the w/a also requires 2 PTE of padding following
                 * the bo. We currently fill all unused PTE with the shadow
                 * page and so we should always have valid PTE following the
@@ -8252,16 +8271,20 @@ static int intel_crtc_cursor_set_obj(struct drm_crtc *crtc,
                ret = i915_gem_object_pin_to_display_plane(obj, alignment, NULL);
                if (ret) {
                        DRM_DEBUG_KMS("failed to move cursor bo into the GTT\n");
+                       intel_runtime_pm_put(dev_priv);
                        goto fail_locked;
                }
 
                ret = i915_gem_object_put_fence(obj);
                if (ret) {
                        DRM_DEBUG_KMS("failed to release fence for cursor");
+                       intel_runtime_pm_put(dev_priv);
                        goto fail_unpin;
                }
 
                addr = i915_gem_obj_ggtt_offset(obj);
+
+               intel_runtime_pm_put(dev_priv);
        } else {
                int align = IS_I830(dev) ? 16 * 1024 : 256;
                ret = i915_gem_object_attach_phys(obj, align);
@@ -12481,6 +12504,9 @@ static struct intel_quirk intel_quirks[] = {
        /* Acer C720 and C720P Chromebooks (Celeron 2955U) have backlights */
        { 0x0a06, 0x1025, 0x0a11, quirk_backlight_present },
 
+       /* Acer C720 Chromebook (Core i3 4005U) */
+       { 0x0a16, 0x1025, 0x0a11, quirk_backlight_present },
+
        /* Toshiba CB35 Chromebook (Celeron 2955U) */
        { 0x0a06, 0x1179, 0x0a88, quirk_backlight_present },
 
index 67cfed6d911ae99eae257a67b8e05ea64ba145d1..81d7681faa638f1c7879b5cd0aafb3f56a948adf 100644 (file)
@@ -3661,24 +3661,12 @@ ironlake_dp_detect(struct intel_dp *intel_dp)
        return intel_dp_detect_dpcd(intel_dp);
 }
 
-static enum drm_connector_status
-g4x_dp_detect(struct intel_dp *intel_dp)
+static int g4x_digital_port_connected(struct drm_device *dev,
+                                      struct intel_digital_port *intel_dig_port)
 {
-       struct drm_device *dev = intel_dp_to_dev(intel_dp);
        struct drm_i915_private *dev_priv = dev->dev_private;
-       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
        uint32_t bit;
 
-       /* Can't disconnect eDP, but you can close the lid... */
-       if (is_edp(intel_dp)) {
-               enum drm_connector_status status;
-
-               status = intel_panel_detect(dev);
-               if (status == connector_status_unknown)
-                       status = connector_status_connected;
-               return status;
-       }
-
        if (IS_VALLEYVIEW(dev)) {
                switch (intel_dig_port->port) {
                case PORT_B:
@@ -3691,7 +3679,7 @@ g4x_dp_detect(struct intel_dp *intel_dp)
                        bit = PORTD_HOTPLUG_LIVE_STATUS_VLV;
                        break;
                default:
-                       return connector_status_unknown;
+                       return -EINVAL;
                }
        } else {
                switch (intel_dig_port->port) {
@@ -3705,11 +3693,36 @@ g4x_dp_detect(struct intel_dp *intel_dp)
                        bit = PORTD_HOTPLUG_LIVE_STATUS_G4X;
                        break;
                default:
-                       return connector_status_unknown;
+                       return -EINVAL;
                }
        }
 
        if ((I915_READ(PORT_HOTPLUG_STAT) & bit) == 0)
+               return 0;
+       return 1;
+}
+
+static enum drm_connector_status
+g4x_dp_detect(struct intel_dp *intel_dp)
+{
+       struct drm_device *dev = intel_dp_to_dev(intel_dp);
+       struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+       int ret;
+
+       /* Can't disconnect eDP, but you can close the lid... */
+       if (is_edp(intel_dp)) {
+               enum drm_connector_status status;
+
+               status = intel_panel_detect(dev);
+               if (status == connector_status_unknown)
+                       status = connector_status_connected;
+               return status;
+       }
+
+       ret = g4x_digital_port_connected(dev, intel_dig_port);
+       if (ret == -EINVAL)
+               return connector_status_unknown;
+       else if (ret == 0)
                return connector_status_disconnected;
 
        return intel_dp_detect_dpcd(intel_dp);
@@ -4066,8 +4079,14 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
        intel_display_power_get(dev_priv, power_domain);
 
        if (long_hpd) {
-               if (!ibx_digital_port_connected(dev_priv, intel_dig_port))
-                       goto mst_fail;
+
+               if (HAS_PCH_SPLIT(dev)) {
+                       if (!ibx_digital_port_connected(dev_priv, intel_dig_port))
+                               goto mst_fail;
+               } else {
+                       if (g4x_digital_port_connected(dev, intel_dig_port) != 1)
+                               goto mst_fail;
+               }
 
                if (!intel_dp_get_dpcd(intel_dp)) {
                        goto mst_fail;
index 881361c0f27e746097414a5ddc30448227175602..fdf40267249c1031a4a52a8f110b41fbf93ff61f 100644 (file)
@@ -538,7 +538,7 @@ static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
        .destroy = intel_encoder_destroy,
 };
 
-static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
+static int intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
 {
        DRM_INFO("Skipping LVDS initialization for %s\n", id->ident);
        return 1;
index 59b028f0b1e8c7a652cc174c17373b90a4782077..8e374449c6b562356f47ac2ba169f974f8e7226f 100644 (file)
@@ -801,7 +801,7 @@ static void pch_enable_backlight(struct intel_connector *connector)
 
        cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
        if (cpu_ctl2 & BLM_PWM_ENABLE) {
-               WARN(1, "cpu backlight already enabled\n");
+               DRM_DEBUG_KMS("cpu backlight already enabled\n");
                cpu_ctl2 &= ~BLM_PWM_ENABLE;
                I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
        }
@@ -845,7 +845,7 @@ static void i9xx_enable_backlight(struct intel_connector *connector)
 
        ctl = I915_READ(BLC_PWM_CTL);
        if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) {
-               WARN(1, "backlight already enabled\n");
+               DRM_DEBUG_KMS("backlight already enabled\n");
                I915_WRITE(BLC_PWM_CTL, 0);
        }
 
@@ -876,7 +876,7 @@ static void i965_enable_backlight(struct intel_connector *connector)
 
        ctl2 = I915_READ(BLC_PWM_CTL2);
        if (ctl2 & BLM_PWM_ENABLE) {
-               WARN(1, "backlight already enabled\n");
+               DRM_DEBUG_KMS("backlight already enabled\n");
                ctl2 &= ~BLM_PWM_ENABLE;
                I915_WRITE(BLC_PWM_CTL2, ctl2);
        }
@@ -910,7 +910,7 @@ static void vlv_enable_backlight(struct intel_connector *connector)
 
        ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe));
        if (ctl2 & BLM_PWM_ENABLE) {
-               WARN(1, "backlight already enabled\n");
+               DRM_DEBUG_KMS("backlight already enabled\n");
                ctl2 &= ~BLM_PWM_ENABLE;
                I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
        }
index 16371a444426d190d73b4baddd38cd8abeae66b2..2d068edd1adc41bc8d71cd919a55361de093b19d 100644 (file)
@@ -1363,54 +1363,66 @@ i965_dispatch_execbuffer(struct intel_engine_cs *ring,
 
 /* Just userspace ABI convention to limit the wa batch bo to a resonable size */
 #define I830_BATCH_LIMIT (256*1024)
+#define I830_TLB_ENTRIES (2)
+#define I830_WA_SIZE max(I830_TLB_ENTRIES*4096, I830_BATCH_LIMIT)
 static int
 i830_dispatch_execbuffer(struct intel_engine_cs *ring,
                                u64 offset, u32 len,
                                unsigned flags)
 {
+       u32 cs_offset = ring->scratch.gtt_offset;
        int ret;
 
-       if (flags & I915_DISPATCH_PINNED) {
-               ret = intel_ring_begin(ring, 4);
-               if (ret)
-                       return ret;
+       ret = intel_ring_begin(ring, 6);
+       if (ret)
+               return ret;
 
-               intel_ring_emit(ring, MI_BATCH_BUFFER);
-               intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE));
-               intel_ring_emit(ring, offset + len - 8);
-               intel_ring_emit(ring, MI_NOOP);
-               intel_ring_advance(ring);
-       } else {
-               u32 cs_offset = ring->scratch.gtt_offset;
+       /* Evict the invalid PTE TLBs */
+       intel_ring_emit(ring, COLOR_BLT_CMD | BLT_WRITE_RGBA);
+       intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_COLOR_COPY | 4096);
+       intel_ring_emit(ring, I830_TLB_ENTRIES << 16 | 4); /* load each page */
+       intel_ring_emit(ring, cs_offset);
+       intel_ring_emit(ring, 0xdeadbeef);
+       intel_ring_emit(ring, MI_NOOP);
+       intel_ring_advance(ring);
 
+       if ((flags & I915_DISPATCH_PINNED) == 0) {
                if (len > I830_BATCH_LIMIT)
                        return -ENOSPC;
 
-               ret = intel_ring_begin(ring, 9+3);
+               ret = intel_ring_begin(ring, 6 + 2);
                if (ret)
                        return ret;
-               /* Blit the batch (which has now all relocs applied) to the stable batch
-                * scratch bo area (so that the CS never stumbles over its tlb
-                * invalidation bug) ... */
-               intel_ring_emit(ring, XY_SRC_COPY_BLT_CMD |
-                               XY_SRC_COPY_BLT_WRITE_ALPHA |
-                               XY_SRC_COPY_BLT_WRITE_RGB);
-               intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_GXCOPY | 4096);
-               intel_ring_emit(ring, 0);
-               intel_ring_emit(ring, (DIV_ROUND_UP(len, 4096) << 16) | 1024);
+
+               /* Blit the batch (which has now all relocs applied) to the
+                * stable batch scratch bo area (so that the CS never
+                * stumbles over its tlb invalidation bug) ...
+                */
+               intel_ring_emit(ring, SRC_COPY_BLT_CMD | BLT_WRITE_RGBA);
+               intel_ring_emit(ring, BLT_DEPTH_32 | BLT_ROP_SRC_COPY | 4096);
+               intel_ring_emit(ring, DIV_ROUND_UP(len, 4096) << 16 | 1024);
                intel_ring_emit(ring, cs_offset);
-               intel_ring_emit(ring, 0);
                intel_ring_emit(ring, 4096);
                intel_ring_emit(ring, offset);
+
                intel_ring_emit(ring, MI_FLUSH);
+               intel_ring_emit(ring, MI_NOOP);
+               intel_ring_advance(ring);
 
                /* ... and execute it. */
-               intel_ring_emit(ring, MI_BATCH_BUFFER);
-               intel_ring_emit(ring, cs_offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE));
-               intel_ring_emit(ring, cs_offset + len - 8);
-               intel_ring_advance(ring);
+               offset = cs_offset;
        }
 
+       ret = intel_ring_begin(ring, 4);
+       if (ret)
+               return ret;
+
+       intel_ring_emit(ring, MI_BATCH_BUFFER);
+       intel_ring_emit(ring, offset | (flags & I915_DISPATCH_SECURE ? 0 : MI_BATCH_NON_SECURE));
+       intel_ring_emit(ring, offset + len - 8);
+       intel_ring_emit(ring, MI_NOOP);
+       intel_ring_advance(ring);
+
        return 0;
 }
 
@@ -2200,7 +2212,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
 
        /* Workaround batchbuffer to combat CS tlb bug. */
        if (HAS_BROKEN_CS_TLB(dev)) {
-               obj = i915_gem_alloc_object(dev, I830_BATCH_LIMIT);
+               obj = i915_gem_alloc_object(dev, I830_WA_SIZE);
                if (obj == NULL) {
                        DRM_ERROR("Failed to allocate batch bo\n");
                        return -ENOMEM;
index 32186a656816e1e4de4c533cbf699e9886dda2d8..c14341ca3ef9386a0be1b432206f00c15ddae09b 100644 (file)
@@ -854,6 +854,10 @@ intel_enable_tv(struct intel_encoder *encoder)
        struct drm_device *dev = encoder->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
 
+       /* Prevents vblank waits from timing out in intel_tv_detect_type() */
+       intel_wait_for_vblank(encoder->base.dev,
+                             to_intel_crtc(encoder->base.crtc)->pipe);
+
        I915_WRITE(TV_CTL, I915_READ(TV_CTL) | TV_ENC_ENABLE);
 }
 
@@ -1311,6 +1315,7 @@ intel_tv_detect(struct drm_connector *connector, bool force)
 {
        struct drm_display_mode mode;
        struct intel_tv *intel_tv = intel_attached_tv(connector);
+       enum drm_connector_status status;
        int type;
 
        DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n",
@@ -1328,16 +1333,19 @@ intel_tv_detect(struct drm_connector *connector, bool force)
                if (intel_get_load_detect_pipe(connector, &mode, &tmp, &ctx)) {
                        type = intel_tv_detect_type(intel_tv, connector);
                        intel_release_load_detect_pipe(connector, &tmp);
+                       status = type < 0 ?
+                               connector_status_disconnected :
+                               connector_status_connected;
                } else
-                       return connector_status_unknown;
+                       status = connector_status_unknown;
 
                drm_modeset_drop_locks(&ctx);
                drm_modeset_acquire_fini(&ctx);
        } else
                return connector->status;
 
-       if (type < 0)
-               return connector_status_disconnected;
+       if (status != connector_status_connected)
+               return status;
 
        intel_tv->type = type;
        intel_tv_find_better_format(connector);
index a125a7e32742c3707bb3e0446a4fdd8f64fffd3e..c6c9b02e0ada9f052249a556a9e2169aa967b91d 100644 (file)
@@ -258,28 +258,30 @@ static void set_hdmi_pdev(struct drm_device *dev,
        priv->hdmi_pdev = pdev;
 }
 
+#ifdef CONFIG_OF
+static int get_gpio(struct device *dev, struct device_node *of_node, const char *name)
+{
+       int gpio = of_get_named_gpio(of_node, name, 0);
+       if (gpio < 0) {
+               char name2[32];
+               snprintf(name2, sizeof(name2), "%s-gpio", name);
+               gpio = of_get_named_gpio(of_node, name2, 0);
+               if (gpio < 0) {
+                       dev_err(dev, "failed to get gpio: %s (%d)\n",
+                                       name, gpio);
+                       gpio = -1;
+               }
+       }
+       return gpio;
+}
+#endif
+
 static int hdmi_bind(struct device *dev, struct device *master, void *data)
 {
        static struct hdmi_platform_config config = {};
 #ifdef CONFIG_OF
        struct device_node *of_node = dev->of_node;
 
-       int get_gpio(const char *name)
-       {
-               int gpio = of_get_named_gpio(of_node, name, 0);
-               if (gpio < 0) {
-                       char name2[32];
-                       snprintf(name2, sizeof(name2), "%s-gpio", name);
-                       gpio = of_get_named_gpio(of_node, name2, 0);
-                       if (gpio < 0) {
-                               dev_err(dev, "failed to get gpio: %s (%d)\n",
-                                               name, gpio);
-                               gpio = -1;
-                       }
-               }
-               return gpio;
-       }
-
        if (of_device_is_compatible(of_node, "qcom,hdmi-tx-8074")) {
                static const char *hpd_reg_names[] = {"hpd-gdsc", "hpd-5v"};
                static const char *pwr_reg_names[] = {"core-vdda", "core-vcc"};
@@ -312,12 +314,12 @@ static int hdmi_bind(struct device *dev, struct device *master, void *data)
        }
 
        config.mmio_name     = "core_physical";
-       config.ddc_clk_gpio  = get_gpio("qcom,hdmi-tx-ddc-clk");
-       config.ddc_data_gpio = get_gpio("qcom,hdmi-tx-ddc-data");
-       config.hpd_gpio      = get_gpio("qcom,hdmi-tx-hpd");
-       config.mux_en_gpio   = get_gpio("qcom,hdmi-tx-mux-en");
-       config.mux_sel_gpio  = get_gpio("qcom,hdmi-tx-mux-sel");
-       config.mux_lpm_gpio  = get_gpio("qcom,hdmi-tx-mux-lpm");
+       config.ddc_clk_gpio  = get_gpio(dev, of_node, "qcom,hdmi-tx-ddc-clk");
+       config.ddc_data_gpio = get_gpio(dev, of_node, "qcom,hdmi-tx-ddc-data");
+       config.hpd_gpio      = get_gpio(dev, of_node, "qcom,hdmi-tx-hpd");
+       config.mux_en_gpio   = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-en");
+       config.mux_sel_gpio  = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-sel");
+       config.mux_lpm_gpio  = get_gpio(dev, of_node, "qcom,hdmi-tx-mux-lpm");
 
 #else
        static const char *hpd_clk_names[] = {
index 902d7685d441f7dca81096626fc6f047f29ca218..f408b69486a8eb83d299abc636356187d2d467bb 100644 (file)
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#ifdef CONFIG_COMMON_CLK
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#endif
 
 #include "hdmi.h"
 
 struct hdmi_phy_8960 {
        struct hdmi_phy base;
        struct hdmi *hdmi;
+#ifdef CONFIG_COMMON_CLK
        struct clk_hw pll_hw;
        struct clk *pll;
        unsigned long pixclk;
+#endif
 };
 #define to_hdmi_phy_8960(x) container_of(x, struct hdmi_phy_8960, base)
+
+#ifdef CONFIG_COMMON_CLK
 #define clk_to_phy(x) container_of(x, struct hdmi_phy_8960, pll_hw)
 
 /*
@@ -374,7 +380,7 @@ static struct clk_init_data pll_init = {
        .parent_names = hdmi_pll_parents,
        .num_parents = ARRAY_SIZE(hdmi_pll_parents),
 };
-
+#endif
 
 /*
  * HDMI Phy:
@@ -480,12 +486,15 @@ struct hdmi_phy *hdmi_phy_8960_init(struct hdmi *hdmi)
 {
        struct hdmi_phy_8960 *phy_8960;
        struct hdmi_phy *phy = NULL;
-       int ret, i;
+       int ret;
+#ifdef CONFIG_COMMON_CLK
+       int i;
 
        /* sanity check: */
        for (i = 0; i < (ARRAY_SIZE(freqtbl) - 1); i++)
                if (WARN_ON(freqtbl[i].rate < freqtbl[i+1].rate))
                        return ERR_PTR(-EINVAL);
+#endif
 
        phy_8960 = kzalloc(sizeof(*phy_8960), GFP_KERNEL);
        if (!phy_8960) {
@@ -499,6 +508,7 @@ struct hdmi_phy *hdmi_phy_8960_init(struct hdmi *hdmi)
 
        phy_8960->hdmi = hdmi;
 
+#ifdef CONFIG_COMMON_CLK
        phy_8960->pll_hw.init = &pll_init;
        phy_8960->pll = devm_clk_register(hdmi->dev->dev, &phy_8960->pll_hw);
        if (IS_ERR(phy_8960->pll)) {
@@ -506,6 +516,7 @@ struct hdmi_phy *hdmi_phy_8960_init(struct hdmi *hdmi)
                phy_8960->pll = NULL;
                goto fail;
        }
+#endif
 
        return phy;
 
index 74cebb51e8c285e23475c6df40ae64a271857b9f..c6c80ea28c35809dbe63bb22aec0a50da9f4d0c6 100644 (file)
@@ -397,6 +397,7 @@ static void mdp4_crtc_prepare(struct drm_crtc *crtc)
        struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
        DBG("%s", mdp4_crtc->name);
        /* make sure we hold a ref to mdp clks while setting up mode: */
+       drm_crtc_vblank_get(crtc);
        mdp4_enable(get_kms(crtc));
        mdp4_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
 }
@@ -407,6 +408,7 @@ static void mdp4_crtc_commit(struct drm_crtc *crtc)
        crtc_flush(crtc);
        /* drop the ref to mdp clk's that we got in prepare: */
        mdp4_disable(get_kms(crtc));
+       drm_crtc_vblank_put(crtc);
 }
 
 static int mdp4_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
index b447c01ad89c86c909b92679444843989df22c9e..fcf95680413d5da99c86fed5a44c9c6386ba3350 100644 (file)
@@ -52,7 +52,7 @@ module_param(reglog, bool, 0600);
 #define reglog 0
 #endif
 
-static char *vram;
+static char *vram = "16m";
 MODULE_PARM_DESC(vram, "Configure VRAM size (for devices without IOMMU/GPUMMU");
 module_param(vram, charp, 0);
 
@@ -974,12 +974,11 @@ static int msm_pdev_probe(struct platform_device *pdev)
 
        for (i = 0; i < ARRAY_SIZE(devnames); i++) {
                struct device *dev;
-               int ret;
 
                dev = bus_find_device_by_name(&platform_bus_type,
                                NULL, devnames[i]);
                if (!dev) {
-                       dev_info(master, "still waiting for %s\n", devnames[i]);
+                       dev_info(&pdev->dev, "still waiting for %s\n", devnames[i]);
                        return -EPROBE_DEFER;
                }
 
index 9c5221ce391ab063cac34ebce428e46939828649..ab5bfd2d0ebf2e29897fa56e1df2c77c0f47aeb8 100644 (file)
@@ -143,7 +143,7 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
        ret = msm_gem_get_iova_locked(fbdev->bo, 0, &paddr);
        if (ret) {
                dev_err(dev->dev, "failed to get buffer obj iova: %d\n", ret);
-               goto fail;
+               goto fail_unlock;
        }
 
        fbi = framebuffer_alloc(0, dev->dev);
index 099af483fdf0328925b23be1fc9c635a5c4c63ba..7acdaa5688b77e89f3afa786da19903d0d0c7b6d 100644 (file)
@@ -27,8 +27,8 @@ struct msm_iommu {
 static int msm_fault_handler(struct iommu_domain *iommu, struct device *dev,
                unsigned long iova, int flags, void *arg)
 {
-       DBG("*** fault: iova=%08lx, flags=%d", iova, flags);
-       return -ENOSYS;
+       pr_warn_ratelimited("*** fault: iova=%08lx, flags=%d\n", iova, flags);
+       return 0;
 }
 
 static int msm_iommu_attach(struct msm_mmu *mmu, const char **names, int cnt)
index 8701968a9743aa7540cdfc0759919c058a45a3fa..30a2911878f893fce40885f2aeb6d8b6bf4d60a3 100644 (file)
@@ -86,7 +86,7 @@ nouveau_parent_lclass(struct nouveau_object *parent, u32 *lclass, int size)
        sclass = nv_parent(parent)->sclass;
        while (sclass) {
                if (++nr < size)
-                       lclass[nr] = sclass->oclass->handle;
+                       lclass[nr] = sclass->oclass->handle & 0xffff;
                sclass = sclass->sclass;
        }
 
@@ -96,7 +96,7 @@ nouveau_parent_lclass(struct nouveau_object *parent, u32 *lclass, int size)
                if (engine && (oclass = engine->sclass)) {
                        while (oclass->ofuncs) {
                                if (++nr < size)
-                                       lclass[nr] = oclass->handle;
+                                       lclass[nr] = oclass->handle & 0xffff;
                                oclass++;
                        }
                }
index b1e11f8434e28badd30572219b1d095a6a06adc4..ac14b67621d36f7a068de85103e06ba644915ea3 100644 (file)
@@ -405,16 +405,13 @@ bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector)
        u8 msg[DP_DPCD_SIZE];
        int ret;
 
-       char dpcd_hex_dump[DP_DPCD_SIZE * 3];
-
        ret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_DPCD_REV, msg,
                               DP_DPCD_SIZE);
        if (ret > 0) {
                memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE);
 
-               hex_dump_to_buffer(dig_connector->dpcd, sizeof(dig_connector->dpcd),
-                                  32, 1, dpcd_hex_dump, sizeof(dpcd_hex_dump), false);
-               DRM_DEBUG_KMS("DPCD: %s\n", dpcd_hex_dump);
+               DRM_DEBUG_KMS("DPCD: %*ph\n", (int)sizeof(dig_connector->dpcd),
+                             dig_connector->dpcd);
 
                radeon_dp_probe_oui(radeon_connector);
 
index 79a5a5519bd67131233508b99d0f11add8b48240..fa9565957f9d4516ab801e645b5ac2153db535ad 100644 (file)
@@ -5749,20 +5749,17 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev)
        WREG32(0x15D8, 0);
        WREG32(0x15DC, 0);
 
-       /* empty context1-15 */
-       /* FIXME start with 4G, once using 2 level pt switch to full
-        * vm size space
-        */
+       /* restore context1-15 */
        /* set vm size, must be a multiple of 4 */
        WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0);
        WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn);
        for (i = 1; i < 16; i++) {
                if (i < 8)
                        WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2),
-                              rdev->gart.table_addr >> 12);
+                              rdev->vm_manager.saved_table_addr[i]);
                else
                        WREG32(VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((i - 8) << 2),
-                              rdev->gart.table_addr >> 12);
+                              rdev->vm_manager.saved_table_addr[i]);
        }
 
        /* enable context1-15 */
@@ -5827,6 +5824,17 @@ static int cik_pcie_gart_enable(struct radeon_device *rdev)
  */
 static void cik_pcie_gart_disable(struct radeon_device *rdev)
 {
+       unsigned i;
+
+       for (i = 1; i < 16; ++i) {
+               uint32_t reg;
+               if (i < 8)
+                       reg = VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2);
+               else
+                       reg = VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((i - 8) << 2);
+               rdev->vm_manager.saved_table_addr[i] = RREG32(reg);
+       }
+
        /* Disable all tables */
        WREG32(VM_CONTEXT0_CNTL, 0);
        WREG32(VM_CONTEXT1_CNTL, 0);
@@ -9555,6 +9563,9 @@ static void cik_pcie_gen3_enable(struct radeon_device *rdev)
        int ret, i;
        u16 tmp16;
 
+       if (pci_is_root_bus(rdev->pdev->bus))
+               return;
+
        if (radeon_pcie_gen2 == 0)
                return;
 
@@ -9781,7 +9792,8 @@ static void cik_program_aspm(struct radeon_device *rdev)
                        if (orig != data)
                                WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, data);
 
-                       if (!disable_clkreq) {
+                       if (!disable_clkreq &&
+                           !pci_is_root_bus(rdev->pdev->bus)) {
                                struct pci_dev *root = rdev->pdev->bus->self;
                                u32 lnkcap;
 
index ba89375f197f9146ddd62cd64368075bb7fc9113..3faee58946dd0027b67d5d835af50f8de899ec93 100644 (file)
@@ -1271,7 +1271,7 @@ static int cayman_pcie_gart_enable(struct radeon_device *rdev)
                WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (i << 2), 0);
                WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), rdev->vm_manager.max_pfn);
                WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2),
-                       rdev->gart.table_addr >> 12);
+                      rdev->vm_manager.saved_table_addr[i]);
        }
 
        /* enable context1-7 */
@@ -1303,6 +1303,13 @@ static int cayman_pcie_gart_enable(struct radeon_device *rdev)
 
 static void cayman_pcie_gart_disable(struct radeon_device *rdev)
 {
+       unsigned i;
+
+       for (i = 1; i < 8; ++i) {
+               rdev->vm_manager.saved_table_addr[i] = RREG32(
+                       VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2));
+       }
+
        /* Disable all tables */
        WREG32(VM_CONTEXT0_CNTL, 0);
        WREG32(VM_CONTEXT1_CNTL, 0);
index e8bf0ea2dadebe7c74069e1cfe0a25d9e82f63e6..3cfb50056f7ac75ec27f1ef3f8bfc09218c2f152 100644 (file)
@@ -1812,7 +1812,6 @@ static void r600_gpu_init(struct radeon_device *rdev)
 {
        u32 tiling_config;
        u32 ramcfg;
-       u32 cc_rb_backend_disable;
        u32 cc_gc_shader_pipe_config;
        u32 tmp;
        int i, j;
@@ -1939,29 +1938,20 @@ static void r600_gpu_init(struct radeon_device *rdev)
        }
        tiling_config |= BANK_SWAPS(1);
 
-       cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000;
-       tmp = R6XX_MAX_BACKENDS -
-               r600_count_pipe_bits((cc_rb_backend_disable >> 16) & R6XX_MAX_BACKENDS_MASK);
-       if (tmp < rdev->config.r600.max_backends) {
-               rdev->config.r600.max_backends = tmp;
-       }
-
        cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0x00ffff00;
-       tmp = R6XX_MAX_PIPES -
-               r600_count_pipe_bits((cc_gc_shader_pipe_config >> 8) & R6XX_MAX_PIPES_MASK);
-       if (tmp < rdev->config.r600.max_pipes) {
-               rdev->config.r600.max_pipes = tmp;
-       }
-       tmp = R6XX_MAX_SIMDS -
-               r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R6XX_MAX_SIMDS_MASK);
-       if (tmp < rdev->config.r600.max_simds) {
-               rdev->config.r600.max_simds = tmp;
-       }
        tmp = rdev->config.r600.max_simds -
                r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R6XX_MAX_SIMDS_MASK);
        rdev->config.r600.active_simds = tmp;
 
        disabled_rb_mask = (RREG32(CC_RB_BACKEND_DISABLE) >> 16) & R6XX_MAX_BACKENDS_MASK;
+       tmp = 0;
+       for (i = 0; i < rdev->config.r600.max_backends; i++)
+               tmp |= (1 << i);
+       /* if all the backends are disabled, fix it up here */
+       if ((disabled_rb_mask & tmp) == tmp) {
+               for (i = 0; i < rdev->config.r600.max_backends; i++)
+                       disabled_rb_mask &= ~(1 << i);
+       }
        tmp = (tiling_config & PIPE_TILING__MASK) >> PIPE_TILING__SHIFT;
        tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.r600.max_backends,
                                        R6XX_MAX_BACKENDS, disabled_rb_mask);
@@ -2779,8 +2769,8 @@ bool r600_semaphore_ring_emit(struct radeon_device *rdev,
        radeon_ring_write(ring, lower_32_bits(addr));
        radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | sel);
 
-       /* PFP_SYNC_ME packet only exists on 7xx+ */
-       if (emit_wait && (rdev->family >= CHIP_RV770)) {
+       /* PFP_SYNC_ME packet only exists on 7xx+, only enable it on eg+ */
+       if (emit_wait && (rdev->family >= CHIP_CEDAR)) {
                /* Prevent the PFP from running ahead of the semaphore wait */
                radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
                radeon_ring_write(ring, 0x0);
index b281886f6f5194609caab9bddb632eadea191004..5f05b4c8433807bf26a1b0ef80fd31a2c25d9a36 100644 (file)
@@ -915,6 +915,8 @@ struct radeon_vm_manager {
        u64                             vram_base_offset;
        /* is vm enabled? */
        bool                            enabled;
+       /* for hw to save the PD addr on suspend/resume */
+       uint32_t                        saved_table_addr[RADEON_NUM_VM];
 };
 
 /*
index 92b2d8dd47355f7f7b601025082868d3e29e60be..e74c7e387ddebfbb74d32866b39d2046d2632540 100644 (file)
@@ -447,6 +447,13 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
                }
        }
 
+       /* Fujitsu D3003-S2 board lists DVI-I as DVI-I and VGA */
+       if ((dev->pdev->device == 0x9805) &&
+           (dev->pdev->subsystem_vendor == 0x1734) &&
+           (dev->pdev->subsystem_device == 0x11bd)) {
+               if (*connector_type == DRM_MODE_CONNECTOR_VGA)
+                       return false;
+       }
 
        return true;
 }
@@ -2281,19 +2288,31 @@ static void radeon_atombios_add_pplib_thermal_controller(struct radeon_device *r
                                 (controller->ucFanParameters &
                                  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
                        rdev->pm.int_thermal_type = THERMAL_TYPE_KV;
-               } else if ((controller->ucType ==
-                           ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) ||
-                          (controller->ucType ==
-                           ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) ||
-                          (controller->ucType ==
-                           ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL)) {
-                       DRM_INFO("Special thermal controller config\n");
+               } else if (controller->ucType ==
+                          ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) {
+                       DRM_INFO("External GPIO thermal controller %s fan control\n",
+                                (controller->ucFanParameters &
+                                 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
+                       rdev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL_GPIO;
+               } else if (controller->ucType ==
+                          ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) {
+                       DRM_INFO("ADT7473 with internal thermal controller %s fan control\n",
+                                (controller->ucFanParameters &
+                                 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
+                       rdev->pm.int_thermal_type = THERMAL_TYPE_ADT7473_WITH_INTERNAL;
+               } else if (controller->ucType ==
+                          ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) {
+                       DRM_INFO("EMC2103 with internal thermal controller %s fan control\n",
+                                (controller->ucFanParameters &
+                                 ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
+                       rdev->pm.int_thermal_type = THERMAL_TYPE_EMC2103_WITH_INTERNAL;
                } else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) {
                        DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n",
                                 pp_lib_thermal_controller_names[controller->ucType],
                                 controller->ucI2cAddress >> 1,
                                 (controller->ucFanParameters &
                                  ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with");
+                       rdev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL;
                        i2c_bus = radeon_lookup_i2c_gpio(rdev, controller->ucI2cLine);
                        rdev->pm.i2c_bus = radeon_i2c_lookup(rdev, &i2c_bus);
                        if (rdev->pm.i2c_bus) {
index 56d9fd66d8aed379c417d1ba4a47de7aa65ba472..abd6753a570afa119ac1e68255231c99f7b27995 100644 (file)
@@ -34,7 +34,7 @@
 int radeon_semaphore_create(struct radeon_device *rdev,
                            struct radeon_semaphore **semaphore)
 {
-       uint32_t *cpu_addr;
+       uint64_t *cpu_addr;
        int i, r;
 
        *semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL);
index 2983f17ea1b38399ab649dbb965cae291e6d9b82..d9f5ce715c9bfe5ff18be2a428809c1b7b217c58 100644 (file)
@@ -1177,7 +1177,6 @@ static void rv770_gpu_init(struct radeon_device *rdev)
        u32 hdp_host_path_cntl;
        u32 sq_dyn_gpr_size_simd_ab_0;
        u32 gb_tiling_config = 0;
-       u32 cc_rb_backend_disable = 0;
        u32 cc_gc_shader_pipe_config = 0;
        u32 mc_arb_ramcfg;
        u32 db_debug4, tmp;
@@ -1311,21 +1310,7 @@ static void rv770_gpu_init(struct radeon_device *rdev)
                WREG32(SPI_CONFIG_CNTL, 0);
        }
 
-       cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000;
-       tmp = R7XX_MAX_BACKENDS - r600_count_pipe_bits(cc_rb_backend_disable >> 16);
-       if (tmp < rdev->config.rv770.max_backends) {
-               rdev->config.rv770.max_backends = tmp;
-       }
-
        cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00;
-       tmp = R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 8) & R7XX_MAX_PIPES_MASK);
-       if (tmp < rdev->config.rv770.max_pipes) {
-               rdev->config.rv770.max_pipes = tmp;
-       }
-       tmp = R7XX_MAX_SIMDS - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R7XX_MAX_SIMDS_MASK);
-       if (tmp < rdev->config.rv770.max_simds) {
-               rdev->config.rv770.max_simds = tmp;
-       }
        tmp = rdev->config.rv770.max_simds -
                r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R7XX_MAX_SIMDS_MASK);
        rdev->config.rv770.active_simds = tmp;
@@ -1348,6 +1333,14 @@ static void rv770_gpu_init(struct radeon_device *rdev)
        rdev->config.rv770.tiling_npipes = rdev->config.rv770.max_tile_pipes;
 
        disabled_rb_mask = (RREG32(CC_RB_BACKEND_DISABLE) >> 16) & R7XX_MAX_BACKENDS_MASK;
+       tmp = 0;
+       for (i = 0; i < rdev->config.rv770.max_backends; i++)
+               tmp |= (1 << i);
+       /* if all the backends are disabled, fix it up here */
+       if ((disabled_rb_mask & tmp) == tmp) {
+               for (i = 0; i < rdev->config.rv770.max_backends; i++)
+                       disabled_rb_mask &= ~(1 << i);
+       }
        tmp = (gb_tiling_config & PIPE_TILING__MASK) >> PIPE_TILING__SHIFT;
        tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.rv770.max_backends,
                                        R7XX_MAX_BACKENDS, disabled_rb_mask);
index a1274a31405c0a207aea2708f28bacbad96d91f4..6bce40847753b822f50be6037654c863833af068 100644 (file)
@@ -4290,10 +4290,10 @@ static int si_pcie_gart_enable(struct radeon_device *rdev)
        for (i = 1; i < 16; i++) {
                if (i < 8)
                        WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2),
-                              rdev->gart.table_addr >> 12);
+                              rdev->vm_manager.saved_table_addr[i]);
                else
                        WREG32(VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((i - 8) << 2),
-                              rdev->gart.table_addr >> 12);
+                              rdev->vm_manager.saved_table_addr[i]);
        }
 
        /* enable context1-15 */
@@ -4325,6 +4325,17 @@ static int si_pcie_gart_enable(struct radeon_device *rdev)
 
 static void si_pcie_gart_disable(struct radeon_device *rdev)
 {
+       unsigned i;
+
+       for (i = 1; i < 16; ++i) {
+               uint32_t reg;
+               if (i < 8)
+                       reg = VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2);
+               else
+                       reg = VM_CONTEXT8_PAGE_TABLE_BASE_ADDR + ((i - 8) << 2);
+               rdev->vm_manager.saved_table_addr[i] = RREG32(reg);
+       }
+
        /* Disable all tables */
        WREG32(VM_CONTEXT0_CNTL, 0);
        WREG32(VM_CONTEXT1_CNTL, 0);
@@ -7177,6 +7188,9 @@ static void si_pcie_gen3_enable(struct radeon_device *rdev)
        int ret, i;
        u16 tmp16;
 
+       if (pci_is_root_bus(rdev->pdev->bus))
+               return;
+
        if (radeon_pcie_gen2 == 0)
                return;
 
@@ -7454,7 +7468,8 @@ static void si_program_aspm(struct radeon_device *rdev)
                        if (orig != data)
                                WREG32_PIF_PHY1(PB1_PIF_CNTL, data);
 
-                       if (!disable_clkreq) {
+                       if (!disable_clkreq &&
+                           !pci_is_root_bus(rdev->pdev->bus)) {
                                struct pci_dev *root = rdev->pdev->bus->self;
                                u32 lnkcap;
 
index 2d9d4252d59867a3aef9ffba5552d7fb3d79e242..ae8850f3e63bc4669e796650a1b76a9e9ff21a9f 100644 (file)
@@ -1,6 +1,7 @@
 config DRM_STI
        tristate "DRM Support for STMicroelectronics SoC stiH41x Series"
        depends on DRM && (SOC_STIH415 || SOC_STIH416 || ARCH_MULTIPLATFORM)
+       select RESET_CONTROLLER
        select DRM_KMS_HELPER
        select DRM_GEM_CMA_HELPER
        select DRM_KMS_CMA_HELPER
index a7cc24917a96c39d9179e55744703171142c3bf5..223d93c3a05d8d7241ad05b669562d0a160af4fa 100644 (file)
@@ -201,8 +201,8 @@ static int sti_drm_platform_probe(struct platform_device *pdev)
        master = platform_device_register_resndata(dev,
                        DRIVER_NAME "__master", -1,
                        NULL, 0, NULL, 0);
-       if (!master)
-               return -EINVAL;
+       if (IS_ERR(master))
+               return PTR_ERR(master);
 
        platform_set_drvdata(pdev, master);
        return 0;
index 72d957f81c057790ad504d2cc626ee6cf08fd721..2ae9a9b7366660632f1745a1dce3e60cf7f03532 100644 (file)
@@ -730,16 +730,16 @@ static int sti_hda_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
        hda->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
-       if (IS_ERR(hda->regs))
-               return PTR_ERR(hda->regs);
+       if (!hda->regs)
+               return -ENOMEM;
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
                        "video-dacs-ctrl");
        if (res) {
                hda->video_dacs_ctrl = devm_ioremap_nocache(dev, res->start,
                                resource_size(res));
-               if (IS_ERR(hda->video_dacs_ctrl))
-                       return PTR_ERR(hda->video_dacs_ctrl);
+               if (!hda->video_dacs_ctrl)
+                       return -ENOMEM;
        } else {
                /* If no existing video-dacs-ctrl resource continue the probe */
                DRM_DEBUG_DRIVER("No video-dacs-ctrl resource\n");
@@ -770,7 +770,7 @@ static int sti_hda_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id hda_of_match[] = {
+static const struct of_device_id hda_of_match[] = {
        { .compatible = "st,stih416-hda", },
        { .compatible = "st,stih407-hda", },
        { /* end node */ }
index 284e541d970d8a1ec2213d2479f3d0f7c29176f7..ef93156a69c6fdad9dd2af368ef68e8ecd9a9b9a 100644 (file)
@@ -677,7 +677,7 @@ static const struct component_ops sti_hdmi_ops = {
        .unbind = sti_hdmi_unbind,
 };
 
-static struct of_device_id hdmi_of_match[] = {
+static const struct of_device_id hdmi_of_match[] = {
        {
                .compatible = "st,stih416-hdmi",
                .data = &tx3g0c55phy_ops,
@@ -713,8 +713,8 @@ static int sti_hdmi_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
        hdmi->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
-       if (IS_ERR(hdmi->regs))
-               return PTR_ERR(hdmi->regs);
+       if (!hdmi->regs)
+               return -ENOMEM;
 
        if (of_device_is_compatible(np, "st,stih416-hdmi")) {
                res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
@@ -725,8 +725,8 @@ static int sti_hdmi_probe(struct platform_device *pdev)
                }
                hdmi->syscfg = devm_ioremap_nocache(dev, res->start,
                                                    resource_size(res));
-               if (IS_ERR(hdmi->syscfg))
-                       return PTR_ERR(hdmi->syscfg);
+               if (!hdmi->syscfg)
+                       return -ENOMEM;
 
        }
 
index b69e26fee76e0736af3062053e25b41cd47979f9..b8afe490356aedf09bb361d295764020dfff5eac 100644 (file)
@@ -591,8 +591,8 @@ static int sti_tvout_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
        tvout->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
-       if (IS_ERR(tvout->regs))
-               return PTR_ERR(tvout->regs);
+       if (!tvout->regs)
+               return -ENOMEM;
 
        /* get reset resources */
        tvout->reset = devm_reset_control_get(dev, "tvout");
@@ -624,7 +624,7 @@ static int sti_tvout_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id tvout_of_match[] = {
+static const struct of_device_id tvout_of_match[] = {
        { .compatible = "st,stih416-tvout", },
        { .compatible = "st,stih407-tvout", },
        { /* end node */ }
index 7bfdaa163a33a19fb7ca8d775e654277aea497ea..36b871686d3c6147a7b033b9db45a07ed39e9530 100644 (file)
@@ -450,11 +450,11 @@ static int vmw_cmd_res_reloc_add(struct vmw_private *dev_priv,
                                          res,
                                          id_loc - sw_context->buf_start);
        if (unlikely(ret != 0))
-               goto out_err;
+               return ret;
 
        ret = vmw_resource_val_add(sw_context, res, &node);
        if (unlikely(ret != 0))
-               goto out_err;
+               return ret;
 
        if (res_type == vmw_res_context && dev_priv->has_mob &&
            node->first_usage) {
@@ -468,13 +468,13 @@ static int vmw_cmd_res_reloc_add(struct vmw_private *dev_priv,
 
                ret = vmw_resource_context_res_add(dev_priv, sw_context, res);
                if (unlikely(ret != 0))
-                       goto out_err;
+                       return ret;
                node->staged_bindings =
                        kzalloc(sizeof(*node->staged_bindings), GFP_KERNEL);
                if (node->staged_bindings == NULL) {
                        DRM_ERROR("Failed to allocate context binding "
                                  "information.\n");
-                       goto out_err;
+                       return -ENOMEM;
                }
                INIT_LIST_HEAD(&node->staged_bindings->list);
        }
@@ -482,8 +482,7 @@ static int vmw_cmd_res_reloc_add(struct vmw_private *dev_priv,
        if (p_val)
                *p_val = node;
 
-out_err:
-       return ret;
+       return 0;
 }
 
 
index 6ccd993e26bf4ead66d0e8d1f1b4b592856d7599..6eae14d2a3f73511143a42da95757418edf01207 100644 (file)
@@ -180,8 +180,9 @@ void vmw_fifo_release(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
 
        mutex_lock(&dev_priv->hw_mutex);
 
+       vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC);
        while (vmw_read(dev_priv, SVGA_REG_BUSY) != 0)
-               vmw_write(dev_priv, SVGA_REG_SYNC, SVGA_SYNC_GENERIC);
+               ;
 
        dev_priv->last_read_seqno = ioread32(fifo_mem + SVGA_FIFO_FENCE);
 
index b7ba82960c7925c5d04eb898af55a95b3be058f4..9bf8637747a57f1b362680eeb36faf649b35f2fd 100644 (file)
@@ -656,7 +656,6 @@ static int logi_dj_raw_event(struct hid_device *hdev,
        struct dj_receiver_dev *djrcv_dev = hid_get_drvdata(hdev);
        struct dj_report *dj_report = (struct dj_report *) data;
        unsigned long flags;
-       bool report_processed = false;
 
        dbg_hid("%s, size:%d\n", __func__, size);
 
@@ -683,34 +682,42 @@ static int logi_dj_raw_event(struct hid_device *hdev,
         * device (via hid_input_report() ) and return 1 so hid-core does not do
         * anything else with it.
         */
+
+       /* case 1) */
+       if (data[0] != REPORT_ID_DJ_SHORT)
+               return false;
+
        if ((dj_report->device_index < DJ_DEVICE_INDEX_MIN) ||
            (dj_report->device_index > DJ_DEVICE_INDEX_MAX)) {
-               dev_err(&hdev->dev, "%s: invalid device index:%d\n",
+               /*
+                * Device index is wrong, bail out.
+                * This driver can ignore safely the receiver notifications,
+                * so ignore those reports too.
+                */
+               if (dj_report->device_index != DJ_RECEIVER_INDEX)
+                       dev_err(&hdev->dev, "%s: invalid device index:%d\n",
                                __func__, dj_report->device_index);
                return false;
        }
 
        spin_lock_irqsave(&djrcv_dev->lock, flags);
-       if (dj_report->report_id == REPORT_ID_DJ_SHORT) {
-               switch (dj_report->report_type) {
-               case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
-               case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
-                       logi_dj_recv_queue_notification(djrcv_dev, dj_report);
-                       break;
-               case REPORT_TYPE_NOTIF_CONNECTION_STATUS:
-                       if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] ==
-                           STATUS_LINKLOSS) {
-                               logi_dj_recv_forward_null_report(djrcv_dev, dj_report);
-                       }
-                       break;
-               default:
-                       logi_dj_recv_forward_report(djrcv_dev, dj_report);
+       switch (dj_report->report_type) {
+       case REPORT_TYPE_NOTIF_DEVICE_PAIRED:
+       case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED:
+               logi_dj_recv_queue_notification(djrcv_dev, dj_report);
+               break;
+       case REPORT_TYPE_NOTIF_CONNECTION_STATUS:
+               if (dj_report->report_params[CONNECTION_STATUS_PARAM_STATUS] ==
+                   STATUS_LINKLOSS) {
+                       logi_dj_recv_forward_null_report(djrcv_dev, dj_report);
                }
-               report_processed = true;
+               break;
+       default:
+               logi_dj_recv_forward_report(djrcv_dev, dj_report);
        }
        spin_unlock_irqrestore(&djrcv_dev->lock, flags);
 
-       return report_processed;
+       return true;
 }
 
 static int logi_dj_probe(struct hid_device *hdev,
index 4a4000340ce1ed8cf6be1f81ee8e0f21d8ba5f5a..daeb0aa4bee99a60f3391c0ab4a56803b37a2568 100644 (file)
@@ -27,6 +27,7 @@
 
 #define DJ_MAX_PAIRED_DEVICES                  6
 #define DJ_MAX_NUMBER_NOTIFICATIONS            8
+#define DJ_RECEIVER_INDEX                      0
 #define DJ_DEVICE_INDEX_MIN                    1
 #define DJ_DEVICE_INDEX_MAX                    6
 
index ecc2cbf300cc39bc31e3ff5ad5979dff49822402..29a74c1efcb85fa727536c4b72be844f9963cd70 100644 (file)
@@ -290,6 +290,11 @@ static int magicmouse_raw_event(struct hid_device *hdev,
                if (size < 4 || ((size - 4) % 9) != 0)
                        return 0;
                npoints = (size - 4) / 9;
+               if (npoints > 15) {
+                       hid_warn(hdev, "invalid size value (%d) for TRACKPAD_REPORT_ID\n",
+                                       size);
+                       return 0;
+               }
                msc->ntouches = 0;
                for (ii = 0; ii < npoints; ii++)
                        magicmouse_emit_touch(msc, ii, data + ii * 9 + 4);
@@ -307,6 +312,11 @@ static int magicmouse_raw_event(struct hid_device *hdev,
                if (size < 6 || ((size - 6) % 8) != 0)
                        return 0;
                npoints = (size - 6) / 8;
+               if (npoints > 15) {
+                       hid_warn(hdev, "invalid size value (%d) for MOUSE_REPORT_ID\n",
+                                       size);
+                       return 0;
+               }
                msc->ntouches = 0;
                for (ii = 0; ii < npoints; ii++)
                        magicmouse_emit_touch(msc, ii, data + ii * 8 + 6);
index acbb021065ece8287c9d3ea433c860afc0711855..020df3c2e8b42717c62bbe0470aa47845535e4a5 100644 (file)
@@ -350,6 +350,12 @@ static int picolcd_raw_event(struct hid_device *hdev,
        if (!data)
                return 1;
 
+       if (size > 64) {
+               hid_warn(hdev, "invalid size value (%d) for picolcd raw event\n",
+                               size);
+               return 0;
+       }
+
        if (report->id == REPORT_KEY_STATE) {
                if (data->input_keys)
                        ret = picolcd_raw_keypad(data, report, raw_data+1, size-1);
index fc6f5d54e7f755282025045f843ba62dcff68fa9..8890870309e4db7f5f875c202756006b3323538b 100644 (file)
@@ -309,6 +309,7 @@ static ssize_t set_convrate(struct device *dev, struct device_attribute *da,
        data->conf |= (resol << DS1621_REG_CONFIG_RESOL_SHIFT);
        i2c_smbus_write_byte_data(client, DS1621_REG_CONF, data->conf);
        data->update_interval = ds1721_convrates[resol];
+       data->zbits = 7 - resol;
        mutex_unlock(&data->update_lock);
 
        return count;
index 79a68999a6962914f93106b4fc9154129b9071f0..917d54588d95c14f966abd326e12467bea244342 100644 (file)
@@ -101,6 +101,7 @@ struct at91_twi_dev {
        unsigned twi_cwgr_reg;
        struct at91_twi_pdata *pdata;
        bool use_dma;
+       bool recv_len_abort;
        struct at91_twi_dma dma;
 };
 
@@ -267,12 +268,24 @@ static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
        *dev->buf = at91_twi_read(dev, AT91_TWI_RHR) & 0xff;
        --dev->buf_len;
 
+       /* return if aborting, we only needed to read RHR to clear RXRDY*/
+       if (dev->recv_len_abort)
+               return;
+
        /* handle I2C_SMBUS_BLOCK_DATA */
        if (unlikely(dev->msg->flags & I2C_M_RECV_LEN)) {
-               dev->msg->flags &= ~I2C_M_RECV_LEN;
-               dev->buf_len += *dev->buf;
-               dev->msg->len = dev->buf_len + 1;
-               dev_dbg(dev->dev, "received block length %d\n", dev->buf_len);
+               /* ensure length byte is a valid value */
+               if (*dev->buf <= I2C_SMBUS_BLOCK_MAX && *dev->buf > 0) {
+                       dev->msg->flags &= ~I2C_M_RECV_LEN;
+                       dev->buf_len += *dev->buf;
+                       dev->msg->len = dev->buf_len + 1;
+                       dev_dbg(dev->dev, "received block length %d\n",
+                                        dev->buf_len);
+               } else {
+                       /* abort and send the stop by reading one more byte */
+                       dev->recv_len_abort = true;
+                       dev->buf_len = 1;
+               }
        }
 
        /* send stop if second but last byte has been read */
@@ -421,8 +434,8 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
                }
        }
 
-       ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
-                                                       dev->adapter.timeout);
+       ret = wait_for_completion_io_timeout(&dev->cmd_complete,
+                                            dev->adapter.timeout);
        if (ret == 0) {
                dev_err(dev->dev, "controller timed out\n");
                at91_init_twi_bus(dev);
@@ -444,6 +457,12 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
                ret = -EIO;
                goto error;
        }
+       if (dev->recv_len_abort) {
+               dev_err(dev->dev, "invalid smbus block length recvd\n");
+               ret = -EPROTO;
+               goto error;
+       }
+
        dev_dbg(dev->dev, "transfer complete\n");
 
        return 0;
@@ -500,6 +519,7 @@ static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
        dev->buf_len = m_start->len;
        dev->buf = m_start->buf;
        dev->msg = m_start;
+       dev->recv_len_abort = false;
 
        ret = at91_do_twi_transfer(dev);
 
index 6dc5ded86f6262e8b9eb4bceeae83e4d8eafd4e9..2f64273d3f2bba63c8f930e66fad83fdf5750551 100644 (file)
@@ -746,8 +746,7 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
        }
        tclk = clk_get_rate(drv_data->clk);
 
-       rc = of_property_read_u32(np, "clock-frequency", &bus_freq);
-       if (rc)
+       if (of_property_read_u32(np, "clock-frequency", &bus_freq))
                bus_freq = 100000; /* 100kHz by default */
 
        if (!mv64xxx_find_baud_factors(bus_freq, tclk,
index f3c7139dfa251f51b6c67da1b9f2de869fb6860d..1cc146cfc1f3dce02d4d83c7e79b698f07b161c9 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
+#include <linux/spinlock.h>
 
 /* register offsets */
 #define ICSCR  0x00    /* slave ctrl */
@@ -95,6 +96,7 @@ struct rcar_i2c_priv {
        struct i2c_msg  *msg;
        struct clk *clk;
 
+       spinlock_t lock;
        wait_queue_head_t wait;
 
        int pos;
@@ -365,20 +367,20 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
        struct rcar_i2c_priv *priv = ptr;
        u32 msr;
 
+       /*-------------- spin lock -----------------*/
+       spin_lock(&priv->lock);
+
        msr = rcar_i2c_read(priv, ICMSR);
 
+       /* Only handle interrupts that are currently enabled */
+       msr &= rcar_i2c_read(priv, ICMIER);
+
        /* Arbitration lost */
        if (msr & MAL) {
                rcar_i2c_flags_set(priv, (ID_DONE | ID_ARBLOST));
                goto out;
        }
 
-       /* Stop */
-       if (msr & MST) {
-               rcar_i2c_flags_set(priv, ID_DONE);
-               goto out;
-       }
-
        /* Nack */
        if (msr & MNR) {
                /* go to stop phase */
@@ -388,6 +390,12 @@ static irqreturn_t rcar_i2c_irq(int irq, void *ptr)
                goto out;
        }
 
+       /* Stop */
+       if (msr & MST) {
+               rcar_i2c_flags_set(priv, ID_DONE);
+               goto out;
+       }
+
        if (rcar_i2c_is_recv(priv))
                rcar_i2c_flags_set(priv, rcar_i2c_irq_recv(priv, msr));
        else
@@ -400,6 +408,9 @@ out:
                wake_up(&priv->wait);
        }
 
+       spin_unlock(&priv->lock);
+       /*-------------- spin unlock -----------------*/
+
        return IRQ_HANDLED;
 }
 
@@ -409,14 +420,21 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
 {
        struct rcar_i2c_priv *priv = i2c_get_adapdata(adap);
        struct device *dev = rcar_i2c_priv_to_dev(priv);
+       unsigned long flags;
        int i, ret, timeout;
 
        pm_runtime_get_sync(dev);
 
+       /*-------------- spin lock -----------------*/
+       spin_lock_irqsave(&priv->lock, flags);
+
        rcar_i2c_init(priv);
        /* start clock */
        rcar_i2c_write(priv, ICCCR, priv->icccr);
 
+       spin_unlock_irqrestore(&priv->lock, flags);
+       /*-------------- spin unlock -----------------*/
+
        ret = rcar_i2c_bus_barrier(priv);
        if (ret < 0)
                goto out;
@@ -428,6 +446,9 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
                        break;
                }
 
+               /*-------------- spin lock -----------------*/
+               spin_lock_irqsave(&priv->lock, flags);
+
                /* init each data */
                priv->msg       = &msgs[i];
                priv->pos       = 0;
@@ -437,6 +458,9 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
 
                ret = rcar_i2c_prepare_msg(priv);
 
+               spin_unlock_irqrestore(&priv->lock, flags);
+               /*-------------- spin unlock -----------------*/
+
                if (ret < 0)
                        break;
 
@@ -540,6 +564,7 @@ static int rcar_i2c_probe(struct platform_device *pdev)
 
        irq = platform_get_irq(pdev, 0);
        init_waitqueue_head(&priv->wait);
+       spin_lock_init(&priv->lock);
 
        adap = &priv->adap;
        adap->nr = pdev->id;
index 69e11853e8bff187e09459167506ec24b8f7a122..e637c32ae5172bcaa77bdd2c5eda8dee34457176 100644 (file)
@@ -323,6 +323,10 @@ static void rk3x_i2c_handle_read(struct rk3x_i2c *i2c, unsigned int ipd)
        /* ack interrupt */
        i2c_writel(i2c, REG_INT_MBRF, REG_IPD);
 
+       /* Can only handle a maximum of 32 bytes at a time */
+       if (len > 32)
+               len = 32;
+
        /* read the data from receive buffer */
        for (i = 0; i < len; ++i) {
                if (i % 4 == 0)
index e1e558a3d692bbd8b907a84efe222481b0ae1a8e..af8256353c7de6a9449f3da753b4b07e8df025fc 100644 (file)
@@ -1089,6 +1089,30 @@ static int __mlx4_ib_destroy_flow(struct mlx4_dev *dev, u64 reg_id)
        return err;
 }
 
+static int mlx4_ib_tunnel_steer_add(struct ib_qp *qp, struct ib_flow_attr *flow_attr,
+                                   u64 *reg_id)
+{
+       void *ib_flow;
+       union ib_flow_spec *ib_spec;
+       struct mlx4_dev *dev = to_mdev(qp->device)->dev;
+       int err = 0;
+
+       if (dev->caps.tunnel_offload_mode != MLX4_TUNNEL_OFFLOAD_MODE_VXLAN)
+               return 0; /* do nothing */
+
+       ib_flow = flow_attr + 1;
+       ib_spec = (union ib_flow_spec *)ib_flow;
+
+       if (ib_spec->type !=  IB_FLOW_SPEC_ETH || flow_attr->num_of_specs != 1)
+               return 0; /* do nothing */
+
+       err = mlx4_tunnel_steer_add(to_mdev(qp->device)->dev, ib_spec->eth.val.dst_mac,
+                                   flow_attr->port, qp->qp_num,
+                                   MLX4_DOMAIN_UVERBS | (flow_attr->priority & 0xff),
+                                   reg_id);
+       return err;
+}
+
 static struct ib_flow *mlx4_ib_create_flow(struct ib_qp *qp,
                                    struct ib_flow_attr *flow_attr,
                                    int domain)
@@ -1136,6 +1160,12 @@ static struct ib_flow *mlx4_ib_create_flow(struct ib_qp *qp,
                i++;
        }
 
+       if (i < ARRAY_SIZE(type) && flow_attr->type == IB_FLOW_ATTR_NORMAL) {
+               err = mlx4_ib_tunnel_steer_add(qp, flow_attr, &mflow->reg_id[i]);
+               if (err)
+                       goto err_free;
+       }
+
        return &mflow->ibflow;
 
 err_free:
index 67780452f0cfb85d72fc98bfd0faefbe005fb32a..efb9eff8906c34845053ba04ced5dea9bfe8cbe4 100644 (file)
@@ -1677,9 +1677,15 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
                }
        }
 
-       if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET)
+       if (qp->ibqp.qp_type == IB_QPT_RAW_PACKET) {
                context->pri_path.ackto = (context->pri_path.ackto & 0xf8) |
                                        MLX4_IB_LINK_TYPE_ETH;
+               if (dev->dev->caps.tunnel_offload_mode ==  MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) {
+                       /* set QP to receive both tunneled & non-tunneled packets */
+                       if (!(context->flags & (1 << MLX4_RSS_QPC_FLAG_OFFSET)))
+                               context->srqn = cpu_to_be32(7 << 28);
+               }
+       }
 
        if (ibqp->qp_type == IB_QPT_UD && (new_state == IB_QPS_RTR)) {
                int is_eth = rdma_port_get_link_layer(
index c30204f2fa3097a376eec7a32072f0c29b9c1a90..fbe29fcb15c5b85d27c5e001df59fe20d144b577 100644 (file)
@@ -236,6 +236,18 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count)
 }
 EXPORT_SYMBOL(input_mt_report_pointer_emulation);
 
+static void __input_mt_drop_unused(struct input_dev *dev, struct input_mt *mt)
+{
+       int i;
+
+       for (i = 0; i < mt->num_slots; i++) {
+               if (!input_mt_is_used(mt, &mt->slots[i])) {
+                       input_mt_slot(dev, i);
+                       input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
+               }
+       }
+}
+
 /**
  * input_mt_drop_unused() - Inactivate slots not seen in this frame
  * @dev: input device with allocated MT slots
@@ -245,19 +257,11 @@ EXPORT_SYMBOL(input_mt_report_pointer_emulation);
 void input_mt_drop_unused(struct input_dev *dev)
 {
        struct input_mt *mt = dev->mt;
-       int i;
 
-       if (!mt)
-               return;
-
-       for (i = 0; i < mt->num_slots; i++) {
-               if (!input_mt_is_used(mt, &mt->slots[i])) {
-                       input_mt_slot(dev, i);
-                       input_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1);
-               }
+       if (mt) {
+               __input_mt_drop_unused(dev, mt);
+               mt->frame++;
        }
-
-       mt->frame++;
 }
 EXPORT_SYMBOL(input_mt_drop_unused);
 
@@ -278,12 +282,14 @@ void input_mt_sync_frame(struct input_dev *dev)
                return;
 
        if (mt->flags & INPUT_MT_DROP_UNUSED)
-               input_mt_drop_unused(dev);
+               __input_mt_drop_unused(dev, mt);
 
        if ((mt->flags & INPUT_MT_POINTER) && !(mt->flags & INPUT_MT_SEMI_MT))
                use_count = true;
 
        input_mt_report_pointer_emulation(dev, use_count);
+
+       mt->frame++;
 }
 EXPORT_SYMBOL(input_mt_sync_frame);
 
index 180b184ab90f31935e1fa9c71bd7eb8fa4e68593..d70b65a14ced24ffe09e298562de54ab9b9a52e4 100644 (file)
@@ -33,8 +33,8 @@
 #define CAP1106_REG_SENSOR_CONFIG      0x22
 #define CAP1106_REG_SENSOR_CONFIG2     0x23
 #define CAP1106_REG_SAMPLING_CONFIG    0x24
-#define CAP1106_REG_CALIBRATION                0x25
-#define CAP1106_REG_INT_ENABLE         0x26
+#define CAP1106_REG_CALIBRATION                0x26
+#define CAP1106_REG_INT_ENABLE         0x27
 #define CAP1106_REG_REPEAT_RATE                0x28
 #define CAP1106_REG_MT_CONFIG          0x2a
 #define CAP1106_REG_MT_PATTERN_CONFIG  0x2b
index 8d2e19e81e1e59b63c31eccd989b441f503e8706..e651fa692afef3959f0d48ee844a40c3ccb2aba0 100644 (file)
@@ -332,23 +332,24 @@ static int matrix_keypad_init_gpio(struct platform_device *pdev,
        }
 
        if (pdata->clustered_irq > 0) {
-               err = request_irq(pdata->clustered_irq,
+               err = request_any_context_irq(pdata->clustered_irq,
                                matrix_keypad_interrupt,
                                pdata->clustered_irq_flags,
                                "matrix-keypad", keypad);
-               if (err) {
+               if (err < 0) {
                        dev_err(&pdev->dev,
                                "Unable to acquire clustered interrupt\n");
                        goto err_free_rows;
                }
        } else {
                for (i = 0; i < pdata->num_row_gpios; i++) {
-                       err = request_irq(gpio_to_irq(pdata->row_gpios[i]),
+                       err = request_any_context_irq(
+                                       gpio_to_irq(pdata->row_gpios[i]),
                                        matrix_keypad_interrupt,
                                        IRQF_TRIGGER_RISING |
                                        IRQF_TRIGGER_FALLING,
                                        "matrix-keypad", keypad);
-                       if (err) {
+                       if (err < 0) {
                                dev_err(&pdev->dev,
                                        "Unable to acquire interrupt for GPIO line %i\n",
                                        pdata->row_gpios[i]);
index a59a1a64b6746745522e1da15e541008d738fcca..35a49bf572273e464399944c05e8072a7b06e138 100644 (file)
@@ -2234,8 +2234,8 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
                return 0;
        }
 
-       psmouse_info(psmouse,
-                    "Unknown ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec);
+       psmouse_dbg(psmouse,
+                   "Likely not an ALPS touchpad: E7=%3ph, EC=%3ph\n", e7, ec);
 
        return -EINVAL;
 }
@@ -2373,6 +2373,10 @@ int alps_init(struct psmouse *psmouse)
        dev2->keybit[BIT_WORD(BTN_LEFT)] =
                BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT);
 
+       __set_bit(INPUT_PROP_POINTER, dev2->propbit);
+       if (priv->flags & ALPS_DUALPOINT)
+               __set_bit(INPUT_PROP_POINTING_STICK, dev2->propbit);
+
        if (input_register_device(priv->dev2))
                goto init_fail;
 
index ee2a04d90d20c1bfe1fd785350119a44eb835109..06fc6e76ffbe0cf725053b8a1bdb3faaefa1c629 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/input/mt.h>
 #include <linux/serio.h>
 #include <linux/libps2.h>
+#include <asm/unaligned.h>
 #include "psmouse.h"
 #include "elantech.h"
 
@@ -403,6 +404,68 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse)
        input_sync(dev);
 }
 
+static void elantech_report_trackpoint(struct psmouse *psmouse,
+                                      int packet_type)
+{
+       /*
+        * byte 0:  0   0  sx  sy   0   M   R   L
+        * byte 1:~sx   0   0   0   0   0   0   0
+        * byte 2:~sy   0   0   0   0   0   0   0
+        * byte 3:  0   0 ~sy ~sx   0   1   1   0
+        * byte 4: x7  x6  x5  x4  x3  x2  x1  x0
+        * byte 5: y7  y6  y5  y4  y3  y2  y1  y0
+        *
+        * x and y are written in two's complement spread
+        * over 9 bits with sx/sy the relative top bit and
+        * x7..x0 and y7..y0 the lower bits.
+        * The sign of y is opposite to what the input driver
+        * expects for a relative movement
+        */
+
+       struct elantech_data *etd = psmouse->private;
+       struct input_dev *tp_dev = etd->tp_dev;
+       unsigned char *packet = psmouse->packet;
+       int x, y;
+       u32 t;
+
+       if (dev_WARN_ONCE(&psmouse->ps2dev.serio->dev,
+                         !tp_dev,
+                         psmouse_fmt("Unexpected trackpoint message\n"))) {
+               if (etd->debug == 1)
+                       elantech_packet_dump(psmouse);
+               return;
+       }
+
+       t = get_unaligned_le32(&packet[0]);
+
+       switch (t & ~7U) {
+       case 0x06000030U:
+       case 0x16008020U:
+       case 0x26800010U:
+       case 0x36808000U:
+               x = packet[4] - (int)((packet[1]^0x80) << 1);
+               y = (int)((packet[2]^0x80) << 1) - packet[5];
+
+               input_report_key(tp_dev, BTN_LEFT, packet[0] & 0x01);
+               input_report_key(tp_dev, BTN_RIGHT, packet[0] & 0x02);
+               input_report_key(tp_dev, BTN_MIDDLE, packet[0] & 0x04);
+
+               input_report_rel(tp_dev, REL_X, x);
+               input_report_rel(tp_dev, REL_Y, y);
+
+               input_sync(tp_dev);
+
+               break;
+
+       default:
+               /* Dump unexpected packet sequences if debug=1 (default) */
+               if (etd->debug == 1)
+                       elantech_packet_dump(psmouse);
+
+               break;
+       }
+}
+
 /*
  * Interpret complete data packets and report absolute mode input events for
  * hardware version 3. (12 byte packets for two fingers)
@@ -715,6 +778,8 @@ static int elantech_packet_check_v3(struct psmouse *psmouse)
 
                if ((packet[0] & 0x0c) == 0x0c && (packet[3] & 0xce) == 0x0c)
                        return PACKET_V3_TAIL;
+               if ((packet[3] & 0x0f) == 0x06)
+                       return PACKET_TRACKPOINT;
        }
 
        return PACKET_UNKNOWN;
@@ -791,14 +856,23 @@ static psmouse_ret_t elantech_process_byte(struct psmouse *psmouse)
 
        case 3:
                packet_type = elantech_packet_check_v3(psmouse);
-               /* ignore debounce */
-               if (packet_type == PACKET_DEBOUNCE)
-                       return PSMOUSE_FULL_PACKET;
-
-               if (packet_type == PACKET_UNKNOWN)
+               switch (packet_type) {
+               case PACKET_UNKNOWN:
                        return PSMOUSE_BAD_DATA;
 
-               elantech_report_absolute_v3(psmouse, packet_type);
+               case PACKET_DEBOUNCE:
+                       /* ignore debounce */
+                       break;
+
+               case PACKET_TRACKPOINT:
+                       elantech_report_trackpoint(psmouse, packet_type);
+                       break;
+
+               default:
+                       elantech_report_absolute_v3(psmouse, packet_type);
+                       break;
+               }
+
                break;
 
        case 4:
@@ -1018,8 +1092,10 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
  * Asus UX31               0x361f00        20, 15, 0e      clickpad
  * Asus UX32VD             0x361f02        00, 15, 0e      clickpad
  * Avatar AVIU-145A2       0x361f00        ?               clickpad
+ * Fujitsu H730            0x570f00        c0, 14, 0c      3 hw buttons (**)
  * Gigabyte U2442          0x450f01        58, 17, 0c      2 hw buttons
  * Lenovo L430             0x350f02        b9, 15, 0c      2 hw buttons (*)
+ * Lenovo L530             0x350f02        b9, 15, 0c      2 hw buttons (*)
  * Samsung NF210           0x150b00        78, 14, 0a      2 hw buttons
  * Samsung NP770Z5E        0x575f01        10, 15, 0f      clickpad
  * Samsung NP700Z5B        0x361f06        21, 15, 0f      clickpad
@@ -1029,6 +1105,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
  * Samsung RF710           0x450f00        ?               2 hw buttons
  * System76 Pangolin       0x250f01        ?               2 hw buttons
  * (*) + 3 trackpoint buttons
+ * (**) + 0 trackpoint buttons
+ * Note: Lenovo L430 and Lenovo L430 have the same fw_version/caps
  */
 static void elantech_set_buttonpad_prop(struct psmouse *psmouse)
 {
@@ -1253,6 +1331,13 @@ static bool elantech_is_signature_valid(const unsigned char *param)
        if (param[1] == 0)
                return true;
 
+       /*
+        * Some models have a revision higher then 20. Meaning param[2] may
+        * be 10 or 20, skip the rates check for these.
+        */
+       if (param[0] == 0x46 && (param[1] & 0xef) == 0x0f && param[2] < 40)
+               return true;
+
        for (i = 0; i < ARRAY_SIZE(rates); i++)
                if (param[2] == rates[i])
                        return false;
@@ -1324,6 +1409,10 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties)
  */
 static void elantech_disconnect(struct psmouse *psmouse)
 {
+       struct elantech_data *etd = psmouse->private;
+
+       if (etd->tp_dev)
+               input_unregister_device(etd->tp_dev);
        sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj,
                           &elantech_attr_group);
        kfree(psmouse->private);
@@ -1438,8 +1527,10 @@ static int elantech_set_properties(struct elantech_data *etd)
 int elantech_init(struct psmouse *psmouse)
 {
        struct elantech_data *etd;
-       int i, error;
+       int i;
+       int error = -EINVAL;
        unsigned char param[3];
+       struct input_dev *tp_dev;
 
        psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL);
        if (!etd)
@@ -1498,14 +1589,53 @@ int elantech_init(struct psmouse *psmouse)
                goto init_fail;
        }
 
+       /* The MSB indicates the presence of the trackpoint */
+       if ((etd->capabilities[0] & 0x80) == 0x80) {
+               tp_dev = input_allocate_device();
+
+               if (!tp_dev) {
+                       error = -ENOMEM;
+                       goto init_fail_tp_alloc;
+               }
+
+               etd->tp_dev = tp_dev;
+               snprintf(etd->tp_phys, sizeof(etd->tp_phys), "%s/input1",
+                       psmouse->ps2dev.serio->phys);
+               tp_dev->phys = etd->tp_phys;
+               tp_dev->name = "Elantech PS/2 TrackPoint";
+               tp_dev->id.bustype = BUS_I8042;
+               tp_dev->id.vendor  = 0x0002;
+               tp_dev->id.product = PSMOUSE_ELANTECH;
+               tp_dev->id.version = 0x0000;
+               tp_dev->dev.parent = &psmouse->ps2dev.serio->dev;
+               tp_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+               tp_dev->relbit[BIT_WORD(REL_X)] =
+                       BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+               tp_dev->keybit[BIT_WORD(BTN_LEFT)] =
+                       BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) |
+                       BIT_MASK(BTN_RIGHT);
+
+               __set_bit(INPUT_PROP_POINTER, tp_dev->propbit);
+               __set_bit(INPUT_PROP_POINTING_STICK, tp_dev->propbit);
+
+               error = input_register_device(etd->tp_dev);
+               if (error < 0)
+                       goto init_fail_tp_reg;
+       }
+
        psmouse->protocol_handler = elantech_process_byte;
        psmouse->disconnect = elantech_disconnect;
        psmouse->reconnect = elantech_reconnect;
        psmouse->pktsize = etd->hw_version > 1 ? 6 : 4;
 
        return 0;
-
+ init_fail_tp_reg:
+       input_free_device(tp_dev);
+ init_fail_tp_alloc:
+       sysfs_remove_group(&psmouse->ps2dev.serio->dev.kobj,
+                          &elantech_attr_group);
  init_fail:
+       psmouse_reset(psmouse);
        kfree(etd);
-       return -1;
+       return error;
 }
index 9e0e2a1f340d52817fc18bf79d849bed6d340932..6f3afec02f03ee0cec8b74cbe13bae6a5cba83c5 100644 (file)
@@ -94,6 +94,7 @@
 #define PACKET_V4_HEAD                 0x05
 #define PACKET_V4_MOTION               0x06
 #define PACKET_V4_STATUS               0x07
+#define PACKET_TRACKPOINT              0x08
 
 /*
  * track up to 5 fingers for v4 hardware
@@ -114,6 +115,8 @@ struct finger_pos {
 };
 
 struct elantech_data {
+       struct input_dev *tp_dev;       /* Relative device for trackpoint */
+       char tp_phys[32];
        unsigned char reg_07;
        unsigned char reg_10;
        unsigned char reg_11;
index cff065f6261cf31a3188226f14fe28e9291f6770..b4e1f014ddc2297affeda8abc73c15954fdfabf0 100644 (file)
@@ -670,6 +670,8 @@ static void psmouse_apply_defaults(struct psmouse *psmouse)
        __set_bit(REL_X, input_dev->relbit);
        __set_bit(REL_Y, input_dev->relbit);
 
+       __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+
        psmouse->set_rate = psmouse_set_rate;
        psmouse->set_resolution = psmouse_set_resolution;
        psmouse->poll = psmouse_poll;
index e8573c68f77e900e83e054c720443328adfa2f7f..fd23181c1fb741112f1cc33fa0fc6111284823c3 100644 (file)
@@ -629,10 +629,61 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
                         ((buf[0] & 0x04) >> 1) |
                         ((buf[3] & 0x04) >> 2));
 
+               if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
+                       SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) &&
+                   hw->w == 2) {
+                       synaptics_parse_agm(buf, priv, hw);
+                       return 1;
+               }
+
+               hw->x = (((buf[3] & 0x10) << 8) |
+                        ((buf[1] & 0x0f) << 8) |
+                        buf[4]);
+               hw->y = (((buf[3] & 0x20) << 7) |
+                        ((buf[1] & 0xf0) << 4) |
+                        buf[5]);
+               hw->z = buf[2];
+
                hw->left  = (buf[0] & 0x01) ? 1 : 0;
                hw->right = (buf[0] & 0x02) ? 1 : 0;
 
-               if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
+               if (SYN_CAP_FORCEPAD(priv->ext_cap_0c)) {
+                       /*
+                        * ForcePads, like Clickpads, use middle button
+                        * bits to report primary button clicks.
+                        * Unfortunately they report primary button not
+                        * only when user presses on the pad above certain
+                        * threshold, but also when there are more than one
+                        * finger on the touchpad, which interferes with
+                        * out multi-finger gestures.
+                        */
+                       if (hw->z == 0) {
+                               /* No contacts */
+                               priv->press = priv->report_press = false;
+                       } else if (hw->w >= 4 && ((buf[0] ^ buf[3]) & 0x01)) {
+                               /*
+                                * Single-finger touch with pressure above
+                                * the threshold. If pressure stays long
+                                * enough, we'll start reporting primary
+                                * button. We rely on the device continuing
+                                * sending data even if finger does not
+                                * move.
+                                */
+                               if  (!priv->press) {
+                                       priv->press_start = jiffies;
+                                       priv->press = true;
+                               } else if (time_after(jiffies,
+                                               priv->press_start +
+                                                       msecs_to_jiffies(50))) {
+                                       priv->report_press = true;
+                               }
+                       } else {
+                               priv->press = false;
+                       }
+
+                       hw->left = priv->report_press;
+
+               } else if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) {
                        /*
                         * Clickpad's button is transmitted as middle button,
                         * however, since it is primary button, we will report
@@ -651,21 +702,6 @@ static int synaptics_parse_hw_state(const unsigned char buf[],
                        hw->down = ((buf[0] ^ buf[3]) & 0x02) ? 1 : 0;
                }
 
-               if ((SYN_CAP_ADV_GESTURE(priv->ext_cap_0c) ||
-                       SYN_CAP_IMAGE_SENSOR(priv->ext_cap_0c)) &&
-                   hw->w == 2) {
-                       synaptics_parse_agm(buf, priv, hw);
-                       return 1;
-               }
-
-               hw->x = (((buf[3] & 0x10) << 8) |
-                        ((buf[1] & 0x0f) << 8) |
-                        buf[4]);
-               hw->y = (((buf[3] & 0x20) << 7) |
-                        ((buf[1] & 0xf0) << 4) |
-                        buf[5]);
-               hw->z = buf[2];
-
                if (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) &&
                    ((buf[0] ^ buf[3]) & 0x02)) {
                        switch (SYN_CAP_MULTI_BUTTON_NO(priv->ext_cap) & ~0x01) {
index e594af0b264b7f147569d77fe5a1d84825ed1a9e..fb2e076738ae3bee7fdd844de7e93dd3fa5146c6 100644 (file)
  * 2   0x08    image sensor            image sensor tracks 5 fingers, but only
  *                                     reports 2.
  * 2   0x20    report min              query 0x0f gives min coord reported
+ * 2   0x80    forcepad                forcepad is a variant of clickpad that
+ *                                     does not have physical buttons but rather
+ *                                     uses pressure above certain threshold to
+ *                                     report primary clicks. Forcepads also have
+ *                                     clickpad bit set.
  */
 #define SYN_CAP_CLICKPAD(ex0c)         ((ex0c) & 0x100000) /* 1-button ClickPad */
 #define SYN_CAP_CLICKPAD2BTN(ex0c)     ((ex0c) & 0x000100) /* 2-button ClickPad */
@@ -86,6 +91,7 @@
 #define SYN_CAP_ADV_GESTURE(ex0c)      ((ex0c) & 0x080000)
 #define SYN_CAP_REDUCED_FILTERING(ex0c)        ((ex0c) & 0x000400)
 #define SYN_CAP_IMAGE_SENSOR(ex0c)     ((ex0c) & 0x000800)
+#define SYN_CAP_FORCEPAD(ex0c)         ((ex0c) & 0x008000)
 
 /* synaptics modes query bits */
 #define SYN_MODE_ABSOLUTE(m)           ((m) & (1 << 7))
@@ -177,6 +183,11 @@ struct synaptics_data {
         */
        struct synaptics_hw_state agm;
        bool agm_pending;                       /* new AGM packet received */
+
+       /* ForcePad handling */
+       unsigned long                           press_start;
+       bool                                    press;
+       bool                                    report_press;
 };
 
 void synaptics_module_init(void);
index e122bda16aabddcf555f84dd06eed4dfbebca031..6bcc0189c1c99898dc39bd5ced920f60c13bd553 100644 (file)
@@ -387,6 +387,7 @@ static int synusb_probe(struct usb_interface *intf,
                __set_bit(EV_REL, input_dev->evbit);
                __set_bit(REL_X, input_dev->relbit);
                __set_bit(REL_Y, input_dev->relbit);
+               __set_bit(INPUT_PROP_POINTING_STICK, input_dev->propbit);
                input_set_abs_params(input_dev, ABS_PRESSURE, 0, 127, 0, 0);
        } else {
                input_set_abs_params(input_dev, ABS_X,
@@ -401,6 +402,11 @@ static int synusb_probe(struct usb_interface *intf,
                __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
        }
 
+       if (synusb->flags & SYNUSB_TOUCHSCREEN)
+               __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+       else
+               __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
+
        __set_bit(BTN_LEFT, input_dev->keybit);
        __set_bit(BTN_RIGHT, input_dev->keybit);
        __set_bit(BTN_MIDDLE, input_dev->keybit);
index ca843b6cf6bd9f536c984cf455c83952ff8e2a18..30c8b6998808fa452a19e437c33bd7e9db8a0888 100644 (file)
@@ -393,6 +393,9 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
        if ((button_info & 0x0f) >= 3)
                __set_bit(BTN_MIDDLE, psmouse->dev->keybit);
 
+       __set_bit(INPUT_PROP_POINTER, psmouse->dev->propbit);
+       __set_bit(INPUT_PROP_POINTING_STICK, psmouse->dev->propbit);
+
        trackpoint_defaults(psmouse->private);
 
        error = trackpoint_power_on_reset(&psmouse->ps2dev);
index d6aa4c67dbb6208e0584c098864a52e580950cff..93cb7912703cee4a9dbd2f75594a16da2937bcef 100644 (file)
@@ -17,7 +17,6 @@ static int i8042_aux_irq = -1;
 #define I8042_MUX_PHYS_DESC "sparcps2/serio%d"
 
 static void __iomem *kbd_iobase;
-static struct resource *kbd_res;
 
 #define I8042_COMMAND_REG      (kbd_iobase + 0x64UL)
 #define I8042_DATA_REG         (kbd_iobase + 0x60UL)
@@ -44,6 +43,8 @@ static inline void i8042_write_command(int val)
 
 #ifdef CONFIG_PCI
 
+static struct resource *kbd_res;
+
 #define OBP_PS2KBD_NAME1       "kb_ps2"
 #define OBP_PS2KBD_NAME2       "keyboard"
 #define OBP_PS2MS_NAME1                "kdmouse"
index 0cb7ef59071b792a350a914e88f4e9be7da34efc..69175b8253468cf5d2319659b1496e3ac32d5b10 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/serio.h>
 #include <linux/tty.h>
+#include <linux/compat.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Input device TTY line discipline");
@@ -198,28 +199,55 @@ static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, u
        return 0;
 }
 
+static void serport_set_type(struct tty_struct *tty, unsigned long type)
+{
+       struct serport *serport = tty->disc_data;
+
+       serport->id.proto = type & 0x000000ff;
+       serport->id.id    = (type & 0x0000ff00) >> 8;
+       serport->id.extra = (type & 0x00ff0000) >> 16;
+}
+
 /*
  * serport_ldisc_ioctl() allows to set the port protocol, and device ID
  */
 
-static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg)
+static int serport_ldisc_ioctl(struct tty_struct *tty, struct file *file,
+                              unsigned int cmd, unsigned long arg)
 {
-       struct serport *serport = (struct serport*) tty->disc_data;
-       unsigned long type;
-
        if (cmd == SPIOCSTYPE) {
+               unsigned long type;
+
                if (get_user(type, (unsigned long __user *) arg))
                        return -EFAULT;
 
-               serport->id.proto = type & 0x000000ff;
-               serport->id.id    = (type & 0x0000ff00) >> 8;
-               serport->id.extra = (type & 0x00ff0000) >> 16;
+               serport_set_type(tty, type);
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+#ifdef CONFIG_COMPAT
+#define COMPAT_SPIOCSTYPE      _IOW('q', 0x01, compat_ulong_t)
+static long serport_ldisc_compat_ioctl(struct tty_struct *tty,
+                                      struct file *file,
+                                      unsigned int cmd, unsigned long arg)
+{
+       if (cmd == COMPAT_SPIOCSTYPE) {
+               void __user *uarg = compat_ptr(arg);
+               compat_ulong_t compat_type;
+
+               if (get_user(compat_type, (compat_ulong_t __user *)uarg))
+                       return -EFAULT;
 
+               serport_set_type(tty, compat_type);
                return 0;
        }
 
        return -EINVAL;
 }
+#endif
 
 static void serport_ldisc_write_wakeup(struct tty_struct * tty)
 {
@@ -243,6 +271,9 @@ static struct tty_ldisc_ops serport_ldisc = {
        .close =        serport_ldisc_close,
        .read =         serport_ldisc_read,
        .ioctl =        serport_ldisc_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = serport_ldisc_compat_ioctl,
+#endif
        .receive_buf =  serport_ldisc_receive,
        .write_wakeup = serport_ldisc_write_wakeup
 };
index db178ed2b47ee282c27a5f424f45df168b99a091..aaacf8bfa61fded723f48bcb18dc59ebbd10ab86 100644 (file)
@@ -837,7 +837,12 @@ static irqreturn_t mxt_process_messages_t44(struct mxt_data *data)
        count = data->msg_buf[0];
 
        if (count == 0) {
-               dev_warn(dev, "Interrupt triggered but zero messages\n");
+               /*
+                * This condition is caused by the CHG line being configured
+                * in Mode 0. It results in unnecessary I2C operations but it
+                * is benign.
+                */
+               dev_dbg(dev, "Interrupt triggered but zero messages\n");
                return IRQ_NONE;
        } else if (count > data->max_reportid) {
                dev_err(dev, "T44 count %d exceeded max report id\n", count);
@@ -1374,11 +1379,16 @@ static int mxt_get_info(struct mxt_data *data)
        return 0;
 }
 
-static void mxt_free_object_table(struct mxt_data *data)
+static void mxt_free_input_device(struct mxt_data *data)
 {
-       input_unregister_device(data->input_dev);
-       data->input_dev = NULL;
+       if (data->input_dev) {
+               input_unregister_device(data->input_dev);
+               data->input_dev = NULL;
+       }
+}
 
+static void mxt_free_object_table(struct mxt_data *data)
+{
        kfree(data->object_table);
        data->object_table = NULL;
        kfree(data->msg_buf);
@@ -1957,11 +1967,13 @@ static int mxt_load_fw(struct device *dev, const char *fn)
                ret = mxt_lookup_bootloader_address(data, 0);
                if (ret)
                        goto release_firmware;
+
+               mxt_free_input_device(data);
+               mxt_free_object_table(data);
        } else {
                enable_irq(data->irq);
        }
 
-       mxt_free_object_table(data);
        reinit_completion(&data->bl_completion);
 
        ret = mxt_check_bootloader(data, MXT_WAITING_BOOTLOAD_CMD, false);
@@ -2210,6 +2222,7 @@ static int mxt_probe(struct i2c_client *client, const struct i2c_device_id *id)
        return 0;
 
 err_free_object:
+       mxt_free_input_device(data);
        mxt_free_object_table(data);
 err_free_irq:
        free_irq(client->irq, data);
@@ -2224,7 +2237,7 @@ static int mxt_remove(struct i2c_client *client)
 
        sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
        free_irq(data->irq, data);
-       input_unregister_device(data->input_dev);
+       mxt_free_input_device(data);
        mxt_free_object_table(data);
        kfree(data);
 
index 16b52115c27fd49fc9cce79735df7fcad18347c5..705ffa1e064a9ceb391abf51b28343bc3b2ed7ce 100644 (file)
@@ -41,7 +41,7 @@
  */
 static int rpu = 8;
 module_param(rpu, int, 0);
-MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
+MODULE_PARM_DESC(rpu, "Set internal pull up resistor for pen detect.");
 
 /*
  * Set current used for pressure measurement.
index 7405353199d7353e31e1bfac4b2f39db3b222fc3..572a5a64face0bff34c0099fa35213442b8a0860 100644 (file)
@@ -41,7 +41,7 @@
  */
 static int rpu = 8;
 module_param(rpu, int, 0);
-MODULE_PARM_DESC(rpu, "Set internal pull up resitor for pen detect.");
+MODULE_PARM_DESC(rpu, "Set internal pull up resistor for pen detect.");
 
 /*
  * Set current used for pressure measurement.
index ca18d6d42a9be2a90389882f737a811d2c63dc54..a83cc2a2a2cab5464bd7b4f85d514b00afe580f2 100644 (file)
 #define ID0_CTTW                       (1 << 14)
 #define ID0_NUMIRPT_SHIFT              16
 #define ID0_NUMIRPT_MASK               0xff
+#define ID0_NUMSIDB_SHIFT              9
+#define ID0_NUMSIDB_MASK               0xf
 #define ID0_NUMSMRG_SHIFT              0
 #define ID0_NUMSMRG_MASK               0xff
 
@@ -524,9 +526,18 @@ static int register_smmu_master(struct arm_smmu_device *smmu,
        master->of_node                 = masterspec->np;
        master->cfg.num_streamids       = masterspec->args_count;
 
-       for (i = 0; i < master->cfg.num_streamids; ++i)
-               master->cfg.streamids[i] = masterspec->args[i];
+       for (i = 0; i < master->cfg.num_streamids; ++i) {
+               u16 streamid = masterspec->args[i];
 
+               if (!(smmu->features & ARM_SMMU_FEAT_STREAM_MATCH) &&
+                    (streamid >= smmu->num_mapping_groups)) {
+                       dev_err(dev,
+                               "stream ID for master device %s greater than maximum allowed (%d)\n",
+                               masterspec->np->name, smmu->num_mapping_groups);
+                       return -ERANGE;
+               }
+               master->cfg.streamids[i] = streamid;
+       }
        return insert_smmu_master(smmu, master);
 }
 
@@ -623,7 +634,7 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
 
        if (fsr & FSR_IGN)
                dev_err_ratelimited(smmu->dev,
-                                   "Unexpected context fault (fsr 0x%u)\n",
+                                   "Unexpected context fault (fsr 0x%x)\n",
                                    fsr);
 
        fsynr = readl_relaxed(cb_base + ARM_SMMU_CB_FSYNR0);
@@ -752,6 +763,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
                        reg = (TTBCR2_ADDR_36 << TTBCR2_SEP_SHIFT);
                        break;
                case 39:
+               case 40:
                        reg = (TTBCR2_ADDR_40 << TTBCR2_SEP_SHIFT);
                        break;
                case 42:
@@ -773,6 +785,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
                        reg |= (TTBCR2_ADDR_36 << TTBCR2_PASIZE_SHIFT);
                        break;
                case 39:
+               case 40:
                        reg |= (TTBCR2_ADDR_40 << TTBCR2_PASIZE_SHIFT);
                        break;
                case 42:
@@ -843,8 +856,11 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
        reg |= TTBCR_EAE |
              (TTBCR_SH_IS << TTBCR_SH0_SHIFT) |
              (TTBCR_RGN_WBWA << TTBCR_ORGN0_SHIFT) |
-             (TTBCR_RGN_WBWA << TTBCR_IRGN0_SHIFT) |
-             (TTBCR_SL0_LVL_1 << TTBCR_SL0_SHIFT);
+             (TTBCR_RGN_WBWA << TTBCR_IRGN0_SHIFT);
+
+       if (!stage1)
+               reg |= (TTBCR_SL0_LVL_1 << TTBCR_SL0_SHIFT);
+
        writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR);
 
        /* MAIR0 (stage-1 only) */
@@ -868,10 +884,15 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain)
 static int arm_smmu_init_domain_context(struct iommu_domain *domain,
                                        struct arm_smmu_device *smmu)
 {
-       int irq, ret, start;
+       int irq, start, ret = 0;
+       unsigned long flags;
        struct arm_smmu_domain *smmu_domain = domain->priv;
        struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
 
+       spin_lock_irqsave(&smmu_domain->lock, flags);
+       if (smmu_domain->smmu)
+               goto out_unlock;
+
        if (smmu->features & ARM_SMMU_FEAT_TRANS_NESTED) {
                /*
                 * We will likely want to change this if/when KVM gets
@@ -890,7 +911,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
        ret = __arm_smmu_alloc_bitmap(smmu->context_map, start,
                                      smmu->num_context_banks);
        if (IS_ERR_VALUE(ret))
-               return ret;
+               goto out_unlock;
 
        cfg->cbndx = ret;
        if (smmu->version == 1) {
@@ -900,6 +921,10 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
                cfg->irptndx = cfg->cbndx;
        }
 
+       ACCESS_ONCE(smmu_domain->smmu) = smmu;
+       arm_smmu_init_context_bank(smmu_domain);
+       spin_unlock_irqrestore(&smmu_domain->lock, flags);
+
        irq = smmu->irqs[smmu->num_global_irqs + cfg->irptndx];
        ret = request_irq(irq, arm_smmu_context_fault, IRQF_SHARED,
                          "arm-smmu-context-fault", domain);
@@ -907,15 +932,12 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
                dev_err(smmu->dev, "failed to request context IRQ %d (%u)\n",
                        cfg->irptndx, irq);
                cfg->irptndx = INVALID_IRPTNDX;
-               goto out_free_context;
        }
 
-       smmu_domain->smmu = smmu;
-       arm_smmu_init_context_bank(smmu_domain);
        return 0;
 
-out_free_context:
-       __arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
+out_unlock:
+       spin_unlock_irqrestore(&smmu_domain->lock, flags);
        return ret;
 }
 
@@ -975,7 +997,6 @@ static void arm_smmu_free_ptes(pmd_t *pmd)
 {
        pgtable_t table = pmd_pgtable(*pmd);
 
-       pgtable_page_dtor(table);
        __free_page(table);
 }
 
@@ -1108,6 +1129,9 @@ static void arm_smmu_master_free_smrs(struct arm_smmu_device *smmu,
        void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
        struct arm_smmu_smr *smrs = cfg->smrs;
 
+       if (!smrs)
+               return;
+
        /* Invalidate the SMRs before freeing back to the allocator */
        for (i = 0; i < cfg->num_streamids; ++i) {
                u8 idx = smrs[i].idx;
@@ -1120,20 +1144,6 @@ static void arm_smmu_master_free_smrs(struct arm_smmu_device *smmu,
        kfree(smrs);
 }
 
-static void arm_smmu_bypass_stream_mapping(struct arm_smmu_device *smmu,
-                                          struct arm_smmu_master_cfg *cfg)
-{
-       int i;
-       void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
-
-       for (i = 0; i < cfg->num_streamids; ++i) {
-               u16 sid = cfg->streamids[i];
-
-               writel_relaxed(S2CR_TYPE_BYPASS,
-                              gr0_base + ARM_SMMU_GR0_S2CR(sid));
-       }
-}
-
 static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
                                      struct arm_smmu_master_cfg *cfg)
 {
@@ -1160,23 +1170,30 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
 static void arm_smmu_domain_remove_master(struct arm_smmu_domain *smmu_domain,
                                          struct arm_smmu_master_cfg *cfg)
 {
+       int i;
        struct arm_smmu_device *smmu = smmu_domain->smmu;
+       void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
 
        /*
         * We *must* clear the S2CR first, because freeing the SMR means
         * that it can be re-allocated immediately.
         */
-       arm_smmu_bypass_stream_mapping(smmu, cfg);
+       for (i = 0; i < cfg->num_streamids; ++i) {
+               u32 idx = cfg->smrs ? cfg->smrs[i].idx : cfg->streamids[i];
+
+               writel_relaxed(S2CR_TYPE_BYPASS,
+                              gr0_base + ARM_SMMU_GR0_S2CR(idx));
+       }
+
        arm_smmu_master_free_smrs(smmu, cfg);
 }
 
 static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
 {
-       int ret = -EINVAL;
+       int ret;
        struct arm_smmu_domain *smmu_domain = domain->priv;
-       struct arm_smmu_device *smmu;
+       struct arm_smmu_device *smmu, *dom_smmu;
        struct arm_smmu_master_cfg *cfg;
-       unsigned long flags;
 
        smmu = dev_get_master_dev(dev)->archdata.iommu;
        if (!smmu) {
@@ -1188,20 +1205,22 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
         * Sanity check the domain. We don't support domains across
         * different SMMUs.
         */
-       spin_lock_irqsave(&smmu_domain->lock, flags);
-       if (!smmu_domain->smmu) {
+       dom_smmu = ACCESS_ONCE(smmu_domain->smmu);
+       if (!dom_smmu) {
                /* Now that we have a master, we can finalise the domain */
                ret = arm_smmu_init_domain_context(domain, smmu);
                if (IS_ERR_VALUE(ret))
-                       goto err_unlock;
-       } else if (smmu_domain->smmu != smmu) {
+                       return ret;
+
+               dom_smmu = smmu_domain->smmu;
+       }
+
+       if (dom_smmu != smmu) {
                dev_err(dev,
                        "cannot attach to SMMU %s whilst already attached to domain on SMMU %s\n",
-                       dev_name(smmu_domain->smmu->dev),
-                       dev_name(smmu->dev));
-               goto err_unlock;
+                       dev_name(smmu_domain->smmu->dev), dev_name(smmu->dev));
+               return -EINVAL;
        }
-       spin_unlock_irqrestore(&smmu_domain->lock, flags);
 
        /* Looks ok, so add the device to the domain */
        cfg = find_smmu_master_cfg(smmu_domain->smmu, dev);
@@ -1209,10 +1228,6 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
                return -ENODEV;
 
        return arm_smmu_domain_add_master(smmu_domain, cfg);
-
-err_unlock:
-       spin_unlock_irqrestore(&smmu_domain->lock, flags);
-       return ret;
 }
 
 static void arm_smmu_detach_dev(struct iommu_domain *domain, struct device *dev)
@@ -1247,10 +1262,6 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd,
                        return -ENOMEM;
 
                arm_smmu_flush_pgtable(smmu, page_address(table), PAGE_SIZE);
-               if (!pgtable_page_ctor(table)) {
-                       __free_page(table);
-                       return -ENOMEM;
-               }
                pmd_populate(NULL, pmd, table);
                arm_smmu_flush_pgtable(smmu, pmd, sizeof(*pmd));
        }
@@ -1626,7 +1637,7 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
 
        /* Mark all SMRn as invalid and all S2CRn as bypass */
        for (i = 0; i < smmu->num_mapping_groups; ++i) {
-               writel_relaxed(~SMR_VALID, gr0_base + ARM_SMMU_GR0_SMR(i));
+               writel_relaxed(0, gr0_base + ARM_SMMU_GR0_SMR(i));
                writel_relaxed(S2CR_TYPE_BYPASS,
                        gr0_base + ARM_SMMU_GR0_S2CR(i));
        }
@@ -1761,6 +1772,9 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
                dev_notice(smmu->dev,
                           "\tstream matching with %u register groups, mask 0x%x",
                           smmu->num_mapping_groups, mask);
+       } else {
+               smmu->num_mapping_groups = (id >> ID0_NUMSIDB_SHIFT) &
+                                          ID0_NUMSIDB_MASK;
        }
 
        /* ID1 */
@@ -1794,11 +1808,16 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
         * Stage-1 output limited by stage-2 input size due to pgd
         * allocation (PTRS_PER_PGD).
         */
+       if (smmu->features & ARM_SMMU_FEAT_TRANS_NESTED) {
 #ifdef CONFIG_64BIT
-       smmu->s1_output_size = min_t(unsigned long, VA_BITS, size);
+               smmu->s1_output_size = min_t(unsigned long, VA_BITS, size);
 #else
-       smmu->s1_output_size = min(32UL, size);
+               smmu->s1_output_size = min(32UL, size);
 #endif
+       } else {
+               smmu->s1_output_size = min_t(unsigned long, PHYS_MASK_SHIFT,
+                                            size);
+       }
 
        /* The stage-2 output mask is also applied for bypass */
        size = arm_smmu_id_size_to_bits((id >> ID2_OAS_SHIFT) & ID2_OAS_MASK);
@@ -1889,6 +1908,10 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
                smmu->irqs[i] = irq;
        }
 
+       err = arm_smmu_device_cfg_probe(smmu);
+       if (err)
+               return err;
+
        i = 0;
        smmu->masters = RB_ROOT;
        while (!of_parse_phandle_with_args(dev->of_node, "mmu-masters",
@@ -1905,10 +1928,6 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev)
        }
        dev_notice(dev, "registered %d master devices\n", i);
 
-       err = arm_smmu_device_cfg_probe(smmu);
-       if (err)
-               goto out_put_masters;
-
        parse_driver_options(smmu);
 
        if (smmu->version > 1 &&
index 60ab474bfff38e58ba1e246d7da6ca3a201677cb..06d268abe951bebd946deac82cf092f3f7a67ee3 100644 (file)
@@ -678,8 +678,7 @@ static int __init dmar_acpi_dev_scope_init(void)
                                       andd->device_name);
                                continue;
                        }
-                       acpi_bus_get_device(h, &adev);
-                       if (!adev) {
+                       if (acpi_bus_get_device(h, &adev)) {
                                pr_err("Failed to get device for ACPI object %s\n",
                                       andd->device_name);
                                continue;
index 61d1dafa242d7d01bfff167f610774aff547b1eb..56feed7cec15ca77ef23df1e214e79f58d74935c 100644 (file)
@@ -984,7 +984,7 @@ static int fsl_pamu_add_device(struct device *dev)
        struct iommu_group *group = ERR_PTR(-ENODEV);
        struct pci_dev *pdev;
        const u32 *prop;
-       int ret, len;
+       int ret = 0, len;
 
        /*
         * For platform devices we allocate a separate group for
@@ -1007,7 +1007,13 @@ static int fsl_pamu_add_device(struct device *dev)
        if (IS_ERR(group))
                return PTR_ERR(group);
 
-       ret = iommu_group_add_device(group, dev);
+       /*
+        * Check if device has already been added to an iommu group.
+        * Group could have already been created for a PCI device in
+        * the iommu_group_get_for_dev path.
+        */
+       if (!dev->iommu_group)
+               ret = iommu_group_add_device(group, dev);
 
        iommu_group_put(group);
        return ret;
index ac4adb337038bc990077a2c0557d1f07d8b1de8e..0639b9274b114ac24de51446a636d43f8497557e 100644 (file)
@@ -678,15 +678,17 @@ static struct iommu_group *iommu_group_get_for_pci_dev(struct pci_dev *pdev)
  */
 struct iommu_group *iommu_group_get_for_dev(struct device *dev)
 {
-       struct iommu_group *group = ERR_PTR(-EIO);
+       struct iommu_group *group;
        int ret;
 
        group = iommu_group_get(dev);
        if (group)
                return group;
 
-       if (dev_is_pci(dev))
-               group = iommu_group_get_for_pci_dev(to_pci_dev(dev));
+       if (!dev_is_pci(dev))
+               return ERR_PTR(-EINVAL);
+
+       group = iommu_group_get_for_pci_dev(to_pci_dev(dev));
 
        if (IS_ERR(group))
                return group;
index 129729d35478bf5934cb69c90a688a9c43399759..aa29198fca3e2b2c892268eb2549444b1beb499c 100644 (file)
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/device.h>
+#include <linux/timer.h>
 #include <linux/err.h>
 #include <linux/ctype.h>
 #include <linux/leds.h>
-#include <linux/workqueue.h>
 #include "leds.h"
 
 static struct class *leds_class;
@@ -97,10 +97,9 @@ static const struct attribute_group *led_groups[] = {
        NULL,
 };
 
-static void led_work_function(struct work_struct *ws)
+static void led_timer_function(unsigned long data)
 {
-       struct led_classdev *led_cdev =
-               container_of(ws, struct led_classdev, blink_work.work);
+       struct led_classdev *led_cdev = (void *)data;
        unsigned long brightness;
        unsigned long delay;
 
@@ -144,8 +143,7 @@ static void led_work_function(struct work_struct *ws)
                }
        }
 
-       queue_delayed_work(system_wq, &led_cdev->blink_work,
-                          msecs_to_jiffies(delay));
+       mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay));
 }
 
 static void set_brightness_delayed(struct work_struct *ws)
@@ -233,7 +231,9 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
 
        INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed);
 
-       INIT_DELAYED_WORK(&led_cdev->blink_work, led_work_function);
+       init_timer(&led_cdev->blink_timer);
+       led_cdev->blink_timer.function = led_timer_function;
+       led_cdev->blink_timer.data = (unsigned long)led_cdev;
 
 #ifdef CONFIG_LEDS_TRIGGERS
        led_trigger_set_default(led_cdev);
index 4bb116867b88af7249c1576e614e8ad0685f7945..71b40d3bf77604e32829f391b6e804bbeefb0cf1 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/module.h>
 #include <linux/rwsem.h>
 #include <linux/leds.h>
-#include <linux/workqueue.h>
 #include "leds.h"
 
 DECLARE_RWSEM(leds_list_lock);
@@ -52,7 +51,7 @@ static void led_set_software_blink(struct led_classdev *led_cdev,
                return;
        }
 
-       queue_delayed_work(system_wq, &led_cdev->blink_work, 1);
+       mod_timer(&led_cdev->blink_timer, jiffies + 1);
 }
 
 
@@ -76,7 +75,7 @@ void led_blink_set(struct led_classdev *led_cdev,
                   unsigned long *delay_on,
                   unsigned long *delay_off)
 {
-       cancel_delayed_work_sync(&led_cdev->blink_work);
+       del_timer_sync(&led_cdev->blink_timer);
 
        led_cdev->flags &= ~LED_BLINK_ONESHOT;
        led_cdev->flags &= ~LED_BLINK_ONESHOT_STOP;
@@ -91,7 +90,7 @@ void led_blink_set_oneshot(struct led_classdev *led_cdev,
                           int invert)
 {
        if ((led_cdev->flags & LED_BLINK_ONESHOT) &&
-            delayed_work_pending(&led_cdev->blink_work))
+            timer_pending(&led_cdev->blink_timer))
                return;
 
        led_cdev->flags |= LED_BLINK_ONESHOT;
@@ -108,7 +107,7 @@ EXPORT_SYMBOL(led_blink_set_oneshot);
 
 void led_stop_software_blink(struct led_classdev *led_cdev)
 {
-       cancel_delayed_work_sync(&led_cdev->blink_work);
+       del_timer_sync(&led_cdev->blink_timer);
        led_cdev->blink_delay_on = 0;
        led_cdev->blink_delay_off = 0;
 }
@@ -117,7 +116,7 @@ EXPORT_SYMBOL_GPL(led_stop_software_blink);
 void led_set_brightness(struct led_classdev *led_cdev,
                        enum led_brightness brightness)
 {
-       /* delay brightness setting if need to stop soft-blink work */
+       /* delay brightness setting if need to stop soft-blink timer */
        if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) {
                led_cdev->delayed_set_value = brightness;
                schedule_work(&led_cdev->set_brightness_work);
index ce48aa72bb429ef724eb4f15cb695e9c70d3a8e2..bde2fc0724103a26864476cb27e0718c3937e2a9 100644 (file)
@@ -1754,7 +1754,7 @@ static int ab8500_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-#if CONFIG_DEBUG_FS
+#ifdef CONFIG_DEBUG_FS
        /* Pass to debugfs */
        ab8500_debug_resources[0].start = ab8500->irq;
        ab8500_debug_resources[0].end = ab8500->irq;
index b44f0203983bfb5117c02be8469074814c24a18f..6bdb78c2ac77de535214d80a09cd9a302653d219 100644 (file)
@@ -404,7 +404,7 @@ static int htcpld_register_chip_i2c(
        }
 
        i2c_set_clientdata(client, chip);
-       snprintf(client->name, I2C_NAME_SIZE, "Chip_0x%d", client->addr);
+       snprintf(client->name, I2C_NAME_SIZE, "Chip_0x%x", client->addr);
        chip->client = client;
 
        /* Reset the chip */
index 33a9234b701c51b7c30c899c026fc92f6d4a0771..83dab2f0a50e2a1f6d63fe3d340d38a85b4afe3b 100644 (file)
@@ -647,7 +647,7 @@ static int usbhs_omap_probe(struct platform_device *pdev)
                default:
                        omap->nports = OMAP3_HS_USB_PORTS;
                        dev_dbg(dev,
-                        "USB HOST Rev:0x%d not recognized, assuming %d ports\n",
+                        "USB HOST Rev:0x%x not recognized, assuming %d ports\n",
                         omap->usbhs_rev, omap->nports);
                        break;
                }
index 3bc969a5916b8249c193a44e71eb89c4c077be85..4d3ff37714916451903f39aa30d47ab46e0f4d62 100644 (file)
@@ -724,24 +724,24 @@ static struct twl4030_script *omap3_idle_scripts[] = {
  * above.
  */
 static struct twl4030_resconfig omap3_idle_rconfig[] = {
-       TWL_REMAP_SLEEP(RES_VAUX1, DEV_GRP_NULL, 0, 0),
-       TWL_REMAP_SLEEP(RES_VAUX2, DEV_GRP_NULL, 0, 0),
-       TWL_REMAP_SLEEP(RES_VAUX3, DEV_GRP_NULL, 0, 0),
-       TWL_REMAP_SLEEP(RES_VAUX4, DEV_GRP_NULL, 0, 0),
-       TWL_REMAP_SLEEP(RES_VMMC1, DEV_GRP_NULL, 0, 0),
-       TWL_REMAP_SLEEP(RES_VMMC2, DEV_GRP_NULL, 0, 0),
+       TWL_REMAP_SLEEP(RES_VAUX1, TWL4030_RESCONFIG_UNDEF, 0, 0),
+       TWL_REMAP_SLEEP(RES_VAUX2, TWL4030_RESCONFIG_UNDEF, 0, 0),
+       TWL_REMAP_SLEEP(RES_VAUX3, TWL4030_RESCONFIG_UNDEF, 0, 0),
+       TWL_REMAP_SLEEP(RES_VAUX4, TWL4030_RESCONFIG_UNDEF, 0, 0),
+       TWL_REMAP_SLEEP(RES_VMMC1, TWL4030_RESCONFIG_UNDEF, 0, 0),
+       TWL_REMAP_SLEEP(RES_VMMC2, TWL4030_RESCONFIG_UNDEF, 0, 0),
        TWL_REMAP_OFF(RES_VPLL1, DEV_GRP_P1, 3, 1),
        TWL_REMAP_SLEEP(RES_VPLL2, DEV_GRP_P1, 0, 0),
-       TWL_REMAP_SLEEP(RES_VSIM, DEV_GRP_NULL, 0, 0),
-       TWL_REMAP_SLEEP(RES_VDAC, DEV_GRP_NULL, 0, 0),
+       TWL_REMAP_SLEEP(RES_VSIM, TWL4030_RESCONFIG_UNDEF, 0, 0),
+       TWL_REMAP_SLEEP(RES_VDAC, TWL4030_RESCONFIG_UNDEF, 0, 0),
        TWL_REMAP_SLEEP(RES_VINTANA1, TWL_DEV_GRP_P123, 1, 2),
        TWL_REMAP_SLEEP(RES_VINTANA2, TWL_DEV_GRP_P123, 0, 2),
        TWL_REMAP_SLEEP(RES_VINTDIG, TWL_DEV_GRP_P123, 1, 2),
        TWL_REMAP_SLEEP(RES_VIO, TWL_DEV_GRP_P123, 2, 2),
        TWL_REMAP_OFF(RES_VDD1, DEV_GRP_P1, 4, 1),
        TWL_REMAP_OFF(RES_VDD2, DEV_GRP_P1, 3, 1),
-       TWL_REMAP_SLEEP(RES_VUSB_1V5, DEV_GRP_NULL, 0, 0),
-       TWL_REMAP_SLEEP(RES_VUSB_1V8, DEV_GRP_NULL, 0, 0),
+       TWL_REMAP_SLEEP(RES_VUSB_1V5, TWL4030_RESCONFIG_UNDEF, 0, 0),
+       TWL_REMAP_SLEEP(RES_VUSB_1V8, TWL4030_RESCONFIG_UNDEF, 0, 0),
        TWL_REMAP_SLEEP(RES_VUSB_3V1, TWL_DEV_GRP_P123, 0, 0),
        /* Resource #20 USB charge pump skipped */
        TWL_REMAP_SLEEP(RES_REGEN, TWL_DEV_GRP_P123, 2, 1),
index 7ffdb589841ed2fe2e25ec2580218e4dfd07a2a2..7e1efd5f58f0b04ed8b303d142628755f56a72d7 100644 (file)
@@ -79,6 +79,11 @@ static void firmware_load(const struct firmware *fw, void *context)
        u32 jedec_id;
        u32 status;
 
+       if (fw == NULL) {
+               dev_err(&spi->dev, "Cannot load firmware, aborting\n");
+               return;
+       }
+
        if (fw->size == 0) {
                dev_err(&spi->dev, "Error: Firmware size is 0!\n");
                return;
index 324e1de936871952c726d42a33826c19a827cdb8..2da05c0e113d0b62d917e4de4b12e15b46defac8 100644 (file)
@@ -601,6 +601,7 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
                cl->timer_count = MEI_CONNECT_TIMEOUT;
                list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
        } else {
+               cl->state = MEI_FILE_INITIALIZING;
                list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
        }
 
index 3095fc514a65f3a44868587e6adae91b0eef5612..5ccc23bc76904a3b1dbe2770667e7aad502f96cf 100644 (file)
@@ -342,9 +342,10 @@ static int mei_nfc_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
        ndev = (struct mei_nfc_dev *) cldev->priv_data;
        dev = ndev->cl->dev;
 
+       err = -ENOMEM;
        mei_buf = kzalloc(length + MEI_NFC_HEADER_SIZE, GFP_KERNEL);
        if (!mei_buf)
-               return -ENOMEM;
+               goto out;
 
        hdr = (struct mei_nfc_hci_hdr *) mei_buf;
        hdr->cmd = MEI_NFC_CMD_HCI_SEND;
@@ -354,12 +355,9 @@ static int mei_nfc_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
        hdr->data_size = length;
 
        memcpy(mei_buf + MEI_NFC_HEADER_SIZE, buf, length);
-
        err = __mei_cl_send(ndev->cl, mei_buf, length + MEI_NFC_HEADER_SIZE);
        if (err < 0)
-               return err;
-
-       kfree(mei_buf);
+               goto out;
 
        if (!wait_event_interruptible_timeout(ndev->send_wq,
                                ndev->recv_req_id == ndev->req_id, HZ)) {
@@ -368,7 +366,8 @@ static int mei_nfc_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
        } else {
                ndev->req_id++;
        }
-
+out:
+       kfree(mei_buf);
        return err;
 }
 
index 5a4bfe33112aba9307bdeac6877a4404b24bc7e7..46c4643b7a0776986890bef600674ec3823d01f0 100644 (file)
@@ -1434,6 +1434,10 @@ static int cfi_amdstd_otp_walk(struct mtd_info *mtd, loff_t from, size_t len,
 
                                mutex_lock(&chip->mutex);
                                ret = get_chip(map, chip, base, FL_LOCKING);
+                               if (ret) {
+                                       mutex_unlock(&chip->mutex);
+                                       return ret;
+                               }
 
                                /* Enter lock register command */
                                cfi_send_gen_cmd(0xAA, cfi->addr_unlock1,
index f0ed92e210a1fc39d1944e8240d0f4728d91835b..5967b385141b7f49bc669beda18ac69fbd7e06d0 100644 (file)
@@ -931,7 +931,7 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
        u32 val;
 
        val = readl(info->reg.gpmc_ecc_config);
-       if (((val >> ECC_CONFIG_CS_SHIFT)  & ~CS_MASK) != info->gpmc_cs)
+       if (((val >> ECC_CONFIG_CS_SHIFT) CS_MASK) != info->gpmc_cs)
                return -EINVAL;
 
        /* read ecc result */
@@ -1794,9 +1794,12 @@ static int omap_nand_probe(struct platform_device *pdev)
        }
 
        /* populate MTD interface based on ECC scheme */
-       nand_chip->ecc.layout   = &omap_oobinfo;
        ecclayout               = &omap_oobinfo;
        switch (info->ecc_opt) {
+       case OMAP_ECC_HAM1_CODE_SW:
+               nand_chip->ecc.mode = NAND_ECC_SOFT;
+               break;
+
        case OMAP_ECC_HAM1_CODE_HW:
                pr_info("nand: using OMAP_ECC_HAM1_CODE_HW\n");
                nand_chip->ecc.mode             = NAND_ECC_HW;
@@ -1848,7 +1851,7 @@ static int omap_nand_probe(struct platform_device *pdev)
                nand_chip->ecc.priv             = nand_bch_init(mtd,
                                                        nand_chip->ecc.size,
                                                        nand_chip->ecc.bytes,
-                                                       &nand_chip->ecc.layout);
+                                                       &ecclayout);
                if (!nand_chip->ecc.priv) {
                        pr_err("nand: error: unable to use s/w BCH library\n");
                        err = -EINVAL;
@@ -1923,7 +1926,7 @@ static int omap_nand_probe(struct platform_device *pdev)
                nand_chip->ecc.priv             = nand_bch_init(mtd,
                                                        nand_chip->ecc.size,
                                                        nand_chip->ecc.bytes,
-                                                       &nand_chip->ecc.layout);
+                                                       &ecclayout);
                if (!nand_chip->ecc.priv) {
                        pr_err("nand: error: unable to use s/w BCH library\n");
                        err = -EINVAL;
@@ -2012,6 +2015,9 @@ static int omap_nand_probe(struct platform_device *pdev)
                goto return_error;
        }
 
+       if (info->ecc_opt == OMAP_ECC_HAM1_CODE_SW)
+               goto scan_tail;
+
        /* all OOB bytes from oobfree->offset till end off OOB are free */
        ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset;
        /* check if NAND device's OOB is enough to store ECC signatures */
@@ -2021,7 +2027,9 @@ static int omap_nand_probe(struct platform_device *pdev)
                err = -EINVAL;
                goto return_error;
        }
+       nand_chip->ecc.layout = ecclayout;
 
+scan_tail:
        /* second phase scan */
        if (nand_scan_tail(mtd)) {
                err = -ENXIO;
index 059c7414e30318b3ccaab436a248d63319823369..3fe45c705933f08a0aaa5b269362e1afe4300813 100644 (file)
@@ -2177,10 +2177,10 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
                        vp->tx_ring[entry].frag[i+1].addr =
-                                       cpu_to_le32(pci_map_single(
-                                               VORTEX_PCI(vp),
-                                               (void *)skb_frag_address(frag),
-                                               skb_frag_size(frag), PCI_DMA_TODEVICE));
+                                       cpu_to_le32(skb_frag_dma_map(
+                                               &VORTEX_PCI(vp)->dev,
+                                               frag,
+                                               frag->page_offset, frag->size, DMA_TO_DEVICE));
 
                        if (i == skb_shinfo(skb)->nr_frags-1)
                                        vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(skb_frag_size(frag)|LAST_FRAG);
index 23578dfee249879064c1b86526ee80aead68b79f..3005155e412b2e0e1ab1d2c969e4895a2723644c 100644 (file)
@@ -123,6 +123,12 @@ static inline void greth_enable_tx(struct greth_private *greth)
        GRETH_REGORIN(greth->regs->control, GRETH_TXEN);
 }
 
+static inline void greth_enable_tx_and_irq(struct greth_private *greth)
+{
+       wmb(); /* BDs must been written to memory before enabling TX */
+       GRETH_REGORIN(greth->regs->control, GRETH_TXEN | GRETH_TXI);
+}
+
 static inline void greth_disable_tx(struct greth_private *greth)
 {
        GRETH_REGANDIN(greth->regs->control, ~GRETH_TXEN);
@@ -447,29 +453,30 @@ out:
        return err;
 }
 
+static inline u16 greth_num_free_bds(u16 tx_last, u16 tx_next)
+{
+       if (tx_next < tx_last)
+               return (tx_last - tx_next) - 1;
+       else
+               return GRETH_TXBD_NUM - (tx_next - tx_last) - 1;
+}
 
 static netdev_tx_t
 greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev)
 {
        struct greth_private *greth = netdev_priv(dev);
        struct greth_bd *bdp;
-       u32 status = 0, dma_addr, ctrl;
+       u32 status, dma_addr;
        int curr_tx, nr_frags, i, err = NETDEV_TX_OK;
        unsigned long flags;
+       u16 tx_last;
 
        nr_frags = skb_shinfo(skb)->nr_frags;
+       tx_last = greth->tx_last;
+       rmb(); /* tx_last is updated by the poll task */
 
-       /* Clean TX Ring */
-       greth_clean_tx_gbit(dev);
-
-       if (greth->tx_free < nr_frags + 1) {
-               spin_lock_irqsave(&greth->devlock, flags);/*save from poll/irq*/
-               ctrl = GRETH_REGLOAD(greth->regs->control);
-               /* Enable TX IRQ only if not already in poll() routine */
-               if (ctrl & GRETH_RXI)
-                       GRETH_REGSAVE(greth->regs->control, ctrl | GRETH_TXI);
+       if (greth_num_free_bds(tx_last, greth->tx_next) < nr_frags + 1) {
                netif_stop_queue(dev);
-               spin_unlock_irqrestore(&greth->devlock, flags);
                err = NETDEV_TX_BUSY;
                goto out;
        }
@@ -488,6 +495,8 @@ greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev)
        /* Linear buf */
        if (nr_frags != 0)
                status = GRETH_TXBD_MORE;
+       else
+               status = GRETH_BD_IE;
 
        if (skb->ip_summed == CHECKSUM_PARTIAL)
                status |= GRETH_TXBD_CSALL;
@@ -545,14 +554,12 @@ greth_start_xmit_gbit(struct sk_buff *skb, struct net_device *dev)
 
        /* Enable the descriptor chain by enabling the first descriptor */
        bdp = greth->tx_bd_base + greth->tx_next;
-       greth_write_bd(&bdp->stat, greth_read_bd(&bdp->stat) | GRETH_BD_EN);
-       greth->tx_next = curr_tx;
-       greth->tx_free -= nr_frags + 1;
-
-       wmb();
+       greth_write_bd(&bdp->stat,
+                      greth_read_bd(&bdp->stat) | GRETH_BD_EN);
 
        spin_lock_irqsave(&greth->devlock, flags); /*save from poll/irq*/
-       greth_enable_tx(greth);
+       greth->tx_next = curr_tx;
+       greth_enable_tx_and_irq(greth);
        spin_unlock_irqrestore(&greth->devlock, flags);
 
        return NETDEV_TX_OK;
@@ -648,7 +655,6 @@ static void greth_clean_tx(struct net_device *dev)
        if (greth->tx_free > 0) {
                netif_wake_queue(dev);
        }
-
 }
 
 static inline void greth_update_tx_stats(struct net_device *dev, u32 stat)
@@ -670,20 +676,22 @@ static void greth_clean_tx_gbit(struct net_device *dev)
 {
        struct greth_private *greth;
        struct greth_bd *bdp, *bdp_last_frag;
-       struct sk_buff *skb;
+       struct sk_buff *skb = NULL;
        u32 stat;
        int nr_frags, i;
+       u16 tx_last;
 
        greth = netdev_priv(dev);
+       tx_last = greth->tx_last;
 
-       while (greth->tx_free < GRETH_TXBD_NUM) {
+       while (tx_last != greth->tx_next) {
 
-               skb = greth->tx_skbuff[greth->tx_last];
+               skb = greth->tx_skbuff[tx_last];
 
                nr_frags = skb_shinfo(skb)->nr_frags;
 
                /* We only clean fully completed SKBs */
-               bdp_last_frag = greth->tx_bd_base + SKIP_TX(greth->tx_last, nr_frags);
+               bdp_last_frag = greth->tx_bd_base + SKIP_TX(tx_last, nr_frags);
 
                GRETH_REGSAVE(greth->regs->status, GRETH_INT_TE | GRETH_INT_TX);
                mb();
@@ -692,14 +700,14 @@ static void greth_clean_tx_gbit(struct net_device *dev)
                if (stat & GRETH_BD_EN)
                        break;
 
-               greth->tx_skbuff[greth->tx_last] = NULL;
+               greth->tx_skbuff[tx_last] = NULL;
 
                greth_update_tx_stats(dev, stat);
                dev->stats.tx_bytes += skb->len;
 
-               bdp = greth->tx_bd_base + greth->tx_last;
+               bdp = greth->tx_bd_base + tx_last;
 
-               greth->tx_last = NEXT_TX(greth->tx_last);
+               tx_last = NEXT_TX(tx_last);
 
                dma_unmap_single(greth->dev,
                                 greth_read_bd(&bdp->addr),
@@ -708,21 +716,26 @@ static void greth_clean_tx_gbit(struct net_device *dev)
 
                for (i = 0; i < nr_frags; i++) {
                        skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
-                       bdp = greth->tx_bd_base + greth->tx_last;
+                       bdp = greth->tx_bd_base + tx_last;
 
                        dma_unmap_page(greth->dev,
                                       greth_read_bd(&bdp->addr),
                                       skb_frag_size(frag),
                                       DMA_TO_DEVICE);
 
-                       greth->tx_last = NEXT_TX(greth->tx_last);
+                       tx_last = NEXT_TX(tx_last);
                }
-               greth->tx_free += nr_frags+1;
                dev_kfree_skb(skb);
        }
+       if (skb) { /* skb is set only if the above while loop was entered */
+               wmb();
+               greth->tx_last = tx_last;
 
-       if (netif_queue_stopped(dev) && (greth->tx_free > (MAX_SKB_FRAGS+1)))
-               netif_wake_queue(dev);
+               if (netif_queue_stopped(dev) &&
+                   (greth_num_free_bds(tx_last, greth->tx_next) >
+                   (MAX_SKB_FRAGS+1)))
+                       netif_wake_queue(dev);
+       }
 }
 
 static int greth_rx(struct net_device *dev, int limit)
@@ -965,16 +978,12 @@ static int greth_poll(struct napi_struct *napi, int budget)
        greth = container_of(napi, struct greth_private, napi);
 
 restart_txrx_poll:
-       if (netif_queue_stopped(greth->netdev)) {
-               if (greth->gbit_mac)
-                       greth_clean_tx_gbit(greth->netdev);
-               else
-                       greth_clean_tx(greth->netdev);
-       }
-
        if (greth->gbit_mac) {
+               greth_clean_tx_gbit(greth->netdev);
                work_done += greth_rx_gbit(greth->netdev, budget - work_done);
        } else {
+               if (netif_queue_stopped(greth->netdev))
+                       greth_clean_tx(greth->netdev);
                work_done += greth_rx(greth->netdev, budget - work_done);
        }
 
@@ -983,7 +992,8 @@ restart_txrx_poll:
                spin_lock_irqsave(&greth->devlock, flags);
 
                ctrl = GRETH_REGLOAD(greth->regs->control);
-               if (netif_queue_stopped(greth->netdev)) {
+               if ((greth->gbit_mac && (greth->tx_last != greth->tx_next)) ||
+                   (!greth->gbit_mac && netif_queue_stopped(greth->netdev))) {
                        GRETH_REGSAVE(greth->regs->control,
                                        ctrl | GRETH_TXI | GRETH_RXI);
                        mask = GRETH_INT_RX | GRETH_INT_RE |
index 232a622a85b7006ce8cb235f1d9790ea7b2c4929..ae16ac94daf825a5b800356603cb1c1213636d34 100644 (file)
@@ -107,7 +107,7 @@ struct greth_private {
 
        u16 tx_next;
        u16 tx_last;
-       u16 tx_free;
+       u16 tx_free; /* only used on 10/100Mbit */
        u16 rx_cur;
 
        struct greth_regs *regs;        /* Address of controller registers. */
index 346592dca33ce98dd94e24f33f99eabb373f60cb..a3c11355a34dd199a40252dab901ab23cb908ffb 100644 (file)
@@ -272,8 +272,8 @@ static ssize_t xpcs_reg_value_read(struct file *filp, char __user *buffer,
        struct xgbe_prv_data *pdata = filp->private_data;
        unsigned int value;
 
-       value = pdata->hw_if.read_mmd_regs(pdata, pdata->debugfs_xpcs_mmd,
-                                          pdata->debugfs_xpcs_reg);
+       value = XMDIO_READ(pdata, pdata->debugfs_xpcs_mmd,
+                          pdata->debugfs_xpcs_reg);
 
        return xgbe_common_read(buffer, count, ppos, value);
 }
@@ -290,8 +290,8 @@ static ssize_t xpcs_reg_value_write(struct file *filp,
        if (len < 0)
                return len;
 
-       pdata->hw_if.write_mmd_regs(pdata, pdata->debugfs_xpcs_mmd,
-                                   pdata->debugfs_xpcs_reg, value);
+       XMDIO_WRITE(pdata, pdata->debugfs_xpcs_mmd, pdata->debugfs_xpcs_reg,
+                   value);
 
        return len;
 }
index edaca4496264862063835a444594471df29658a2..ea273836d999c854d89d45789e33d1ff81afc92b 100644 (file)
@@ -348,7 +348,7 @@ static int xgbe_disable_tx_flow_control(struct xgbe_prv_data *pdata)
 
        /* Clear MAC flow control */
        max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
-       q_count = min_t(unsigned int, pdata->rx_q_count, max_q_count);
+       q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count);
        reg = MAC_Q0TFCR;
        for (i = 0; i < q_count; i++) {
                reg_val = XGMAC_IOREAD(pdata, reg);
@@ -373,7 +373,7 @@ static int xgbe_enable_tx_flow_control(struct xgbe_prv_data *pdata)
 
        /* Set MAC flow control */
        max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
-       q_count = min_t(unsigned int, pdata->rx_q_count, max_q_count);
+       q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count);
        reg = MAC_Q0TFCR;
        for (i = 0; i < q_count; i++) {
                reg_val = XGMAC_IOREAD(pdata, reg);
@@ -509,8 +509,8 @@ static void xgbe_enable_mac_interrupts(struct xgbe_prv_data *pdata)
        XGMAC_IOWRITE(pdata, MAC_IER, mac_ier);
 
        /* Enable all counter interrupts */
-       XGMAC_IOWRITE_BITS(pdata, MMC_RIER, ALL_INTERRUPTS, 0xff);
-       XGMAC_IOWRITE_BITS(pdata, MMC_TIER, ALL_INTERRUPTS, 0xff);
+       XGMAC_IOWRITE_BITS(pdata, MMC_RIER, ALL_INTERRUPTS, 0xffffffff);
+       XGMAC_IOWRITE_BITS(pdata, MMC_TIER, ALL_INTERRUPTS, 0xffffffff);
 }
 
 static int xgbe_set_gmii_speed(struct xgbe_prv_data *pdata)
@@ -1633,6 +1633,9 @@ static int xgbe_flush_tx_queues(struct xgbe_prv_data *pdata)
 {
        unsigned int i, count;
 
+       if (XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER) < 0x21)
+               return 0;
+
        for (i = 0; i < pdata->tx_q_count; i++)
                XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_TQOMR, FTQ, 1);
 
@@ -1703,8 +1706,8 @@ static void xgbe_config_mtl_mode(struct xgbe_prv_data *pdata)
        XGMAC_IOWRITE_BITS(pdata, MTL_OMR, RAA, MTL_RAA_SP);
 }
 
-static unsigned int xgbe_calculate_per_queue_fifo(unsigned long fifo_size,
-                                                 unsigned char queue_count)
+static unsigned int xgbe_calculate_per_queue_fifo(unsigned int fifo_size,
+                                                 unsigned int queue_count)
 {
        unsigned int q_fifo_size = 0;
        enum xgbe_mtl_fifo_size p_fifo = XGMAC_MTL_FIFO_SIZE_256;
@@ -1748,6 +1751,10 @@ static unsigned int xgbe_calculate_per_queue_fifo(unsigned long fifo_size,
                q_fifo_size = XGBE_FIFO_SIZE_KB(256);
                break;
        }
+
+       /* The configured value is not the actual amount of fifo RAM */
+       q_fifo_size = min_t(unsigned int, XGBE_FIFO_MAX, q_fifo_size);
+
        q_fifo_size = q_fifo_size / queue_count;
 
        /* Set the queue fifo size programmable value */
@@ -1947,6 +1954,32 @@ static void xgbe_config_vlan_support(struct xgbe_prv_data *pdata)
                xgbe_disable_rx_vlan_stripping(pdata);
 }
 
+static u64 xgbe_mmc_read(struct xgbe_prv_data *pdata, unsigned int reg_lo)
+{
+       bool read_hi;
+       u64 val;
+
+       switch (reg_lo) {
+       /* These registers are always 64 bit */
+       case MMC_TXOCTETCOUNT_GB_LO:
+       case MMC_TXOCTETCOUNT_G_LO:
+       case MMC_RXOCTETCOUNT_GB_LO:
+       case MMC_RXOCTETCOUNT_G_LO:
+               read_hi = true;
+               break;
+
+       default:
+               read_hi = false;
+       };
+
+       val = XGMAC_IOREAD(pdata, reg_lo);
+
+       if (read_hi)
+               val |= ((u64)XGMAC_IOREAD(pdata, reg_lo + 4) << 32);
+
+       return val;
+}
+
 static void xgbe_tx_mmc_int(struct xgbe_prv_data *pdata)
 {
        struct xgbe_mmc_stats *stats = &pdata->mmc_stats;
@@ -1954,75 +1987,75 @@ static void xgbe_tx_mmc_int(struct xgbe_prv_data *pdata)
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXOCTETCOUNT_GB))
                stats->txoctetcount_gb +=
-                       XGMAC_IOREAD(pdata, MMC_TXOCTETCOUNT_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_TXOCTETCOUNT_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXFRAMECOUNT_GB))
                stats->txframecount_gb +=
-                       XGMAC_IOREAD(pdata, MMC_TXFRAMECOUNT_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_TXFRAMECOUNT_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXBROADCASTFRAMES_G))
                stats->txbroadcastframes_g +=
-                       XGMAC_IOREAD(pdata, MMC_TXBROADCASTFRAMES_G_LO);
+                       xgbe_mmc_read(pdata, MMC_TXBROADCASTFRAMES_G_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXMULTICASTFRAMES_G))
                stats->txmulticastframes_g +=
-                       XGMAC_IOREAD(pdata, MMC_TXMULTICASTFRAMES_G_LO);
+                       xgbe_mmc_read(pdata, MMC_TXMULTICASTFRAMES_G_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TX64OCTETS_GB))
                stats->tx64octets_gb +=
-                       XGMAC_IOREAD(pdata, MMC_TX64OCTETS_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_TX64OCTETS_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TX65TO127OCTETS_GB))
                stats->tx65to127octets_gb +=
-                       XGMAC_IOREAD(pdata, MMC_TX65TO127OCTETS_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_TX65TO127OCTETS_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TX128TO255OCTETS_GB))
                stats->tx128to255octets_gb +=
-                       XGMAC_IOREAD(pdata, MMC_TX128TO255OCTETS_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_TX128TO255OCTETS_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TX256TO511OCTETS_GB))
                stats->tx256to511octets_gb +=
-                       XGMAC_IOREAD(pdata, MMC_TX256TO511OCTETS_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_TX256TO511OCTETS_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TX512TO1023OCTETS_GB))
                stats->tx512to1023octets_gb +=
-                       XGMAC_IOREAD(pdata, MMC_TX512TO1023OCTETS_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_TX512TO1023OCTETS_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TX1024TOMAXOCTETS_GB))
                stats->tx1024tomaxoctets_gb +=
-                       XGMAC_IOREAD(pdata, MMC_TX1024TOMAXOCTETS_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_TX1024TOMAXOCTETS_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXUNICASTFRAMES_GB))
                stats->txunicastframes_gb +=
-                       XGMAC_IOREAD(pdata, MMC_TXUNICASTFRAMES_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_TXUNICASTFRAMES_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXMULTICASTFRAMES_GB))
                stats->txmulticastframes_gb +=
-                       XGMAC_IOREAD(pdata, MMC_TXMULTICASTFRAMES_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_TXMULTICASTFRAMES_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXBROADCASTFRAMES_GB))
                stats->txbroadcastframes_g +=
-                       XGMAC_IOREAD(pdata, MMC_TXBROADCASTFRAMES_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_TXBROADCASTFRAMES_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXUNDERFLOWERROR))
                stats->txunderflowerror +=
-                       XGMAC_IOREAD(pdata, MMC_TXUNDERFLOWERROR_LO);
+                       xgbe_mmc_read(pdata, MMC_TXUNDERFLOWERROR_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXOCTETCOUNT_G))
                stats->txoctetcount_g +=
-                       XGMAC_IOREAD(pdata, MMC_TXOCTETCOUNT_G_LO);
+                       xgbe_mmc_read(pdata, MMC_TXOCTETCOUNT_G_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXFRAMECOUNT_G))
                stats->txframecount_g +=
-                       XGMAC_IOREAD(pdata, MMC_TXFRAMECOUNT_G_LO);
+                       xgbe_mmc_read(pdata, MMC_TXFRAMECOUNT_G_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXPAUSEFRAMES))
                stats->txpauseframes +=
-                       XGMAC_IOREAD(pdata, MMC_TXPAUSEFRAMES_LO);
+                       xgbe_mmc_read(pdata, MMC_TXPAUSEFRAMES_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_TISR, TXVLANFRAMES_G))
                stats->txvlanframes_g +=
-                       XGMAC_IOREAD(pdata, MMC_TXVLANFRAMES_G_LO);
+                       xgbe_mmc_read(pdata, MMC_TXVLANFRAMES_G_LO);
 }
 
 static void xgbe_rx_mmc_int(struct xgbe_prv_data *pdata)
@@ -2032,95 +2065,95 @@ static void xgbe_rx_mmc_int(struct xgbe_prv_data *pdata)
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXFRAMECOUNT_GB))
                stats->rxframecount_gb +=
-                       XGMAC_IOREAD(pdata, MMC_RXFRAMECOUNT_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_RXFRAMECOUNT_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXOCTETCOUNT_GB))
                stats->rxoctetcount_gb +=
-                       XGMAC_IOREAD(pdata, MMC_RXOCTETCOUNT_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_RXOCTETCOUNT_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXOCTETCOUNT_G))
                stats->rxoctetcount_g +=
-                       XGMAC_IOREAD(pdata, MMC_RXOCTETCOUNT_G_LO);
+                       xgbe_mmc_read(pdata, MMC_RXOCTETCOUNT_G_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXBROADCASTFRAMES_G))
                stats->rxbroadcastframes_g +=
-                       XGMAC_IOREAD(pdata, MMC_RXBROADCASTFRAMES_G_LO);
+                       xgbe_mmc_read(pdata, MMC_RXBROADCASTFRAMES_G_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXMULTICASTFRAMES_G))
                stats->rxmulticastframes_g +=
-                       XGMAC_IOREAD(pdata, MMC_RXMULTICASTFRAMES_G_LO);
+                       xgbe_mmc_read(pdata, MMC_RXMULTICASTFRAMES_G_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXCRCERROR))
                stats->rxcrcerror +=
-                       XGMAC_IOREAD(pdata, MMC_RXCRCERROR_LO);
+                       xgbe_mmc_read(pdata, MMC_RXCRCERROR_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXRUNTERROR))
                stats->rxrunterror +=
-                       XGMAC_IOREAD(pdata, MMC_RXRUNTERROR);
+                       xgbe_mmc_read(pdata, MMC_RXRUNTERROR);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXJABBERERROR))
                stats->rxjabbererror +=
-                       XGMAC_IOREAD(pdata, MMC_RXJABBERERROR);
+                       xgbe_mmc_read(pdata, MMC_RXJABBERERROR);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXUNDERSIZE_G))
                stats->rxundersize_g +=
-                       XGMAC_IOREAD(pdata, MMC_RXUNDERSIZE_G);
+                       xgbe_mmc_read(pdata, MMC_RXUNDERSIZE_G);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXOVERSIZE_G))
                stats->rxoversize_g +=
-                       XGMAC_IOREAD(pdata, MMC_RXOVERSIZE_G);
+                       xgbe_mmc_read(pdata, MMC_RXOVERSIZE_G);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RX64OCTETS_GB))
                stats->rx64octets_gb +=
-                       XGMAC_IOREAD(pdata, MMC_RX64OCTETS_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_RX64OCTETS_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RX65TO127OCTETS_GB))
                stats->rx65to127octets_gb +=
-                       XGMAC_IOREAD(pdata, MMC_RX65TO127OCTETS_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_RX65TO127OCTETS_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RX128TO255OCTETS_GB))
                stats->rx128to255octets_gb +=
-                       XGMAC_IOREAD(pdata, MMC_RX128TO255OCTETS_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_RX128TO255OCTETS_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RX256TO511OCTETS_GB))
                stats->rx256to511octets_gb +=
-                       XGMAC_IOREAD(pdata, MMC_RX256TO511OCTETS_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_RX256TO511OCTETS_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RX512TO1023OCTETS_GB))
                stats->rx512to1023octets_gb +=
-                       XGMAC_IOREAD(pdata, MMC_RX512TO1023OCTETS_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_RX512TO1023OCTETS_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RX1024TOMAXOCTETS_GB))
                stats->rx1024tomaxoctets_gb +=
-                       XGMAC_IOREAD(pdata, MMC_RX1024TOMAXOCTETS_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_RX1024TOMAXOCTETS_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXUNICASTFRAMES_G))
                stats->rxunicastframes_g +=
-                       XGMAC_IOREAD(pdata, MMC_RXUNICASTFRAMES_G_LO);
+                       xgbe_mmc_read(pdata, MMC_RXUNICASTFRAMES_G_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXLENGTHERROR))
                stats->rxlengtherror +=
-                       XGMAC_IOREAD(pdata, MMC_RXLENGTHERROR_LO);
+                       xgbe_mmc_read(pdata, MMC_RXLENGTHERROR_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXOUTOFRANGETYPE))
                stats->rxoutofrangetype +=
-                       XGMAC_IOREAD(pdata, MMC_RXOUTOFRANGETYPE_LO);
+                       xgbe_mmc_read(pdata, MMC_RXOUTOFRANGETYPE_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXPAUSEFRAMES))
                stats->rxpauseframes +=
-                       XGMAC_IOREAD(pdata, MMC_RXPAUSEFRAMES_LO);
+                       xgbe_mmc_read(pdata, MMC_RXPAUSEFRAMES_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXFIFOOVERFLOW))
                stats->rxfifooverflow +=
-                       XGMAC_IOREAD(pdata, MMC_RXFIFOOVERFLOW_LO);
+                       xgbe_mmc_read(pdata, MMC_RXFIFOOVERFLOW_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXVLANFRAMES_GB))
                stats->rxvlanframes_gb +=
-                       XGMAC_IOREAD(pdata, MMC_RXVLANFRAMES_GB_LO);
+                       xgbe_mmc_read(pdata, MMC_RXVLANFRAMES_GB_LO);
 
        if (XGMAC_GET_BITS(mmc_isr, MMC_RISR, RXWATCHDOGERROR))
                stats->rxwatchdogerror +=
-                       XGMAC_IOREAD(pdata, MMC_RXWATCHDOGERROR);
+                       xgbe_mmc_read(pdata, MMC_RXWATCHDOGERROR);
 }
 
 static void xgbe_read_mmc_stats(struct xgbe_prv_data *pdata)
@@ -2131,127 +2164,127 @@ static void xgbe_read_mmc_stats(struct xgbe_prv_data *pdata)
        XGMAC_IOWRITE_BITS(pdata, MMC_CR, MCF, 1);
 
        stats->txoctetcount_gb +=
-               XGMAC_IOREAD(pdata, MMC_TXOCTETCOUNT_GB_LO);
+               xgbe_mmc_read(pdata, MMC_TXOCTETCOUNT_GB_LO);
 
        stats->txframecount_gb +=
-               XGMAC_IOREAD(pdata, MMC_TXFRAMECOUNT_GB_LO);
+               xgbe_mmc_read(pdata, MMC_TXFRAMECOUNT_GB_LO);
 
        stats->txbroadcastframes_g +=
-               XGMAC_IOREAD(pdata, MMC_TXBROADCASTFRAMES_G_LO);
+               xgbe_mmc_read(pdata, MMC_TXBROADCASTFRAMES_G_LO);
 
        stats->txmulticastframes_g +=
-               XGMAC_IOREAD(pdata, MMC_TXMULTICASTFRAMES_G_LO);
+               xgbe_mmc_read(pdata, MMC_TXMULTICASTFRAMES_G_LO);
 
        stats->tx64octets_gb +=
-               XGMAC_IOREAD(pdata, MMC_TX64OCTETS_GB_LO);
+               xgbe_mmc_read(pdata, MMC_TX64OCTETS_GB_LO);
 
        stats->tx65to127octets_gb +=
-               XGMAC_IOREAD(pdata, MMC_TX65TO127OCTETS_GB_LO);
+               xgbe_mmc_read(pdata, MMC_TX65TO127OCTETS_GB_LO);
 
        stats->tx128to255octets_gb +=
-               XGMAC_IOREAD(pdata, MMC_TX128TO255OCTETS_GB_LO);
+               xgbe_mmc_read(pdata, MMC_TX128TO255OCTETS_GB_LO);
 
        stats->tx256to511octets_gb +=
-               XGMAC_IOREAD(pdata, MMC_TX256TO511OCTETS_GB_LO);
+               xgbe_mmc_read(pdata, MMC_TX256TO511OCTETS_GB_LO);
 
        stats->tx512to1023octets_gb +=
-               XGMAC_IOREAD(pdata, MMC_TX512TO1023OCTETS_GB_LO);
+               xgbe_mmc_read(pdata, MMC_TX512TO1023OCTETS_GB_LO);
 
        stats->tx1024tomaxoctets_gb +=
-               XGMAC_IOREAD(pdata, MMC_TX1024TOMAXOCTETS_GB_LO);
+               xgbe_mmc_read(pdata, MMC_TX1024TOMAXOCTETS_GB_LO);
 
        stats->txunicastframes_gb +=
-               XGMAC_IOREAD(pdata, MMC_TXUNICASTFRAMES_GB_LO);
+               xgbe_mmc_read(pdata, MMC_TXUNICASTFRAMES_GB_LO);
 
        stats->txmulticastframes_gb +=
-               XGMAC_IOREAD(pdata, MMC_TXMULTICASTFRAMES_GB_LO);
+               xgbe_mmc_read(pdata, MMC_TXMULTICASTFRAMES_GB_LO);
 
        stats->txbroadcastframes_g +=
-               XGMAC_IOREAD(pdata, MMC_TXBROADCASTFRAMES_GB_LO);
+               xgbe_mmc_read(pdata, MMC_TXBROADCASTFRAMES_GB_LO);
 
        stats->txunderflowerror +=
-               XGMAC_IOREAD(pdata, MMC_TXUNDERFLOWERROR_LO);
+               xgbe_mmc_read(pdata, MMC_TXUNDERFLOWERROR_LO);
 
        stats->txoctetcount_g +=
-               XGMAC_IOREAD(pdata, MMC_TXOCTETCOUNT_G_LO);
+               xgbe_mmc_read(pdata, MMC_TXOCTETCOUNT_G_LO);
 
        stats->txframecount_g +=
-               XGMAC_IOREAD(pdata, MMC_TXFRAMECOUNT_G_LO);
+               xgbe_mmc_read(pdata, MMC_TXFRAMECOUNT_G_LO);
 
        stats->txpauseframes +=
-               XGMAC_IOREAD(pdata, MMC_TXPAUSEFRAMES_LO);
+               xgbe_mmc_read(pdata, MMC_TXPAUSEFRAMES_LO);
 
        stats->txvlanframes_g +=
-               XGMAC_IOREAD(pdata, MMC_TXVLANFRAMES_G_LO);
+               xgbe_mmc_read(pdata, MMC_TXVLANFRAMES_G_LO);
 
        stats->rxframecount_gb +=
-               XGMAC_IOREAD(pdata, MMC_RXFRAMECOUNT_GB_LO);
+               xgbe_mmc_read(pdata, MMC_RXFRAMECOUNT_GB_LO);
 
        stats->rxoctetcount_gb +=
-               XGMAC_IOREAD(pdata, MMC_RXOCTETCOUNT_GB_LO);
+               xgbe_mmc_read(pdata, MMC_RXOCTETCOUNT_GB_LO);
 
        stats->rxoctetcount_g +=
-               XGMAC_IOREAD(pdata, MMC_RXOCTETCOUNT_G_LO);
+               xgbe_mmc_read(pdata, MMC_RXOCTETCOUNT_G_LO);
 
        stats->rxbroadcastframes_g +=
-               XGMAC_IOREAD(pdata, MMC_RXBROADCASTFRAMES_G_LO);
+               xgbe_mmc_read(pdata, MMC_RXBROADCASTFRAMES_G_LO);
 
        stats->rxmulticastframes_g +=
-               XGMAC_IOREAD(pdata, MMC_RXMULTICASTFRAMES_G_LO);
+               xgbe_mmc_read(pdata, MMC_RXMULTICASTFRAMES_G_LO);
 
        stats->rxcrcerror +=
-               XGMAC_IOREAD(pdata, MMC_RXCRCERROR_LO);
+               xgbe_mmc_read(pdata, MMC_RXCRCERROR_LO);
 
        stats->rxrunterror +=
-               XGMAC_IOREAD(pdata, MMC_RXRUNTERROR);
+               xgbe_mmc_read(pdata, MMC_RXRUNTERROR);
 
        stats->rxjabbererror +=
-               XGMAC_IOREAD(pdata, MMC_RXJABBERERROR);
+               xgbe_mmc_read(pdata, MMC_RXJABBERERROR);
 
        stats->rxundersize_g +=
-               XGMAC_IOREAD(pdata, MMC_RXUNDERSIZE_G);
+               xgbe_mmc_read(pdata, MMC_RXUNDERSIZE_G);
 
        stats->rxoversize_g +=
-               XGMAC_IOREAD(pdata, MMC_RXOVERSIZE_G);
+               xgbe_mmc_read(pdata, MMC_RXOVERSIZE_G);
 
        stats->rx64octets_gb +=
-               XGMAC_IOREAD(pdata, MMC_RX64OCTETS_GB_LO);
+               xgbe_mmc_read(pdata, MMC_RX64OCTETS_GB_LO);
 
        stats->rx65to127octets_gb +=
-               XGMAC_IOREAD(pdata, MMC_RX65TO127OCTETS_GB_LO);
+               xgbe_mmc_read(pdata, MMC_RX65TO127OCTETS_GB_LO);
 
        stats->rx128to255octets_gb +=
-               XGMAC_IOREAD(pdata, MMC_RX128TO255OCTETS_GB_LO);
+               xgbe_mmc_read(pdata, MMC_RX128TO255OCTETS_GB_LO);
 
        stats->rx256to511octets_gb +=
-               XGMAC_IOREAD(pdata, MMC_RX256TO511OCTETS_GB_LO);
+               xgbe_mmc_read(pdata, MMC_RX256TO511OCTETS_GB_LO);
 
        stats->rx512to1023octets_gb +=
-               XGMAC_IOREAD(pdata, MMC_RX512TO1023OCTETS_GB_LO);
+               xgbe_mmc_read(pdata, MMC_RX512TO1023OCTETS_GB_LO);
 
        stats->rx1024tomaxoctets_gb +=
-               XGMAC_IOREAD(pdata, MMC_RX1024TOMAXOCTETS_GB_LO);
+               xgbe_mmc_read(pdata, MMC_RX1024TOMAXOCTETS_GB_LO);
 
        stats->rxunicastframes_g +=
-               XGMAC_IOREAD(pdata, MMC_RXUNICASTFRAMES_G_LO);
+               xgbe_mmc_read(pdata, MMC_RXUNICASTFRAMES_G_LO);
 
        stats->rxlengtherror +=
-               XGMAC_IOREAD(pdata, MMC_RXLENGTHERROR_LO);
+               xgbe_mmc_read(pdata, MMC_RXLENGTHERROR_LO);
 
        stats->rxoutofrangetype +=
-               XGMAC_IOREAD(pdata, MMC_RXOUTOFRANGETYPE_LO);
+               xgbe_mmc_read(pdata, MMC_RXOUTOFRANGETYPE_LO);
 
        stats->rxpauseframes +=
-               XGMAC_IOREAD(pdata, MMC_RXPAUSEFRAMES_LO);
+               xgbe_mmc_read(pdata, MMC_RXPAUSEFRAMES_LO);
 
        stats->rxfifooverflow +=
-               XGMAC_IOREAD(pdata, MMC_RXFIFOOVERFLOW_LO);
+               xgbe_mmc_read(pdata, MMC_RXFIFOOVERFLOW_LO);
 
        stats->rxvlanframes_gb +=
-               XGMAC_IOREAD(pdata, MMC_RXVLANFRAMES_GB_LO);
+               xgbe_mmc_read(pdata, MMC_RXVLANFRAMES_GB_LO);
 
        stats->rxwatchdogerror +=
-               XGMAC_IOREAD(pdata, MMC_RXWATCHDOGERROR);
+               xgbe_mmc_read(pdata, MMC_RXWATCHDOGERROR);
 
        /* Un-freeze counters */
        XGMAC_IOWRITE_BITS(pdata, MMC_CR, MCF, 0);
index dc84f7193c2db62aaf5d922f9beb409b13a975c3..b26d75856553bf62c975e533dc815051f7968de5 100644 (file)
@@ -361,6 +361,8 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata)
 
        memset(hw_feat, 0, sizeof(*hw_feat));
 
+       hw_feat->version = XGMAC_IOREAD(pdata, MAC_VR);
+
        /* Hardware feature register 0 */
        hw_feat->gmii        = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, GMIISEL);
        hw_feat->vlhash      = XGMAC_GET_BITS(mac_hfr0, MAC_HWF0R, VLHASH);
index a076aca138a12ce4cdf69fb872d1d61c4202fbfa..46f613028e9c00ba9b659a4b8ccc7a8f5f47c644 100644 (file)
@@ -361,15 +361,16 @@ static void xgbe_get_drvinfo(struct net_device *netdev,
                             struct ethtool_drvinfo *drvinfo)
 {
        struct xgbe_prv_data *pdata = netdev_priv(netdev);
+       struct xgbe_hw_features *hw_feat = &pdata->hw_feat;
 
        strlcpy(drvinfo->driver, XGBE_DRV_NAME, sizeof(drvinfo->driver));
        strlcpy(drvinfo->version, XGBE_DRV_VERSION, sizeof(drvinfo->version));
        strlcpy(drvinfo->bus_info, dev_name(pdata->dev),
                sizeof(drvinfo->bus_info));
        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%d.%d.%d",
-                XGMAC_IOREAD_BITS(pdata, MAC_VR, USERVER),
-                XGMAC_IOREAD_BITS(pdata, MAC_VR, DEVID),
-                XGMAC_IOREAD_BITS(pdata, MAC_VR, SNPSVER));
+                XGMAC_GET_BITS(hw_feat->version, MAC_VR, USERVER),
+                XGMAC_GET_BITS(hw_feat->version, MAC_VR, DEVID),
+                XGMAC_GET_BITS(hw_feat->version, MAC_VR, SNPSVER));
        drvinfo->n_stats = XGBE_STATS_COUNT;
 }
 
index 8aa6a9353f7bc5b5b3cf7592bc42186a93ca0bce..bdf9cfa70e88c4dac3c7f3c439fa2b3eef29aaa6 100644 (file)
@@ -172,7 +172,7 @@ static struct xgbe_channel *xgbe_alloc_rings(struct xgbe_prv_data *pdata)
                }
 
                if (i < pdata->rx_ring_count) {
-                       spin_lock_init(&tx_ring->lock);
+                       spin_lock_init(&rx_ring->lock);
                        channel->rx_ring = rx_ring++;
                }
 
index 07bf70a82908ead8e75b6e4704946ae10c961b37..e9fe6e6ddcc34acd7469aef6b523855e535f5a99 100644 (file)
 #define XGMAC_DRIVER_CONTEXT   1
 #define XGMAC_IOCTL_CONTEXT    2
 
+#define XGBE_FIFO_MAX          81920
 #define XGBE_FIFO_SIZE_B(x)    (x)
 #define XGBE_FIFO_SIZE_KB(x)   (x * 1024)
 
@@ -526,6 +527,9 @@ struct xgbe_desc_if {
  * or configurations are present in the device.
  */
 struct xgbe_hw_features {
+       /* HW Version */
+       unsigned int version;
+
        /* HW Feature Register0 */
        unsigned int gmii;              /* 1000 Mbps support */
        unsigned int vlhash;            /* VLAN Hash Filter */
index 616dff6d3f5f3cc2837cdd9de776e943283a24fc..f4054d242f3c7ac6e52437c5cb795cac8e3da2dd 100644 (file)
@@ -1,5 +1,6 @@
 config NET_XGENE
        tristate "APM X-Gene SoC Ethernet Driver"
+       depends on HAS_DMA
        select PHYLIB
        help
          This is the Ethernet driver for the on-chip ethernet interface on the
index 7dcfb19a31c888894121aa03c83bc8fe439bc4cf..d8d07a818b89bc694a77b2bdc3172f5bbb6d7010 100644 (file)
@@ -84,7 +84,7 @@ config BNX2
 
 config CNIC
        tristate "QLogic CNIC support"
-       depends on PCI
+       depends on PCI && (IPV6 || IPV6=n)
        select BNX2
        select UIO
        ---help---
index 5ba8af50c84f2bb3ebf9300c9ad8765d25a06a8d..c4daa068f1db5e37bdea6f160dde26b7c13d1659 100644 (file)
@@ -2233,7 +2233,12 @@ struct shmem2_region {
        u32 reserved3;                          /* Offset 0x14C */
        u32 reserved4;                          /* Offset 0x150 */
        u32 link_attr_sync[PORT_MAX];           /* Offset 0x154 */
-       #define LINK_ATTR_SYNC_KR2_ENABLE       (1<<0)
+       #define LINK_ATTR_SYNC_KR2_ENABLE       0x00000001
+       #define LINK_SFP_EEPROM_COMP_CODE_MASK  0x0000ff00
+       #define LINK_SFP_EEPROM_COMP_CODE_SHIFT          8
+       #define LINK_SFP_EEPROM_COMP_CODE_SR    0x00001000
+       #define LINK_SFP_EEPROM_COMP_CODE_LR    0x00002000
+       #define LINK_SFP_EEPROM_COMP_CODE_LRM   0x00004000
 
        u32 reserved5[2];
        u32 reserved6[PORT_MAX];
index 53fb4fa61b405aa540239492fef2d5a4f94fa9bd..549549eaf580f79518295bd4a13234cef8520968 100644 (file)
@@ -154,15 +154,22 @@ typedef int (*read_sfp_module_eeprom_func_p)(struct bnx2x_phy *phy,
                         LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE)
 
 #define SFP_EEPROM_CON_TYPE_ADDR               0x2
+       #define SFP_EEPROM_CON_TYPE_VAL_UNKNOWN 0x0
        #define SFP_EEPROM_CON_TYPE_VAL_LC      0x7
        #define SFP_EEPROM_CON_TYPE_VAL_COPPER  0x21
        #define SFP_EEPROM_CON_TYPE_VAL_RJ45    0x22
 
 
-#define SFP_EEPROM_COMP_CODE_ADDR              0x3
-       #define SFP_EEPROM_COMP_CODE_SR_MASK    (1<<4)
-       #define SFP_EEPROM_COMP_CODE_LR_MASK    (1<<5)
-       #define SFP_EEPROM_COMP_CODE_LRM_MASK   (1<<6)
+#define SFP_EEPROM_10G_COMP_CODE_ADDR          0x3
+       #define SFP_EEPROM_10G_COMP_CODE_SR_MASK        (1<<4)
+       #define SFP_EEPROM_10G_COMP_CODE_LR_MASK        (1<<5)
+       #define SFP_EEPROM_10G_COMP_CODE_LRM_MASK       (1<<6)
+
+#define SFP_EEPROM_1G_COMP_CODE_ADDR           0x6
+       #define SFP_EEPROM_1G_COMP_CODE_SX      (1<<0)
+       #define SFP_EEPROM_1G_COMP_CODE_LX      (1<<1)
+       #define SFP_EEPROM_1G_COMP_CODE_CX      (1<<2)
+       #define SFP_EEPROM_1G_COMP_CODE_BASE_T  (1<<3)
 
 #define SFP_EEPROM_FC_TX_TECH_ADDR             0x8
        #define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE 0x4
@@ -3633,8 +3640,8 @@ static void bnx2x_warpcore_enable_AN_KR2(struct bnx2x_phy *phy,
                                 reg_set[i].val);
 
        /* Start KR2 work-around timer which handles BCM8073 link-parner */
-       vars->link_attr_sync |= LINK_ATTR_SYNC_KR2_ENABLE;
-       bnx2x_update_link_attr(params, vars->link_attr_sync);
+       params->link_attr_sync |= LINK_ATTR_SYNC_KR2_ENABLE;
+       bnx2x_update_link_attr(params, params->link_attr_sync);
 }
 
 static void bnx2x_disable_kr2(struct link_params *params,
@@ -3666,8 +3673,8 @@ static void bnx2x_disable_kr2(struct link_params *params,
        for (i = 0; i < ARRAY_SIZE(reg_set); i++)
                bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
                                 reg_set[i].val);
-       vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;
-       bnx2x_update_link_attr(params, vars->link_attr_sync);
+       params->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;
+       bnx2x_update_link_attr(params, params->link_attr_sync);
 
        vars->check_kr2_recovery_cnt = CHECK_KR2_RECOVERY_CNT;
 }
@@ -4810,7 +4817,7 @@ void bnx2x_link_status_update(struct link_params *params,
                                        ~FEATURE_CONFIG_PFC_ENABLED;
 
        if (SHMEM2_HAS(bp, link_attr_sync))
-               vars->link_attr_sync = SHMEM2_RD(bp,
+               params->link_attr_sync = SHMEM2_RD(bp,
                                                 link_attr_sync[params->port]);
 
        DP(NETIF_MSG_LINK, "link_status 0x%x  phy_link_up %x int_mask 0x%x\n",
@@ -8057,21 +8064,24 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
 {
        struct bnx2x *bp = params->bp;
        u32 sync_offset = 0, phy_idx, media_types;
-       u8 gport, val[2], check_limiting_mode = 0;
+       u8 val[SFP_EEPROM_FC_TX_TECH_ADDR + 1], check_limiting_mode = 0;
        *edc_mode = EDC_MODE_LIMITING;
        phy->media_type = ETH_PHY_UNSPECIFIED;
        /* First check for copper cable */
        if (bnx2x_read_sfp_module_eeprom(phy,
                                         params,
                                         I2C_DEV_ADDR_A0,
-                                        SFP_EEPROM_CON_TYPE_ADDR,
-                                        2,
+                                        0,
+                                        SFP_EEPROM_FC_TX_TECH_ADDR + 1,
                                         (u8 *)val) != 0) {
                DP(NETIF_MSG_LINK, "Failed to read from SFP+ module EEPROM\n");
                return -EINVAL;
        }
-
-       switch (val[0]) {
+       params->link_attr_sync &= ~LINK_SFP_EEPROM_COMP_CODE_MASK;
+       params->link_attr_sync |= val[SFP_EEPROM_10G_COMP_CODE_ADDR] <<
+               LINK_SFP_EEPROM_COMP_CODE_SHIFT;
+       bnx2x_update_link_attr(params, params->link_attr_sync);
+       switch (val[SFP_EEPROM_CON_TYPE_ADDR]) {
        case SFP_EEPROM_CON_TYPE_VAL_COPPER:
        {
                u8 copper_module_type;
@@ -8079,17 +8089,7 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
                /* Check if its active cable (includes SFP+ module)
                 * of passive cable
                 */
-               if (bnx2x_read_sfp_module_eeprom(phy,
-                                              params,
-                                              I2C_DEV_ADDR_A0,
-                                              SFP_EEPROM_FC_TX_TECH_ADDR,
-                                              1,
-                                              &copper_module_type) != 0) {
-                       DP(NETIF_MSG_LINK,
-                               "Failed to read copper-cable-type"
-                               " from SFP+ EEPROM\n");
-                       return -EINVAL;
-               }
+               copper_module_type = val[SFP_EEPROM_FC_TX_TECH_ADDR];
 
                if (copper_module_type &
                    SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE) {
@@ -8115,16 +8115,18 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
                }
                break;
        }
+       case SFP_EEPROM_CON_TYPE_VAL_UNKNOWN:
        case SFP_EEPROM_CON_TYPE_VAL_LC:
        case SFP_EEPROM_CON_TYPE_VAL_RJ45:
                check_limiting_mode = 1;
-               if ((val[1] & (SFP_EEPROM_COMP_CODE_SR_MASK |
-                              SFP_EEPROM_COMP_CODE_LR_MASK |
-                              SFP_EEPROM_COMP_CODE_LRM_MASK)) == 0) {
+               if ((val[SFP_EEPROM_10G_COMP_CODE_ADDR] &
+                    (SFP_EEPROM_10G_COMP_CODE_SR_MASK |
+                     SFP_EEPROM_10G_COMP_CODE_LR_MASK |
+                     SFP_EEPROM_10G_COMP_CODE_LRM_MASK)) == 0) {
                        DP(NETIF_MSG_LINK, "1G SFP module detected\n");
-                       gport = params->port;
                        phy->media_type = ETH_PHY_SFP_1G_FIBER;
                        if (phy->req_line_speed != SPEED_1000) {
+                               u8 gport = params->port;
                                phy->req_line_speed = SPEED_1000;
                                if (!CHIP_IS_E1x(bp)) {
                                        gport = BP_PATH(bp) +
@@ -8134,6 +8136,12 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
                                           "Warning: Link speed was forced to 1000Mbps. Current SFP module in port %d is not compliant with 10G Ethernet\n",
                                           gport);
                        }
+                       if (val[SFP_EEPROM_1G_COMP_CODE_ADDR] &
+                           SFP_EEPROM_1G_COMP_CODE_BASE_T) {
+                               bnx2x_sfp_set_transmitter(params, phy, 0);
+                               msleep(40);
+                               bnx2x_sfp_set_transmitter(params, phy, 1);
+                       }
                } else {
                        int idx, cfg_idx = 0;
                        DP(NETIF_MSG_LINK, "10G Optic module detected\n");
@@ -8149,7 +8157,7 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
                break;
        default:
                DP(NETIF_MSG_LINK, "Unable to determine module type 0x%x !!!\n",
-                        val[0]);
+                        val[SFP_EEPROM_CON_TYPE_ADDR]);
                return -EINVAL;
        }
        sync_offset = params->shmem_base +
@@ -13507,7 +13515,7 @@ static void bnx2x_check_kr2_wa(struct link_params *params,
 
        sigdet = bnx2x_warpcore_get_sigdet(phy, params);
        if (!sigdet) {
-               if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
+               if (!(params->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
                        bnx2x_kr2_recovery(params, vars, phy);
                        DP(NETIF_MSG_LINK, "No sigdet\n");
                }
@@ -13525,7 +13533,7 @@ static void bnx2x_check_kr2_wa(struct link_params *params,
 
        /* CL73 has not begun yet */
        if (base_page == 0) {
-               if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
+               if (!(params->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
                        bnx2x_kr2_recovery(params, vars, phy);
                        DP(NETIF_MSG_LINK, "No BP\n");
                }
@@ -13541,7 +13549,7 @@ static void bnx2x_check_kr2_wa(struct link_params *params,
                            ((next_page & 0xe0) == 0x20))));
 
        /* In case KR2 is already disabled, check if we need to re-enable it */
-       if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
+       if (!(params->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
                if (!not_kr2_device) {
                        DP(NETIF_MSG_LINK, "BP=0x%x, NP=0x%x\n", base_page,
                           next_page);
index 389f5f8cb0a3c3108f2305b62c0843037ea4f72e..d9cce4c3899b7b9d388cf28a6f4bf0feece3c4b2 100644 (file)
@@ -323,6 +323,9 @@ struct link_params {
 #define LINK_FLAGS_INT_DISABLED                (1<<0)
 #define PHY_INITIALIZED                (1<<1)
        u32 lfa_base;
+
+       /* The same definitions as the shmem2 parameter */
+       u32 link_attr_sync;
 };
 
 /* Output parameters */
@@ -364,8 +367,6 @@ struct link_vars {
        u8 rx_tx_asic_rst;
        u8 turn_to_run_wc_rt;
        u16 rsrv2;
-       /* The same definitions as the shmem2 parameter */
-       u32 link_attr_sync;
 };
 
 /***********************************************************/
index 900cab42081068e699e4bc8e2e0bec71659c604d..d1c093dcb054aebb71b1ee701cf175e8ab804515 100644 (file)
@@ -6849,6 +6849,37 @@ static void bnx2x__common_init_phy(struct bnx2x *bp)
        bnx2x_release_phy_lock(bp);
 }
 
+static void bnx2x_config_endianity(struct bnx2x *bp, u32 val)
+{
+       REG_WR(bp, PXP2_REG_RQ_QM_ENDIAN_M, val);
+       REG_WR(bp, PXP2_REG_RQ_TM_ENDIAN_M, val);
+       REG_WR(bp, PXP2_REG_RQ_SRC_ENDIAN_M, val);
+       REG_WR(bp, PXP2_REG_RQ_CDU_ENDIAN_M, val);
+       REG_WR(bp, PXP2_REG_RQ_DBG_ENDIAN_M, val);
+
+       /* make sure this value is 0 */
+       REG_WR(bp, PXP2_REG_RQ_HC_ENDIAN_M, 0);
+
+       REG_WR(bp, PXP2_REG_RD_QM_SWAP_MODE, val);
+       REG_WR(bp, PXP2_REG_RD_TM_SWAP_MODE, val);
+       REG_WR(bp, PXP2_REG_RD_SRC_SWAP_MODE, val);
+       REG_WR(bp, PXP2_REG_RD_CDURD_SWAP_MODE, val);
+}
+
+static void bnx2x_set_endianity(struct bnx2x *bp)
+{
+#ifdef __BIG_ENDIAN
+       bnx2x_config_endianity(bp, 1);
+#else
+       bnx2x_config_endianity(bp, 0);
+#endif
+}
+
+static void bnx2x_reset_endianity(struct bnx2x *bp)
+{
+       bnx2x_config_endianity(bp, 0);
+}
+
 /**
  * bnx2x_init_hw_common - initialize the HW at the COMMON phase.
  *
@@ -6915,23 +6946,7 @@ static int bnx2x_init_hw_common(struct bnx2x *bp)
 
        bnx2x_init_block(bp, BLOCK_PXP2, PHASE_COMMON);
        bnx2x_init_pxp(bp);
-
-#ifdef __BIG_ENDIAN
-       REG_WR(bp, PXP2_REG_RQ_QM_ENDIAN_M, 1);
-       REG_WR(bp, PXP2_REG_RQ_TM_ENDIAN_M, 1);
-       REG_WR(bp, PXP2_REG_RQ_SRC_ENDIAN_M, 1);
-       REG_WR(bp, PXP2_REG_RQ_CDU_ENDIAN_M, 1);
-       REG_WR(bp, PXP2_REG_RQ_DBG_ENDIAN_M, 1);
-       /* make sure this value is 0 */
-       REG_WR(bp, PXP2_REG_RQ_HC_ENDIAN_M, 0);
-
-/*     REG_WR(bp, PXP2_REG_RD_PBF_SWAP_MODE, 1); */
-       REG_WR(bp, PXP2_REG_RD_QM_SWAP_MODE, 1);
-       REG_WR(bp, PXP2_REG_RD_TM_SWAP_MODE, 1);
-       REG_WR(bp, PXP2_REG_RD_SRC_SWAP_MODE, 1);
-       REG_WR(bp, PXP2_REG_RD_CDURD_SWAP_MODE, 1);
-#endif
-
+       bnx2x_set_endianity(bp);
        bnx2x_ilt_init_page_size(bp, INITOP_SET);
 
        if (CHIP_REV_IS_FPGA(bp) && CHIP_IS_E1H(bp))
@@ -13169,9 +13184,15 @@ static void __bnx2x_remove(struct pci_dev *pdev,
        bnx2x_iov_remove_one(bp);
 
        /* Power on: we can't let PCI layer write to us while we are in D3 */
-       if (IS_PF(bp))
+       if (IS_PF(bp)) {
                bnx2x_set_power_state(bp, PCI_D0);
 
+               /* Set endianity registers to reset values in case next driver
+                * boots in different endianty environment.
+                */
+               bnx2x_reset_endianity(bp);
+       }
+
        /* Disable MSI/MSI-X */
        bnx2x_disable_msi(bp);
 
index 27861a6c7ca55966048b4cb94b0b92a0dde1d269..a6a9f284c8dd762579e062a9d9d62f03e1ce6f96 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/if_vlan.h>
 #include <linux/prefetch.h>
 #include <linux/random.h>
-#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+#if IS_ENABLED(CONFIG_VLAN_8021Q)
 #define BCM_VLAN 1
 #endif
 #include <net/ip.h>
@@ -3685,7 +3685,7 @@ static int cnic_get_v4_route(struct sockaddr_in *dst_addr,
 static int cnic_get_v6_route(struct sockaddr_in6 *dst_addr,
                             struct dst_entry **dst)
 {
-#if defined(CONFIG_IPV6) || (defined(CONFIG_IPV6_MODULE) && defined(MODULE))
+#if IS_ENABLED(CONFIG_IPV6)
        struct flowi6 fl6;
 
        memset(&fl6, 0, sizeof(fl6));
index 3ac5d23454a8dae9b2e618205d14dc91d822f1fe..cb77ae93d89a120591afc700ae4650d4f4002291 100644 (file)
@@ -11617,6 +11617,12 @@ static int tg3_open(struct net_device *dev)
        struct tg3 *tp = netdev_priv(dev);
        int err;
 
+       if (tp->pcierr_recovery) {
+               netdev_err(dev, "Failed to open device. PCI error recovery "
+                          "in progress\n");
+               return -EAGAIN;
+       }
+
        if (tp->fw_needed) {
                err = tg3_request_firmware(tp);
                if (tg3_asic_rev(tp) == ASIC_REV_57766) {
@@ -11674,6 +11680,12 @@ static int tg3_close(struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
 
+       if (tp->pcierr_recovery) {
+               netdev_err(dev, "Failed to close device. PCI error recovery "
+                          "in progress\n");
+               return -EAGAIN;
+       }
+
        tg3_ptp_fini(tp);
 
        tg3_stop(tp);
@@ -17561,6 +17573,7 @@ static int tg3_init_one(struct pci_dev *pdev,
        tp->rx_mode = TG3_DEF_RX_MODE;
        tp->tx_mode = TG3_DEF_TX_MODE;
        tp->irq_sync = 1;
+       tp->pcierr_recovery = false;
 
        if (tg3_debug > 0)
                tp->msg_enable = tg3_debug;
@@ -18071,6 +18084,8 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev,
 
        rtnl_lock();
 
+       tp->pcierr_recovery = true;
+
        /* We probably don't have netdev yet */
        if (!netdev || !netif_running(netdev))
                goto done;
@@ -18195,6 +18210,7 @@ static void tg3_io_resume(struct pci_dev *pdev)
        tg3_phy_start(tp);
 
 done:
+       tp->pcierr_recovery = false;
        rtnl_unlock();
 }
 
index 461accaf0aa40242c3756880dd6659371cdfe5f0..31c9f829595384cb843e299c6b51054101d8f6c6 100644 (file)
@@ -3407,6 +3407,7 @@ struct tg3 {
 
        struct device                   *hwmon_dev;
        bool                            link_up;
+       bool                            pcierr_recovery;
 };
 
 /* Accessor macros for chip and asic attributes
index ff8cae5e2535b6e068159180105f84b2ff922b1d..ffc92a41d75be550d27698af6ca3e600d9a146fe 100644 (file)
@@ -2506,7 +2506,7 @@ bnad_tso_prepare(struct bnad *bnad, struct sk_buff *skb)
         * For TSO, the TCP checksum field is seeded with pseudo-header sum
         * excluding the length field.
         */
-       if (skb->protocol == htons(ETH_P_IP)) {
+       if (vlan_get_protocol(skb) == htons(ETH_P_IP)) {
                struct iphdr *iph = ip_hdr(skb);
 
                /* Do we really need these? */
@@ -2870,12 +2870,13 @@ bnad_txq_wi_prepare(struct bnad *bnad, struct bna_tcb *tcb,
                }
 
                if (skb->ip_summed == CHECKSUM_PARTIAL) {
+                       __be16 net_proto = vlan_get_protocol(skb);
                        u8 proto = 0;
 
-                       if (skb->protocol == htons(ETH_P_IP))
+                       if (net_proto == htons(ETH_P_IP))
                                proto = ip_hdr(skb)->protocol;
 #ifdef NETIF_F_IPV6_CSUM
-                       else if (skb->protocol == htons(ETH_P_IPV6)) {
+                       else if (net_proto == htons(ETH_P_IPV6)) {
                                /* nexthdr may not be TCP immediately. */
                                proto = ipv6_hdr(skb)->nexthdr;
                        }
index 184a063bed5fa59bbdc705e29355134a2d31d731..07d2201530d26c85e26cf0987553451acad936a6 100644 (file)
@@ -1,6 +1,7 @@
 config NET_CALXEDA_XGMAC
        tristate "Calxeda 1G/10G XGMAC Ethernet driver"
        depends on HAS_IOMEM && HAS_DMA
+       depends on ARCH_HIGHBANK || COMPILE_TEST
        select CRC32
        help
          This is the driver for the XGMAC Ethernet IP block found on Calxeda
index 18fb9c61d7bacfd19319a664d2287786938ecec7..8c34811a112843239cb50d496b50fe73c5647472 100644 (file)
@@ -1253,7 +1253,9 @@ freeout:  t4_free_sge_resources(adap);
                        goto freeout;
        }
 
-       t4_write_reg(adap, MPS_TRC_RSS_CONTROL,
+       t4_write_reg(adap, is_t4(adap->params.chip) ?
+                               MPS_TRC_RSS_CONTROL :
+                               MPS_T5_TRC_RSS_CONTROL,
                     RSSCONTROL(netdev2pinfo(adap->port[0])->tx_chan) |
                     QUEUENUMBER(s->ethrxq[0].rspq.abs_id));
        return 0;
@@ -1761,7 +1763,8 @@ static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
                0xd004, 0xd03c,
                0xdfc0, 0xdfe0,
                0xe000, 0xea7c,
-               0xf000, 0x11190,
+               0xf000, 0x11110,
+               0x11118, 0x11190,
                0x19040, 0x1906c,
                0x19078, 0x19080,
                0x1908c, 0x19124,
@@ -1968,7 +1971,8 @@ static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
                0xd004, 0xd03c,
                0xdfc0, 0xdfe0,
                0xe000, 0x11088,
-               0x1109c, 0x1117c,
+               0x1109c, 0x11110,
+               0x11118, 0x1117c,
                0x11190, 0x11204,
                0x19040, 0x1906c,
                0x19078, 0x19080,
@@ -5955,7 +5959,8 @@ static int adap_init0(struct adapter *adap)
                params[3] = FW_PARAM_PFVF(CQ_END);
                params[4] = FW_PARAM_PFVF(OCQ_START);
                params[5] = FW_PARAM_PFVF(OCQ_END);
-               ret = t4_query_params(adap, 0, 0, 0, 6, params, val);
+               ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 6, params,
+                                     val);
                if (ret < 0)
                        goto bye;
                adap->vres.qp.start = val[0];
@@ -5967,7 +5972,8 @@ static int adap_init0(struct adapter *adap)
 
                params[0] = FW_PARAM_DEV(MAXORDIRD_QP);
                params[1] = FW_PARAM_DEV(MAXIRD_ADAPTER);
-               ret = t4_query_params(adap, 0, 0, 0, 2, params, val);
+               ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2, params,
+                                     val);
                if (ret < 0) {
                        adap->params.max_ordird_qp = 8;
                        adap->params.max_ird_adapter = 32 * adap->tids.ntids;
index a853133d8db826029ac042006e89c6d99348f2d7..41d04462b72eb158f7699c38000e6331291d2447 100644 (file)
@@ -167,6 +167,34 @@ void t4_hw_pci_read_cfg4(struct adapter *adap, int reg, u32 *val)
        t4_write_reg(adap, PCIE_CFG_SPACE_REQ, 0);
 }
 
+/*
+ * t4_report_fw_error - report firmware error
+ * @adap: the adapter
+ *
+ * The adapter firmware can indicate error conditions to the host.
+ * If the firmware has indicated an error, print out the reason for
+ * the firmware error.
+ */
+static void t4_report_fw_error(struct adapter *adap)
+{
+       static const char *const reason[] = {
+               "Crash",                        /* PCIE_FW_EVAL_CRASH */
+               "During Device Preparation",    /* PCIE_FW_EVAL_PREP */
+               "During Device Configuration",  /* PCIE_FW_EVAL_CONF */
+               "During Device Initialization", /* PCIE_FW_EVAL_INIT */
+               "Unexpected Event",             /* PCIE_FW_EVAL_UNEXPECTEDEVENT */
+               "Insufficient Airflow",         /* PCIE_FW_EVAL_OVERHEAT */
+               "Device Shutdown",              /* PCIE_FW_EVAL_DEVICESHUTDOWN */
+               "Reserved",                     /* reserved */
+       };
+       u32 pcie_fw;
+
+       pcie_fw = t4_read_reg(adap, MA_PCIE_FW);
+       if (pcie_fw & FW_PCIE_FW_ERR)
+               dev_err(adap->pdev_dev, "Firmware reports adapter error: %s\n",
+                       reason[FW_PCIE_FW_EVAL_GET(pcie_fw)]);
+}
+
 /*
  * Get the reply to a mailbox command and store it in @rpl in big-endian order.
  */
@@ -300,6 +328,7 @@ int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
        dump_mbox(adap, mbox, data_reg);
        dev_err(adap->pdev_dev, "command %#x in mailbox %d timed out\n",
                *(const u8 *)cmd, mbox);
+       t4_report_fw_error(adap);
        return -ETIMEDOUT;
 }
 
@@ -566,6 +595,7 @@ int t4_memory_rw(struct adapter *adap, int win, int mtype, u32 addr,
 #define VPD_BASE           0x400
 #define VPD_BASE_OLD       0
 #define VPD_LEN            1024
+#define CHELSIO_VPD_UNIQUE_ID 0x82
 
 /**
  *     t4_seeprom_wp - enable/disable EEPROM write protection
@@ -603,7 +633,14 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
        ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(u32), vpd);
        if (ret < 0)
                goto out;
-       addr = *vpd == 0x82 ? VPD_BASE : VPD_BASE_OLD;
+
+       /* The VPD shall have a unique identifier specified by the PCI SIG.
+        * For chelsio adapters, the identifier is 0x82. The first byte of a VPD
+        * shall be CHELSIO_VPD_UNIQUE_ID (0x82). The VPD programming software
+        * is expected to automatically put this entry at the
+        * beginning of the VPD.
+        */
+       addr = *vpd == CHELSIO_VPD_UNIQUE_ID ? VPD_BASE : VPD_BASE_OLD;
 
        ret = pci_read_vpd(adapter->pdev, addr, VPD_LEN, vpd);
        if (ret < 0)
@@ -667,6 +704,7 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
        i = pci_vpd_info_field_size(vpd + sn - PCI_VPD_INFO_FLD_HDR_SIZE);
        memcpy(p->sn, vpd + sn, min(i, SERNUM_LEN));
        strim(p->sn);
+       i = pci_vpd_info_field_size(vpd + pn - PCI_VPD_INFO_FLD_HDR_SIZE);
        memcpy(p->pn, vpd + pn, min(i, PN_LEN));
        strim(p->pn);
 
@@ -1394,15 +1432,18 @@ static void pcie_intr_handler(struct adapter *adapter)
 
        int fat;
 
-       fat = t4_handle_intr_status(adapter,
-                                   PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
-                                   sysbus_intr_info) +
-             t4_handle_intr_status(adapter,
-                                   PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
-                                   pcie_port_intr_info) +
-             t4_handle_intr_status(adapter, PCIE_INT_CAUSE,
-                                   is_t4(adapter->params.chip) ?
-                                   pcie_intr_info : t5_pcie_intr_info);
+       if (is_t4(adapter->params.chip))
+               fat = t4_handle_intr_status(adapter,
+                                           PCIE_CORE_UTL_SYSTEM_BUS_AGENT_STATUS,
+                                           sysbus_intr_info) +
+                       t4_handle_intr_status(adapter,
+                                             PCIE_CORE_UTL_PCI_EXPRESS_PORT_STATUS,
+                                             pcie_port_intr_info) +
+                       t4_handle_intr_status(adapter, PCIE_INT_CAUSE,
+                                             pcie_intr_info);
+       else
+               fat = t4_handle_intr_status(adapter, PCIE_INT_CAUSE,
+                                           t5_pcie_intr_info);
 
        if (fat)
                t4_fatal_err(adapter);
@@ -1521,6 +1562,9 @@ static void cim_intr_handler(struct adapter *adapter)
 
        int fat;
 
+       if (t4_read_reg(adapter, MA_PCIE_FW) & FW_PCIE_FW_ERR)
+               t4_report_fw_error(adapter);
+
        fat = t4_handle_intr_status(adapter, CIM_HOST_INT_CAUSE,
                                    cim_intr_info) +
              t4_handle_intr_status(adapter, CIM_HOST_UPACC_INT_CAUSE,
@@ -1768,10 +1812,16 @@ static void ma_intr_handler(struct adapter *adap)
 {
        u32 v, status = t4_read_reg(adap, MA_INT_CAUSE);
 
-       if (status & MEM_PERR_INT_CAUSE)
+       if (status & MEM_PERR_INT_CAUSE) {
                dev_alert(adap->pdev_dev,
                          "MA parity error, parity status %#x\n",
                          t4_read_reg(adap, MA_PARITY_ERROR_STATUS));
+               if (is_t5(adap->params.chip))
+                       dev_alert(adap->pdev_dev,
+                                 "MA parity error, parity status %#x\n",
+                                 t4_read_reg(adap,
+                                             MA_PARITY_ERROR_STATUS2));
+       }
        if (status & MEM_WRAP_INT_CAUSE) {
                v = t4_read_reg(adap, MA_INT_WRAP_STATUS);
                dev_alert(adap->pdev_dev, "MA address wrap-around error by "
@@ -2733,12 +2783,16 @@ retry:
        /*
         * Issue the HELLO command to the firmware.  If it's not successful
         * but indicates that we got a "busy" or "timeout" condition, retry
-        * the HELLO until we exhaust our retry limit.
+        * the HELLO until we exhaust our retry limit.  If we do exceed our
+        * retry limit, check to see if the firmware left us any error
+        * information and report that if so.
         */
        ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
        if (ret < 0) {
                if ((ret == -EBUSY || ret == -ETIMEDOUT) && retries-- > 0)
                        goto retry;
+               if (t4_read_reg(adap, MA_PCIE_FW) & FW_PCIE_FW_ERR)
+                       t4_report_fw_error(adap);
                return ret;
        }
 
@@ -3742,6 +3796,7 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
                        lc->link_ok = link_ok;
                        lc->speed = speed;
                        lc->fc = fc;
+                       lc->supported = be16_to_cpu(p->u.info.pcap);
                        t4_os_link_changed(adap, port, link_ok);
                }
                if (mod != pi->mod_type) {
index e3146e83df2043ae59436e7eff6b8c276a3fb3e4..39fb325474f7e7499534d142d47cdcd0b7fbc1f4 100644 (file)
 #define  MEM_WRAP_CLIENT_NUM_GET(x) (((x) & MEM_WRAP_CLIENT_NUM_MASK) >> MEM_WRAP_CLIENT_NUM_SHIFT)
 #define MA_PCIE_FW 0x30b8
 #define MA_PARITY_ERROR_STATUS 0x77f4
+#define MA_PARITY_ERROR_STATUS2 0x7804
 
 #define MA_EXT_MEMORY1_BAR 0x7808
 #define EDC_0_BASE_ADDR 0x7900
 #define  TRCMULTIFILTER     0x00000001U
 
 #define MPS_TRC_RSS_CONTROL 0x9808
+#define MPS_T5_TRC_RSS_CONTROL 0xa00c
 #define  RSSCONTROL_MASK    0x00ff0000U
 #define  RSSCONTROL_SHIFT   16
 #define  RSSCONTROL(x)      ((x) << RSSCONTROL_SHIFT)
index 5f2729ebadbe14c4d6c1e56fcc29d078380db437..3409756a85b95586f7640033dc06bb274c4db139 100644 (file)
@@ -2228,6 +2228,10 @@ struct fw_debug_cmd {
 #define FW_PCIE_FW_MASTER(x)     ((x) << FW_PCIE_FW_MASTER_SHIFT)
 #define FW_PCIE_FW_MASTER_GET(x) (((x) >> FW_PCIE_FW_MASTER_SHIFT) & \
                                 FW_PCIE_FW_MASTER_MASK)
+#define FW_PCIE_FW_EVAL_MASK   0x7
+#define FW_PCIE_FW_EVAL_SHIFT  24
+#define FW_PCIE_FW_EVAL_GET(x) (((x) >> FW_PCIE_FW_EVAL_SHIFT) & \
+                                FW_PCIE_FW_EVAL_MASK)
 
 struct fw_hdr {
        u8 ver;
index a0b418e007a0d09303a32838d8acf1a06ca9d061..566b17db135a306a2bb8eea0ce167a70e6e165f4 100644 (file)
@@ -1994,7 +1994,7 @@ static void xmit_common(struct sk_buff *skb, struct ehea_swqe *swqe)
 {
        swqe->tx_control |= EHEA_SWQE_IMM_DATA_PRESENT | EHEA_SWQE_CRC;
 
-       if (skb->protocol != htons(ETH_P_IP))
+       if (vlan_get_protocol(skb) != htons(ETH_P_IP))
                return;
 
        if (skb->ip_summed == CHECKSUM_PARTIAL)
index cbc330b301cdcfb8dd7e62695700a4e4ee2920e6..ad3d5d12173faea9992f9e46f74f57e21043b05d 100644 (file)
@@ -2674,7 +2674,8 @@ set_itr_now:
 #define E1000_TX_FLAGS_VLAN_SHIFT      16
 
 static int e1000_tso(struct e1000_adapter *adapter,
-                    struct e1000_tx_ring *tx_ring, struct sk_buff *skb)
+                    struct e1000_tx_ring *tx_ring, struct sk_buff *skb,
+                    __be16 protocol)
 {
        struct e1000_context_desc *context_desc;
        struct e1000_buffer *buffer_info;
@@ -2692,7 +2693,7 @@ static int e1000_tso(struct e1000_adapter *adapter,
 
                hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
                mss = skb_shinfo(skb)->gso_size;
-               if (skb->protocol == htons(ETH_P_IP)) {
+               if (protocol == htons(ETH_P_IP)) {
                        struct iphdr *iph = ip_hdr(skb);
                        iph->tot_len = 0;
                        iph->check = 0;
@@ -2702,7 +2703,7 @@ static int e1000_tso(struct e1000_adapter *adapter,
                                                                 0);
                        cmd_length = E1000_TXD_CMD_IP;
                        ipcse = skb_transport_offset(skb) - 1;
-               } else if (skb->protocol == htons(ETH_P_IPV6)) {
+               } else if (skb_is_gso_v6(skb)) {
                        ipv6_hdr(skb)->payload_len = 0;
                        tcp_hdr(skb)->check =
                                ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
@@ -2745,7 +2746,8 @@ static int e1000_tso(struct e1000_adapter *adapter,
 }
 
 static bool e1000_tx_csum(struct e1000_adapter *adapter,
-                         struct e1000_tx_ring *tx_ring, struct sk_buff *skb)
+                         struct e1000_tx_ring *tx_ring, struct sk_buff *skb,
+                         __be16 protocol)
 {
        struct e1000_context_desc *context_desc;
        struct e1000_buffer *buffer_info;
@@ -2756,7 +2758,7 @@ static bool e1000_tx_csum(struct e1000_adapter *adapter,
        if (skb->ip_summed != CHECKSUM_PARTIAL)
                return false;
 
-       switch (skb->protocol) {
+       switch (protocol) {
        case cpu_to_be16(ETH_P_IP):
                if (ip_hdr(skb)->protocol == IPPROTO_TCP)
                        cmd_len |= E1000_TXD_CMD_TCP;
@@ -3097,6 +3099,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
        int count = 0;
        int tso;
        unsigned int f;
+       __be16 protocol = vlan_get_protocol(skb);
 
        /* This goes back to the question of how to logically map a Tx queue
         * to a flow.  Right now, performance is impacted slightly negatively
@@ -3210,7 +3213,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
 
        first = tx_ring->next_to_use;
 
-       tso = e1000_tso(adapter, tx_ring, skb);
+       tso = e1000_tso(adapter, tx_ring, skb, protocol);
        if (tso < 0) {
                dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
@@ -3220,10 +3223,10 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
                if (likely(hw->mac_type != e1000_82544))
                        tx_ring->last_tx_tso = true;
                tx_flags |= E1000_TX_FLAGS_TSO;
-       } else if (likely(e1000_tx_csum(adapter, tx_ring, skb)))
+       } else if (likely(e1000_tx_csum(adapter, tx_ring, skb, protocol)))
                tx_flags |= E1000_TX_FLAGS_CSUM;
 
-       if (likely(skb->protocol == htons(ETH_P_IP)))
+       if (protocol == htons(ETH_P_IP))
                tx_flags |= E1000_TX_FLAGS_IPV4;
 
        if (unlikely(skb->no_fcs))
index 65c3aef2bd36a2ee01bab5a11649caa589b83c95..247335d2c7ec26cb9c50bb93c6a675b4ff35879a 100644 (file)
@@ -5164,7 +5164,8 @@ link_up:
 #define E1000_TX_FLAGS_VLAN_MASK       0xffff0000
 #define E1000_TX_FLAGS_VLAN_SHIFT      16
 
-static int e1000_tso(struct e1000_ring *tx_ring, struct sk_buff *skb)
+static int e1000_tso(struct e1000_ring *tx_ring, struct sk_buff *skb,
+                    __be16 protocol)
 {
        struct e1000_context_desc *context_desc;
        struct e1000_buffer *buffer_info;
@@ -5183,7 +5184,7 @@ static int e1000_tso(struct e1000_ring *tx_ring, struct sk_buff *skb)
 
        hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
        mss = skb_shinfo(skb)->gso_size;
-       if (skb->protocol == htons(ETH_P_IP)) {
+       if (protocol == htons(ETH_P_IP)) {
                struct iphdr *iph = ip_hdr(skb);
                iph->tot_len = 0;
                iph->check = 0;
@@ -5231,7 +5232,8 @@ static int e1000_tso(struct e1000_ring *tx_ring, struct sk_buff *skb)
        return 1;
 }
 
-static bool e1000_tx_csum(struct e1000_ring *tx_ring, struct sk_buff *skb)
+static bool e1000_tx_csum(struct e1000_ring *tx_ring, struct sk_buff *skb,
+                         __be16 protocol)
 {
        struct e1000_adapter *adapter = tx_ring->adapter;
        struct e1000_context_desc *context_desc;
@@ -5239,16 +5241,10 @@ static bool e1000_tx_csum(struct e1000_ring *tx_ring, struct sk_buff *skb)
        unsigned int i;
        u8 css;
        u32 cmd_len = E1000_TXD_CMD_DEXT;
-       __be16 protocol;
 
        if (skb->ip_summed != CHECKSUM_PARTIAL)
                return false;
 
-       if (skb->protocol == cpu_to_be16(ETH_P_8021Q))
-               protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
-       else
-               protocol = skb->protocol;
-
        switch (protocol) {
        case cpu_to_be16(ETH_P_IP):
                if (ip_hdr(skb)->protocol == IPPROTO_TCP)
@@ -5546,6 +5542,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
        int count = 0;
        int tso;
        unsigned int f;
+       __be16 protocol = vlan_get_protocol(skb);
 
        if (test_bit(__E1000_DOWN, &adapter->state)) {
                dev_kfree_skb_any(skb);
@@ -5620,7 +5617,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
 
        first = tx_ring->next_to_use;
 
-       tso = e1000_tso(tx_ring, skb);
+       tso = e1000_tso(tx_ring, skb, protocol);
        if (tso < 0) {
                dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
@@ -5628,14 +5625,14 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
 
        if (tso)
                tx_flags |= E1000_TX_FLAGS_TSO;
-       else if (e1000_tx_csum(tx_ring, skb))
+       else if (e1000_tx_csum(tx_ring, skb, protocol))
                tx_flags |= E1000_TX_FLAGS_CSUM;
 
        /* Old method was to assume IPv4 packet by default if TSO was enabled.
         * 82571 hardware supports TSO capabilities for IPv6 as well...
         * no longer assume, we must.
         */
-       if (skb->protocol == htons(ETH_P_IP))
+       if (protocol == htons(ETH_P_IP))
                tx_flags |= E1000_TX_FLAGS_IPV4;
 
        if (unlikely(skb->no_fcs))
index a51aa37b7b5af10a5204c1ef8329ce9229b1ce57..369848e107f8ed37952b4849ed632655f598b6ba 100644 (file)
@@ -2295,7 +2295,7 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
                goto out_drop;
 
        /* obtain protocol of skb */
-       protocol = skb->protocol;
+       protocol = vlan_get_protocol(skb);
 
        /* record the location of the first descriptor for this packet */
        first = &tx_ring->tx_bi[tx_ring->next_to_use];
index 79bf96ca648954b390dbf60728ae687181292097..95a3ec236b4951ab7166637159393df569da97fb 100644 (file)
@@ -1597,7 +1597,7 @@ static netdev_tx_t i40e_xmit_frame_ring(struct sk_buff *skb,
                goto out_drop;
 
        /* obtain protocol of skb */
-       protocol = skb->protocol;
+       protocol = vlan_get_protocol(skb);
 
        /* record the location of the first descriptor for this packet */
        first = &tx_ring->tx_bi[tx_ring->next_to_use];
index c9f1d1b7ef378bef042b12c9e00f5bf2786594a8..ade067de168959b30c9e7eafc07ed40df0967ee0 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/mbus.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
+#include <linux/if_vlan.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
 #include <linux/io.h>
@@ -1371,15 +1372,16 @@ static u32 mvneta_skb_tx_csum(struct mvneta_port *pp, struct sk_buff *skb)
 {
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
                int ip_hdr_len = 0;
+               __be16 l3_proto = vlan_get_protocol(skb);
                u8 l4_proto;
 
-               if (skb->protocol == htons(ETH_P_IP)) {
+               if (l3_proto == htons(ETH_P_IP)) {
                        struct iphdr *ip4h = ip_hdr(skb);
 
                        /* Calculate IPv4 checksum and L4 checksum */
                        ip_hdr_len = ip4h->ihl;
                        l4_proto = ip4h->protocol;
-               } else if (skb->protocol == htons(ETH_P_IPV6)) {
+               } else if (l3_proto == htons(ETH_P_IPV6)) {
                        struct ipv6hdr *ip6h = ipv6_hdr(skb);
 
                        /* Read l4_protocol from one of IPv6 extra headers */
@@ -1390,7 +1392,7 @@ static u32 mvneta_skb_tx_csum(struct mvneta_port *pp, struct sk_buff *skb)
                        return MVNETA_TX_L4_CSUM_NOT;
 
                return mvneta_txq_desc_csum(skb_network_offset(skb),
-                               skb->protocol, ip_hdr_len, l4_proto);
+                                           l3_proto, ip_hdr_len, l4_proto);
        }
 
        return MVNETA_TX_L4_CSUM_NOT;
index bb536aa613f483434f35c4bde31ae36ab9ced290..abddcf8c40aa120c4d4ade2822ccef68d00ea434 100644 (file)
@@ -474,39 +474,12 @@ static int mlx4_en_tunnel_steer_add(struct mlx4_en_priv *priv, unsigned char *ad
                                    int qpn, u64 *reg_id)
 {
        int err;
-       struct mlx4_spec_list spec_eth_outer = { {NULL} };
-       struct mlx4_spec_list spec_vxlan     = { {NULL} };
-       struct mlx4_spec_list spec_eth_inner = { {NULL} };
-
-       struct mlx4_net_trans_rule rule = {
-               .queue_mode = MLX4_NET_TRANS_Q_FIFO,
-               .exclusive = 0,
-               .allow_loopback = 1,
-               .promisc_mode = MLX4_FS_REGULAR,
-               .priority = MLX4_DOMAIN_NIC,
-       };
-
-       __be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
 
        if (priv->mdev->dev->caps.tunnel_offload_mode != MLX4_TUNNEL_OFFLOAD_MODE_VXLAN)
                return 0; /* do nothing */
 
-       rule.port = priv->port;
-       rule.qpn = qpn;
-       INIT_LIST_HEAD(&rule.list);
-
-       spec_eth_outer.id = MLX4_NET_TRANS_RULE_ID_ETH;
-       memcpy(spec_eth_outer.eth.dst_mac, addr, ETH_ALEN);
-       memcpy(spec_eth_outer.eth.dst_mac_msk, &mac_mask, ETH_ALEN);
-
-       spec_vxlan.id = MLX4_NET_TRANS_RULE_ID_VXLAN;    /* any vxlan header */
-       spec_eth_inner.id = MLX4_NET_TRANS_RULE_ID_ETH;  /* any inner eth header */
-
-       list_add_tail(&spec_eth_outer.list, &rule.list);
-       list_add_tail(&spec_vxlan.list,     &rule.list);
-       list_add_tail(&spec_eth_inner.list, &rule.list);
-
-       err = mlx4_flow_attach(priv->mdev->dev, &rule, reg_id);
+       err = mlx4_tunnel_steer_add(priv->mdev->dev, addr, priv->port, qpn,
+                                   MLX4_DOMAIN_NIC, reg_id);
        if (err) {
                en_err(priv, "failed to add vxlan steering rule, err %d\n", err);
                return err;
index d80e7a6fac74c4381cea11f946c889216a5ce05d..ca0f98c951054945cd29fc3be2284fc7eeb7d729 100644 (file)
@@ -1020,6 +1020,44 @@ int mlx4_flow_detach(struct mlx4_dev *dev, u64 reg_id)
 }
 EXPORT_SYMBOL_GPL(mlx4_flow_detach);
 
+int mlx4_tunnel_steer_add(struct mlx4_dev *dev, unsigned char *addr,
+                         int port, int qpn, u16 prio, u64 *reg_id)
+{
+       int err;
+       struct mlx4_spec_list spec_eth_outer = { {NULL} };
+       struct mlx4_spec_list spec_vxlan     = { {NULL} };
+       struct mlx4_spec_list spec_eth_inner = { {NULL} };
+
+       struct mlx4_net_trans_rule rule = {
+               .queue_mode = MLX4_NET_TRANS_Q_FIFO,
+               .exclusive = 0,
+               .allow_loopback = 1,
+               .promisc_mode = MLX4_FS_REGULAR,
+       };
+
+       __be64 mac_mask = cpu_to_be64(MLX4_MAC_MASK << 16);
+
+       rule.port = port;
+       rule.qpn = qpn;
+       rule.priority = prio;
+       INIT_LIST_HEAD(&rule.list);
+
+       spec_eth_outer.id = MLX4_NET_TRANS_RULE_ID_ETH;
+       memcpy(spec_eth_outer.eth.dst_mac, addr, ETH_ALEN);
+       memcpy(spec_eth_outer.eth.dst_mac_msk, &mac_mask, ETH_ALEN);
+
+       spec_vxlan.id = MLX4_NET_TRANS_RULE_ID_VXLAN;    /* any vxlan header */
+       spec_eth_inner.id = MLX4_NET_TRANS_RULE_ID_ETH;  /* any inner eth header */
+
+       list_add_tail(&spec_eth_outer.list, &rule.list);
+       list_add_tail(&spec_vxlan.list,     &rule.list);
+       list_add_tail(&spec_eth_inner.list, &rule.list);
+
+       err = mlx4_flow_attach(dev, &rule, reg_id);
+       return err;
+}
+EXPORT_SYMBOL(mlx4_tunnel_steer_add);
+
 int mlx4_FLOW_STEERING_IB_UC_QP_RANGE(struct mlx4_dev *dev, u32 min_range_qpn,
                                      u32 max_range_qpn)
 {
index 5020fd47825d65c359f010a9bcbf0f2e9a0ceaf7..2f12c88c66abfa1cd0bb0e099e4a33a761327fd6 100644 (file)
@@ -206,7 +206,7 @@ static int moxart_rx_poll(struct napi_struct *napi, int budget)
        int rx_head = priv->rx_head;
        int rx = 0;
 
-       while (1) {
+       while (rx < budget) {
                desc = priv->rx_desc_base + (RX_REG_DESC_SIZE * rx_head);
                desc0 = readl(desc + RX_REG_OFFSET_DESC0);
 
@@ -218,7 +218,7 @@ static int moxart_rx_poll(struct napi_struct *napi, int budget)
                        net_dbg_ratelimited("packet error\n");
                        priv->stats.rx_dropped++;
                        priv->stats.rx_errors++;
-                       continue;
+                       goto rx_next;
                }
 
                len = desc0 & RX_DESC0_FRAME_LEN_MASK;
@@ -226,13 +226,19 @@ static int moxart_rx_poll(struct napi_struct *napi, int budget)
                if (len > RX_BUF_SIZE)
                        len = RX_BUF_SIZE;
 
-               skb = build_skb(priv->rx_buf[rx_head], priv->rx_buf_size);
+               dma_sync_single_for_cpu(&ndev->dev,
+                                       priv->rx_mapping[rx_head],
+                                       priv->rx_buf_size, DMA_FROM_DEVICE);
+               skb = netdev_alloc_skb_ip_align(ndev, len);
+
                if (unlikely(!skb)) {
-                       net_dbg_ratelimited("build_skb failed\n");
+                       net_dbg_ratelimited("netdev_alloc_skb_ip_align failed\n");
                        priv->stats.rx_dropped++;
                        priv->stats.rx_errors++;
+                       goto rx_next;
                }
 
+               memcpy(skb->data, priv->rx_buf[rx_head], len);
                skb_put(skb, len);
                skb->protocol = eth_type_trans(skb, ndev);
                napi_gro_receive(&priv->napi, skb);
@@ -244,18 +250,15 @@ static int moxart_rx_poll(struct napi_struct *napi, int budget)
                if (desc0 & RX_DESC0_MULTICAST)
                        priv->stats.multicast++;
 
+rx_next:
                writel(RX_DESC0_DMA_OWN, desc + RX_REG_OFFSET_DESC0);
 
                rx_head = RX_NEXT(rx_head);
                priv->rx_head = rx_head;
-
-               if (rx >= budget)
-                       break;
        }
 
        if (rx < budget) {
-               napi_gro_flush(napi, false);
-               __napi_complete(napi);
+               napi_complete(napi);
        }
 
        priv->reg_imr |= RPKT_FINISH_M;
@@ -346,10 +349,12 @@ static int moxart_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                len = ETH_ZLEN;
        }
 
-       txdes1 = readl(desc + TX_REG_OFFSET_DESC1);
-       txdes1 |= TX_DESC1_LTS | TX_DESC1_FTS;
-       txdes1 &= ~(TX_DESC1_FIFO_COMPLETE | TX_DESC1_INTR_COMPLETE);
-       txdes1 |= (len & TX_DESC1_BUF_SIZE_MASK);
+       dma_sync_single_for_device(&ndev->dev, priv->tx_mapping[tx_head],
+                                  priv->tx_buf_size, DMA_TO_DEVICE);
+
+       txdes1 = TX_DESC1_LTS | TX_DESC1_FTS | (len & TX_DESC1_BUF_SIZE_MASK);
+       if (tx_head == TX_DESC_NUM_MASK)
+               txdes1 |= TX_DESC1_END;
        writel(txdes1, desc + TX_REG_OFFSET_DESC1);
        writel(TX_DESC0_DMA_OWN, desc + TX_REG_OFFSET_DESC0);
 
@@ -465,8 +470,7 @@ static int moxart_mac_probe(struct platform_device *pdev)
        spin_lock_init(&priv->txlock);
 
        priv->tx_buf_size = TX_BUF_SIZE;
-       priv->rx_buf_size = RX_BUF_SIZE +
-                           SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+       priv->rx_buf_size = RX_BUF_SIZE;
 
        priv->tx_desc_base = dma_alloc_coherent(NULL, TX_REG_DESC_SIZE *
                                                TX_DESC_NUM, &priv->tx_base,
index 8706c0dbd0c36a2c3b7af167eaa4c29cda3905a5..a44a03c45014903a6410ebe2d665f3651ee30db2 100644 (file)
@@ -1220,6 +1220,9 @@ static int lpc_eth_open(struct net_device *ndev)
 
        __lpc_eth_clock_enable(pldat, true);
 
+       /* Suspended PHY makes LPC ethernet core block, so resume now */
+       phy_resume(pldat->phy_dev);
+
        /* Reset and initialize */
        __lpc_eth_reset(pldat);
        __lpc_eth_init(pldat);
index 188626e2a861d317510617dce742595b88bd3abd..3e96f269150d197253fdcdf3066c1a2da5b62985 100644 (file)
@@ -2556,6 +2556,7 @@ static int ql_tso(struct sk_buff *skb, struct ob_mac_tso_iocb_req *mac_iocb_ptr)
 
        if (skb_is_gso(skb)) {
                int err;
+               __be16 l3_proto = vlan_get_protocol(skb);
 
                err = skb_cow_head(skb, 0);
                if (err < 0)
@@ -2572,7 +2573,7 @@ static int ql_tso(struct sk_buff *skb, struct ob_mac_tso_iocb_req *mac_iocb_ptr)
                                << OB_MAC_TRANSPORT_HDR_SHIFT);
                mac_iocb_ptr->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
                mac_iocb_ptr->flags2 |= OB_MAC_TSO_IOCB_LSO;
-               if (likely(skb->protocol == htons(ETH_P_IP))) {
+               if (likely(l3_proto == htons(ETH_P_IP))) {
                        struct iphdr *iph = ip_hdr(skb);
                        iph->check = 0;
                        mac_iocb_ptr->flags1 |= OB_MAC_TSO_IOCB_IP4;
@@ -2580,7 +2581,7 @@ static int ql_tso(struct sk_buff *skb, struct ob_mac_tso_iocb_req *mac_iocb_ptr)
                                                                 iph->daddr, 0,
                                                                 IPPROTO_TCP,
                                                                 0);
-               } else if (skb->protocol == htons(ETH_P_IPV6)) {
+               } else if (l3_proto == htons(ETH_P_IPV6)) {
                        mac_iocb_ptr->flags1 |= OB_MAC_TSO_IOCB_IP6;
                        tcp_hdr(skb)->check =
                            ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
index 9e757c792d846f300288c9848225e1db9a9584fa..196e98a2d93bbfa905a0b13d8a372da00add0f7b 100644 (file)
@@ -5,6 +5,7 @@
 config SH_ETH
        tristate "Renesas SuperH Ethernet support"
        depends on HAS_DMA
+       depends on ARCH_SHMOBILE || SUPERH || COMPILE_TEST
        select CRC32
        select MII
        select MDIO_BITBANG
index c553f6b5a9131f0af16230f59ccd0557fe1116a5..cf28daba4346f0c288d1718513554b38e4de2176 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "stmmac.h"
 
-static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
+static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
 {
        struct stmmac_priv *priv = (struct stmmac_priv *)p;
        unsigned int txsize = priv->dma_tx_size;
@@ -47,7 +47,9 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
 
        desc->des2 = dma_map_single(priv->device, skb->data,
                                    bmax, DMA_TO_DEVICE);
-       priv->tx_skbuff_dma[entry] = desc->des2;
+       if (dma_mapping_error(priv->device, desc->des2))
+               return -1;
+       priv->tx_skbuff_dma[entry].buf = desc->des2;
        priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE);
 
        while (len != 0) {
@@ -59,7 +61,9 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
                        desc->des2 = dma_map_single(priv->device,
                                                    (skb->data + bmax * i),
                                                    bmax, DMA_TO_DEVICE);
-                       priv->tx_skbuff_dma[entry] = desc->des2;
+                       if (dma_mapping_error(priv->device, desc->des2))
+                               return -1;
+                       priv->tx_skbuff_dma[entry].buf = desc->des2;
                        priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum,
                                                        STMMAC_CHAIN_MODE);
                        priv->hw->desc->set_tx_owner(desc);
@@ -69,7 +73,9 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
                        desc->des2 = dma_map_single(priv->device,
                                                    (skb->data + bmax * i), len,
                                                    DMA_TO_DEVICE);
-                       priv->tx_skbuff_dma[entry] = desc->des2;
+                       if (dma_mapping_error(priv->device, desc->des2))
+                               return -1;
+                       priv->tx_skbuff_dma[entry].buf = desc->des2;
                        priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
                                                        STMMAC_CHAIN_MODE);
                        priv->hw->desc->set_tx_owner(desc);
index de507c32036c75331e393ad5b013890ffffb9d1b..593e6c4144a7c197140f875f73e86c5583c215d1 100644 (file)
@@ -220,10 +220,10 @@ enum dma_irq_status {
        handle_tx = 0x8,
 };
 
-#define        CORE_IRQ_TX_PATH_IN_LPI_MODE    (1 << 1)
-#define        CORE_IRQ_TX_PATH_EXIT_LPI_MODE  (1 << 2)
-#define        CORE_IRQ_RX_PATH_IN_LPI_MODE    (1 << 3)
-#define        CORE_IRQ_RX_PATH_EXIT_LPI_MODE  (1 << 4)
+#define        CORE_IRQ_TX_PATH_IN_LPI_MODE    (1 << 0)
+#define        CORE_IRQ_TX_PATH_EXIT_LPI_MODE  (1 << 1)
+#define        CORE_IRQ_RX_PATH_IN_LPI_MODE    (1 << 2)
+#define        CORE_IRQ_RX_PATH_EXIT_LPI_MODE  (1 << 3)
 
 #define        CORE_PCS_ANE_COMPLETE           (1 << 5)
 #define        CORE_PCS_LINK_STATUS            (1 << 6)
@@ -287,7 +287,7 @@ struct dma_features {
 
 /* Default LPI timers */
 #define STMMAC_DEFAULT_LIT_LS  0x3E8
-#define STMMAC_DEFAULT_TWT_LS  0x0
+#define STMMAC_DEFAULT_TWT_LS  0x1E
 
 #define STMMAC_CHAIN_MODE      0x1
 #define STMMAC_RING_MODE       0x2
@@ -425,7 +425,7 @@ struct stmmac_mode_ops {
        void (*init) (void *des, dma_addr_t phy_addr, unsigned int size,
                      unsigned int extend_desc);
        unsigned int (*is_jumbo_frm) (int len, int ehn_desc);
-       unsigned int (*jumbo_frm) (void *priv, struct sk_buff *skb, int csum);
+       int (*jumbo_frm)(void *priv, struct sk_buff *skb, int csum);
        int (*set_16kib_bfsize)(int mtu);
        void (*init_desc3)(struct dma_desc *p);
        void (*refill_desc3) (void *priv, struct dma_desc *p);
@@ -445,6 +445,7 @@ struct mac_device_info {
        int multicast_filter_bins;
        int unicast_filter_entries;
        int mcast_bits_log2;
+       unsigned int rx_csum;
 };
 
 struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins,
index 71b5419256c138e335c77aab87cf37784ff79037..64d8f56a9c1732f9199cc3a748e25ae8c1107ed7 100644 (file)
@@ -153,7 +153,7 @@ enum inter_frame_gap {
 #define GMAC_CONTROL_RE                0x00000004      /* Receiver Enable */
 
 #define GMAC_CORE_INIT (GMAC_CONTROL_JD | GMAC_CONTROL_PS | GMAC_CONTROL_ACS | \
-                       GMAC_CONTROL_BE)
+                       GMAC_CONTROL_BE | GMAC_CONTROL_DCRS)
 
 /* GMAC Frame Filter defines */
 #define GMAC_FRAME_FILTER_PR   0x00000001      /* Promiscuous Mode */
index d8ef18786a1cadae60f5d550269a0036a3f24661..5efe60ea6526b3d06305530b75240b9de719f1f3 100644 (file)
@@ -58,7 +58,11 @@ static int dwmac1000_rx_ipc_enable(struct mac_device_info *hw)
        void __iomem *ioaddr = hw->pcsr;
        u32 value = readl(ioaddr + GMAC_CONTROL);
 
-       value |= GMAC_CONTROL_IPC;
+       if (hw->rx_csum)
+               value |= GMAC_CONTROL_IPC;
+       else
+               value &= ~GMAC_CONTROL_IPC;
+
        writel(value, ioaddr + GMAC_CONTROL);
 
        value = readl(ioaddr + GMAC_CONTROL);
index 8607488cbcfcfaea7bc70510f0a3f601c5dade7d..192c2491330b1070348f5ccf5c5eb51d492e7b24 100644 (file)
@@ -68,7 +68,7 @@ struct stmmac_counters {
        unsigned int mmc_rx_octetcount_g;
        unsigned int mmc_rx_broadcastframe_g;
        unsigned int mmc_rx_multicastframe_g;
-       unsigned int mmc_rx_crc_errror;
+       unsigned int mmc_rx_crc_error;
        unsigned int mmc_rx_align_error;
        unsigned int mmc_rx_run_error;
        unsigned int mmc_rx_jabber_error;
index 50617c5a0bdb5e63fc930f7af277a1a9fb139af4..08c483bd2ec7bd94d5434f9567c75f609ce27d35 100644 (file)
@@ -196,7 +196,7 @@ void dwmac_mmc_read(void __iomem *ioaddr, struct stmmac_counters *mmc)
        mmc->mmc_rx_octetcount_g += readl(ioaddr + MMC_RX_OCTETCOUNT_G);
        mmc->mmc_rx_broadcastframe_g += readl(ioaddr + MMC_RX_BROADCASTFRAME_G);
        mmc->mmc_rx_multicastframe_g += readl(ioaddr + MMC_RX_MULTICASTFRAME_G);
-       mmc->mmc_rx_crc_errror += readl(ioaddr + MMC_RX_CRC_ERRROR);
+       mmc->mmc_rx_crc_error += readl(ioaddr + MMC_RX_CRC_ERRROR);
        mmc->mmc_rx_align_error += readl(ioaddr + MMC_RX_ALIGN_ERROR);
        mmc->mmc_rx_run_error += readl(ioaddr + MMC_RX_RUN_ERROR);
        mmc->mmc_rx_jabber_error += readl(ioaddr + MMC_RX_JABBER_ERROR);
index 650a4be6bce5243e046fcd226719e669f66444e8..5dd50c6cda5be0280e235152057a329a89fb187c 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "stmmac.h"
 
-static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
+static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
 {
        struct stmmac_priv *priv = (struct stmmac_priv *)p;
        unsigned int txsize = priv->dma_tx_size;
@@ -53,7 +53,10 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
 
                desc->des2 = dma_map_single(priv->device, skb->data,
                                            bmax, DMA_TO_DEVICE);
-               priv->tx_skbuff_dma[entry] = desc->des2;
+               if (dma_mapping_error(priv->device, desc->des2))
+                       return -1;
+
+               priv->tx_skbuff_dma[entry].buf = desc->des2;
                desc->des3 = desc->des2 + BUF_SIZE_4KiB;
                priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum,
                                                STMMAC_RING_MODE);
@@ -68,7 +71,9 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
 
                desc->des2 = dma_map_single(priv->device, skb->data + bmax,
                                            len, DMA_TO_DEVICE);
-               priv->tx_skbuff_dma[entry] = desc->des2;
+               if (dma_mapping_error(priv->device, desc->des2))
+                       return -1;
+               priv->tx_skbuff_dma[entry].buf = desc->des2;
                desc->des3 = desc->des2 + BUF_SIZE_4KiB;
                priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
                                                STMMAC_RING_MODE);
@@ -77,7 +82,9 @@ static unsigned int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
        } else {
                desc->des2 = dma_map_single(priv->device, skb->data,
                                            nopaged_len, DMA_TO_DEVICE);
-               priv->tx_skbuff_dma[entry] = desc->des2;
+               if (dma_mapping_error(priv->device, desc->des2))
+                       return -1;
+               priv->tx_skbuff_dma[entry].buf = desc->des2;
                desc->des3 = desc->des2 + BUF_SIZE_4KiB;
                priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, csum,
                                                STMMAC_RING_MODE);
index ca01035634a76fbc88414f6550849cfa1c772403..58097c0e2ad502699ace45392bb3f12855101625 100644 (file)
 #include <linux/ptp_clock_kernel.h>
 #include <linux/reset.h>
 
+struct stmmac_tx_info {
+       dma_addr_t buf;
+       bool map_as_page;
+};
+
 struct stmmac_priv {
        /* Frequently used values are kept adjacent for cache effect */
        struct dma_extended_desc *dma_etx ____cacheline_aligned_in_smp;
@@ -45,7 +50,7 @@ struct stmmac_priv {
        u32 tx_count_frames;
        u32 tx_coal_frames;
        u32 tx_coal_timer;
-       dma_addr_t *tx_skbuff_dma;
+       struct stmmac_tx_info *tx_skbuff_dma;
        dma_addr_t dma_tx_phy;
        int tx_coalesce;
        int hwts_tx_en;
@@ -105,6 +110,8 @@ struct stmmac_priv {
        struct ptp_clock *ptp_clock;
        struct ptp_clock_info ptp_clock_ops;
        unsigned int default_addend;
+       struct clk *clk_ptp_ref;
+       unsigned int clk_ptp_rate;
        u32 adv_ts;
        int use_riwt;
        int irq_wake;
index 9af50bae4dde67c543c15e0344f90ac9d53fd2b8..cf4f38db1c0a60338c1d7479b0cfe28f50b6b558 100644 (file)
@@ -175,7 +175,7 @@ static const struct stmmac_stats stmmac_mmc[] = {
        STMMAC_MMC_STAT(mmc_rx_octetcount_g),
        STMMAC_MMC_STAT(mmc_rx_broadcastframe_g),
        STMMAC_MMC_STAT(mmc_rx_multicastframe_g),
-       STMMAC_MMC_STAT(mmc_rx_crc_errror),
+       STMMAC_MMC_STAT(mmc_rx_crc_error),
        STMMAC_MMC_STAT(mmc_rx_align_error),
        STMMAC_MMC_STAT(mmc_rx_run_error),
        STMMAC_MMC_STAT(mmc_rx_jabber_error),
index 08addd65372818f48075b585eeb1d36ab682025b..6e6ee226de04f60dc8511334db8ca48310fd5cff 100644 (file)
@@ -275,6 +275,7 @@ static void stmmac_eee_ctrl_timer(unsigned long arg)
  */
 bool stmmac_eee_init(struct stmmac_priv *priv)
 {
+       char *phy_bus_name = priv->plat->phy_bus_name;
        bool ret = false;
 
        /* Using PCS we cannot dial with the phy registers at this stage
@@ -284,6 +285,10 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
            (priv->pcs == STMMAC_PCS_RTBI))
                goto out;
 
+       /* Never init EEE in case of a switch is attached */
+       if (phy_bus_name && (!strcmp(phy_bus_name, "fixed")))
+               goto out;
+
        /* MAC core supports the EEE feature. */
        if (priv->dma_cap.eee) {
                int tx_lpi_timer = priv->tx_lpi_timer;
@@ -316,10 +321,9 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
                        priv->hw->mac->set_eee_timer(priv->hw,
                                                     STMMAC_DEFAULT_LIT_LS,
                                                     tx_lpi_timer);
-               } else
-                       /* Set HW EEE according to the speed */
-                       priv->hw->mac->set_eee_pls(priv->hw,
-                                                  priv->phydev->link);
+               }
+               /* Set HW EEE according to the speed */
+               priv->hw->mac->set_eee_pls(priv->hw, priv->phydev->link);
 
                pr_debug("stmmac: Energy-Efficient Ethernet initialized\n");
 
@@ -603,16 +607,16 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
                /* calculate default added value:
                 * formula is :
                 * addend = (2^32)/freq_div_ratio;
-                * where, freq_div_ratio = STMMAC_SYSCLOCK/50MHz
-                * hence, addend = ((2^32) * 50MHz)/STMMAC_SYSCLOCK;
-                * NOTE: STMMAC_SYSCLOCK should be >= 50MHz to
+                * where, freq_div_ratio = clk_ptp_ref_i/50MHz
+                * hence, addend = ((2^32) * 50MHz)/clk_ptp_ref_i;
+                * NOTE: clk_ptp_ref_i should be >= 50MHz to
                 *       achive 20ns accuracy.
                 *
                 * 2^x * y == (y << x), hence
                 * 2^32 * 50000000 ==> (50000000 << 32)
                 */
                temp = (u64) (50000000ULL << 32);
-               priv->default_addend = div_u64(temp, STMMAC_SYSCLOCK);
+               priv->default_addend = div_u64(temp, priv->clk_ptp_rate);
                priv->hw->ptp->config_addend(priv->ioaddr,
                                             priv->default_addend);
 
@@ -638,6 +642,16 @@ static int stmmac_init_ptp(struct stmmac_priv *priv)
        if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
                return -EOPNOTSUPP;
 
+       /* Fall-back to main clock in case of no PTP ref is passed */
+       priv->clk_ptp_ref = devm_clk_get(priv->device, "clk_ptp_ref");
+       if (IS_ERR(priv->clk_ptp_ref)) {
+               priv->clk_ptp_rate = clk_get_rate(priv->stmmac_clk);
+               priv->clk_ptp_ref = NULL;
+       } else {
+               clk_prepare_enable(priv->clk_ptp_ref);
+               priv->clk_ptp_rate = clk_get_rate(priv->clk_ptp_ref);
+       }
+
        priv->adv_ts = 0;
        if (priv->dma_cap.atime_stamp && priv->extend_desc)
                priv->adv_ts = 1;
@@ -657,6 +671,8 @@ static int stmmac_init_ptp(struct stmmac_priv *priv)
 
 static void stmmac_release_ptp(struct stmmac_priv *priv)
 {
+       if (priv->clk_ptp_ref)
+               clk_disable_unprepare(priv->clk_ptp_ref);
        stmmac_ptp_unregister(priv);
 }
 
@@ -1061,7 +1077,8 @@ static int init_dma_desc_rings(struct net_device *dev)
                else
                        p = priv->dma_tx + i;
                p->des2 = 0;
-               priv->tx_skbuff_dma[i] = 0;
+               priv->tx_skbuff_dma[i].buf = 0;
+               priv->tx_skbuff_dma[i].map_as_page = false;
                priv->tx_skbuff[i] = NULL;
        }
 
@@ -1100,17 +1117,24 @@ static void dma_free_tx_skbufs(struct stmmac_priv *priv)
                else
                        p = priv->dma_tx + i;
 
-               if (priv->tx_skbuff_dma[i]) {
-                       dma_unmap_single(priv->device,
-                                        priv->tx_skbuff_dma[i],
-                                        priv->hw->desc->get_tx_len(p),
-                                        DMA_TO_DEVICE);
-                       priv->tx_skbuff_dma[i] = 0;
+               if (priv->tx_skbuff_dma[i].buf) {
+                       if (priv->tx_skbuff_dma[i].map_as_page)
+                               dma_unmap_page(priv->device,
+                                              priv->tx_skbuff_dma[i].buf,
+                                              priv->hw->desc->get_tx_len(p),
+                                              DMA_TO_DEVICE);
+                       else
+                               dma_unmap_single(priv->device,
+                                                priv->tx_skbuff_dma[i].buf,
+                                                priv->hw->desc->get_tx_len(p),
+                                                DMA_TO_DEVICE);
                }
 
                if (priv->tx_skbuff[i] != NULL) {
                        dev_kfree_skb_any(priv->tx_skbuff[i]);
                        priv->tx_skbuff[i] = NULL;
+                       priv->tx_skbuff_dma[i].buf = 0;
+                       priv->tx_skbuff_dma[i].map_as_page = false;
                }
        }
 }
@@ -1131,7 +1155,8 @@ static int alloc_dma_desc_resources(struct stmmac_priv *priv)
        if (!priv->rx_skbuff)
                goto err_rx_skbuff;
 
-       priv->tx_skbuff_dma = kmalloc_array(txsize, sizeof(dma_addr_t),
+       priv->tx_skbuff_dma = kmalloc_array(txsize,
+                                           sizeof(*priv->tx_skbuff_dma),
                                            GFP_KERNEL);
        if (!priv->tx_skbuff_dma)
                goto err_tx_skbuff_dma;
@@ -1293,12 +1318,19 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
                        pr_debug("%s: curr %d, dirty %d\n", __func__,
                                 priv->cur_tx, priv->dirty_tx);
 
-               if (likely(priv->tx_skbuff_dma[entry])) {
-                       dma_unmap_single(priv->device,
-                                        priv->tx_skbuff_dma[entry],
-                                        priv->hw->desc->get_tx_len(p),
-                                        DMA_TO_DEVICE);
-                       priv->tx_skbuff_dma[entry] = 0;
+               if (likely(priv->tx_skbuff_dma[entry].buf)) {
+                       if (priv->tx_skbuff_dma[entry].map_as_page)
+                               dma_unmap_page(priv->device,
+                                              priv->tx_skbuff_dma[entry].buf,
+                                              priv->hw->desc->get_tx_len(p),
+                                              DMA_TO_DEVICE);
+                       else
+                               dma_unmap_single(priv->device,
+                                                priv->tx_skbuff_dma[entry].buf,
+                                                priv->hw->desc->get_tx_len(p),
+                                                DMA_TO_DEVICE);
+                       priv->tx_skbuff_dma[entry].buf = 0;
+                       priv->tx_skbuff_dma[entry].map_as_page = false;
                }
                priv->hw->mode->clean_desc3(priv, p);
 
@@ -1637,6 +1669,13 @@ static int stmmac_hw_setup(struct net_device *dev)
        /* Initialize the MAC Core */
        priv->hw->mac->core_init(priv->hw, dev->mtu);
 
+       ret = priv->hw->mac->rx_ipc(priv->hw);
+       if (!ret) {
+               pr_warn(" RX IPC Checksum Offload disabled\n");
+               priv->plat->rx_coe = STMMAC_RX_COE_NONE;
+               priv->hw->rx_csum = 0;
+       }
+
        /* Enable the MAC Rx/Tx */
        stmmac_set_mac(priv->ioaddr, true);
 
@@ -1887,12 +1926,16 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
        if (likely(!is_jumbo)) {
                desc->des2 = dma_map_single(priv->device, skb->data,
                                            nopaged_len, DMA_TO_DEVICE);
-               priv->tx_skbuff_dma[entry] = desc->des2;
+               if (dma_mapping_error(priv->device, desc->des2))
+                       goto dma_map_err;
+               priv->tx_skbuff_dma[entry].buf = desc->des2;
                priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len,
                                                csum_insertion, priv->mode);
        } else {
                desc = first;
                entry = priv->hw->mode->jumbo_frm(priv, skb, csum_insertion);
+               if (unlikely(entry < 0))
+                       goto dma_map_err;
        }
 
        for (i = 0; i < nfrags; i++) {
@@ -1908,7 +1951,11 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
                desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len,
                                              DMA_TO_DEVICE);
-               priv->tx_skbuff_dma[entry] = desc->des2;
+               if (dma_mapping_error(priv->device, desc->des2))
+                       goto dma_map_err; /* should reuse desc w/o issues */
+
+               priv->tx_skbuff_dma[entry].buf = desc->des2;
+               priv->tx_skbuff_dma[entry].map_as_page = true;
                priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion,
                                                priv->mode);
                wmb();
@@ -1975,7 +2022,12 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
        priv->hw->dma->enable_dma_transmission(priv->ioaddr);
 
        spin_unlock(&priv->tx_lock);
+       return NETDEV_TX_OK;
 
+dma_map_err:
+       dev_err(priv->device, "Tx dma map failed\n");
+       dev_kfree_skb(skb);
+       priv->dev->stats.tx_dropped++;
        return NETDEV_TX_OK;
 }
 
@@ -2028,7 +2080,12 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv)
                        priv->rx_skbuff_dma[entry] =
                            dma_map_single(priv->device, skb->data, bfsize,
                                           DMA_FROM_DEVICE);
-
+                       if (dma_mapping_error(priv->device,
+                                             priv->rx_skbuff_dma[entry])) {
+                               dev_err(priv->device, "Rx dma map failed\n");
+                               dev_kfree_skb(skb);
+                               break;
+                       }
                        p->des2 = priv->rx_skbuff_dma[entry];
 
                        priv->hw->mode->refill_desc3(priv, p);
@@ -2055,7 +2112,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
        unsigned int entry = priv->cur_rx % rxsize;
        unsigned int next_entry;
        unsigned int count = 0;
-       int coe = priv->plat->rx_coe;
+       int coe = priv->hw->rx_csum;
 
        if (netif_msg_rx_status(priv)) {
                pr_debug("%s: descriptor ring:\n", __func__);
@@ -2276,8 +2333,7 @@ static netdev_features_t stmmac_fix_features(struct net_device *dev,
 
        if (priv->plat->rx_coe == STMMAC_RX_COE_NONE)
                features &= ~NETIF_F_RXCSUM;
-       else if (priv->plat->rx_coe == STMMAC_RX_COE_TYPE1)
-               features &= ~NETIF_F_IPV6_CSUM;
+
        if (!priv->plat->tx_coe)
                features &= ~NETIF_F_ALL_CSUM;
 
@@ -2292,6 +2348,24 @@ static netdev_features_t stmmac_fix_features(struct net_device *dev,
        return features;
 }
 
+static int stmmac_set_features(struct net_device *netdev,
+                              netdev_features_t features)
+{
+       struct stmmac_priv *priv = netdev_priv(netdev);
+
+       /* Keep the COE Type in case of csum is supporting */
+       if (features & NETIF_F_RXCSUM)
+               priv->hw->rx_csum = priv->plat->rx_coe;
+       else
+               priv->hw->rx_csum = 0;
+       /* No check needed because rx_coe has been set before and it will be
+        * fixed in case of issue.
+        */
+       priv->hw->mac->rx_ipc(priv->hw);
+
+       return 0;
+}
+
 /**
  *  stmmac_interrupt - main ISR
  *  @irq: interrupt number.
@@ -2572,6 +2646,7 @@ static const struct net_device_ops stmmac_netdev_ops = {
        .ndo_stop = stmmac_release,
        .ndo_change_mtu = stmmac_change_mtu,
        .ndo_fix_features = stmmac_fix_features,
+       .ndo_set_features = stmmac_set_features,
        .ndo_set_rx_mode = stmmac_set_rx_mode,
        .ndo_tx_timeout = stmmac_tx_timeout,
        .ndo_do_ioctl = stmmac_ioctl,
@@ -2592,7 +2667,6 @@ static const struct net_device_ops stmmac_netdev_ops = {
  */
 static int stmmac_hw_init(struct stmmac_priv *priv)
 {
-       int ret;
        struct mac_device_info *mac;
 
        /* Identify the MAC HW device */
@@ -2649,15 +2723,11 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
        /* To use alternate (extended) or normal descriptor structures */
        stmmac_selec_desc_mode(priv);
 
-       ret = priv->hw->mac->rx_ipc(priv->hw);
-       if (!ret) {
-               pr_warn(" RX IPC Checksum Offload not configured.\n");
-               priv->plat->rx_coe = STMMAC_RX_COE_NONE;
-       }
-
-       if (priv->plat->rx_coe)
+       if (priv->plat->rx_coe) {
+               priv->hw->rx_csum = priv->plat->rx_coe;
                pr_info(" RX Checksum Offload Engine supported (type %d)\n",
                        priv->plat->rx_coe);
+       }
        if (priv->plat->tx_coe)
                pr_info(" TX Checksum insertion supported\n");
 
index b7ad3565566cc8a09b7964fcb59aca3921e8e57c..c5ee79d8a8c56478f9987efc2c0631c140aafc0d 100644 (file)
@@ -206,6 +206,7 @@ void stmmac_ptp_unregister(struct stmmac_priv *priv)
 {
        if (priv->ptp_clock) {
                ptp_clock_unregister(priv->ptp_clock);
+               priv->ptp_clock = NULL;
                pr_debug("Removed PTP HW clock successfully on %s\n",
                         priv->dev->name);
        }
index 3dbc047622fa8bee67ed44213b0f8cd74a4ca956..4535df37c22767824d1f7bbe6db56a8e3d0644ab 100644 (file)
@@ -25,8 +25,6 @@
 #ifndef __STMMAC_PTP_H__
 #define __STMMAC_PTP_H__
 
-#define STMMAC_SYSCLOCK 62500000
-
 /* IEEE 1588 PTP register offsets */
 #define PTP_TCR                0x0700  /* Timestamp Control Reg */
 #define PTP_SSIR       0x0704  /* Sub-Second Increment Reg */
index c1ba26c06d731252771dfe7f2273b724bc675068..3de2f0d15fe24b22c58a912c1502e7513ad6e6cc 100644 (file)
 #define        PCI_MEM64BIT    (2<<1)       /* Base addr anywhere in 64 Bit range */
 #define        PCI_MEMSPACE    0x00000001L  /* Bit 0:  Memory Space Indic. */
 
-/*     PCI_BASE_2ND    32 bit  2nd Base address */
-#define        PCI_IOBASE      0xffffff00L  /* Bit 31..8:  I/O Base address */
-#define        PCI_IOSIZE      0x000000fcL  /* Bit 7..2:   I/O Size Requirements */
-#define        PCI_IOSPACE     0x00000001L  /* Bit 0:      I/O Space Indicator */
-
 /*     PCI_SUB_VID     16 bit  Subsystem Vendor ID */
 /*     PCI_SUB_ID      16 bit  Subsystem ID */
 
index c94e2a27446a33a685b8b1c17dee4e559c33afd7..a854d38c231dfebc983a3bcd4840fdd5a2257bd2 100644 (file)
@@ -1036,31 +1036,31 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
                /* First check if the EEE ability is supported */
                eee_cap = phy_read_mmd_indirect(phydev, MDIO_PCS_EEE_ABLE,
                                                MDIO_MMD_PCS, phydev->addr);
-               if (eee_cap < 0)
-                       return eee_cap;
+               if (eee_cap <= 0)
+                       goto eee_exit_err;
 
                cap = mmd_eee_cap_to_ethtool_sup_t(eee_cap);
                if (!cap)
-                       return -EPROTONOSUPPORT;
+                       goto eee_exit_err;
 
                /* Check which link settings negotiated and verify it in
                 * the EEE advertising registers.
                 */
                eee_lp = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_LPABLE,
                                               MDIO_MMD_AN, phydev->addr);
-               if (eee_lp < 0)
-                       return eee_lp;
+               if (eee_lp <= 0)
+                       goto eee_exit_err;
 
                eee_adv = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_ADV,
                                                MDIO_MMD_AN, phydev->addr);
-               if (eee_adv < 0)
-                       return eee_adv;
+               if (eee_adv <= 0)
+                       goto eee_exit_err;
 
                adv = mmd_eee_adv_to_ethtool_adv_t(eee_adv);
                lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp);
                idx = phy_find_setting(phydev->speed, phydev->duplex);
                if (!(lp & adv & settings[idx].setting))
-                       return -EPROTONOSUPPORT;
+                       goto eee_exit_err;
 
                if (clk_stop_enable) {
                        /* Configure the PHY to stop receiving xMII
@@ -1080,7 +1080,7 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
 
                return 0; /* EEE supported */
        }
-
+eee_exit_err:
        return -EPROTONOSUPPORT;
 }
 EXPORT_SYMBOL(phy_init_eee);
index d6e90c72c257ebe6740d3980dc7273c6b128978d..6dfcbf523936ef69527f5d23168dbf51ee638094 100644 (file)
@@ -2056,7 +2056,6 @@ vmxnet3_set_mc(struct net_device *netdev)
                if (!netdev_mc_empty(netdev)) {
                        new_table = vmxnet3_copy_mc(netdev);
                        if (new_table) {
-                               new_mode |= VMXNET3_RXM_MCAST;
                                rxConf->mfTableLen = cpu_to_le16(
                                        netdev_mc_count(netdev) * ETH_ALEN);
                                new_table_pa = dma_map_single(
@@ -2064,15 +2063,18 @@ vmxnet3_set_mc(struct net_device *netdev)
                                                        new_table,
                                                        rxConf->mfTableLen,
                                                        PCI_DMA_TODEVICE);
+                       }
+
+                       if (new_table_pa) {
+                               new_mode |= VMXNET3_RXM_MCAST;
                                rxConf->mfTablePA = cpu_to_le64(new_table_pa);
                        } else {
-                               netdev_info(netdev, "failed to copy mcast list"
-                                           ", setting ALL_MULTI\n");
+                               netdev_info(netdev,
+                                           "failed to copy mcast list, setting ALL_MULTI\n");
                                new_mode |= VMXNET3_RXM_ALL_MULTI;
                        }
                }
 
-
        if (!(new_mode & VMXNET3_RXM_MCAST)) {
                rxConf->mfTableLen = 0;
                rxConf->mfTablePA = 0;
@@ -2091,11 +2093,10 @@ vmxnet3_set_mc(struct net_device *netdev)
                               VMXNET3_CMD_UPDATE_MAC_FILTERS);
        spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 
-       if (new_table) {
+       if (new_table_pa)
                dma_unmap_single(&adapter->pdev->dev, new_table_pa,
                                 rxConf->mfTableLen, PCI_DMA_TODEVICE);
-               kfree(new_table);
-       }
+       kfree(new_table);
 }
 
 void
index 29ee77f2c97f3cc0e27e2985751297e3fbf01f90..3759479f959a43b86654e7b493a5d1beb5b6034b 100644 (file)
 /*
  * Version numbers
  */
-#define VMXNET3_DRIVER_VERSION_STRING   "1.2.0.0-k"
+#define VMXNET3_DRIVER_VERSION_STRING   "1.2.1.0-k"
 
 /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */
-#define VMXNET3_DRIVER_VERSION_NUM      0x01020000
+#define VMXNET3_DRIVER_VERSION_NUM      0x01020100
 
 #if defined(CONFIG_PCI_MSI)
        /* RSS only makes sense if MSI-X is supported. */
index 1fb7b37d1402a447b84298829bab61d4f8b6d129..beb377b2d4b78e67e15fa2c7fe6404bef240eba0 100644 (file)
@@ -1327,7 +1327,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb)
        } else if (vxlan->flags & VXLAN_F_L3MISS) {
                union vxlan_addr ipa = {
                        .sin.sin_addr.s_addr = tip,
-                       .sa.sa_family = AF_INET,
+                       .sin.sin_family = AF_INET,
                };
 
                vxlan_ip_miss(dev, &ipa);
@@ -1488,7 +1488,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb)
        } else if (vxlan->flags & VXLAN_F_L3MISS) {
                union vxlan_addr ipa = {
                        .sin6.sin6_addr = msg->target,
-                       .sa.sa_family = AF_INET6,
+                       .sin6.sin6_family = AF_INET6,
                };
 
                vxlan_ip_miss(dev, &ipa);
@@ -1521,7 +1521,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
                if (!n && (vxlan->flags & VXLAN_F_L3MISS)) {
                        union vxlan_addr ipa = {
                                .sin.sin_addr.s_addr = pip->daddr,
-                               .sa.sa_family = AF_INET,
+                               .sin.sin_family = AF_INET,
                        };
 
                        vxlan_ip_miss(dev, &ipa);
@@ -1542,7 +1542,7 @@ static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
                if (!n && (vxlan->flags & VXLAN_F_L3MISS)) {
                        union vxlan_addr ipa = {
                                .sin6.sin6_addr = pip6->daddr,
-                               .sa.sa_family = AF_INET6,
+                               .sin6.sin6_family = AF_INET6,
                        };
 
                        vxlan_ip_miss(dev, &ipa);
index 334c2ece855a92af6576b01ec87cd47af58b8540..da92bfa76b7cf1d37e9ea819edf00c59d84e350b 100644 (file)
@@ -2423,8 +2423,6 @@ static void at76_delete_device(struct at76_priv *priv)
 
        kfree_skb(priv->rx_skb);
 
-       usb_put_dev(priv->udev);
-
        at76_dbg(DBG_PROC_ENTRY, "%s: before freeing priv/ieee80211_hw",
                 __func__);
        ieee80211_free_hw(priv->hw);
@@ -2558,6 +2556,7 @@ static void at76_disconnect(struct usb_interface *interface)
 
        wiphy_info(priv->hw->wiphy, "disconnecting\n");
        at76_delete_device(priv);
+       usb_put_dev(priv->udev);
        dev_info(&interface->dev, "disconnected\n");
 }
 
index 5fe29b9f8fa26e31b05eaab237ac4830aaf21471..8f68426ca653d93dc58ea990a213c7091a13553a 100644 (file)
@@ -253,7 +253,7 @@ static ssize_t write_file_spec_scan_ctl(struct file *file,
 
        if (strncmp("trigger", buf, 7) == 0) {
                ath9k_spectral_scan_trigger(sc->hw);
-       } else if (strncmp("background", buf, 9) == 0) {
+       } else if (strncmp("background", buf, 10) == 0) {
                ath9k_spectral_scan_config(sc->hw, SPECTRAL_BACKGROUND);
                ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n");
        } else if (strncmp("chanscan", buf, 8) == 0) {
index 6451d2b6abcff3c33f486c9d7eb90390647a1266..824f5e2877835d8a829f643d8b15cf1ed85e2572 100644 (file)
@@ -51,7 +51,6 @@ config IWLWIFI_LEDS
 
 config IWLDVM
        tristate "Intel Wireless WiFi DVM Firmware support"
-       depends on m
        default IWLWIFI
        help
          This is the driver that supports the DVM firmware which is
@@ -60,7 +59,6 @@ config IWLDVM
 
 config IWLMVM
        tristate "Intel Wireless WiFi MVM Firmware support"
-       depends on m
        help
          This is the driver that supports the MVM firmware which is
          currently only available for 7260 and 3160 devices.
index 6dc5dd3ced44723943934f114c6fde78c98a565f..ed50de6362ed1d5dcd56b45243ff0b140dcbafe5 100644 (file)
@@ -1068,6 +1068,13 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
        /* recalculate basic rates */
        iwl_calc_basic_rates(priv, ctx);
 
+       /*
+        * force CTS-to-self frames protection if RTS-CTS is not preferred
+        * one aggregation protection method
+        */
+       if (!priv->hw_params.use_rts_for_aggregation)
+               ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
+
        if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
            !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK))
                ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
@@ -1473,6 +1480,11 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
        else
                ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
 
+       if (bss_conf->use_cts_prot)
+               ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
+       else
+               ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
+
        memcpy(ctx->staging.bssid_addr, bss_conf->bssid, ETH_ALEN);
 
        if (vif->type == NL80211_IFTYPE_AP ||
index 48730064da73f5e1e058f756d9473a2a0a5bc376..d67a37a786aa136a20b192f0a7712992ffdb527d 100644 (file)
@@ -67,8 +67,8 @@
 #include "iwl-agn-hw.h"
 
 /* Highest firmware API version supported */
-#define IWL7260_UCODE_API_MAX  9
-#define IWL3160_UCODE_API_MAX  9
+#define IWL7260_UCODE_API_MAX  10
+#define IWL3160_UCODE_API_MAX  10
 
 /* Oldest version we won't warn about */
 #define IWL7260_UCODE_API_OK   9
index 44b19e015102096e39fd086539794ab608c4c359..e93c6972290b84de3cf26214ca6894d0db0c4f79 100644 (file)
@@ -67,7 +67,7 @@
 #include "iwl-agn-hw.h"
 
 /* Highest firmware API version supported */
-#define IWL8000_UCODE_API_MAX  9
+#define IWL8000_UCODE_API_MAX  10
 
 /* Oldest version we won't warn about */
 #define IWL8000_UCODE_API_OK   8
index 33da3dfcfa4f05f112e4271487c9f5131bb3f20a..d4bd550f505c7dcfa59bc60f4c852a5cf6aed39e 100644 (file)
@@ -101,7 +101,7 @@ static bool halbtc_legacy(struct rtl_priv *adapter)
 
        bool is_legacy = false;
 
-       if ((mac->mode == WIRELESS_MODE_B) || (mac->mode == WIRELESS_MODE_B))
+       if ((mac->mode == WIRELESS_MODE_B) || (mac->mode == WIRELESS_MODE_G))
                is_legacy = true;
 
        return is_legacy;
index 361435f8608a125ca4cfdfd38b1bfa6212215ec9..1ac6383e79471f5944e4267f3ae8bc28715c53e2 100644 (file)
@@ -317,6 +317,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        {RTL_USB_DEVICE(0x0bda, 0x5088, rtl92cu_hal_cfg)}, /*Thinkware-CC&C*/
        {RTL_USB_DEVICE(0x0df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
        {RTL_USB_DEVICE(0x0df6, 0x005c, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
+       {RTL_USB_DEVICE(0x0df6, 0x0070, rtl92cu_hal_cfg)}, /*Sitecom - 150N */
        {RTL_USB_DEVICE(0x0df6, 0x0077, rtl92cu_hal_cfg)}, /*Sitecom-WLA2100V2*/
        {RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/
        {RTL_USB_DEVICE(0x4856, 0x0091, rtl92cu_hal_cfg)}, /*NetweeN - Feixun*/
index e29e15dca86ee3b7d1efc6d84a2607bcd173b449..f379689dde309b7bf63eb511ef7f28a827f71fc5 100644 (file)
@@ -576,6 +576,9 @@ int xenvif_connect(struct xenvif_queue *queue, unsigned long tx_ring_ref,
        init_waitqueue_head(&queue->dealloc_wq);
        atomic_set(&queue->inflight_packets, 0);
 
+       netif_napi_add(queue->vif->dev, &queue->napi, xenvif_poll,
+                       XENVIF_NAPI_WEIGHT);
+
        if (tx_evtchn == rx_evtchn) {
                /* feature-split-event-channels == 0 */
                err = bind_interdomain_evtchn_to_irqhandler(
@@ -629,9 +632,6 @@ int xenvif_connect(struct xenvif_queue *queue, unsigned long tx_ring_ref,
        wake_up_process(queue->task);
        wake_up_process(queue->dealloc_task);
 
-       netif_napi_add(queue->vif->dev, &queue->napi, xenvif_poll,
-                       XENVIF_NAPI_WEIGHT);
-
        return 0;
 
 err_rx_unbind:
index 8922c376456aee763090296a7045211aaae90839..90f5ccacce4ba819786506054deec71f05473026 100644 (file)
@@ -56,7 +56,7 @@ config PCI_HOST_GENERIC
          controller, such as the one emulated by kvmtool.
 
 config PCIE_SPEAR13XX
-       tristate "STMicroelectronics SPEAr PCIe controller"
+       bool "STMicroelectronics SPEAr PCIe controller"
        depends on ARCH_SPEAR13XX
        select PCIEPORTBUS
        select PCIE_DW
index 0dd742719154a9d7172dcd9c4f9f9dc3e26e6030..4ff8cbb620d3204e84a7afbb6925ed7faf055812 100644 (file)
@@ -41,9 +41,9 @@ config PHY_MVEBU_SATA
 config PHY_MIPHY365X
        tristate "STMicroelectronics MIPHY365X PHY driver for STiH41x series"
        depends on ARCH_STI
-       depends on GENERIC_PHY
        depends on HAS_IOMEM
        depends on OF
+       select GENERIC_PHY
        help
          Enable this to support the miphy transceiver (for SATA/PCIE)
          that is part of STMicroelectronics STiH41x SoC series.
index b05302b09c9fd0f0bdca202f1b52f1e51b94e0f1..392101c8d6b04aad1f9cc25119c65cac0ff73471 100644 (file)
@@ -542,6 +542,7 @@ static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
        },
        { },
 };
+MODULE_DEVICE_TABLE(of, exynos5_usbdrd_phy_of_match);
 
 static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
 {
index e1a6623d4696f1c24267292764b58f65b6137f47..9cd33a4bcfb193c99bd03d981f9d75d0e54f7bac 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/delay.h>
 #include <linux/usb/otg.h>
 #include <linux/phy/phy.h>
+#include <linux/pm_runtime.h>
 #include <linux/usb/musb-omap.h>
 #include <linux/usb/ulpi.h>
 #include <linux/i2c/twl.h>
@@ -422,37 +423,55 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on)
        }
 }
 
-static int twl4030_phy_power_off(struct phy *phy)
+static int twl4030_usb_runtime_suspend(struct device *dev)
 {
-       struct twl4030_usb *twl = phy_get_drvdata(phy);
+       struct twl4030_usb *twl = dev_get_drvdata(dev);
 
+       dev_dbg(twl->dev, "%s\n", __func__);
        if (twl->asleep)
                return 0;
 
        twl4030_phy_power(twl, 0);
        twl->asleep = 1;
-       dev_dbg(twl->dev, "%s\n", __func__);
+
        return 0;
 }
 
-static void __twl4030_phy_power_on(struct twl4030_usb *twl)
+static int twl4030_usb_runtime_resume(struct device *dev)
 {
+       struct twl4030_usb *twl = dev_get_drvdata(dev);
+
+       dev_dbg(twl->dev, "%s\n", __func__);
+       if (!twl->asleep)
+               return 0;
+
        twl4030_phy_power(twl, 1);
-       twl4030_i2c_access(twl, 1);
-       twl4030_usb_set_mode(twl, twl->usb_mode);
-       if (twl->usb_mode == T2_USB_MODE_ULPI)
-               twl4030_i2c_access(twl, 0);
+       twl->asleep = 0;
+
+       return 0;
+}
+
+static int twl4030_phy_power_off(struct phy *phy)
+{
+       struct twl4030_usb *twl = phy_get_drvdata(phy);
+
+       dev_dbg(twl->dev, "%s\n", __func__);
+       pm_runtime_mark_last_busy(twl->dev);
+       pm_runtime_put_autosuspend(twl->dev);
+
+       return 0;
 }
 
 static int twl4030_phy_power_on(struct phy *phy)
 {
        struct twl4030_usb *twl = phy_get_drvdata(phy);
 
-       if (!twl->asleep)
-               return 0;
-       __twl4030_phy_power_on(twl);
-       twl->asleep = 0;
        dev_dbg(twl->dev, "%s\n", __func__);
+       pm_runtime_get_sync(twl->dev);
+       twl4030_i2c_access(twl, 1);
+       twl4030_usb_set_mode(twl, twl->usb_mode);
+       if (twl->usb_mode == T2_USB_MODE_ULPI)
+               twl4030_i2c_access(twl, 0);
 
        /*
         * XXX When VBUS gets driven after musb goes to A mode,
@@ -558,9 +577,27 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl)
                 * USB_LINK_VBUS state.  musb_hdrc won't care until it
                 * starts to handle softconnect right.
                 */
+               if ((status == OMAP_MUSB_VBUS_VALID) ||
+                   (status == OMAP_MUSB_ID_GROUND)) {
+                       if (twl->asleep)
+                               pm_runtime_get_sync(twl->dev);
+               } else {
+                       if (!twl->asleep) {
+                               pm_runtime_mark_last_busy(twl->dev);
+                               pm_runtime_put_autosuspend(twl->dev);
+                       }
+               }
                omap_musb_mailbox(status);
        }
-       sysfs_notify(&twl->dev->kobj, NULL, "vbus");
+
+       /* don't schedule during sleep - irq works right then */
+       if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) {
+               cancel_delayed_work(&twl->id_workaround_work);
+               schedule_delayed_work(&twl->id_workaround_work, HZ);
+       }
+
+       if (irq)
+               sysfs_notify(&twl->dev->kobj, NULL, "vbus");
 
        return IRQ_HANDLED;
 }
@@ -569,29 +606,8 @@ static void twl4030_id_workaround_work(struct work_struct *work)
 {
        struct twl4030_usb *twl = container_of(work, struct twl4030_usb,
                id_workaround_work.work);
-       enum omap_musb_vbus_id_status status;
-       bool status_changed = false;
-
-       status = twl4030_usb_linkstat(twl);
-
-       spin_lock_irq(&twl->lock);
-       if (status >= 0 && status != twl->linkstat) {
-               twl->linkstat = status;
-               status_changed = true;
-       }
-       spin_unlock_irq(&twl->lock);
-
-       if (status_changed) {
-               dev_dbg(twl->dev, "handle missing status change to %d\n",
-                               status);
-               omap_musb_mailbox(status);
-       }
 
-       /* don't schedule during sleep - irq works right then */
-       if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) {
-               cancel_delayed_work(&twl->id_workaround_work);
-               schedule_delayed_work(&twl->id_workaround_work, HZ);
-       }
+       twl4030_usb_irq(0, twl);
 }
 
 static int twl4030_phy_init(struct phy *phy)
@@ -599,22 +615,17 @@ static int twl4030_phy_init(struct phy *phy)
        struct twl4030_usb *twl = phy_get_drvdata(phy);
        enum omap_musb_vbus_id_status status;
 
-       /*
-        * Start in sleep state, we'll get called through set_suspend()
-        * callback when musb is runtime resumed and it's time to start.
-        */
-       __twl4030_phy_power(twl, 0);
-       twl->asleep = 1;
-
+       pm_runtime_get_sync(twl->dev);
        status = twl4030_usb_linkstat(twl);
        twl->linkstat = status;
 
-       if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) {
+       if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID)
                omap_musb_mailbox(twl->linkstat);
-               twl4030_phy_power_on(phy);
-       }
 
        sysfs_notify(&twl->dev->kobj, NULL, "vbus");
+       pm_runtime_mark_last_busy(twl->dev);
+       pm_runtime_put_autosuspend(twl->dev);
+
        return 0;
 }
 
@@ -650,6 +661,11 @@ static const struct phy_ops ops = {
        .owner          = THIS_MODULE,
 };
 
+static const struct dev_pm_ops twl4030_usb_pm_ops = {
+       SET_RUNTIME_PM_OPS(twl4030_usb_runtime_suspend,
+                          twl4030_usb_runtime_resume, NULL)
+};
+
 static int twl4030_usb_probe(struct platform_device *pdev)
 {
        struct twl4030_usb_data *pdata = dev_get_platdata(&pdev->dev);
@@ -726,6 +742,11 @@ static int twl4030_usb_probe(struct platform_device *pdev)
 
        ATOMIC_INIT_NOTIFIER_HEAD(&twl->phy.notifier);
 
+       pm_runtime_use_autosuspend(&pdev->dev);
+       pm_runtime_set_autosuspend_delay(&pdev->dev, 2000);
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_get_sync(&pdev->dev);
+
        /* Our job is to use irqs and status from the power module
         * to keep the transceiver disabled when nothing's connected.
         *
@@ -744,6 +765,9 @@ static int twl4030_usb_probe(struct platform_device *pdev)
                return status;
        }
 
+       pm_runtime_mark_last_busy(&pdev->dev);
+       pm_runtime_put_autosuspend(twl->dev);
+
        dev_info(&pdev->dev, "Initialized TWL4030 USB module\n");
        return 0;
 }
@@ -753,6 +777,7 @@ static int twl4030_usb_remove(struct platform_device *pdev)
        struct twl4030_usb *twl = platform_get_drvdata(pdev);
        int val;
 
+       pm_runtime_get_sync(twl->dev);
        cancel_delayed_work(&twl->id_workaround_work);
        device_remove_file(twl->dev, &dev_attr_vbus);
 
@@ -772,9 +797,8 @@ static int twl4030_usb_remove(struct platform_device *pdev)
 
        /* disable complete OTG block */
        twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB);
-
-       if (!twl->asleep)
-               twl4030_phy_power(twl, 0);
+       pm_runtime_mark_last_busy(twl->dev);
+       pm_runtime_put(twl->dev);
 
        return 0;
 }
@@ -792,6 +816,7 @@ static struct platform_driver twl4030_usb_driver = {
        .remove         = twl4030_usb_remove,
        .driver         = {
                .name   = "twl4030_usb",
+               .pm     = &twl4030_usb_pm_ops,
                .owner  = THIS_MODULE,
                .of_match_table = of_match_ptr(twl4030_usb_id_table),
        },
index a53a689a2bfaa371024369dfc7a9e8dc72fc2ca3..8c6fd8d4dd3cedc26401492346fd8ab79893dac9 100644 (file)
@@ -620,8 +620,7 @@ static void abx500_gpio_dbg_show_one(struct seq_file *s,
        } else
                seq_printf(s, " %-9s", chip->get(chip, offset) ? "hi" : "lo");
 
-       if (pctldev)
-               mode = abx500_get_mode(pctldev, chip, offset);
+       mode = abx500_get_mode(pctldev, chip, offset);
 
        seq_printf(s, " %s", (mode < 0) ? "unknown" : modes[mode]);
 
index af1ba4fc150dd4e10509b8e53ccab89458d7d09a..60464a2648aa0dfb7c31fe13c75dc419472c3b31 100644 (file)
@@ -497,10 +497,10 @@ static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
 static void at91_pin_dbg(const struct device *dev, const struct at91_pmx_pin *pin)
 {
        if (pin->mux) {
-               dev_dbg(dev, "pio%c%d configured as periph%c with conf = 0x%lu\n",
+               dev_dbg(dev, "pio%c%d configured as periph%c with conf = 0x%lx\n",
                        pin->bank + 'A', pin->pin, pin->mux - 1 + 'A', pin->conf);
        } else {
-               dev_dbg(dev, "pio%c%d configured as gpio with conf = 0x%lu\n",
+               dev_dbg(dev, "pio%c%d configured as gpio with conf = 0x%lx\n",
                        pin->bank + 'A', pin->pin, pin->conf);
        }
 }
index 9ca59a01874316585a190093b0265401e17975a3..e12e5b07f6d751aba9cce63cf49d2acabe50b7ab 100644 (file)
@@ -461,6 +461,7 @@ static struct irq_chip byt_irqchip = {
        .irq_mask = byt_irq_mask,
        .irq_unmask = byt_irq_unmask,
        .irq_set_type = byt_irq_type,
+       .flags = IRQCHIP_SKIP_SET_WAKE,
 };
 
 static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
index 5e8b2e04cd7a322e6aefa85adbd3996ad04cc19e..0c372a300cb88058e9957e017db99f3d127fb08d 100644 (file)
@@ -438,7 +438,7 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
        int reg, ret, mask;
        unsigned long flags;
        u8 bit;
-       u32 data;
+       u32 data, rmask;
 
        if (iomux_num > 3)
                return -EINVAL;
@@ -478,8 +478,9 @@ static int rockchip_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
        spin_lock_irqsave(&bank->slock, flags);
 
        data = (mask << (bit + 16));
+       rmask = data | (data >> 16);
        data |= (mux & mask) << bit;
-       ret = regmap_write(regmap, reg, data);
+       ret = regmap_update_bits(regmap, reg, rmask, data);
 
        spin_unlock_irqrestore(&bank->slock, flags);
 
@@ -634,7 +635,7 @@ static int rk3288_set_drive(struct rockchip_pin_bank *bank, int pin_num,
        struct regmap *regmap;
        unsigned long flags;
        int reg, ret, i;
-       u32 data;
+       u32 data, rmask;
        u8 bit;
 
        rk3288_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
@@ -657,9 +658,10 @@ static int rk3288_set_drive(struct rockchip_pin_bank *bank, int pin_num,
 
        /* enable the write to the equivalent lower bits */
        data = ((1 << RK3288_DRV_BITS_PER_PIN) - 1) << (bit + 16);
+       rmask = data | (data >> 16);
        data |= (ret << bit);
 
-       ret = regmap_write(regmap, reg, data);
+       ret = regmap_update_bits(regmap, reg, rmask, data);
        spin_unlock_irqrestore(&bank->slock, flags);
 
        return ret;
@@ -722,7 +724,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
        int reg, ret;
        unsigned long flags;
        u8 bit;
-       u32 data;
+       u32 data, rmask;
 
        dev_dbg(info->dev, "setting pull of GPIO%d-%d to %d\n",
                 bank->bank_num, pin_num, pull);
@@ -750,6 +752,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
 
                /* enable the write to the equivalent lower bits */
                data = ((1 << RK3188_PULL_BITS_PER_PIN) - 1) << (bit + 16);
+               rmask = data | (data >> 16);
 
                switch (pull) {
                case PIN_CONFIG_BIAS_DISABLE:
@@ -770,7 +773,7 @@ static int rockchip_set_pull(struct rockchip_pin_bank *bank,
                        return -EINVAL;
                }
 
-               ret = regmap_write(regmap, reg, data);
+               ret = regmap_update_bits(regmap, reg, rmask, data);
 
                spin_unlock_irqrestore(&bank->slock, flags);
                break;
index a06620474845964667bea51b387395360f206bf0..e641b4226c422fe9afac1d9be8eee73e65509b02 100644 (file)
@@ -680,7 +680,7 @@ static struct phy *tegra_xusb_padctl_xlate(struct device *dev,
        if (args->args_count <= 0)
                return ERR_PTR(-EINVAL);
 
-       if (index > ARRAY_SIZE(padctl->phys))
+       if (index >= ARRAY_SIZE(padctl->phys))
                return ERR_PTR(-EINVAL);
 
        return padctl->phys[index];
@@ -930,7 +930,8 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)
 
        padctl->provider = devm_of_phy_provider_register(&pdev->dev,
                                                         tegra_xusb_padctl_xlate);
-       if (err < 0) {
+       if (IS_ERR(padctl->provider)) {
+               err = PTR_ERR(padctl->provider);
                dev_err(&pdev->dev, "failed to register PHYs: %d\n", err);
                goto unregister;
        }
index 003bfd874a6155ca8dc70a50d527c3151ee6a797..d7154ed0b0eb19347fa1bd26ca82dee99a4c9e87 100644 (file)
@@ -127,14 +127,10 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
        struct irq_chip *chip = irq_data_get_irq_chip(irqd);
        struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
        struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
-       struct samsung_pin_bank_type *bank_type = bank->type;
        struct samsung_pinctrl_drv_data *d = bank->drvdata;
-       unsigned int pin = irqd->hwirq;
-       unsigned int shift = EXYNOS_EINT_CON_LEN * pin;
+       unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq;
        unsigned int con, trig_type;
        unsigned long reg_con = our_chip->eint_con + bank->eint_offset;
-       unsigned long flags;
-       unsigned int mask;
 
        switch (type) {
        case IRQ_TYPE_EDGE_RISING:
@@ -167,8 +163,32 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
        con |= trig_type << shift;
        writel(con, d->virt_base + reg_con);
 
+       return 0;
+}
+
+static int exynos_irq_request_resources(struct irq_data *irqd)
+{
+       struct irq_chip *chip = irq_data_get_irq_chip(irqd);
+       struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
+       struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+       struct samsung_pin_bank_type *bank_type = bank->type;
+       struct samsung_pinctrl_drv_data *d = bank->drvdata;
+       unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq;
+       unsigned long reg_con = our_chip->eint_con + bank->eint_offset;
+       unsigned long flags;
+       unsigned int mask;
+       unsigned int con;
+       int ret;
+
+       ret = gpio_lock_as_irq(&bank->gpio_chip, irqd->hwirq);
+       if (ret) {
+               dev_err(bank->gpio_chip.dev, "unable to lock pin %s-%lu IRQ\n",
+                       bank->name, irqd->hwirq);
+               return ret;
+       }
+
        reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC];
-       shift = pin * bank_type->fld_width[PINCFG_TYPE_FUNC];
+       shift = irqd->hwirq * bank_type->fld_width[PINCFG_TYPE_FUNC];
        mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
 
        spin_lock_irqsave(&bank->slock, flags);
@@ -180,9 +200,42 @@ static int exynos_irq_set_type(struct irq_data *irqd, unsigned int type)
 
        spin_unlock_irqrestore(&bank->slock, flags);
 
+       exynos_irq_unmask(irqd);
+
        return 0;
 }
 
+static void exynos_irq_release_resources(struct irq_data *irqd)
+{
+       struct irq_chip *chip = irq_data_get_irq_chip(irqd);
+       struct exynos_irq_chip *our_chip = to_exynos_irq_chip(chip);
+       struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+       struct samsung_pin_bank_type *bank_type = bank->type;
+       struct samsung_pinctrl_drv_data *d = bank->drvdata;
+       unsigned int shift = EXYNOS_EINT_CON_LEN * irqd->hwirq;
+       unsigned long reg_con = our_chip->eint_con + bank->eint_offset;
+       unsigned long flags;
+       unsigned int mask;
+       unsigned int con;
+
+       reg_con = bank->pctl_offset + bank_type->reg_offset[PINCFG_TYPE_FUNC];
+       shift = irqd->hwirq * bank_type->fld_width[PINCFG_TYPE_FUNC];
+       mask = (1 << bank_type->fld_width[PINCFG_TYPE_FUNC]) - 1;
+
+       exynos_irq_mask(irqd);
+
+       spin_lock_irqsave(&bank->slock, flags);
+
+       con = readl(d->virt_base + reg_con);
+       con &= ~(mask << shift);
+       con |= FUNC_INPUT << shift;
+       writel(con, d->virt_base + reg_con);
+
+       spin_unlock_irqrestore(&bank->slock, flags);
+
+       gpio_unlock_as_irq(&bank->gpio_chip, irqd->hwirq);
+}
+
 /*
  * irq_chip for gpio interrupts.
  */
@@ -193,6 +246,8 @@ static struct exynos_irq_chip exynos_gpio_irq_chip = {
                .irq_mask = exynos_irq_mask,
                .irq_ack = exynos_irq_ack,
                .irq_set_type = exynos_irq_set_type,
+               .irq_request_resources = exynos_irq_request_resources,
+               .irq_release_resources = exynos_irq_release_resources,
        },
        .eint_con = EXYNOS_GPIO_ECON_OFFSET,
        .eint_mask = EXYNOS_GPIO_EMASK_OFFSET,
@@ -336,6 +391,8 @@ static struct exynos_irq_chip exynos_wkup_irq_chip = {
                .irq_ack = exynos_irq_ack,
                .irq_set_type = exynos_irq_set_type,
                .irq_set_wake = exynos_wkup_irq_set_wake,
+               .irq_request_resources = exynos_irq_request_resources,
+               .irq_release_resources = exynos_irq_release_resources,
        },
        .eint_con = EXYNOS_WKUP_ECON_OFFSET,
        .eint_mask = EXYNOS_WKUP_EMASK_OFFSET,
index 2b882320e8e97077fca276200a970e10296be939..5cedc9d26390fae0d5aa77c785116eceaac3146b 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/gpio.h>
 
 /* pinmux function number for pin as gpio output line */
+#define FUNC_INPUT     0x0
 #define FUNC_OUTPUT    0x1
 
 /**
index 576d41b459e97fd4f3675e2a8f1cf981a3a2b410..c6e5deba238ec5dc9311ba51e21a52cca70327d2 100644 (file)
@@ -4509,24 +4509,24 @@ static const char * const audio_clk_groups[] = {
 };
 
 static const char * const can0_groups[] = {
-       "can0_data_a",
+       "can0_data",
        "can0_data_b",
        "can0_data_c",
        "can0_data_d",
        "can0_data_e",
        "can0_data_f",
-       "can_clk_a",
+       "can_clk",
        "can_clk_b",
        "can_clk_c",
        "can_clk_d",
 };
 
 static const char * const can1_groups[] = {
-       "can1_data_a",
+       "can1_data",
        "can1_data_b",
        "can1_data_c",
        "can1_data_d",
-       "can_clk_a",
+       "can_clk",
        "can_clk_b",
        "can_clk_c",
        "can_clk_d",
index fc468a3d95cea3a2f4a8bc260717e6b1c920449d..02152de135b5c43b79318c6c5ac7971f0723e478 100644 (file)
@@ -88,7 +88,6 @@ struct ideapad_private {
        struct dentry *debug;
        unsigned long cfg;
        bool has_hw_rfkill_switch;
-       bool has_touchpad_control;
 };
 
 static bool no_bt_rfkill;
@@ -456,7 +455,7 @@ struct ideapad_rfk_data {
        int type;
 };
 
-const const struct ideapad_rfk_data ideapad_rfk_data[] = {
+static const struct ideapad_rfk_data ideapad_rfk_data[] = {
        { "ideapad_wlan",    CFG_WIFI_BIT, VPCCMD_W_WIFI, RFKILL_TYPE_WLAN },
        { "ideapad_bluetooth", CFG_BT_BIT, VPCCMD_W_BT, RFKILL_TYPE_BLUETOOTH },
        { "ideapad_3g",        CFG_3G_BIT, VPCCMD_W_3G, RFKILL_TYPE_WWAN },
@@ -767,9 +766,6 @@ static void ideapad_sync_touchpad_state(struct ideapad_private *priv)
 {
        unsigned long value;
 
-       if (!priv->has_touchpad_control)
-               return;
-
        /* Without reading from EC touchpad LED doesn't switch state */
        if (!read_ec_data(priv->adev->handle, VPCCMD_R_TOUCHPAD, &value)) {
                /* Some IdeaPads don't really turn off touchpad - they only
@@ -833,29 +829,7 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
  * always results in 0 on these models, causing ideapad_laptop to wrongly
  * report all radios as hardware-blocked.
  */
-static struct dmi_system_id no_hw_rfkill_list[] = {
-       {
-               .ident = "Lenovo Yoga 2 11 / 13 / Pro",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 2"),
-               },
-       },
-       {}
-};
-
-/*
- * Some models don't offer touchpad ctrl through the ideapad interface, causing
- * ideapad_sync_touchpad_state to send wrong touchpad enable/disable events.
- */
-static struct dmi_system_id no_touchpad_ctrl_list[] = {
-       {
-               .ident = "Lenovo Yoga 1 series",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo IdeaPad Yoga"),
-               },
-       },
+static const struct dmi_system_id no_hw_rfkill_list[] = {
        {
                .ident = "Lenovo Yoga 2 11 / 13 / Pro",
                .matches = {
@@ -889,7 +863,6 @@ static int ideapad_acpi_add(struct platform_device *pdev)
        priv->adev = adev;
        priv->platform_device = pdev;
        priv->has_hw_rfkill_switch = !dmi_check_system(no_hw_rfkill_list);
-       priv->has_touchpad_control = !dmi_check_system(no_touchpad_ctrl_list);
 
        ret = ideapad_sysfs_init(priv);
        if (ret)
index b062d3d7b37304e9e724fd869419febfae522c19..d0dce734b2edb37e055d6f30f6901a234645708f 100644 (file)
@@ -1255,10 +1255,15 @@ static ssize_t toshiba_kbd_bl_mode_store(struct device *dev,
                                         const char *buf, size_t count)
 {
        struct toshiba_acpi_dev *toshiba = dev_get_drvdata(dev);
-       int mode = -1;
-       int time = -1;
+       int mode;
+       int time;
+       int ret;
 
-       if (sscanf(buf, "%i", &mode) != 1 && (mode != 2 || mode != 1))
+
+       ret = kstrtoint(buf, 0, &mode);
+       if (ret)
+               return ret;
+       if (mode != SCI_KBD_MODE_FNZ && mode != SCI_KBD_MODE_AUTO)
                return -EINVAL;
 
        /* Set the Keyboard Backlight Mode where:
@@ -1266,11 +1271,12 @@ static ssize_t toshiba_kbd_bl_mode_store(struct device *dev,
         *      Auto - KBD backlight turns off automatically in given time
         *      FN-Z - KBD backlight "toggles" when hotkey pressed
         */
-       if (mode != -1 && toshiba->kbd_mode != mode) {
+       if (toshiba->kbd_mode != mode) {
                time = toshiba->kbd_time << HCI_MISC_SHIFT;
                time = time + toshiba->kbd_mode;
-               if (toshiba_kbd_illum_status_set(toshiba, time) < 0)
-                       return -EIO;
+               ret = toshiba_kbd_illum_status_set(toshiba, time);
+               if (ret)
+                       return ret;
                toshiba->kbd_mode = mode;
        }
 
@@ -1857,9 +1863,16 @@ static int toshiba_acpi_resume(struct device *device)
 {
        struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device));
        u32 result;
+       acpi_status status;
+
+       if (dev->hotkey_dev) {
+               status = acpi_evaluate_object(dev->acpi_dev->handle, "ENAB",
+                               NULL, NULL);
+               if (ACPI_FAILURE(status))
+                       pr_info("Unable to re-enable hotkeys\n");
 
-       if (dev->hotkey_dev)
                hci_write1(dev, HCI_HOTKEY_EVENT, HCI_HOTKEY_ENABLE, &result);
+       }
 
        return 0;
 }
index b1cda6ffdbcc5f6bfc6aa5d3e4c42d44b038823b..45e05b32f9b66ea0fc0c27c997ebdefecd3fa3c0 100644 (file)
@@ -953,6 +953,7 @@ static const struct x86_cpu_id rapl_ids[] = {
        { X86_VENDOR_INTEL, 6, 0x3a},/* Ivy Bridge */
        { X86_VENDOR_INTEL, 6, 0x3c},/* Haswell */
        { X86_VENDOR_INTEL, 6, 0x3d},/* Broadwell */
+       { X86_VENDOR_INTEL, 6, 0x3f},/* Haswell */
        { X86_VENDOR_INTEL, 6, 0x45},/* Haswell ULT */
        /* TODO: Add more CPU IDs after testing */
        {}
@@ -1166,11 +1167,10 @@ static int rapl_detect_domains(struct rapl_package *rp, int cpu)
 
        for (i = 0; i < RAPL_DOMAIN_MAX; i++) {
                /* use physical package id to read counters */
-               if (!rapl_check_domain(cpu, i))
+               if (!rapl_check_domain(cpu, i)) {
                        rp->domain_map |= 1 << i;
-               else
-                       pr_warn("RAPL domain %s detection failed\n",
-                               rapl_domain_names[i]);
+                       pr_info("Found RAPL domain %s\n", rapl_domain_names[i]);
+               }
        }
        rp->nr_domains = bitmap_weight(&rp->domain_map, RAPL_DOMAIN_MAX);
        if (!rp->nr_domains) {
index 8f06250a0389cbeffd0a6a0aaf4789ca581c342f..8754c33361e8c70744aa8e468e1579c6876be29e 100644 (file)
@@ -717,12 +717,14 @@ static int s5m_rtc_probe(struct platform_device *pdev)
        info->device_type = s5m87xx->device_type;
        info->wtsr_smpl = s5m87xx->wtsr_smpl;
 
-       info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq);
-       if (info->irq <= 0) {
-               ret = -EINVAL;
-               dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n",
+       if (s5m87xx->irq_data) {
+               info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq);
+               if (info->irq <= 0) {
+                       ret = -EINVAL;
+                       dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n",
                                alarm_irq);
-               goto err;
+                       goto err;
+               }
        }
 
        platform_set_drvdata(pdev, info);
@@ -744,6 +746,11 @@ static int s5m_rtc_probe(struct platform_device *pdev)
                goto err;
        }
 
+       if (!info->irq) {
+               dev_info(&pdev->dev, "Alarm IRQ not available\n");
+               return 0;
+       }
+
        ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
                                        s5m_rtc_alarm_irq, 0, "rtc-alarm0",
                                        info);
@@ -802,7 +809,7 @@ static int s5m_rtc_resume(struct device *dev)
        struct s5m_rtc_info *info = dev_get_drvdata(dev);
        int ret = 0;
 
-       if (device_may_wakeup(dev))
+       if (info->irq && device_may_wakeup(dev))
                ret = disable_irq_wake(info->irq);
 
        return ret;
@@ -813,7 +820,7 @@ static int s5m_rtc_suspend(struct device *dev)
        struct s5m_rtc_info *info = dev_get_drvdata(dev);
        int ret = 0;
 
-       if (device_may_wakeup(dev))
+       if (info->irq && device_may_wakeup(dev))
                ret = enable_irq_wake(info->irq);
 
        return ret;
index 2ead7e78c4568ec7fe50ece74c3109d424efa852..14ba80bfa571bc4b34eb795c85f6725b96f6ad7b 100644 (file)
@@ -77,7 +77,7 @@ EXPORT_SYMBOL_GPL(dasd_nofcx);
  * strings when running as a module.
  */
 static char *dasd[256];
-module_param_array(dasd, charp, NULL, 0);
+module_param_array(dasd, charp, NULL, S_IRUGO);
 
 /*
  * Single spinlock to protect devmap and servermap structures and lists.
index a6d47e5eee9e0add1485533915832107659d2df6..c43aca69fb30dffed727c210b725b46a365440dd 100644 (file)
@@ -1035,12 +1035,26 @@ static int tty3215_write(struct tty_struct * tty,
                         const unsigned char *buf, int count)
 {
        struct raw3215_info *raw;
+       int i, written;
 
        if (!tty)
                return 0;
        raw = (struct raw3215_info *) tty->driver_data;
-       raw3215_write(raw, buf, count);
-       return count;
+       written = count;
+       while (count > 0) {
+               for (i = 0; i < count; i++)
+                       if (buf[i] == '\t' || buf[i] == '\n')
+                               break;
+               raw3215_write(raw, buf, i);
+               count -= i;
+               buf += i;
+               if (count > 0) {
+                       raw3215_putchar(raw, *buf);
+                       count--;
+                       buf++;
+               }
+       }
+       return written;
 }
 
 /*
@@ -1188,7 +1202,7 @@ static int __init tty3215_init(void)
        driver->subtype = SYSTEM_TYPE_TTY;
        driver->init_termios = tty_std_termios;
        driver->init_termios.c_iflag = IGNBRK | IGNPAR;
-       driver->init_termios.c_oflag = ONLCR | XTABS;
+       driver->init_termios.c_oflag = ONLCR;
        driver->init_termios.c_lflag = ISIG;
        driver->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(driver, &tty3215_ops);
index 7ed7a59878165bf8ef265e3fae90ee4b10017827..003663288e29b7f60405fa9bf721dcc6dbe19c0c 100644 (file)
@@ -559,7 +559,7 @@ sclp_tty_init(void)
        driver->subtype = SYSTEM_TYPE_TTY;
        driver->init_termios = tty_std_termios;
        driver->init_termios.c_iflag = IGNBRK | IGNPAR;
-       driver->init_termios.c_oflag = ONLCR | XTABS;
+       driver->init_termios.c_oflag = ONLCR;
        driver->init_termios.c_lflag = ISIG | ECHO;
        driver->flags = TTY_DRIVER_REAL_RAW;
        tty_set_operations(driver, &sclp_ops);
index 97ef37b51068369b44d41376e630534d014241a5..e7646ce3d659218ca7fd9762e05cf0d7c4c95a5c 100644 (file)
@@ -889,6 +889,7 @@ extern const struct attribute_group *qeth_generic_attr_groups[];
 extern const struct attribute_group *qeth_osn_attr_groups[];
 extern struct workqueue_struct *qeth_wq;
 
+int qeth_card_hw_is_reachable(struct qeth_card *);
 const char *qeth_get_cardname_short(struct qeth_card *);
 int qeth_realloc_buffer_pool(struct qeth_card *, int);
 int qeth_core_load_discipline(struct qeth_card *, enum qeth_discipline_id);
index c0d6ba8655c742991bc13fe1b2fe2a7a740ea4ac..fd22c811cbe195d2056f6bb5b6339fa33113b8cc 100644 (file)
@@ -73,6 +73,13 @@ static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int);
 struct workqueue_struct *qeth_wq;
 EXPORT_SYMBOL_GPL(qeth_wq);
 
+int qeth_card_hw_is_reachable(struct qeth_card *card)
+{
+       return (card->state == CARD_STATE_SOFTSETUP) ||
+               (card->state == CARD_STATE_UP);
+}
+EXPORT_SYMBOL_GPL(qeth_card_hw_is_reachable);
+
 static void qeth_close_dev_handler(struct work_struct *work)
 {
        struct qeth_card *card;
@@ -5790,6 +5797,7 @@ int qeth_core_ethtool_get_settings(struct net_device *netdev,
        struct qeth_card *card = netdev->ml_priv;
        enum qeth_link_types link_type;
        struct carrier_info carrier_info;
+       int rc;
        u32 speed;
 
        if ((card->info.type == QETH_CARD_TYPE_IQD) || (card->info.guestlan))
@@ -5832,8 +5840,14 @@ int qeth_core_ethtool_get_settings(struct net_device *netdev,
        /* Check if we can obtain more accurate information.     */
        /* If QUERY_CARD_INFO command is not supported or fails, */
        /* just return the heuristics that was filled above.     */
-       if (qeth_query_card_info(card, &carrier_info) != 0)
+       if (!qeth_card_hw_is_reachable(card))
+               return -ENODEV;
+       rc = qeth_query_card_info(card, &carrier_info);
+       if (rc == -EOPNOTSUPP) /* for old hardware, return heuristic */
                return 0;
+       if (rc) /* report error from the hardware operation */
+               return rc;
+       /* on success, fill in the information got from the hardware */
 
        netdev_dbg(netdev,
        "card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n",
index ae1bc04b8653eed571dbbc9a271ec9cdc93205f3..59e3aa538b4da4594456b0965bc0fe42a49379f3 100644 (file)
@@ -5,17 +5,12 @@
 
 #include <linux/slab.h>
 #include <asm/ebcdic.h>
+#include "qeth_core.h"
 #include "qeth_l2.h"
 
 #define QETH_DEVICE_ATTR(_id, _name, _mode, _show, _store) \
 struct device_attribute dev_attr_##_id = __ATTR(_name, _mode, _show, _store)
 
-static int qeth_card_hw_is_reachable(struct qeth_card *card)
-{
-       return (card->state == CARD_STATE_SOFTSETUP) ||
-               (card->state == CARD_STATE_UP);
-}
-
 static ssize_t qeth_bridge_port_role_state_show(struct device *dev,
                                struct device_attribute *attr, char *buf,
                                int show_state)
index ce62e8798cc80da072b452bced0a26fb44b5eb11..d837dc180522142fa1dcaf5b4e09c141effbfc4a 100644 (file)
@@ -1808,7 +1808,6 @@ static int scsi_mq_prep_fn(struct request *req)
 
        cmd->tag = req->tag;
 
-       req->cmd = req->__cmd;
        cmd->cmnd = req->cmd;
        cmd->prot_op = SCSI_PROT_NORMAL;
 
index 40c3d43c9292ddd58e1b3f278a4d8b821a86d6f3..f40b34cdf2fc433ddb9722238cc80004efec52bf 100644 (file)
@@ -945,7 +945,7 @@ static int au1550_spi_remove(struct platform_device *pdev)
        spi_bitbang_stop(&hw->bitbang);
        free_irq(hw->irq, hw);
        iounmap((void __iomem *)hw->regs);
-       release_mem_region(r->start, sizeof(psc_spi_t));
+       release_mem_region(hw->ioarea->start, sizeof(psc_spi_t));
 
        if (hw->usedma) {
                au1550_spi_dma_rxtmp_free(hw);
index 276a3884fb3c1d43c928b0b975b8d7aa67f6be58..48f1d26e6ad9868f9ac8c8e11fb0953e90f707da 100644 (file)
@@ -417,16 +417,16 @@ static int davinci_spi_setup(struct spi_device *spi)
                                                  flags, dev_name(&spi->dev));
                        internal_cs = false;
                }
-       }
 
-       if (retval) {
-               dev_err(&spi->dev, "GPIO %d setup failed (%d)\n",
-                       spi->cs_gpio, retval);
-               return retval;
-       }
+               if (retval) {
+                       dev_err(&spi->dev, "GPIO %d setup failed (%d)\n",
+                               spi->cs_gpio, retval);
+                       return retval;
+               }
 
-       if (internal_cs)
-               set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select);
+               if (internal_cs)
+                       set_io_bits(dspi->base + SPIPC0, 1 << spi->chip_select);
+       }
 
        if (spi->mode & SPI_READY)
                set_io_bits(dspi->base + SPIPC0, SPIPC0_SPIENA_MASK);
index 3f3dc1226edf19aefad97630e2112287f419cabc..e14960470d8d46a96eef045f612cc4bd23c1a7cb 100644 (file)
@@ -62,6 +62,8 @@ static int spi_pci_probe(struct pci_dev *pdev,
        if (ret)
                return ret;
 
+       dws->regs = pcim_iomap_table(pdev)[pci_bar];
+
        dws->bus_num = 0;
        dws->num_cs = 4;
        dws->irq = pdev->irq;
index 29f33143b795651e773ea7b9d5cc0f80c7cb2575..670f0627f3bfc793092495be55f3d6fd9854dd34 100644 (file)
@@ -271,7 +271,7 @@ static void giveback(struct dw_spi *dws)
                                        transfer_list);
 
        if (!last_transfer->cs_change)
-               spi_chip_sel(dws, dws->cur_msg->spi, 0);
+               spi_chip_sel(dws, msg->spi, 0);
 
        spi_finalize_current_message(dws->master);
 }
index 68441fa448de46323192325154c930afe191f3ab..352eed7463aca0dc23d104178538236f5534257c 100644 (file)
@@ -329,7 +329,8 @@ static void omap2_mcspi_set_fifo(const struct spi_device *spi,
 disable_fifo:
        if (t->rx_buf != NULL)
                chconf &= ~OMAP2_MCSPI_CHCONF_FFER;
-       else
+
+       if (t->tx_buf != NULL)
                chconf &= ~OMAP2_MCSPI_CHCONF_FFET;
 
        mcspi_write_chconf0(spi, chconf);
index fe792106bdc5e65df920368eb495d14fab826841..46f45ca2c69400888de13f390decbf09a30f27d1 100644 (file)
@@ -1074,6 +1074,7 @@ static struct acpi_device_id pxa2xx_spi_acpi_match[] = {
        { "INT3430", 0 },
        { "INT3431", 0 },
        { "80860F0E", 0 },
+       { "8086228E", 0 },
        { },
 };
 MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
index c0743604b906c749b62d1fedaaa8f3250b70c0c9..cd0e08b0c9f66c7d99d1421e8fdbf882f62f7e77 100644 (file)
@@ -499,7 +499,7 @@ static void rockchip_spi_config(struct rockchip_spi *rs)
        }
 
        /* div doesn't support odd number */
-       div = rs->max_freq / rs->speed;
+       div = max_t(u32, rs->max_freq / rs->speed, 1);
        div = (div + 1) & 0xfffe;
 
        spi_enable_chip(rs, 0);
@@ -678,7 +678,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
                rs->dma_tx.addr = (dma_addr_t)(mem->start + ROCKCHIP_SPI_TXDR);
                rs->dma_rx.addr = (dma_addr_t)(mem->start + ROCKCHIP_SPI_RXDR);
                rs->dma_tx.direction = DMA_MEM_TO_DEV;
-               rs->dma_tx.direction = DMA_DEV_TO_MEM;
+               rs->dma_rx.direction = DMA_DEV_TO_MEM;
 
                master->can_dma = rockchip_spi_can_dma;
                master->dma_tx = rs->dma_tx.ch;
index c850dfdfa9e32712136ed7515f1440dbe7906805..ad87a98f8f68f48f4191bac3f2202c45eb26dadf 100644 (file)
@@ -472,25 +472,52 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
        dma_cookie_t cookie;
        int ret;
 
-       if (tx) {
-               desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx,
-                                       tx->sgl, tx->nents, DMA_TO_DEVICE,
-                                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-               if (!desc_tx)
-                       goto no_dma;
-
-               irq_mask |= SPCR_SPTIE;
-       }
+       /* First prepare and submit the DMA request(s), as this may fail */
        if (rx) {
                desc_rx = dmaengine_prep_slave_sg(rspi->master->dma_rx,
                                        rx->sgl, rx->nents, DMA_FROM_DEVICE,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-               if (!desc_rx)
-                       goto no_dma;
+               if (!desc_rx) {
+                       ret = -EAGAIN;
+                       goto no_dma_rx;
+               }
+
+               desc_rx->callback = rspi_dma_complete;
+               desc_rx->callback_param = rspi;
+               cookie = dmaengine_submit(desc_rx);
+               if (dma_submit_error(cookie)) {
+                       ret = cookie;
+                       goto no_dma_rx;
+               }
 
                irq_mask |= SPCR_SPRIE;
        }
 
+       if (tx) {
+               desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx,
+                                       tx->sgl, tx->nents, DMA_TO_DEVICE,
+                                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+               if (!desc_tx) {
+                       ret = -EAGAIN;
+                       goto no_dma_tx;
+               }
+
+               if (rx) {
+                       /* No callback */
+                       desc_tx->callback = NULL;
+               } else {
+                       desc_tx->callback = rspi_dma_complete;
+                       desc_tx->callback_param = rspi;
+               }
+               cookie = dmaengine_submit(desc_tx);
+               if (dma_submit_error(cookie)) {
+                       ret = cookie;
+                       goto no_dma_tx;
+               }
+
+               irq_mask |= SPCR_SPTIE;
+       }
+
        /*
         * DMAC needs SPxIE, but if SPxIE is set, the IRQ routine will be
         * called. So, this driver disables the IRQ while DMA transfer.
@@ -503,34 +530,24 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
        rspi_enable_irq(rspi, irq_mask);
        rspi->dma_callbacked = 0;
 
-       if (rx) {
-               desc_rx->callback = rspi_dma_complete;
-               desc_rx->callback_param = rspi;
-               cookie = dmaengine_submit(desc_rx);
-               if (dma_submit_error(cookie))
-                       return cookie;
+       /* Now start DMA */
+       if (rx)
                dma_async_issue_pending(rspi->master->dma_rx);
-       }
-       if (tx) {
-               if (rx) {
-                       /* No callback */
-                       desc_tx->callback = NULL;
-               } else {
-                       desc_tx->callback = rspi_dma_complete;
-                       desc_tx->callback_param = rspi;
-               }
-               cookie = dmaengine_submit(desc_tx);
-               if (dma_submit_error(cookie))
-                       return cookie;
+       if (tx)
                dma_async_issue_pending(rspi->master->dma_tx);
-       }
 
        ret = wait_event_interruptible_timeout(rspi->wait,
                                               rspi->dma_callbacked, HZ);
        if (ret > 0 && rspi->dma_callbacked)
                ret = 0;
-       else if (!ret)
+       else if (!ret) {
+               dev_err(&rspi->master->dev, "DMA timeout\n");
                ret = -ETIMEDOUT;
+               if (tx)
+                       dmaengine_terminate_all(rspi->master->dma_tx);
+               if (rx)
+                       dmaengine_terminate_all(rspi->master->dma_rx);
+       }
 
        rspi_disable_irq(rspi, irq_mask);
 
@@ -541,11 +558,16 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
 
        return ret;
 
-no_dma:
-       pr_warn_once("%s %s: DMA not available, falling back to PIO\n",
-                    dev_driver_string(&rspi->master->dev),
-                    dev_name(&rspi->master->dev));
-       return -EAGAIN;
+no_dma_tx:
+       if (rx)
+               dmaengine_terminate_all(rspi->master->dma_rx);
+no_dma_rx:
+       if (ret == -EAGAIN) {
+               pr_warn_once("%s %s: DMA not available, falling back to PIO\n",
+                            dev_driver_string(&rspi->master->dev),
+                            dev_name(&rspi->master->dev));
+       }
+       return ret;
 }
 
 static void rspi_receive_init(const struct rspi_data *rspi)
index 2a4354dcd6611ffb706105354dc8840513e0c43a..543075b80f166db0a6ec810ab931889d1019a9e4 100644 (file)
@@ -636,48 +636,38 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
        dma_cookie_t cookie;
        int ret;
 
-       if (tx) {
-               ier_bits |= IER_TDREQE | IER_TDMAE;
-               dma_sync_single_for_device(p->master->dma_tx->device->dev,
-                                          p->tx_dma_addr, len, DMA_TO_DEVICE);
-               desc_tx = dmaengine_prep_slave_single(p->master->dma_tx,
-                                       p->tx_dma_addr, len, DMA_TO_DEVICE,
-                                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-               if (!desc_tx)
-                       return -EAGAIN;
-       }
-
+       /* First prepare and submit the DMA request(s), as this may fail */
        if (rx) {
                ier_bits |= IER_RDREQE | IER_RDMAE;
                desc_rx = dmaengine_prep_slave_single(p->master->dma_rx,
                                        p->rx_dma_addr, len, DMA_FROM_DEVICE,
                                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-               if (!desc_rx)
-                       return -EAGAIN;
-       }
-
-       /* 1 stage FIFO watermarks for DMA */
-       sh_msiof_write(p, FCTR, FCTR_TFWM_1 | FCTR_RFWM_1);
-
-       /* setup msiof transfer mode registers (32-bit words) */
-       sh_msiof_spi_set_mode_regs(p, tx, rx, 32, len / 4);
-
-       sh_msiof_write(p, IER, ier_bits);
-
-       reinit_completion(&p->done);
+               if (!desc_rx) {
+                       ret = -EAGAIN;
+                       goto no_dma_rx;
+               }
 
-       if (rx) {
                desc_rx->callback = sh_msiof_dma_complete;
                desc_rx->callback_param = p;
                cookie = dmaengine_submit(desc_rx);
                if (dma_submit_error(cookie)) {
                        ret = cookie;
-                       goto stop_ier;
+                       goto no_dma_rx;
                }
-               dma_async_issue_pending(p->master->dma_rx);
        }
 
        if (tx) {
+               ier_bits |= IER_TDREQE | IER_TDMAE;
+               dma_sync_single_for_device(p->master->dma_tx->device->dev,
+                                          p->tx_dma_addr, len, DMA_TO_DEVICE);
+               desc_tx = dmaengine_prep_slave_single(p->master->dma_tx,
+                                       p->tx_dma_addr, len, DMA_TO_DEVICE,
+                                       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+               if (!desc_tx) {
+                       ret = -EAGAIN;
+                       goto no_dma_tx;
+               }
+
                if (rx) {
                        /* No callback */
                        desc_tx->callback = NULL;
@@ -688,15 +678,30 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
                cookie = dmaengine_submit(desc_tx);
                if (dma_submit_error(cookie)) {
                        ret = cookie;
-                       goto stop_rx;
+                       goto no_dma_tx;
                }
-               dma_async_issue_pending(p->master->dma_tx);
        }
 
+       /* 1 stage FIFO watermarks for DMA */
+       sh_msiof_write(p, FCTR, FCTR_TFWM_1 | FCTR_RFWM_1);
+
+       /* setup msiof transfer mode registers (32-bit words) */
+       sh_msiof_spi_set_mode_regs(p, tx, rx, 32, len / 4);
+
+       sh_msiof_write(p, IER, ier_bits);
+
+       reinit_completion(&p->done);
+
+       /* Now start DMA */
+       if (rx)
+               dma_async_issue_pending(p->master->dma_rx);
+       if (tx)
+               dma_async_issue_pending(p->master->dma_tx);
+
        ret = sh_msiof_spi_start(p, rx);
        if (ret) {
                dev_err(&p->pdev->dev, "failed to start hardware\n");
-               goto stop_tx;
+               goto stop_dma;
        }
 
        /* wait for tx fifo to be emptied / rx fifo to be filled */
@@ -726,14 +731,14 @@ static int sh_msiof_dma_once(struct sh_msiof_spi_priv *p, const void *tx,
 stop_reset:
        sh_msiof_reset_str(p);
        sh_msiof_spi_stop(p, rx);
-stop_tx:
+stop_dma:
        if (tx)
                dmaengine_terminate_all(p->master->dma_tx);
-stop_rx:
+no_dma_tx:
        if (rx)
                dmaengine_terminate_all(p->master->dma_rx);
-stop_ier:
        sh_msiof_write(p, IER, 0);
+no_dma_rx:
        return ret;
 }
 
index e0531baf2782ae78f086db7af5201fcaef4bc92a..ca935df80c88e98b7ae2e8ddbd24cf87c54f55ef 100644 (file)
@@ -848,6 +848,7 @@ out:
 
 /**
  * spi_finalize_current_transfer - report completion of a transfer
+ * @master: the master reporting completion
  *
  * Called by SPI drivers using the core transfer_one_message()
  * implementation to notify it that the current interrupt driven
index 19396dc4ee47f947f569a26308416f99401acb21..bed2fedeb05710f8d17313ee49e5a6e00ce7f471 100644 (file)
@@ -38,6 +38,7 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432c) },
        { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4350) },
+       { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4351) },
        { 0, },
 };
 MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl);
index 2c486ea6236bb99aeb938c9c67bea7d5f39f80e5..35b494f5667f1ca836c01fdcf054e1c4f99d110a 100644 (file)
@@ -28,8 +28,6 @@ source "drivers/staging/et131x/Kconfig"
 
 source "drivers/staging/slicoss/Kconfig"
 
-source "drivers/staging/usbip/Kconfig"
-
 source "drivers/staging/wlan-ng/Kconfig"
 
 source "drivers/staging/comedi/Kconfig"
index 1e1a3a10faf73d8c77fa0621a121e596cfbeddbf..e66a5dbd9b02c35e44ad02bdd0a235181d10a1f1 100644 (file)
@@ -6,7 +6,6 @@ obj-$(CONFIG_STAGING)           += staging.o
 obj-y                          += media/
 obj-$(CONFIG_ET131X)           += et131x/
 obj-$(CONFIG_SLICOSS)          += slicoss/
-obj-$(CONFIG_USBIP_CORE)       += usbip/
 obj-$(CONFIG_PRISM2_USB)       += wlan-ng/
 obj-$(CONFIG_COMEDI)           += comedi/
 obj-$(CONFIG_FB_OLPC_DCON)     += olpc_dcon/
index 9b47e66599a3761ed995db78d57aaf585db6359d..0bf0d24d12d5b8be9f077ba3422a07832ad5e7cb 100644 (file)
@@ -790,7 +790,7 @@ static int __init create_log(char *log_name, int size)
        if (unlikely(ret)) {
                pr_err("failed to register misc device for log '%s'!\n",
                                log->misc.name);
-               goto out_free_log;
+               goto out_free_misc_name;
        }
 
        pr_info("created %luK log '%s'\n",
@@ -798,6 +798,9 @@ static int __init create_log(char *log_name, int size)
 
        return 0;
 
+out_free_misc_name:
+       kfree(log->misc.name);
+
 out_free_log:
        kfree(log);
 
index e7b2e02341962426ea6e07a351d9932a01739f9d..69139ce7420d65bb751c2691e954fd1299bd1262 100644 (file)
@@ -199,7 +199,6 @@ struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt)
        fence->num_fences = 1;
        atomic_set(&fence->status, 1);
 
-       fence_get(&pt->base);
        fence->cbs[0].sync_pt = &pt->base;
        fence->cbs[0].fence = fence;
        if (fence_add_callback(&pt->base, &fence->cbs[0].cb,
index 8bf1eb48516376e552dbc23c7b6a1969d8488984..831b7c6fe4948074f26604083f350e33d54a5edb 100644 (file)
@@ -1421,22 +1421,16 @@ static int et131x_mii_read(struct et131x_adapter *adapter, u8 reg, u16 *value)
  * @reg: the register to read
  * @value: 16-bit value to write
  */
-static int et131x_mii_write(struct et131x_adapter *adapter, u8 reg, u16 value)
+static int et131x_mii_write(struct et131x_adapter *adapter, u8 addr, u8 reg,
+                           u16 value)
 {
        struct mac_regs __iomem *mac = &adapter->regs->mac;
-       struct phy_device *phydev = adapter->phydev;
        int status = 0;
-       u8 addr;
        u32 delay = 0;
        u32 mii_addr;
        u32 mii_cmd;
        u32 mii_indicator;
 
-       if (!phydev)
-               return -EIO;
-
-       addr = phydev->addr;
-
        /* Save a local copy of the registers we are dealing with so we can
         * set them back
         */
@@ -1631,17 +1625,7 @@ static int et131x_mdio_write(struct mii_bus *bus, int phy_addr,
        struct net_device *netdev = bus->priv;
        struct et131x_adapter *adapter = netdev_priv(netdev);
 
-       return et131x_mii_write(adapter, reg, value);
-}
-
-static int et131x_mdio_reset(struct mii_bus *bus)
-{
-       struct net_device *netdev = bus->priv;
-       struct et131x_adapter *adapter = netdev_priv(netdev);
-
-       et131x_mii_write(adapter, MII_BMCR, BMCR_RESET);
-
-       return 0;
+       return et131x_mii_write(adapter, phy_addr, reg, value);
 }
 
 /*     et1310_phy_power_switch -       PHY power control
@@ -1656,18 +1640,20 @@ static int et131x_mdio_reset(struct mii_bus *bus)
 static void et1310_phy_power_switch(struct et131x_adapter *adapter, bool down)
 {
        u16 data;
+       struct  phy_device *phydev = adapter->phydev;
 
        et131x_mii_read(adapter, MII_BMCR, &data);
        data &= ~BMCR_PDOWN;
        if (down)
                data |= BMCR_PDOWN;
-       et131x_mii_write(adapter, MII_BMCR, data);
+       et131x_mii_write(adapter, phydev->addr, MII_BMCR, data);
 }
 
 /* et131x_xcvr_init - Init the phy if we are setting it into force mode */
 static void et131x_xcvr_init(struct et131x_adapter *adapter)
 {
        u16 lcr2;
+       struct  phy_device *phydev = adapter->phydev;
 
        /* Set the LED behavior such that LED 1 indicates speed (off =
         * 10Mbits, blink = 100Mbits, on = 1000Mbits) and LED 2 indicates
@@ -1688,7 +1674,7 @@ static void et131x_xcvr_init(struct et131x_adapter *adapter)
                else
                        lcr2 |= (LED_VAL_LINKON << LED_TXRX_SHIFT);
 
-               et131x_mii_write(adapter, PHY_LED_2, lcr2);
+               et131x_mii_write(adapter, phydev->addr, PHY_LED_2, lcr2);
        }
 }
 
@@ -3643,14 +3629,14 @@ static void et131x_adjust_link(struct net_device *netdev)
 
                        et131x_mii_read(adapter, PHY_MPHY_CONTROL_REG,
                                         &register18);
-                       et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG,
-                                        register18 | 0x4);
-                       et131x_mii_write(adapter, PHY_INDEX_REG,
+                       et131x_mii_write(adapter, phydev->addr,
+                                        PHY_MPHY_CONTROL_REG, register18 | 0x4);
+                       et131x_mii_write(adapter, phydev->addr, PHY_INDEX_REG,
                                         register18 | 0x8402);
-                       et131x_mii_write(adapter, PHY_DATA_REG,
+                       et131x_mii_write(adapter, phydev->addr, PHY_DATA_REG,
                                         register18 | 511);
-                       et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG,
-                                        register18);
+                       et131x_mii_write(adapter, phydev->addr,
+                                        PHY_MPHY_CONTROL_REG, register18);
                }
 
                et1310_config_flow_control(adapter);
@@ -3662,7 +3648,8 @@ static void et131x_adjust_link(struct net_device *netdev)
                        et131x_mii_read(adapter, PHY_CONFIG, &reg);
                        reg &= ~ET_PHY_CONFIG_TX_FIFO_DEPTH;
                        reg |= ET_PHY_CONFIG_FIFO_DEPTH_32;
-                       et131x_mii_write(adapter, PHY_CONFIG, reg);
+                       et131x_mii_write(adapter, phydev->addr, PHY_CONFIG,
+                                        reg);
                }
 
                et131x_set_rx_dma_timer(adapter);
@@ -3675,14 +3662,14 @@ static void et131x_adjust_link(struct net_device *netdev)
 
                        et131x_mii_read(adapter, PHY_MPHY_CONTROL_REG,
                                         &register18);
-                       et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG,
-                                        register18 | 0x4);
-                       et131x_mii_write(adapter, PHY_INDEX_REG,
-                                        register18 | 0x8402);
-                       et131x_mii_write(adapter, PHY_DATA_REG,
-                                        register18 | 511);
-                       et131x_mii_write(adapter, PHY_MPHY_CONTROL_REG,
-                                        register18);
+                       et131x_mii_write(adapter, phydev->addr,
+                                       PHY_MPHY_CONTROL_REG, register18 | 0x4);
+                       et131x_mii_write(adapter, phydev->addr,
+                                       PHY_INDEX_REG, register18 | 0x8402);
+                       et131x_mii_write(adapter, phydev->addr,
+                                       PHY_DATA_REG, register18 | 511);
+                       et131x_mii_write(adapter, phydev->addr,
+                                       PHY_MPHY_CONTROL_REG, register18);
                }
 
                /* Free the packets being actively sent & stopped */
@@ -4644,10 +4631,6 @@ static int et131x_pci_setup(struct pci_dev *pdev,
        /* Copy address into the net_device struct */
        memcpy(netdev->dev_addr, adapter->addr, ETH_ALEN);
 
-       /* Init variable for counting how long we do not have link status */
-       adapter->boot_coma = 0;
-       et1310_disable_phy_coma(adapter);
-
        rc = -ENOMEM;
 
        /* Setup the mii_bus struct */
@@ -4663,7 +4646,6 @@ static int et131x_pci_setup(struct pci_dev *pdev,
        adapter->mii_bus->priv = netdev;
        adapter->mii_bus->read = et131x_mdio_read;
        adapter->mii_bus->write = et131x_mdio_write;
-       adapter->mii_bus->reset = et131x_mdio_reset;
        adapter->mii_bus->irq = kmalloc_array(PHY_MAX_ADDR, sizeof(int),
                                              GFP_KERNEL);
        if (!adapter->mii_bus->irq)
@@ -4687,6 +4669,10 @@ static int et131x_pci_setup(struct pci_dev *pdev,
        /* Setup et1310 as per the documentation */
        et131x_adapter_setup(adapter);
 
+       /* Init variable for counting how long we do not have link status */
+       adapter->boot_coma = 0;
+       et1310_disable_phy_coma(adapter);
+
        /* We can enable interrupts now
         *
         *  NOTE - Because registration of interrupt handler is done in the
index 7e3f019d7e72543c40dd11299a051383a1a57224..4662e00b456a25d4c08b755bc68b6bdbf37e8ed2 100644 (file)
@@ -574,6 +574,9 @@ static void imx_ldb_unbind(struct device *dev, struct device *master,
        for (i = 0; i < 2; i++) {
                struct imx_ldb_channel *channel = &imx_ldb->channel[i];
 
+               if (!channel->connector.funcs)
+                       continue;
+
                channel->connector.funcs->destroy(&channel->connector);
                channel->encoder.funcs->destroy(&channel->encoder);
        }
index 6f393a11f44d2d57fa074defc77ce048796b36cc..50de10a550e970f5c1710653eb1449215a67e3e0 100644 (file)
@@ -281,7 +281,8 @@ static void ipu_plane_dpms(struct ipu_plane *ipu_plane, int mode)
 
                ipu_idmac_put(ipu_plane->ipu_ch);
                ipu_dmfc_put(ipu_plane->dmfc);
-               ipu_dp_put(ipu_plane->dp);
+               if (ipu_plane->dp)
+                       ipu_dp_put(ipu_plane->dp);
        }
 }
 
index 65629579bd7d8c11a66c12bd7d43a51ee98ff883..03ab9e046784c0d598b43e26f97fad2ca1aafcdd 100644 (file)
@@ -365,6 +365,7 @@ cfs_wi_sched_create(char *name, struct cfs_cpt_table *cptab,
                return -ENOMEM;
 
        strncpy(sched->ws_name, name, CFS_WS_NAME_LEN);
+       sched->ws_name[CFS_WS_NAME_LEN - 1] = '\0';
        sched->ws_cptab = cptab;
        sched->ws_cpt = cpt;
 
index 8b19f3caa68ff95e4f68691611ca3f1bfcf19159..701c6a77652496260a5aab7e92d93f6ae9e49b34 100644 (file)
@@ -35,7 +35,7 @@
  */
 
 #define DEBUG_SUBSYSTEM S_CLASS
-# include <asm/atomic.h>
+# include <linux/atomic.h>
 
 #include "../include/obd_support.h"
 #include "../include/obd_class.h"
index b8676ac77b0c720040aa2ccd7eae730873ece565..407a318b09dbe2837dc64573792e6f886cc88d62 100644 (file)
@@ -43,9 +43,11 @@ static struct usb_device_id rtw_usb_id_tbl[] = {
        {USB_DEVICE(USB_VENDER_ID_REALTEK, 0x0179)}, /* 8188ETV */
        /*=== Customer ID ===*/
        /****** 8188EUS ********/
+       {USB_DEVICE(0x056e, 0x4008)}, /* Elecom WDC-150SU2M */
        {USB_DEVICE(0x07b8, 0x8179)}, /* Abocom - Abocom */
        {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
        {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */
+       {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */
        {}      /* Terminating entry */
 };
 
diff --git a/drivers/staging/usbip/Kconfig b/drivers/staging/usbip/Kconfig
deleted file mode 100644 (file)
index bd99e9e..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-config USBIP_CORE
-       tristate "USB/IP support"
-       depends on USB && NET
-       ---help---
-         This enables pushing USB packets over IP to allow remote
-         machines direct access to USB devices. It provides the
-         USB/IP core that is required by both drivers.
-
-         For more details, and to get the userspace utility
-         programs, please see <http://usbip.sourceforge.net/>.
-
-         To compile this as a module, choose M here: the module will
-         be called usbip-core.
-
-         If unsure, say N.
-
-config USBIP_VHCI_HCD
-       tristate "VHCI hcd"
-       depends on USBIP_CORE
-       ---help---
-         This enables the USB/IP virtual host controller driver,
-         which is run on the remote machine.
-
-         To compile this driver as a module, choose M here: the
-         module will be called vhci-hcd.
-
-config USBIP_HOST
-       tristate "Host driver"
-       depends on USBIP_CORE
-       ---help---
-         This enables the USB/IP host driver, which is run on the
-         machine that is sharing the USB devices.
-
-         To compile this driver as a module, choose M here: the
-         module will be called usbip-host.
-
-config USBIP_DEBUG
-       bool "Debug messages for USB/IP"
-       depends on USBIP_CORE
-       ---help---
-         This enables the debug messages from the USB/IP drivers.
diff --git a/drivers/staging/usbip/Makefile b/drivers/staging/usbip/Makefile
deleted file mode 100644 (file)
index 9ecd615..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-ccflags-$(CONFIG_USBIP_DEBUG) := -DDEBUG
-
-obj-$(CONFIG_USBIP_CORE) += usbip-core.o
-usbip-core-y := usbip_common.o usbip_event.o
-
-obj-$(CONFIG_USBIP_VHCI_HCD) += vhci-hcd.o
-vhci-hcd-y := vhci_sysfs.o vhci_tx.o vhci_rx.o vhci_hcd.o
-
-obj-$(CONFIG_USBIP_HOST) += usbip-host.o
-usbip-host-y := stub_dev.o stub_main.o stub_rx.o stub_tx.o
diff --git a/drivers/staging/usbip/README b/drivers/staging/usbip/README
deleted file mode 100644 (file)
index 41a2cf2..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-TODO:
-       - more discussion about the protocol
-       - testing
-       - review of the userspace interface
-       - document the protocol
-
-Please send patches for this code to Greg Kroah-Hartman <greg@kroah.com>
diff --git a/drivers/staging/usbip/stub.h b/drivers/staging/usbip/stub.h
deleted file mode 100644 (file)
index 266e2b0..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2003-2008 Takahiro Hirofuchi
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#ifndef __USBIP_STUB_H
-#define __USBIP_STUB_H
-
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-#include <linux/usb.h>
-#include <linux/wait.h>
-
-#define STUB_BUSID_OTHER 0
-#define STUB_BUSID_REMOV 1
-#define STUB_BUSID_ADDED 2
-#define STUB_BUSID_ALLOC 3
-
-struct stub_device {
-       struct usb_interface *interface;
-       struct usb_device *udev;
-
-       struct usbip_device ud;
-       __u32 devid;
-
-       /*
-        * stub_priv preserves private data of each urb.
-        * It is allocated as stub_priv_cache and assigned to urb->context.
-        *
-        * stub_priv is always linked to any one of 3 lists;
-        *      priv_init: linked to this until the comletion of a urb.
-        *      priv_tx  : linked to this after the completion of a urb.
-        *      priv_free: linked to this after the sending of the result.
-        *
-        * Any of these list operations should be locked by priv_lock.
-        */
-       spinlock_t priv_lock;
-       struct list_head priv_init;
-       struct list_head priv_tx;
-       struct list_head priv_free;
-
-       /* see comments for unlinking in stub_rx.c */
-       struct list_head unlink_tx;
-       struct list_head unlink_free;
-
-       wait_queue_head_t tx_waitq;
-};
-
-/* private data into urb->priv */
-struct stub_priv {
-       unsigned long seqnum;
-       struct list_head list;
-       struct stub_device *sdev;
-       struct urb *urb;
-
-       int unlinking;
-};
-
-struct stub_unlink {
-       unsigned long seqnum;
-       struct list_head list;
-       __u32 status;
-};
-
-/* same as SYSFS_BUS_ID_SIZE */
-#define BUSID_SIZE 32
-
-struct bus_id_priv {
-       char name[BUSID_SIZE];
-       char status;
-       int interf_count;
-       struct stub_device *sdev;
-       struct usb_device *udev;
-       char shutdown_busid;
-};
-
-/* stub_priv is allocated from stub_priv_cache */
-extern struct kmem_cache *stub_priv_cache;
-
-/* stub_dev.c */
-extern struct usb_device_driver stub_driver;
-
-/* stub_main.c */
-struct bus_id_priv *get_busid_priv(const char *busid);
-int del_match_busid(char *busid);
-void stub_device_cleanup_urbs(struct stub_device *sdev);
-
-/* stub_rx.c */
-int stub_rx_loop(void *data);
-
-/* stub_tx.c */
-void stub_enqueue_ret_unlink(struct stub_device *sdev, __u32 seqnum,
-                            __u32 status);
-void stub_complete(struct urb *urb);
-int stub_tx_loop(void *data);
-
-#endif /* __USBIP_STUB_H */
diff --git a/drivers/staging/usbip/stub_dev.c b/drivers/staging/usbip/stub_dev.c
deleted file mode 100644 (file)
index 51d0c71..0000000
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
- * Copyright (C) 2003-2008 Takahiro Hirofuchi
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#include <linux/device.h>
-#include <linux/file.h>
-#include <linux/kthread.h>
-#include <linux/module.h>
-
-#include "usbip_common.h"
-#include "stub.h"
-
-/*
- * Define device IDs here if you want to explicitly limit exportable devices.
- * In most cases, wildcard matching will be okay because driver binding can be
- * changed dynamically by a userland program.
- */
-static struct usb_device_id stub_table[] = {
-#if 0
-       /* just an example */
-       { USB_DEVICE(0x05ac, 0x0301) },   /* Mac 1 button mouse */
-       { USB_DEVICE(0x0430, 0x0009) },   /* Plat Home Keyboard */
-       { USB_DEVICE(0x059b, 0x0001) },   /* Iomega USB Zip 100 */
-       { USB_DEVICE(0x04b3, 0x4427) },   /* IBM USB CD-ROM */
-       { USB_DEVICE(0x05a9, 0xa511) },   /* LifeView USB cam */
-       { USB_DEVICE(0x55aa, 0x0201) },   /* Imation card reader */
-       { USB_DEVICE(0x046d, 0x0870) },   /* Qcam Express(QV-30) */
-       { USB_DEVICE(0x04bb, 0x0101) },   /* IO-DATA HD 120GB */
-       { USB_DEVICE(0x04bb, 0x0904) },   /* IO-DATA USB-ET/TX */
-       { USB_DEVICE(0x04bb, 0x0201) },   /* IO-DATA USB-ET/TX */
-       { USB_DEVICE(0x08bb, 0x2702) },   /* ONKYO USB Speaker */
-       { USB_DEVICE(0x046d, 0x08b2) },   /* Logicool Qcam 4000 Pro */
-#endif
-       /* magic for wild card */
-       { .driver_info = 1 },
-       { 0, }                                     /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, stub_table);
-
-/*
- * usbip_status shows the status of usbip-host as long as this driver is bound
- * to the target device.
- */
-static ssize_t usbip_status_show(struct device *dev,
-                                struct device_attribute *attr, char *buf)
-{
-       struct stub_device *sdev = dev_get_drvdata(dev);
-       int status;
-
-       if (!sdev) {
-               dev_err(dev, "sdev is null\n");
-               return -ENODEV;
-       }
-
-       spin_lock_irq(&sdev->ud.lock);
-       status = sdev->ud.status;
-       spin_unlock_irq(&sdev->ud.lock);
-
-       return snprintf(buf, PAGE_SIZE, "%d\n", status);
-}
-static DEVICE_ATTR_RO(usbip_status);
-
-/*
- * usbip_sockfd gets a socket descriptor of an established TCP connection that
- * is used to transfer usbip requests by kernel threads. -1 is a magic number
- * by which usbip connection is finished.
- */
-static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr,
-                           const char *buf, size_t count)
-{
-       struct stub_device *sdev = dev_get_drvdata(dev);
-       int sockfd = 0;
-       struct socket *socket;
-       int rv;
-
-       if (!sdev) {
-               dev_err(dev, "sdev is null\n");
-               return -ENODEV;
-       }
-
-       rv = sscanf(buf, "%d", &sockfd);
-       if (rv != 1)
-               return -EINVAL;
-
-       if (sockfd != -1) {
-               int err;
-
-               dev_info(dev, "stub up\n");
-
-               spin_lock_irq(&sdev->ud.lock);
-
-               if (sdev->ud.status != SDEV_ST_AVAILABLE) {
-                       dev_err(dev, "not ready\n");
-                       goto err;
-               }
-
-               socket = sockfd_lookup(sockfd, &err);
-               if (!socket)
-                       goto err;
-
-               sdev->ud.tcp_socket = socket;
-
-               spin_unlock_irq(&sdev->ud.lock);
-
-               sdev->ud.tcp_rx = kthread_get_run(stub_rx_loop, &sdev->ud,
-                                                 "stub_rx");
-               sdev->ud.tcp_tx = kthread_get_run(stub_tx_loop, &sdev->ud,
-                                                 "stub_tx");
-
-               spin_lock_irq(&sdev->ud.lock);
-               sdev->ud.status = SDEV_ST_USED;
-               spin_unlock_irq(&sdev->ud.lock);
-
-       } else {
-               dev_info(dev, "stub down\n");
-
-               spin_lock_irq(&sdev->ud.lock);
-               if (sdev->ud.status != SDEV_ST_USED)
-                       goto err;
-
-               spin_unlock_irq(&sdev->ud.lock);
-
-               usbip_event_add(&sdev->ud, SDEV_EVENT_DOWN);
-       }
-
-       return count;
-
-err:
-       spin_unlock_irq(&sdev->ud.lock);
-       return -EINVAL;
-}
-static DEVICE_ATTR(usbip_sockfd, S_IWUSR, NULL, store_sockfd);
-
-static int stub_add_files(struct device *dev)
-{
-       int err = 0;
-
-       err = device_create_file(dev, &dev_attr_usbip_status);
-       if (err)
-               goto err_status;
-
-       err = device_create_file(dev, &dev_attr_usbip_sockfd);
-       if (err)
-               goto err_sockfd;
-
-       err = device_create_file(dev, &dev_attr_usbip_debug);
-       if (err)
-               goto err_debug;
-
-       return 0;
-
-err_debug:
-       device_remove_file(dev, &dev_attr_usbip_sockfd);
-err_sockfd:
-       device_remove_file(dev, &dev_attr_usbip_status);
-err_status:
-       return err;
-}
-
-static void stub_remove_files(struct device *dev)
-{
-       device_remove_file(dev, &dev_attr_usbip_status);
-       device_remove_file(dev, &dev_attr_usbip_sockfd);
-       device_remove_file(dev, &dev_attr_usbip_debug);
-}
-
-static void stub_shutdown_connection(struct usbip_device *ud)
-{
-       struct stub_device *sdev = container_of(ud, struct stub_device, ud);
-
-       /*
-        * When removing an exported device, kernel panic sometimes occurred
-        * and then EIP was sk_wait_data of stub_rx thread. Is this because
-        * sk_wait_data returned though stub_rx thread was already finished by
-        * step 1?
-        */
-       if (ud->tcp_socket) {
-               dev_dbg(&sdev->udev->dev, "shutdown tcp_socket %p\n",
-                       ud->tcp_socket);
-               kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR);
-       }
-
-       /* 1. stop threads */
-       if (ud->tcp_rx) {
-               kthread_stop_put(ud->tcp_rx);
-               ud->tcp_rx = NULL;
-       }
-       if (ud->tcp_tx) {
-               kthread_stop_put(ud->tcp_tx);
-               ud->tcp_tx = NULL;
-       }
-
-       /*
-        * 2. close the socket
-        *
-        * tcp_socket is freed after threads are killed so that usbip_xmit does
-        * not touch NULL socket.
-        */
-       if (ud->tcp_socket) {
-               sockfd_put(ud->tcp_socket);
-               ud->tcp_socket = NULL;
-       }
-
-       /* 3. free used data */
-       stub_device_cleanup_urbs(sdev);
-
-       /* 4. free stub_unlink */
-       {
-               unsigned long flags;
-               struct stub_unlink *unlink, *tmp;
-
-               spin_lock_irqsave(&sdev->priv_lock, flags);
-               list_for_each_entry_safe(unlink, tmp, &sdev->unlink_tx, list) {
-                       list_del(&unlink->list);
-                       kfree(unlink);
-               }
-               list_for_each_entry_safe(unlink, tmp, &sdev->unlink_free,
-                                        list) {
-                       list_del(&unlink->list);
-                       kfree(unlink);
-               }
-               spin_unlock_irqrestore(&sdev->priv_lock, flags);
-       }
-}
-
-static void stub_device_reset(struct usbip_device *ud)
-{
-       struct stub_device *sdev = container_of(ud, struct stub_device, ud);
-       struct usb_device *udev = sdev->udev;
-       int ret;
-
-       dev_dbg(&udev->dev, "device reset");
-
-       ret = usb_lock_device_for_reset(udev, sdev->interface);
-       if (ret < 0) {
-               dev_err(&udev->dev, "lock for reset\n");
-               spin_lock_irq(&ud->lock);
-               ud->status = SDEV_ST_ERROR;
-               spin_unlock_irq(&ud->lock);
-               return;
-       }
-
-       /* try to reset the device */
-       ret = usb_reset_device(udev);
-       usb_unlock_device(udev);
-
-       spin_lock_irq(&ud->lock);
-       if (ret) {
-               dev_err(&udev->dev, "device reset\n");
-               ud->status = SDEV_ST_ERROR;
-       } else {
-               dev_info(&udev->dev, "device reset\n");
-               ud->status = SDEV_ST_AVAILABLE;
-       }
-       spin_unlock_irq(&ud->lock);
-}
-
-static void stub_device_unusable(struct usbip_device *ud)
-{
-       spin_lock_irq(&ud->lock);
-       ud->status = SDEV_ST_ERROR;
-       spin_unlock_irq(&ud->lock);
-}
-
-/**
- * stub_device_alloc - allocate a new stub_device struct
- * @interface: usb_interface of a new device
- *
- * Allocates and initializes a new stub_device struct.
- */
-static struct stub_device *stub_device_alloc(struct usb_device *udev)
-{
-       struct stub_device *sdev;
-       int busnum = udev->bus->busnum;
-       int devnum = udev->devnum;
-
-       dev_dbg(&udev->dev, "allocating stub device");
-
-       /* yes, it's a new device */
-       sdev = kzalloc(sizeof(struct stub_device), GFP_KERNEL);
-       if (!sdev)
-               return NULL;
-
-       sdev->udev = usb_get_dev(udev);
-
-       /*
-        * devid is defined with devnum when this driver is first allocated.
-        * devnum may change later if a device is reset. However, devid never
-        * changes during a usbip connection.
-        */
-       sdev->devid             = (busnum << 16) | devnum;
-       sdev->ud.side           = USBIP_STUB;
-       sdev->ud.status         = SDEV_ST_AVAILABLE;
-       spin_lock_init(&sdev->ud.lock);
-       sdev->ud.tcp_socket     = NULL;
-
-       INIT_LIST_HEAD(&sdev->priv_init);
-       INIT_LIST_HEAD(&sdev->priv_tx);
-       INIT_LIST_HEAD(&sdev->priv_free);
-       INIT_LIST_HEAD(&sdev->unlink_free);
-       INIT_LIST_HEAD(&sdev->unlink_tx);
-       spin_lock_init(&sdev->priv_lock);
-
-       init_waitqueue_head(&sdev->tx_waitq);
-
-       sdev->ud.eh_ops.shutdown = stub_shutdown_connection;
-       sdev->ud.eh_ops.reset    = stub_device_reset;
-       sdev->ud.eh_ops.unusable = stub_device_unusable;
-
-       usbip_start_eh(&sdev->ud);
-
-       dev_dbg(&udev->dev, "register new device\n");
-
-       return sdev;
-}
-
-static void stub_device_free(struct stub_device *sdev)
-{
-       kfree(sdev);
-}
-
-static int stub_probe(struct usb_device *udev)
-{
-       struct stub_device *sdev = NULL;
-       const char *udev_busid = dev_name(&udev->dev);
-       int err = 0;
-       struct bus_id_priv *busid_priv;
-       int rc;
-
-       dev_dbg(&udev->dev, "Enter\n");
-
-       /* check we should claim or not by busid_table */
-       busid_priv = get_busid_priv(udev_busid);
-       if (!busid_priv || (busid_priv->status == STUB_BUSID_REMOV) ||
-           (busid_priv->status == STUB_BUSID_OTHER)) {
-               dev_info(&udev->dev,
-                       "%s is not in match_busid table... skip!\n",
-                       udev_busid);
-
-               /*
-                * Return value should be ENODEV or ENOXIO to continue trying
-                * other matched drivers by the driver core.
-                * See driver_probe_device() in driver/base/dd.c
-                */
-               return -ENODEV;
-       }
-
-       if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) {
-               dev_dbg(&udev->dev, "%s is a usb hub device... skip!\n",
-                        udev_busid);
-               return -ENODEV;
-       }
-
-       if (!strcmp(udev->bus->bus_name, "vhci_hcd")) {
-               dev_dbg(&udev->dev,
-                       "%s is attached on vhci_hcd... skip!\n",
-                       udev_busid);
-
-               return -ENODEV;
-       }
-
-       /* ok, this is my device */
-       sdev = stub_device_alloc(udev);
-       if (!sdev)
-               return -ENOMEM;
-
-       dev_info(&udev->dev,
-               "usbip-host: register new device (bus %u dev %u)\n",
-               udev->bus->busnum, udev->devnum);
-
-       busid_priv->shutdown_busid = 0;
-
-       /* set private data to usb_device */
-       dev_set_drvdata(&udev->dev, sdev);
-       busid_priv->sdev = sdev;
-       busid_priv->udev = udev;
-
-       /*
-        * Claim this hub port.
-        * It doesn't matter what value we pass as owner
-        * (struct dev_state) as long as it is unique.
-        */
-       rc = usb_hub_claim_port(udev->parent, udev->portnum,
-                       (struct usb_dev_state *) udev);
-       if (rc) {
-               dev_dbg(&udev->dev, "unable to claim port\n");
-               return rc;
-       }
-
-       err = stub_add_files(&udev->dev);
-       if (err) {
-               dev_err(&udev->dev, "stub_add_files for %s\n", udev_busid);
-               dev_set_drvdata(&udev->dev, NULL);
-               usb_put_dev(udev);
-               kthread_stop_put(sdev->ud.eh);
-
-               busid_priv->sdev = NULL;
-               stub_device_free(sdev);
-               return err;
-       }
-       busid_priv->status = STUB_BUSID_ALLOC;
-
-       return 0;
-}
-
-static void shutdown_busid(struct bus_id_priv *busid_priv)
-{
-       if (busid_priv->sdev && !busid_priv->shutdown_busid) {
-               busid_priv->shutdown_busid = 1;
-               usbip_event_add(&busid_priv->sdev->ud, SDEV_EVENT_REMOVED);
-
-               /* wait for the stop of the event handler */
-               usbip_stop_eh(&busid_priv->sdev->ud);
-       }
-}
-
-/*
- * called in usb_disconnect() or usb_deregister()
- * but only if actconfig(active configuration) exists
- */
-static void stub_disconnect(struct usb_device *udev)
-{
-       struct stub_device *sdev;
-       const char *udev_busid = dev_name(&udev->dev);
-       struct bus_id_priv *busid_priv;
-       int rc;
-
-       dev_dbg(&udev->dev, "Enter\n");
-
-       busid_priv = get_busid_priv(udev_busid);
-       if (!busid_priv) {
-               BUG();
-               return;
-       }
-
-       sdev = dev_get_drvdata(&udev->dev);
-
-       /* get stub_device */
-       if (!sdev) {
-               dev_err(&udev->dev, "could not get device");
-               return;
-       }
-
-       dev_set_drvdata(&udev->dev, NULL);
-
-       /*
-        * NOTE: rx/tx threads are invoked for each usb_device.
-        */
-       stub_remove_files(&udev->dev);
-
-       /* release port */
-       rc = usb_hub_release_port(udev->parent, udev->portnum,
-                                 (struct usb_dev_state *) udev);
-       if (rc) {
-               dev_dbg(&udev->dev, "unable to release port\n");
-               return;
-       }
-
-       /* If usb reset is called from event handler */
-       if (busid_priv->sdev->ud.eh == current)
-               return;
-
-       /* shutdown the current connection */
-       shutdown_busid(busid_priv);
-
-       usb_put_dev(sdev->udev);
-
-       /* free sdev */
-       busid_priv->sdev = NULL;
-       stub_device_free(sdev);
-
-       if (busid_priv->status == STUB_BUSID_ALLOC) {
-               busid_priv->status = STUB_BUSID_ADDED;
-       } else {
-               busid_priv->status = STUB_BUSID_OTHER;
-               del_match_busid((char *)udev_busid);
-       }
-}
-
-#ifdef CONFIG_PM
-
-/* These functions need usb_port_suspend and usb_port_resume,
- * which reside in drivers/usb/core/usb.h. Skip for now. */
-
-static int stub_suspend(struct usb_device *udev, pm_message_t message)
-{
-       dev_dbg(&udev->dev, "stub_suspend\n");
-
-       return 0;
-}
-
-static int stub_resume(struct usb_device *udev, pm_message_t message)
-{
-       dev_dbg(&udev->dev, "stub_resume\n");
-
-       return 0;
-}
-
-#endif /* CONFIG_PM */
-
-struct usb_device_driver stub_driver = {
-       .name           = "usbip-host",
-       .probe          = stub_probe,
-       .disconnect     = stub_disconnect,
-#ifdef CONFIG_PM
-       .suspend        = stub_suspend,
-       .resume         = stub_resume,
-#endif
-       .supports_autosuspend   =       0,
-};
diff --git a/drivers/staging/usbip/stub_main.c b/drivers/staging/usbip/stub_main.c
deleted file mode 100644 (file)
index 44ab43f..0000000
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright (C) 2003-2008 Takahiro Hirofuchi
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#include <linux/string.h>
-#include <linux/module.h>
-#include <linux/device.h>
-
-#include "usbip_common.h"
-#include "stub.h"
-
-#define DRIVER_AUTHOR "Takahiro Hirofuchi"
-#define DRIVER_DESC "USB/IP Host Driver"
-
-struct kmem_cache *stub_priv_cache;
-/*
- * busid_tables defines matching busids that usbip can grab. A user can change
- * dynamically what device is locally used and what device is exported to a
- * remote host.
- */
-#define MAX_BUSID 16
-static struct bus_id_priv busid_table[MAX_BUSID];
-static spinlock_t busid_table_lock;
-
-static void init_busid_table(void)
-{
-       /*
-        * This also sets the bus_table[i].status to
-        * STUB_BUSID_OTHER, which is 0.
-        */
-       memset(busid_table, 0, sizeof(busid_table));
-
-       spin_lock_init(&busid_table_lock);
-}
-
-/*
- * Find the index of the busid by name.
- * Must be called with busid_table_lock held.
- */
-static int get_busid_idx(const char *busid)
-{
-       int i;
-       int idx = -1;
-
-       for (i = 0; i < MAX_BUSID; i++)
-               if (busid_table[i].name[0])
-                       if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
-                               idx = i;
-                               break;
-                       }
-       return idx;
-}
-
-struct bus_id_priv *get_busid_priv(const char *busid)
-{
-       int idx;
-       struct bus_id_priv *bid = NULL;
-
-       spin_lock(&busid_table_lock);
-       idx = get_busid_idx(busid);
-       if (idx >= 0)
-               bid = &(busid_table[idx]);
-       spin_unlock(&busid_table_lock);
-
-       return bid;
-}
-
-static int add_match_busid(char *busid)
-{
-       int i;
-       int ret = -1;
-
-       spin_lock(&busid_table_lock);
-       /* already registered? */
-       if (get_busid_idx(busid) >= 0) {
-               ret = 0;
-               goto out;
-       }
-
-       for (i = 0; i < MAX_BUSID; i++)
-               if (!busid_table[i].name[0]) {
-                       strlcpy(busid_table[i].name, busid, BUSID_SIZE);
-                       if ((busid_table[i].status != STUB_BUSID_ALLOC) &&
-                           (busid_table[i].status != STUB_BUSID_REMOV))
-                               busid_table[i].status = STUB_BUSID_ADDED;
-                       ret = 0;
-                       break;
-               }
-
-out:
-       spin_unlock(&busid_table_lock);
-
-       return ret;
-}
-
-int del_match_busid(char *busid)
-{
-       int idx;
-       int ret = -1;
-
-       spin_lock(&busid_table_lock);
-       idx = get_busid_idx(busid);
-       if (idx < 0)
-               goto out;
-
-       /* found */
-       ret = 0;
-
-       if (busid_table[idx].status == STUB_BUSID_OTHER)
-               memset(busid_table[idx].name, 0, BUSID_SIZE);
-
-       if ((busid_table[idx].status != STUB_BUSID_OTHER) &&
-           (busid_table[idx].status != STUB_BUSID_ADDED))
-               busid_table[idx].status = STUB_BUSID_REMOV;
-
-out:
-       spin_unlock(&busid_table_lock);
-
-       return ret;
-}
-
-static ssize_t show_match_busid(struct device_driver *drv, char *buf)
-{
-       int i;
-       char *out = buf;
-
-       spin_lock(&busid_table_lock);
-       for (i = 0; i < MAX_BUSID; i++)
-               if (busid_table[i].name[0])
-                       out += sprintf(out, "%s ", busid_table[i].name);
-       spin_unlock(&busid_table_lock);
-       out += sprintf(out, "\n");
-
-       return out - buf;
-}
-
-static ssize_t store_match_busid(struct device_driver *dev, const char *buf,
-                                size_t count)
-{
-       int len;
-       char busid[BUSID_SIZE];
-
-       if (count < 5)
-               return -EINVAL;
-
-       /* busid needs to include \0 termination */
-       len = strlcpy(busid, buf + 4, BUSID_SIZE);
-       if (sizeof(busid) <= len)
-               return -EINVAL;
-
-       if (!strncmp(buf, "add ", 4)) {
-               if (add_match_busid(busid) < 0)
-                       return -ENOMEM;
-
-               pr_debug("add busid %s\n", busid);
-               return count;
-       }
-
-       if (!strncmp(buf, "del ", 4)) {
-               if (del_match_busid(busid) < 0)
-                       return -ENODEV;
-
-               pr_debug("del busid %s\n", busid);
-               return count;
-       }
-
-       return -EINVAL;
-}
-static DRIVER_ATTR(match_busid, S_IRUSR | S_IWUSR, show_match_busid,
-                  store_match_busid);
-
-static ssize_t rebind_store(struct device_driver *dev, const char *buf,
-                                size_t count)
-{
-       int ret;
-       int len;
-       struct bus_id_priv *bid;
-
-       /* buf length should be less that BUSID_SIZE */
-       len = strnlen(buf, BUSID_SIZE);
-
-       if (!(len < BUSID_SIZE))
-               return -EINVAL;
-
-       bid = get_busid_priv(buf);
-       if (!bid)
-               return -ENODEV;
-
-       ret = device_attach(&bid->udev->dev);
-       if (ret < 0) {
-               dev_err(&bid->udev->dev, "rebind failed\n");
-               return ret;
-       }
-
-       return count;
-}
-
-static DRIVER_ATTR_WO(rebind);
-
-static struct stub_priv *stub_priv_pop_from_listhead(struct list_head *listhead)
-{
-       struct stub_priv *priv, *tmp;
-
-       list_for_each_entry_safe(priv, tmp, listhead, list) {
-               list_del(&priv->list);
-               return priv;
-       }
-
-       return NULL;
-}
-
-static struct stub_priv *stub_priv_pop(struct stub_device *sdev)
-{
-       unsigned long flags;
-       struct stub_priv *priv;
-
-       spin_lock_irqsave(&sdev->priv_lock, flags);
-
-       priv = stub_priv_pop_from_listhead(&sdev->priv_init);
-       if (priv)
-               goto done;
-
-       priv = stub_priv_pop_from_listhead(&sdev->priv_tx);
-       if (priv)
-               goto done;
-
-       priv = stub_priv_pop_from_listhead(&sdev->priv_free);
-
-done:
-       spin_unlock_irqrestore(&sdev->priv_lock, flags);
-
-       return priv;
-}
-
-void stub_device_cleanup_urbs(struct stub_device *sdev)
-{
-       struct stub_priv *priv;
-       struct urb *urb;
-
-       dev_dbg(&sdev->udev->dev, "free sdev %p\n", sdev);
-
-       while ((priv = stub_priv_pop(sdev))) {
-               urb = priv->urb;
-               dev_dbg(&sdev->udev->dev, "free urb %p\n", urb);
-               usb_kill_urb(urb);
-
-               kmem_cache_free(stub_priv_cache, priv);
-
-               kfree(urb->transfer_buffer);
-               kfree(urb->setup_packet);
-               usb_free_urb(urb);
-       }
-}
-
-static int __init usbip_host_init(void)
-{
-       int ret;
-
-       init_busid_table();
-
-       stub_priv_cache = KMEM_CACHE(stub_priv, SLAB_HWCACHE_ALIGN);
-       if (!stub_priv_cache) {
-               pr_err("kmem_cache_create failed\n");
-               return -ENOMEM;
-       }
-
-       ret = usb_register_device_driver(&stub_driver, THIS_MODULE);
-       if (ret) {
-               pr_err("usb_register failed %d\n", ret);
-               goto err_usb_register;
-       }
-
-       ret = driver_create_file(&stub_driver.drvwrap.driver,
-                                &driver_attr_match_busid);
-       if (ret) {
-               pr_err("driver_create_file failed\n");
-               goto err_create_file;
-       }
-
-       ret = driver_create_file(&stub_driver.drvwrap.driver,
-                                &driver_attr_rebind);
-       if (ret) {
-               pr_err("driver_create_file failed\n");
-               goto err_create_file;
-       }
-
-       pr_info(DRIVER_DESC " v" USBIP_VERSION "\n");
-       return ret;
-
-err_create_file:
-       usb_deregister_device_driver(&stub_driver);
-err_usb_register:
-       kmem_cache_destroy(stub_priv_cache);
-       return ret;
-}
-
-static void __exit usbip_host_exit(void)
-{
-       driver_remove_file(&stub_driver.drvwrap.driver,
-                          &driver_attr_match_busid);
-
-       driver_remove_file(&stub_driver.drvwrap.driver,
-                          &driver_attr_rebind);
-
-       /*
-        * deregister() calls stub_disconnect() for all devices. Device
-        * specific data is cleared in stub_disconnect().
-        */
-       usb_deregister_device_driver(&stub_driver);
-
-       kmem_cache_destroy(stub_priv_cache);
-}
-
-module_init(usbip_host_init);
-module_exit(usbip_host_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-MODULE_VERSION(USBIP_VERSION);
diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c
deleted file mode 100644 (file)
index 00e475c..0000000
+++ /dev/null
@@ -1,594 +0,0 @@
-/*
- * Copyright (C) 2003-2008 Takahiro Hirofuchi
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#include <asm/byteorder.h>
-#include <linux/kthread.h>
-#include <linux/usb.h>
-#include <linux/usb/hcd.h>
-
-#include "usbip_common.h"
-#include "stub.h"
-
-static int is_clear_halt_cmd(struct urb *urb)
-{
-       struct usb_ctrlrequest *req;
-
-       req = (struct usb_ctrlrequest *) urb->setup_packet;
-
-        return (req->bRequest == USB_REQ_CLEAR_FEATURE) &&
-                (req->bRequestType == USB_RECIP_ENDPOINT) &&
-                (req->wValue == USB_ENDPOINT_HALT);
-}
-
-static int is_set_interface_cmd(struct urb *urb)
-{
-       struct usb_ctrlrequest *req;
-
-       req = (struct usb_ctrlrequest *) urb->setup_packet;
-
-       return (req->bRequest == USB_REQ_SET_INTERFACE) &&
-               (req->bRequestType == USB_RECIP_INTERFACE);
-}
-
-static int is_set_configuration_cmd(struct urb *urb)
-{
-       struct usb_ctrlrequest *req;
-
-       req = (struct usb_ctrlrequest *) urb->setup_packet;
-
-       return (req->bRequest == USB_REQ_SET_CONFIGURATION) &&
-               (req->bRequestType == USB_RECIP_DEVICE);
-}
-
-static int is_reset_device_cmd(struct urb *urb)
-{
-       struct usb_ctrlrequest *req;
-       __u16 value;
-       __u16 index;
-
-       req = (struct usb_ctrlrequest *) urb->setup_packet;
-       value = le16_to_cpu(req->wValue);
-       index = le16_to_cpu(req->wIndex);
-
-       if ((req->bRequest == USB_REQ_SET_FEATURE) &&
-           (req->bRequestType == USB_RT_PORT) &&
-           (value == USB_PORT_FEAT_RESET)) {
-               usbip_dbg_stub_rx("reset_device_cmd, port %u\n", index);
-               return 1;
-       } else
-               return 0;
-}
-
-static int tweak_clear_halt_cmd(struct urb *urb)
-{
-       struct usb_ctrlrequest *req;
-       int target_endp;
-       int target_dir;
-       int target_pipe;
-       int ret;
-
-       req = (struct usb_ctrlrequest *) urb->setup_packet;
-
-       /*
-        * The stalled endpoint is specified in the wIndex value. The endpoint
-        * of the urb is the target of this clear_halt request (i.e., control
-        * endpoint).
-        */
-       target_endp = le16_to_cpu(req->wIndex) & 0x000f;
-
-       /* the stalled endpoint direction is IN or OUT?. USB_DIR_IN is 0x80.  */
-       target_dir = le16_to_cpu(req->wIndex) & 0x0080;
-
-       if (target_dir)
-               target_pipe = usb_rcvctrlpipe(urb->dev, target_endp);
-       else
-               target_pipe = usb_sndctrlpipe(urb->dev, target_endp);
-
-       ret = usb_clear_halt(urb->dev, target_pipe);
-       if (ret < 0)
-               dev_err(&urb->dev->dev,
-                       "usb_clear_halt error: devnum %d endp %d ret %d\n",
-                       urb->dev->devnum, target_endp, ret);
-       else
-               dev_info(&urb->dev->dev,
-                        "usb_clear_halt done: devnum %d endp %d\n",
-                        urb->dev->devnum, target_endp);
-
-       return ret;
-}
-
-static int tweak_set_interface_cmd(struct urb *urb)
-{
-       struct usb_ctrlrequest *req;
-       __u16 alternate;
-       __u16 interface;
-       int ret;
-
-       req = (struct usb_ctrlrequest *) urb->setup_packet;
-       alternate = le16_to_cpu(req->wValue);
-       interface = le16_to_cpu(req->wIndex);
-
-       usbip_dbg_stub_rx("set_interface: inf %u alt %u\n",
-                         interface, alternate);
-
-       ret = usb_set_interface(urb->dev, interface, alternate);
-       if (ret < 0)
-               dev_err(&urb->dev->dev,
-                       "usb_set_interface error: inf %u alt %u ret %d\n",
-                       interface, alternate, ret);
-       else
-               dev_info(&urb->dev->dev,
-                       "usb_set_interface done: inf %u alt %u\n",
-                       interface, alternate);
-
-       return ret;
-}
-
-static int tweak_set_configuration_cmd(struct urb *urb)
-{
-       struct stub_priv *priv = (struct stub_priv *) urb->context;
-       struct stub_device *sdev = priv->sdev;
-       struct usb_ctrlrequest *req;
-       __u16 config;
-       int err;
-
-       req = (struct usb_ctrlrequest *) urb->setup_packet;
-       config = le16_to_cpu(req->wValue);
-
-       err = usb_set_configuration(sdev->udev, config);
-       if (err && err != -ENODEV)
-               dev_err(&sdev->udev->dev, "can't set config #%d, error %d\n",
-                       config, err);
-       return 0;
-}
-
-static int tweak_reset_device_cmd(struct urb *urb)
-{
-       struct stub_priv *priv = (struct stub_priv *) urb->context;
-       struct stub_device *sdev = priv->sdev;
-
-       dev_info(&urb->dev->dev, "usb_queue_reset_device\n");
-
-       /*
-        * With the implementation of pre_reset and post_reset the driver no
-        * longer unbinds. This allows the use of synchronous reset.
-        */
-
-       if (usb_lock_device_for_reset(sdev->udev, sdev->interface) < 0) {
-               dev_err(&urb->dev->dev, "could not obtain lock to reset device\n");
-               return 0;
-       }
-       usb_reset_device(sdev->udev);
-       usb_unlock_device(sdev->udev);
-
-       return 0;
-}
-
-/*
- * clear_halt, set_interface, and set_configuration require special tricks.
- */
-static void tweak_special_requests(struct urb *urb)
-{
-       if (!urb || !urb->setup_packet)
-               return;
-
-       if (usb_pipetype(urb->pipe) != PIPE_CONTROL)
-               return;
-
-       if (is_clear_halt_cmd(urb))
-               /* tweak clear_halt */
-                tweak_clear_halt_cmd(urb);
-
-       else if (is_set_interface_cmd(urb))
-               /* tweak set_interface */
-               tweak_set_interface_cmd(urb);
-
-       else if (is_set_configuration_cmd(urb))
-               /* tweak set_configuration */
-               tweak_set_configuration_cmd(urb);
-
-       else if (is_reset_device_cmd(urb))
-               tweak_reset_device_cmd(urb);
-       else
-               usbip_dbg_stub_rx("no need to tweak\n");
-}
-
-/*
- * stub_recv_unlink() unlinks the URB by a call to usb_unlink_urb().
- * By unlinking the urb asynchronously, stub_rx can continuously
- * process coming urbs.  Even if the urb is unlinked, its completion
- * handler will be called and stub_tx will send a return pdu.
- *
- * See also comments about unlinking strategy in vhci_hcd.c.
- */
-static int stub_recv_cmd_unlink(struct stub_device *sdev,
-                               struct usbip_header *pdu)
-{
-       int ret;
-       unsigned long flags;
-       struct stub_priv *priv;
-
-       spin_lock_irqsave(&sdev->priv_lock, flags);
-
-       list_for_each_entry(priv, &sdev->priv_init, list) {
-               if (priv->seqnum != pdu->u.cmd_unlink.seqnum)
-                       continue;
-
-               dev_info(&priv->urb->dev->dev, "unlink urb %p\n",
-                        priv->urb);
-
-               /*
-                * This matched urb is not completed yet (i.e., be in
-                * flight in usb hcd hardware/driver). Now we are
-                * cancelling it. The unlinking flag means that we are
-                * now not going to return the normal result pdu of a
-                * submission request, but going to return a result pdu
-                * of the unlink request.
-                */
-               priv->unlinking = 1;
-
-               /*
-                * In the case that unlinking flag is on, prev->seqnum
-                * is changed from the seqnum of the cancelling urb to
-                * the seqnum of the unlink request. This will be used
-                * to make the result pdu of the unlink request.
-                */
-               priv->seqnum = pdu->base.seqnum;
-
-               spin_unlock_irqrestore(&sdev->priv_lock, flags);
-
-               /*
-                * usb_unlink_urb() is now out of spinlocking to avoid
-                * spinlock recursion since stub_complete() is
-                * sometimes called in this context but not in the
-                * interrupt context.  If stub_complete() is executed
-                * before we call usb_unlink_urb(), usb_unlink_urb()
-                * will return an error value. In this case, stub_tx
-                * will return the result pdu of this unlink request
-                * though submission is completed and actual unlinking
-                * is not executed. OK?
-                */
-               /* In the above case, urb->status is not -ECONNRESET,
-                * so a driver in a client host will know the failure
-                * of the unlink request ?
-                */
-               ret = usb_unlink_urb(priv->urb);
-               if (ret != -EINPROGRESS)
-                       dev_err(&priv->urb->dev->dev,
-                               "failed to unlink a urb %p, ret %d\n",
-                               priv->urb, ret);
-
-               return 0;
-       }
-
-       usbip_dbg_stub_rx("seqnum %d is not pending\n",
-                         pdu->u.cmd_unlink.seqnum);
-
-       /*
-        * The urb of the unlink target is not found in priv_init queue. It was
-        * already completed and its results is/was going to be sent by a
-        * CMD_RET pdu. In this case, usb_unlink_urb() is not needed. We only
-        * return the completeness of this unlink request to vhci_hcd.
-        */
-       stub_enqueue_ret_unlink(sdev, pdu->base.seqnum, 0);
-
-       spin_unlock_irqrestore(&sdev->priv_lock, flags);
-
-       return 0;
-}
-
-static int valid_request(struct stub_device *sdev, struct usbip_header *pdu)
-{
-       struct usbip_device *ud = &sdev->ud;
-       int valid = 0;
-
-       if (pdu->base.devid == sdev->devid) {
-               spin_lock_irq(&ud->lock);
-               if (ud->status == SDEV_ST_USED) {
-                       /* A request is valid. */
-                       valid = 1;
-               }
-               spin_unlock_irq(&ud->lock);
-       }
-
-       return valid;
-}
-
-static struct stub_priv *stub_priv_alloc(struct stub_device *sdev,
-                                        struct usbip_header *pdu)
-{
-       struct stub_priv *priv;
-       struct usbip_device *ud = &sdev->ud;
-       unsigned long flags;
-
-       spin_lock_irqsave(&sdev->priv_lock, flags);
-
-       priv = kmem_cache_zalloc(stub_priv_cache, GFP_ATOMIC);
-       if (!priv) {
-               dev_err(&sdev->interface->dev, "alloc stub_priv\n");
-               spin_unlock_irqrestore(&sdev->priv_lock, flags);
-               usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC);
-               return NULL;
-       }
-
-       priv->seqnum = pdu->base.seqnum;
-       priv->sdev = sdev;
-
-       /*
-        * After a stub_priv is linked to a list_head,
-        * our error handler can free allocated data.
-        */
-       list_add_tail(&priv->list, &sdev->priv_init);
-
-       spin_unlock_irqrestore(&sdev->priv_lock, flags);
-
-       return priv;
-}
-
-static int get_pipe(struct stub_device *sdev, int epnum, int dir)
-{
-       struct usb_device *udev = sdev->udev;
-       struct usb_host_endpoint *ep;
-       struct usb_endpoint_descriptor *epd = NULL;
-
-       if (dir == USBIP_DIR_IN)
-               ep = udev->ep_in[epnum & 0x7f];
-       else
-               ep = udev->ep_out[epnum & 0x7f];
-       if (!ep) {
-               dev_err(&sdev->interface->dev, "no such endpoint?, %d\n",
-                       epnum);
-               BUG();
-       }
-
-       epd = &ep->desc;
-       if (usb_endpoint_xfer_control(epd)) {
-               if (dir == USBIP_DIR_OUT)
-                       return usb_sndctrlpipe(udev, epnum);
-               else
-                       return usb_rcvctrlpipe(udev, epnum);
-       }
-
-       if (usb_endpoint_xfer_bulk(epd)) {
-               if (dir == USBIP_DIR_OUT)
-                       return usb_sndbulkpipe(udev, epnum);
-               else
-                       return usb_rcvbulkpipe(udev, epnum);
-       }
-
-       if (usb_endpoint_xfer_int(epd)) {
-               if (dir == USBIP_DIR_OUT)
-                       return usb_sndintpipe(udev, epnum);
-               else
-                       return usb_rcvintpipe(udev, epnum);
-       }
-
-       if (usb_endpoint_xfer_isoc(epd)) {
-               if (dir == USBIP_DIR_OUT)
-                       return usb_sndisocpipe(udev, epnum);
-               else
-                       return usb_rcvisocpipe(udev, epnum);
-       }
-
-       /* NOT REACHED */
-       dev_err(&sdev->interface->dev, "get pipe, epnum %d\n", epnum);
-       return 0;
-}
-
-static void masking_bogus_flags(struct urb *urb)
-{
-       int                             xfertype;
-       struct usb_device               *dev;
-       struct usb_host_endpoint        *ep;
-       int                             is_out;
-       unsigned int    allowed;
-
-       if (!urb || urb->hcpriv || !urb->complete)
-               return;
-       dev = urb->dev;
-       if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED))
-               return;
-
-       ep = (usb_pipein(urb->pipe) ? dev->ep_in : dev->ep_out)
-               [usb_pipeendpoint(urb->pipe)];
-       if (!ep)
-               return;
-
-       xfertype = usb_endpoint_type(&ep->desc);
-       if (xfertype == USB_ENDPOINT_XFER_CONTROL) {
-               struct usb_ctrlrequest *setup =
-                       (struct usb_ctrlrequest *) urb->setup_packet;
-
-               if (!setup)
-                       return;
-               is_out = !(setup->bRequestType & USB_DIR_IN) ||
-                       !setup->wLength;
-       } else {
-               is_out = usb_endpoint_dir_out(&ep->desc);
-       }
-
-       /* enforce simple/standard policy */
-       allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT |
-                  URB_DIR_MASK | URB_FREE_BUFFER);
-       switch (xfertype) {
-       case USB_ENDPOINT_XFER_BULK:
-               if (is_out)
-                       allowed |= URB_ZERO_PACKET;
-               /* FALLTHROUGH */
-       case USB_ENDPOINT_XFER_CONTROL:
-               allowed |= URB_NO_FSBR; /* only affects UHCI */
-               /* FALLTHROUGH */
-       default:                        /* all non-iso endpoints */
-               if (!is_out)
-                       allowed |= URB_SHORT_NOT_OK;
-               break;
-       case USB_ENDPOINT_XFER_ISOC:
-               allowed |= URB_ISO_ASAP;
-               break;
-       }
-       urb->transfer_flags &= allowed;
-}
-
-static void stub_recv_cmd_submit(struct stub_device *sdev,
-                                struct usbip_header *pdu)
-{
-       int ret;
-       struct stub_priv *priv;
-       struct usbip_device *ud = &sdev->ud;
-       struct usb_device *udev = sdev->udev;
-       int pipe = get_pipe(sdev, pdu->base.ep, pdu->base.direction);
-
-       priv = stub_priv_alloc(sdev, pdu);
-       if (!priv)
-               return;
-
-       /* setup a urb */
-       if (usb_pipeisoc(pipe))
-               priv->urb = usb_alloc_urb(pdu->u.cmd_submit.number_of_packets,
-                                         GFP_KERNEL);
-       else
-               priv->urb = usb_alloc_urb(0, GFP_KERNEL);
-
-       if (!priv->urb) {
-               dev_err(&sdev->interface->dev, "malloc urb\n");
-               usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC);
-               return;
-       }
-
-       /* allocate urb transfer buffer, if needed */
-       if (pdu->u.cmd_submit.transfer_buffer_length > 0) {
-               priv->urb->transfer_buffer =
-                       kzalloc(pdu->u.cmd_submit.transfer_buffer_length,
-                               GFP_KERNEL);
-               if (!priv->urb->transfer_buffer) {
-                       usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC);
-                       return;
-               }
-       }
-
-       /* copy urb setup packet */
-       priv->urb->setup_packet = kmemdup(&pdu->u.cmd_submit.setup, 8,
-                                         GFP_KERNEL);
-       if (!priv->urb->setup_packet) {
-               dev_err(&sdev->interface->dev, "allocate setup_packet\n");
-               usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC);
-               return;
-       }
-
-       /* set other members from the base header of pdu */
-       priv->urb->context                = (void *) priv;
-       priv->urb->dev                    = udev;
-       priv->urb->pipe                   = pipe;
-       priv->urb->complete               = stub_complete;
-
-       usbip_pack_pdu(pdu, priv->urb, USBIP_CMD_SUBMIT, 0);
-
-
-       if (usbip_recv_xbuff(ud, priv->urb) < 0)
-               return;
-
-       if (usbip_recv_iso(ud, priv->urb) < 0)
-               return;
-
-       /* no need to submit an intercepted request, but harmless? */
-       tweak_special_requests(priv->urb);
-
-       masking_bogus_flags(priv->urb);
-       /* urb is now ready to submit */
-       ret = usb_submit_urb(priv->urb, GFP_KERNEL);
-
-       if (ret == 0)
-               usbip_dbg_stub_rx("submit urb ok, seqnum %u\n",
-                                 pdu->base.seqnum);
-       else {
-               dev_err(&sdev->interface->dev, "submit_urb error, %d\n", ret);
-               usbip_dump_header(pdu);
-               usbip_dump_urb(priv->urb);
-
-               /*
-                * Pessimistic.
-                * This connection will be discarded.
-                */
-               usbip_event_add(ud, SDEV_EVENT_ERROR_SUBMIT);
-       }
-
-       usbip_dbg_stub_rx("Leave\n");
-}
-
-/* recv a pdu */
-static void stub_rx_pdu(struct usbip_device *ud)
-{
-       int ret;
-       struct usbip_header pdu;
-       struct stub_device *sdev = container_of(ud, struct stub_device, ud);
-       struct device *dev = &sdev->udev->dev;
-
-       usbip_dbg_stub_rx("Enter\n");
-
-       memset(&pdu, 0, sizeof(pdu));
-
-       /* receive a pdu header */
-       ret = usbip_recv(ud->tcp_socket, &pdu, sizeof(pdu));
-       if (ret != sizeof(pdu)) {
-               dev_err(dev, "recv a header, %d\n", ret);
-               usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
-               return;
-       }
-
-       usbip_header_correct_endian(&pdu, 0);
-
-       if (usbip_dbg_flag_stub_rx)
-               usbip_dump_header(&pdu);
-
-       if (!valid_request(sdev, &pdu)) {
-               dev_err(dev, "recv invalid request\n");
-               usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
-               return;
-       }
-
-       switch (pdu.base.command) {
-       case USBIP_CMD_UNLINK:
-               stub_recv_cmd_unlink(sdev, &pdu);
-               break;
-
-       case USBIP_CMD_SUBMIT:
-               stub_recv_cmd_submit(sdev, &pdu);
-               break;
-
-       default:
-               /* NOTREACHED */
-               dev_err(dev, "unknown pdu\n");
-               usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
-               break;
-       }
-}
-
-int stub_rx_loop(void *data)
-{
-       struct usbip_device *ud = data;
-
-       while (!kthread_should_stop()) {
-               if (usbip_event_happened(ud))
-                       break;
-
-               stub_rx_pdu(ud);
-       }
-
-       return 0;
-}
diff --git a/drivers/staging/usbip/stub_tx.c b/drivers/staging/usbip/stub_tx.c
deleted file mode 100644 (file)
index dbcabc9..0000000
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
- * Copyright (C) 2003-2008 Takahiro Hirofuchi
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#include <linux/kthread.h>
-#include <linux/socket.h>
-
-#include "usbip_common.h"
-#include "stub.h"
-
-static void stub_free_priv_and_urb(struct stub_priv *priv)
-{
-       struct urb *urb = priv->urb;
-
-       kfree(urb->setup_packet);
-       kfree(urb->transfer_buffer);
-       list_del(&priv->list);
-       kmem_cache_free(stub_priv_cache, priv);
-       usb_free_urb(urb);
-}
-
-/* be in spin_lock_irqsave(&sdev->priv_lock, flags) */
-void stub_enqueue_ret_unlink(struct stub_device *sdev, __u32 seqnum,
-                            __u32 status)
-{
-       struct stub_unlink *unlink;
-
-       unlink = kzalloc(sizeof(struct stub_unlink), GFP_ATOMIC);
-       if (!unlink) {
-               usbip_event_add(&sdev->ud, VDEV_EVENT_ERROR_MALLOC);
-               return;
-       }
-
-       unlink->seqnum = seqnum;
-       unlink->status = status;
-
-       list_add_tail(&unlink->list, &sdev->unlink_tx);
-}
-
-/**
- * stub_complete - completion handler of a usbip urb
- * @urb: pointer to the urb completed
- *
- * When a urb has completed, the USB core driver calls this function mostly in
- * the interrupt context. To return the result of a urb, the completed urb is
- * linked to the pending list of returning.
- *
- */
-void stub_complete(struct urb *urb)
-{
-       struct stub_priv *priv = (struct stub_priv *) urb->context;
-       struct stub_device *sdev = priv->sdev;
-       unsigned long flags;
-
-       usbip_dbg_stub_tx("complete! status %d\n", urb->status);
-
-       switch (urb->status) {
-       case 0:
-               /* OK */
-               break;
-       case -ENOENT:
-               dev_info(&urb->dev->dev,
-                        "stopped by a call to usb_kill_urb() because of cleaning up a virtual connection\n");
-               return;
-       case -ECONNRESET:
-               dev_info(&urb->dev->dev,
-                        "unlinked by a call to usb_unlink_urb()\n");
-               break;
-       case -EPIPE:
-               dev_info(&urb->dev->dev, "endpoint %d is stalled\n",
-                        usb_pipeendpoint(urb->pipe));
-               break;
-       case -ESHUTDOWN:
-               dev_info(&urb->dev->dev, "device removed?\n");
-               break;
-       default:
-               dev_info(&urb->dev->dev,
-                        "urb completion with non-zero status %d\n",
-                        urb->status);
-               break;
-       }
-
-       /* link a urb to the queue of tx. */
-       spin_lock_irqsave(&sdev->priv_lock, flags);
-       if (priv->unlinking) {
-               stub_enqueue_ret_unlink(sdev, priv->seqnum, urb->status);
-               stub_free_priv_and_urb(priv);
-       } else {
-               list_move_tail(&priv->list, &sdev->priv_tx);
-       }
-       spin_unlock_irqrestore(&sdev->priv_lock, flags);
-
-       /* wake up tx_thread */
-       wake_up(&sdev->tx_waitq);
-}
-
-static inline void setup_base_pdu(struct usbip_header_basic *base,
-                                 __u32 command, __u32 seqnum)
-{
-       base->command   = command;
-       base->seqnum    = seqnum;
-       base->devid     = 0;
-       base->ep        = 0;
-       base->direction = 0;
-}
-
-static void setup_ret_submit_pdu(struct usbip_header *rpdu, struct urb *urb)
-{
-       struct stub_priv *priv = (struct stub_priv *) urb->context;
-
-       setup_base_pdu(&rpdu->base, USBIP_RET_SUBMIT, priv->seqnum);
-       usbip_pack_pdu(rpdu, urb, USBIP_RET_SUBMIT, 1);
-}
-
-static void setup_ret_unlink_pdu(struct usbip_header *rpdu,
-                                struct stub_unlink *unlink)
-{
-       setup_base_pdu(&rpdu->base, USBIP_RET_UNLINK, unlink->seqnum);
-       rpdu->u.ret_unlink.status = unlink->status;
-}
-
-static struct stub_priv *dequeue_from_priv_tx(struct stub_device *sdev)
-{
-       unsigned long flags;
-       struct stub_priv *priv, *tmp;
-
-       spin_lock_irqsave(&sdev->priv_lock, flags);
-
-       list_for_each_entry_safe(priv, tmp, &sdev->priv_tx, list) {
-               list_move_tail(&priv->list, &sdev->priv_free);
-               spin_unlock_irqrestore(&sdev->priv_lock, flags);
-               return priv;
-       }
-
-       spin_unlock_irqrestore(&sdev->priv_lock, flags);
-
-       return NULL;
-}
-
-static int stub_send_ret_submit(struct stub_device *sdev)
-{
-       unsigned long flags;
-       struct stub_priv *priv, *tmp;
-
-       struct msghdr msg;
-       size_t txsize;
-
-       size_t total_size = 0;
-
-       while ((priv = dequeue_from_priv_tx(sdev)) != NULL) {
-               int ret;
-               struct urb *urb = priv->urb;
-               struct usbip_header pdu_header;
-               struct usbip_iso_packet_descriptor *iso_buffer = NULL;
-               struct kvec *iov = NULL;
-               int iovnum = 0;
-
-               txsize = 0;
-               memset(&pdu_header, 0, sizeof(pdu_header));
-               memset(&msg, 0, sizeof(msg));
-
-               if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
-                       iovnum = 2 + urb->number_of_packets;
-               else
-                       iovnum = 2;
-
-               iov = kcalloc(iovnum, sizeof(struct kvec), GFP_KERNEL);
-
-               if (!iov) {
-                       usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_MALLOC);
-                       return -1;
-               }
-
-               iovnum = 0;
-
-               /* 1. setup usbip_header */
-               setup_ret_submit_pdu(&pdu_header, urb);
-               usbip_dbg_stub_tx("setup txdata seqnum: %d urb: %p\n",
-                                 pdu_header.base.seqnum, urb);
-               usbip_header_correct_endian(&pdu_header, 1);
-
-               iov[iovnum].iov_base = &pdu_header;
-               iov[iovnum].iov_len  = sizeof(pdu_header);
-               iovnum++;
-               txsize += sizeof(pdu_header);
-
-               /* 2. setup transfer buffer */
-               if (usb_pipein(urb->pipe) &&
-                   usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS &&
-                   urb->actual_length > 0) {
-                       iov[iovnum].iov_base = urb->transfer_buffer;
-                       iov[iovnum].iov_len  = urb->actual_length;
-                       iovnum++;
-                       txsize += urb->actual_length;
-               } else if (usb_pipein(urb->pipe) &&
-                          usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
-                       /*
-                        * For isochronous packets: actual length is the sum of
-                        * the actual length of the individual, packets, but as
-                        * the packet offsets are not changed there will be
-                        * padding between the packets. To optimally use the
-                        * bandwidth the padding is not transmitted.
-                        */
-
-                       int i;
-
-                       for (i = 0; i < urb->number_of_packets; i++) {
-                               iov[iovnum].iov_base = urb->transfer_buffer +
-                                       urb->iso_frame_desc[i].offset;
-                               iov[iovnum].iov_len =
-                                       urb->iso_frame_desc[i].actual_length;
-                               iovnum++;
-                               txsize += urb->iso_frame_desc[i].actual_length;
-                       }
-
-                       if (txsize != sizeof(pdu_header) + urb->actual_length) {
-                               dev_err(&sdev->interface->dev,
-                                       "actual length of urb %d does not match iso packet sizes %zu\n",
-                                       urb->actual_length,
-                                       txsize-sizeof(pdu_header));
-                               kfree(iov);
-                               usbip_event_add(&sdev->ud,
-                                               SDEV_EVENT_ERROR_TCP);
-                          return -1;
-                       }
-               }
-
-               /* 3. setup iso_packet_descriptor */
-               if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
-                       ssize_t len = 0;
-
-                       iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len);
-                       if (!iso_buffer) {
-                               usbip_event_add(&sdev->ud,
-                                               SDEV_EVENT_ERROR_MALLOC);
-                               kfree(iov);
-                               return -1;
-                       }
-
-                       iov[iovnum].iov_base = iso_buffer;
-                       iov[iovnum].iov_len  = len;
-                       txsize += len;
-                       iovnum++;
-               }
-
-               ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg,
-                                               iov,  iovnum, txsize);
-               if (ret != txsize) {
-                       dev_err(&sdev->interface->dev,
-                               "sendmsg failed!, retval %d for %zd\n",
-                               ret, txsize);
-                       kfree(iov);
-                       kfree(iso_buffer);
-                       usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP);
-                       return -1;
-               }
-
-               kfree(iov);
-               kfree(iso_buffer);
-
-               total_size += txsize;
-       }
-
-       spin_lock_irqsave(&sdev->priv_lock, flags);
-       list_for_each_entry_safe(priv, tmp, &sdev->priv_free, list) {
-               stub_free_priv_and_urb(priv);
-       }
-       spin_unlock_irqrestore(&sdev->priv_lock, flags);
-
-       return total_size;
-}
-
-static struct stub_unlink *dequeue_from_unlink_tx(struct stub_device *sdev)
-{
-       unsigned long flags;
-       struct stub_unlink *unlink, *tmp;
-
-       spin_lock_irqsave(&sdev->priv_lock, flags);
-
-       list_for_each_entry_safe(unlink, tmp, &sdev->unlink_tx, list) {
-               list_move_tail(&unlink->list, &sdev->unlink_free);
-               spin_unlock_irqrestore(&sdev->priv_lock, flags);
-               return unlink;
-       }
-
-       spin_unlock_irqrestore(&sdev->priv_lock, flags);
-
-       return NULL;
-}
-
-static int stub_send_ret_unlink(struct stub_device *sdev)
-{
-       unsigned long flags;
-       struct stub_unlink *unlink, *tmp;
-
-       struct msghdr msg;
-       struct kvec iov[1];
-       size_t txsize;
-
-       size_t total_size = 0;
-
-       while ((unlink = dequeue_from_unlink_tx(sdev)) != NULL) {
-               int ret;
-               struct usbip_header pdu_header;
-
-               txsize = 0;
-               memset(&pdu_header, 0, sizeof(pdu_header));
-               memset(&msg, 0, sizeof(msg));
-               memset(&iov, 0, sizeof(iov));
-
-               usbip_dbg_stub_tx("setup ret unlink %lu\n", unlink->seqnum);
-
-               /* 1. setup usbip_header */
-               setup_ret_unlink_pdu(&pdu_header, unlink);
-               usbip_header_correct_endian(&pdu_header, 1);
-
-               iov[0].iov_base = &pdu_header;
-               iov[0].iov_len  = sizeof(pdu_header);
-               txsize += sizeof(pdu_header);
-
-               ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov,
-                                    1, txsize);
-               if (ret != txsize) {
-                       dev_err(&sdev->interface->dev,
-                               "sendmsg failed!, retval %d for %zd\n",
-                               ret, txsize);
-                       usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP);
-                       return -1;
-               }
-
-               usbip_dbg_stub_tx("send txdata\n");
-               total_size += txsize;
-       }
-
-       spin_lock_irqsave(&sdev->priv_lock, flags);
-
-       list_for_each_entry_safe(unlink, tmp, &sdev->unlink_free, list) {
-               list_del(&unlink->list);
-               kfree(unlink);
-       }
-
-       spin_unlock_irqrestore(&sdev->priv_lock, flags);
-
-       return total_size;
-}
-
-int stub_tx_loop(void *data)
-{
-       struct usbip_device *ud = data;
-       struct stub_device *sdev = container_of(ud, struct stub_device, ud);
-
-       while (!kthread_should_stop()) {
-               if (usbip_event_happened(ud))
-                       break;
-
-               /*
-                * send_ret_submit comes earlier than send_ret_unlink.  stub_rx
-                * looks at only priv_init queue. If the completion of a URB is
-                * earlier than the receive of CMD_UNLINK, priv is moved to
-                * priv_tx queue and stub_rx does not find the target priv. In
-                * this case, vhci_rx receives the result of the submit request
-                * and then receives the result of the unlink request. The
-                * result of the submit is given back to the usbcore as the
-                * completion of the unlink request. The request of the
-                * unlink is ignored. This is ok because a driver who calls
-                * usb_unlink_urb() understands the unlink was too late by
-                * getting the status of the given-backed URB which has the
-                * status of usb_submit_urb().
-                */
-               if (stub_send_ret_submit(sdev) < 0)
-                       break;
-
-               if (stub_send_ret_unlink(sdev) < 0)
-                       break;
-
-               wait_event_interruptible(sdev->tx_waitq,
-                                        (!list_empty(&sdev->priv_tx) ||
-                                         !list_empty(&sdev->unlink_tx) ||
-                                         kthread_should_stop()));
-       }
-
-       return 0;
-}
diff --git a/drivers/staging/usbip/uapi/usbip.h b/drivers/staging/usbip/uapi/usbip.h
deleted file mode 100644 (file)
index fa5db30..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *     usbip.h
- *
- *     USBIP uapi defines and function prototypes etc.
-*/
-
-#ifndef _UAPI_LINUX_USBIP_H
-#define _UAPI_LINUX_USBIP_H
-
-/* usbip device status - exported in usbip device sysfs status */
-enum usbip_device_status {
-       /* sdev is available. */
-       SDEV_ST_AVAILABLE = 0x01,
-       /* sdev is now used. */
-       SDEV_ST_USED,
-       /* sdev is unusable because of a fatal error. */
-       SDEV_ST_ERROR,
-
-       /* vdev does not connect a remote device. */
-       VDEV_ST_NULL,
-       /* vdev is used, but the USB address is not assigned yet */
-       VDEV_ST_NOTASSIGNED,
-       VDEV_ST_USED,
-       VDEV_ST_ERROR
-};
-#endif /* _UAPI_LINUX_USBIP_H */
diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c
deleted file mode 100644 (file)
index facaaf0..0000000
+++ /dev/null
@@ -1,776 +0,0 @@
-/*
- * Copyright (C) 2003-2008 Takahiro Hirofuchi
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#include <asm/byteorder.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <net/sock.h>
-
-#include "usbip_common.h"
-
-#define DRIVER_AUTHOR "Takahiro Hirofuchi <hirofuchi@users.sourceforge.net>"
-#define DRIVER_DESC "USB/IP Core"
-
-#ifdef CONFIG_USBIP_DEBUG
-unsigned long usbip_debug_flag = 0xffffffff;
-#else
-unsigned long usbip_debug_flag;
-#endif
-EXPORT_SYMBOL_GPL(usbip_debug_flag);
-module_param(usbip_debug_flag, ulong, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(usbip_debug_flag, "debug flags (defined in usbip_common.h)");
-
-/* FIXME */
-struct device_attribute dev_attr_usbip_debug;
-EXPORT_SYMBOL_GPL(dev_attr_usbip_debug);
-
-static ssize_t usbip_debug_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       return sprintf(buf, "%lx\n", usbip_debug_flag);
-}
-
-static ssize_t usbip_debug_store(struct device *dev,
-                                struct device_attribute *attr, const char *buf,
-                                size_t count)
-{
-       if (sscanf(buf, "%lx", &usbip_debug_flag) != 1)
-               return -EINVAL;
-       return count;
-}
-DEVICE_ATTR_RW(usbip_debug);
-
-static void usbip_dump_buffer(char *buff, int bufflen)
-{
-       print_hex_dump(KERN_DEBUG, "usbip-core", DUMP_PREFIX_OFFSET, 16, 4,
-                      buff, bufflen, false);
-}
-
-static void usbip_dump_pipe(unsigned int p)
-{
-       unsigned char type = usb_pipetype(p);
-       unsigned char ep   = usb_pipeendpoint(p);
-       unsigned char dev  = usb_pipedevice(p);
-       unsigned char dir  = usb_pipein(p);
-
-       pr_debug("dev(%d) ep(%d) [%s] ", dev, ep, dir ? "IN" : "OUT");
-
-       switch (type) {
-       case PIPE_ISOCHRONOUS:
-               pr_debug("ISO\n");
-               break;
-       case PIPE_INTERRUPT:
-               pr_debug("INT\n");
-               break;
-       case PIPE_CONTROL:
-               pr_debug("CTRL\n");
-               break;
-       case PIPE_BULK:
-               pr_debug("BULK\n");
-               break;
-       default:
-               pr_debug("ERR\n");
-               break;
-       }
-}
-
-static void usbip_dump_usb_device(struct usb_device *udev)
-{
-       struct device *dev = &udev->dev;
-       int i;
-
-       dev_dbg(dev, "       devnum(%d) devpath(%s) usb speed(%s)",
-               udev->devnum, udev->devpath, usb_speed_string(udev->speed));
-
-       pr_debug("tt %p, ttport %d\n", udev->tt, udev->ttport);
-
-       dev_dbg(dev, "                    ");
-       for (i = 0; i < 16; i++)
-               pr_debug(" %2u", i);
-       pr_debug("\n");
-
-       dev_dbg(dev, "       toggle0(IN) :");
-       for (i = 0; i < 16; i++)
-               pr_debug(" %2u", (udev->toggle[0] & (1 << i)) ? 1 : 0);
-       pr_debug("\n");
-
-       dev_dbg(dev, "       toggle1(OUT):");
-       for (i = 0; i < 16; i++)
-               pr_debug(" %2u", (udev->toggle[1] & (1 << i)) ? 1 : 0);
-       pr_debug("\n");
-
-       dev_dbg(dev, "       epmaxp_in   :");
-       for (i = 0; i < 16; i++) {
-               if (udev->ep_in[i])
-                       pr_debug(" %2u",
-                           le16_to_cpu(udev->ep_in[i]->desc.wMaxPacketSize));
-       }
-       pr_debug("\n");
-
-       dev_dbg(dev, "       epmaxp_out  :");
-       for (i = 0; i < 16; i++) {
-               if (udev->ep_out[i])
-                       pr_debug(" %2u",
-                           le16_to_cpu(udev->ep_out[i]->desc.wMaxPacketSize));
-       }
-       pr_debug("\n");
-
-       dev_dbg(dev, "parent %p, bus %p\n", udev->parent, udev->bus);
-
-       dev_dbg(dev,
-               "descriptor %p, config %p, actconfig %p, rawdescriptors %p\n",
-               &udev->descriptor, udev->config,
-               udev->actconfig, udev->rawdescriptors);
-
-       dev_dbg(dev, "have_langid %d, string_langid %d\n",
-               udev->have_langid, udev->string_langid);
-
-       dev_dbg(dev, "maxchild %d\n", udev->maxchild);
-}
-
-static void usbip_dump_request_type(__u8 rt)
-{
-       switch (rt & USB_RECIP_MASK) {
-       case USB_RECIP_DEVICE:
-               pr_debug("DEVICE");
-               break;
-       case USB_RECIP_INTERFACE:
-               pr_debug("INTERF");
-               break;
-       case USB_RECIP_ENDPOINT:
-               pr_debug("ENDPOI");
-               break;
-       case USB_RECIP_OTHER:
-               pr_debug("OTHER ");
-               break;
-       default:
-               pr_debug("------");
-               break;
-       }
-}
-
-static void usbip_dump_usb_ctrlrequest(struct usb_ctrlrequest *cmd)
-{
-       if (!cmd) {
-               pr_debug("       : null pointer\n");
-               return;
-       }
-
-       pr_debug("       ");
-       pr_debug("bRequestType(%02X) bRequest(%02X) wValue(%04X) wIndex(%04X) wLength(%04X) ",
-                cmd->bRequestType, cmd->bRequest,
-                cmd->wValue, cmd->wIndex, cmd->wLength);
-       pr_debug("\n       ");
-
-       if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
-               pr_debug("STANDARD ");
-               switch (cmd->bRequest) {
-               case USB_REQ_GET_STATUS:
-                       pr_debug("GET_STATUS\n");
-                       break;
-               case USB_REQ_CLEAR_FEATURE:
-                       pr_debug("CLEAR_FEAT\n");
-                       break;
-               case USB_REQ_SET_FEATURE:
-                       pr_debug("SET_FEAT\n");
-                       break;
-               case USB_REQ_SET_ADDRESS:
-                       pr_debug("SET_ADDRRS\n");
-                       break;
-               case USB_REQ_GET_DESCRIPTOR:
-                       pr_debug("GET_DESCRI\n");
-                       break;
-               case USB_REQ_SET_DESCRIPTOR:
-                       pr_debug("SET_DESCRI\n");
-                       break;
-               case USB_REQ_GET_CONFIGURATION:
-                       pr_debug("GET_CONFIG\n");
-                       break;
-               case USB_REQ_SET_CONFIGURATION:
-                       pr_debug("SET_CONFIG\n");
-                       break;
-               case USB_REQ_GET_INTERFACE:
-                       pr_debug("GET_INTERF\n");
-                       break;
-               case USB_REQ_SET_INTERFACE:
-                       pr_debug("SET_INTERF\n");
-                       break;
-               case USB_REQ_SYNCH_FRAME:
-                       pr_debug("SYNC_FRAME\n");
-                       break;
-               default:
-                       pr_debug("REQ(%02X)\n", cmd->bRequest);
-                       break;
-               }
-               usbip_dump_request_type(cmd->bRequestType);
-       } else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS) {
-               pr_debug("CLASS\n");
-       } else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_VENDOR) {
-               pr_debug("VENDOR\n");
-       } else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_RESERVED) {
-               pr_debug("RESERVED\n");
-       }
-}
-
-void usbip_dump_urb(struct urb *urb)
-{
-       struct device *dev;
-
-       if (!urb) {
-               pr_debug("urb: null pointer!!\n");
-               return;
-       }
-
-       if (!urb->dev) {
-               pr_debug("urb->dev: null pointer!!\n");
-               return;
-       }
-
-       dev = &urb->dev->dev;
-
-       dev_dbg(dev, "   urb                   :%p\n", urb);
-       dev_dbg(dev, "   dev                   :%p\n", urb->dev);
-
-       usbip_dump_usb_device(urb->dev);
-
-       dev_dbg(dev, "   pipe                  :%08x ", urb->pipe);
-
-       usbip_dump_pipe(urb->pipe);
-
-       dev_dbg(dev, "   status                :%d\n", urb->status);
-       dev_dbg(dev, "   transfer_flags        :%08X\n", urb->transfer_flags);
-       dev_dbg(dev, "   transfer_buffer       :%p\n", urb->transfer_buffer);
-       dev_dbg(dev, "   transfer_buffer_length:%d\n",
-                                               urb->transfer_buffer_length);
-       dev_dbg(dev, "   actual_length         :%d\n", urb->actual_length);
-       dev_dbg(dev, "   setup_packet          :%p\n", urb->setup_packet);
-
-       if (urb->setup_packet && usb_pipetype(urb->pipe) == PIPE_CONTROL)
-               usbip_dump_usb_ctrlrequest(
-                       (struct usb_ctrlrequest *)urb->setup_packet);
-
-       dev_dbg(dev, "   start_frame           :%d\n", urb->start_frame);
-       dev_dbg(dev, "   number_of_packets     :%d\n", urb->number_of_packets);
-       dev_dbg(dev, "   interval              :%d\n", urb->interval);
-       dev_dbg(dev, "   error_count           :%d\n", urb->error_count);
-       dev_dbg(dev, "   context               :%p\n", urb->context);
-       dev_dbg(dev, "   complete              :%p\n", urb->complete);
-}
-EXPORT_SYMBOL_GPL(usbip_dump_urb);
-
-void usbip_dump_header(struct usbip_header *pdu)
-{
-       pr_debug("BASE: cmd %u seq %u devid %u dir %u ep %u\n",
-                pdu->base.command,
-                pdu->base.seqnum,
-                pdu->base.devid,
-                pdu->base.direction,
-                pdu->base.ep);
-
-       switch (pdu->base.command) {
-       case USBIP_CMD_SUBMIT:
-               pr_debug("USBIP_CMD_SUBMIT: x_flags %u x_len %u sf %u #p %d iv %d\n",
-                        pdu->u.cmd_submit.transfer_flags,
-                        pdu->u.cmd_submit.transfer_buffer_length,
-                        pdu->u.cmd_submit.start_frame,
-                        pdu->u.cmd_submit.number_of_packets,
-                        pdu->u.cmd_submit.interval);
-               break;
-       case USBIP_CMD_UNLINK:
-               pr_debug("USBIP_CMD_UNLINK: seq %u\n",
-                        pdu->u.cmd_unlink.seqnum);
-               break;
-       case USBIP_RET_SUBMIT:
-               pr_debug("USBIP_RET_SUBMIT: st %d al %u sf %d #p %d ec %d\n",
-                        pdu->u.ret_submit.status,
-                        pdu->u.ret_submit.actual_length,
-                        pdu->u.ret_submit.start_frame,
-                        pdu->u.ret_submit.number_of_packets,
-                        pdu->u.ret_submit.error_count);
-               break;
-       case USBIP_RET_UNLINK:
-               pr_debug("USBIP_RET_UNLINK: status %d\n",
-                        pdu->u.ret_unlink.status);
-               break;
-       default:
-               /* NOT REACHED */
-               pr_err("unknown command\n");
-               break;
-       }
-}
-EXPORT_SYMBOL_GPL(usbip_dump_header);
-
-/* Receive data over TCP/IP. */
-int usbip_recv(struct socket *sock, void *buf, int size)
-{
-       int result;
-       struct msghdr msg;
-       struct kvec iov;
-       int total = 0;
-
-       /* for blocks of if (usbip_dbg_flag_xmit) */
-       char *bp = buf;
-       int osize = size;
-
-       usbip_dbg_xmit("enter\n");
-
-       if (!sock || !buf || !size) {
-               pr_err("invalid arg, sock %p buff %p size %d\n", sock, buf,
-                      size);
-               return -EINVAL;
-       }
-
-       do {
-               sock->sk->sk_allocation = GFP_NOIO;
-               iov.iov_base    = buf;
-               iov.iov_len     = size;
-               msg.msg_name    = NULL;
-               msg.msg_namelen = 0;
-               msg.msg_control = NULL;
-               msg.msg_controllen = 0;
-               msg.msg_flags      = MSG_NOSIGNAL;
-
-               result = kernel_recvmsg(sock, &msg, &iov, 1, size, MSG_WAITALL);
-               if (result <= 0) {
-                       pr_debug("receive sock %p buf %p size %u ret %d total %d\n",
-                                sock, buf, size, result, total);
-                       goto err;
-               }
-
-               size -= result;
-               buf += result;
-               total += result;
-       } while (size > 0);
-
-       if (usbip_dbg_flag_xmit) {
-               if (!in_interrupt())
-                       pr_debug("%-10s:", current->comm);
-               else
-                       pr_debug("interrupt  :");
-
-               pr_debug("receiving....\n");
-               usbip_dump_buffer(bp, osize);
-               pr_debug("received, osize %d ret %d size %d total %d\n",
-                        osize, result, size, total);
-       }
-
-       return total;
-
-err:
-       return result;
-}
-EXPORT_SYMBOL_GPL(usbip_recv);
-
-/* there may be more cases to tweak the flags. */
-static unsigned int tweak_transfer_flags(unsigned int flags)
-{
-       flags &= ~URB_NO_TRANSFER_DMA_MAP;
-       return flags;
-}
-
-static void usbip_pack_cmd_submit(struct usbip_header *pdu, struct urb *urb,
-                                 int pack)
-{
-       struct usbip_header_cmd_submit *spdu = &pdu->u.cmd_submit;
-
-       /*
-        * Some members are not still implemented in usbip. I hope this issue
-        * will be discussed when usbip is ported to other operating systems.
-        */
-       if (pack) {
-               spdu->transfer_flags =
-                       tweak_transfer_flags(urb->transfer_flags);
-               spdu->transfer_buffer_length    = urb->transfer_buffer_length;
-               spdu->start_frame               = urb->start_frame;
-               spdu->number_of_packets         = urb->number_of_packets;
-               spdu->interval                  = urb->interval;
-       } else  {
-               urb->transfer_flags         = spdu->transfer_flags;
-               urb->transfer_buffer_length = spdu->transfer_buffer_length;
-               urb->start_frame            = spdu->start_frame;
-               urb->number_of_packets      = spdu->number_of_packets;
-               urb->interval               = spdu->interval;
-       }
-}
-
-static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb,
-                                 int pack)
-{
-       struct usbip_header_ret_submit *rpdu = &pdu->u.ret_submit;
-
-       if (pack) {
-               rpdu->status            = urb->status;
-               rpdu->actual_length     = urb->actual_length;
-               rpdu->start_frame       = urb->start_frame;
-               rpdu->number_of_packets = urb->number_of_packets;
-               rpdu->error_count       = urb->error_count;
-       } else {
-               urb->status             = rpdu->status;
-               urb->actual_length      = rpdu->actual_length;
-               urb->start_frame        = rpdu->start_frame;
-               urb->number_of_packets = rpdu->number_of_packets;
-               urb->error_count        = rpdu->error_count;
-       }
-}
-
-void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd,
-                   int pack)
-{
-       switch (cmd) {
-       case USBIP_CMD_SUBMIT:
-               usbip_pack_cmd_submit(pdu, urb, pack);
-               break;
-       case USBIP_RET_SUBMIT:
-               usbip_pack_ret_submit(pdu, urb, pack);
-               break;
-       default:
-               /* NOT REACHED */
-               pr_err("unknown command\n");
-               break;
-       }
-}
-EXPORT_SYMBOL_GPL(usbip_pack_pdu);
-
-static void correct_endian_basic(struct usbip_header_basic *base, int send)
-{
-       if (send) {
-               base->command   = cpu_to_be32(base->command);
-               base->seqnum    = cpu_to_be32(base->seqnum);
-               base->devid     = cpu_to_be32(base->devid);
-               base->direction = cpu_to_be32(base->direction);
-               base->ep        = cpu_to_be32(base->ep);
-       } else {
-               base->command   = be32_to_cpu(base->command);
-               base->seqnum    = be32_to_cpu(base->seqnum);
-               base->devid     = be32_to_cpu(base->devid);
-               base->direction = be32_to_cpu(base->direction);
-               base->ep        = be32_to_cpu(base->ep);
-       }
-}
-
-static void correct_endian_cmd_submit(struct usbip_header_cmd_submit *pdu,
-                                     int send)
-{
-       if (send) {
-               pdu->transfer_flags = cpu_to_be32(pdu->transfer_flags);
-
-               cpu_to_be32s(&pdu->transfer_buffer_length);
-               cpu_to_be32s(&pdu->start_frame);
-               cpu_to_be32s(&pdu->number_of_packets);
-               cpu_to_be32s(&pdu->interval);
-       } else {
-               pdu->transfer_flags = be32_to_cpu(pdu->transfer_flags);
-
-               be32_to_cpus(&pdu->transfer_buffer_length);
-               be32_to_cpus(&pdu->start_frame);
-               be32_to_cpus(&pdu->number_of_packets);
-               be32_to_cpus(&pdu->interval);
-       }
-}
-
-static void correct_endian_ret_submit(struct usbip_header_ret_submit *pdu,
-                                     int send)
-{
-       if (send) {
-               cpu_to_be32s(&pdu->status);
-               cpu_to_be32s(&pdu->actual_length);
-               cpu_to_be32s(&pdu->start_frame);
-               cpu_to_be32s(&pdu->number_of_packets);
-               cpu_to_be32s(&pdu->error_count);
-       } else {
-               be32_to_cpus(&pdu->status);
-               be32_to_cpus(&pdu->actual_length);
-               be32_to_cpus(&pdu->start_frame);
-               be32_to_cpus(&pdu->number_of_packets);
-               be32_to_cpus(&pdu->error_count);
-       }
-}
-
-static void correct_endian_cmd_unlink(struct usbip_header_cmd_unlink *pdu,
-                                     int send)
-{
-       if (send)
-               pdu->seqnum = cpu_to_be32(pdu->seqnum);
-       else
-               pdu->seqnum = be32_to_cpu(pdu->seqnum);
-}
-
-static void correct_endian_ret_unlink(struct usbip_header_ret_unlink *pdu,
-                                     int send)
-{
-       if (send)
-               cpu_to_be32s(&pdu->status);
-       else
-               be32_to_cpus(&pdu->status);
-}
-
-void usbip_header_correct_endian(struct usbip_header *pdu, int send)
-{
-       __u32 cmd = 0;
-
-       if (send)
-               cmd = pdu->base.command;
-
-       correct_endian_basic(&pdu->base, send);
-
-       if (!send)
-               cmd = pdu->base.command;
-
-       switch (cmd) {
-       case USBIP_CMD_SUBMIT:
-               correct_endian_cmd_submit(&pdu->u.cmd_submit, send);
-               break;
-       case USBIP_RET_SUBMIT:
-               correct_endian_ret_submit(&pdu->u.ret_submit, send);
-               break;
-       case USBIP_CMD_UNLINK:
-               correct_endian_cmd_unlink(&pdu->u.cmd_unlink, send);
-               break;
-       case USBIP_RET_UNLINK:
-               correct_endian_ret_unlink(&pdu->u.ret_unlink, send);
-               break;
-       default:
-               /* NOT REACHED */
-               pr_err("unknown command\n");
-               break;
-       }
-}
-EXPORT_SYMBOL_GPL(usbip_header_correct_endian);
-
-static void usbip_iso_packet_correct_endian(
-               struct usbip_iso_packet_descriptor *iso, int send)
-{
-       /* does not need all members. but copy all simply. */
-       if (send) {
-               iso->offset     = cpu_to_be32(iso->offset);
-               iso->length     = cpu_to_be32(iso->length);
-               iso->status     = cpu_to_be32(iso->status);
-               iso->actual_length = cpu_to_be32(iso->actual_length);
-       } else {
-               iso->offset     = be32_to_cpu(iso->offset);
-               iso->length     = be32_to_cpu(iso->length);
-               iso->status     = be32_to_cpu(iso->status);
-               iso->actual_length = be32_to_cpu(iso->actual_length);
-       }
-}
-
-static void usbip_pack_iso(struct usbip_iso_packet_descriptor *iso,
-                          struct usb_iso_packet_descriptor *uiso, int pack)
-{
-       if (pack) {
-               iso->offset             = uiso->offset;
-               iso->length             = uiso->length;
-               iso->status             = uiso->status;
-               iso->actual_length      = uiso->actual_length;
-       } else {
-               uiso->offset            = iso->offset;
-               uiso->length            = iso->length;
-               uiso->status            = iso->status;
-               uiso->actual_length     = iso->actual_length;
-       }
-}
-
-/* must free buffer */
-struct usbip_iso_packet_descriptor*
-usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen)
-{
-       struct usbip_iso_packet_descriptor *iso;
-       int np = urb->number_of_packets;
-       ssize_t size = np * sizeof(*iso);
-       int i;
-
-       iso = kzalloc(size, GFP_KERNEL);
-       if (!iso)
-               return NULL;
-
-       for (i = 0; i < np; i++) {
-               usbip_pack_iso(&iso[i], &urb->iso_frame_desc[i], 1);
-               usbip_iso_packet_correct_endian(&iso[i], 1);
-       }
-
-       *bufflen = size;
-
-       return iso;
-}
-EXPORT_SYMBOL_GPL(usbip_alloc_iso_desc_pdu);
-
-/* some members of urb must be substituted before. */
-int usbip_recv_iso(struct usbip_device *ud, struct urb *urb)
-{
-       void *buff;
-       struct usbip_iso_packet_descriptor *iso;
-       int np = urb->number_of_packets;
-       int size = np * sizeof(*iso);
-       int i;
-       int ret;
-       int total_length = 0;
-
-       if (!usb_pipeisoc(urb->pipe))
-               return 0;
-
-       /* my Bluetooth dongle gets ISO URBs which are np = 0 */
-       if (np == 0)
-               return 0;
-
-       buff = kzalloc(size, GFP_KERNEL);
-       if (!buff)
-               return -ENOMEM;
-
-       ret = usbip_recv(ud->tcp_socket, buff, size);
-       if (ret != size) {
-               dev_err(&urb->dev->dev, "recv iso_frame_descriptor, %d\n",
-                       ret);
-               kfree(buff);
-
-               if (ud->side == USBIP_STUB)
-                       usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
-               else
-                       usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
-
-               return -EPIPE;
-       }
-
-       iso = (struct usbip_iso_packet_descriptor *) buff;
-       for (i = 0; i < np; i++) {
-               usbip_iso_packet_correct_endian(&iso[i], 0);
-               usbip_pack_iso(&iso[i], &urb->iso_frame_desc[i], 0);
-               total_length += urb->iso_frame_desc[i].actual_length;
-       }
-
-       kfree(buff);
-
-       if (total_length != urb->actual_length) {
-               dev_err(&urb->dev->dev,
-                       "total length of iso packets %d not equal to actual length of buffer %d\n",
-                       total_length, urb->actual_length);
-
-               if (ud->side == USBIP_STUB)
-                       usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
-               else
-                       usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
-
-               return -EPIPE;
-       }
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(usbip_recv_iso);
-
-/*
- * This functions restores the padding which was removed for optimizing
- * the bandwidth during transfer over tcp/ip
- *
- * buffer and iso packets need to be stored and be in propeper endian in urb
- * before calling this function
- */
-void usbip_pad_iso(struct usbip_device *ud, struct urb *urb)
-{
-       int np = urb->number_of_packets;
-       int i;
-       int actualoffset = urb->actual_length;
-
-       if (!usb_pipeisoc(urb->pipe))
-               return;
-
-       /* if no packets or length of data is 0, then nothing to unpack */
-       if (np == 0 || urb->actual_length == 0)
-               return;
-
-       /*
-        * if actual_length is transfer_buffer_length then no padding is
-        * present.
-        */
-       if (urb->actual_length == urb->transfer_buffer_length)
-               return;
-
-       /*
-        * loop over all packets from last to first (to prevent overwritting
-        * memory when padding) and move them into the proper place
-        */
-       for (i = np-1; i > 0; i--) {
-               actualoffset -= urb->iso_frame_desc[i].actual_length;
-               memmove(urb->transfer_buffer + urb->iso_frame_desc[i].offset,
-                       urb->transfer_buffer + actualoffset,
-                       urb->iso_frame_desc[i].actual_length);
-       }
-}
-EXPORT_SYMBOL_GPL(usbip_pad_iso);
-
-/* some members of urb must be substituted before. */
-int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb)
-{
-       int ret;
-       int size;
-
-       if (ud->side == USBIP_STUB) {
-               /* the direction of urb must be OUT. */
-               if (usb_pipein(urb->pipe))
-                       return 0;
-
-               size = urb->transfer_buffer_length;
-       } else {
-               /* the direction of urb must be IN. */
-               if (usb_pipeout(urb->pipe))
-                       return 0;
-
-               size = urb->actual_length;
-       }
-
-       /* no need to recv xbuff */
-       if (!(size > 0))
-               return 0;
-
-       ret = usbip_recv(ud->tcp_socket, urb->transfer_buffer, size);
-       if (ret != size) {
-               dev_err(&urb->dev->dev, "recv xbuf, %d\n", ret);
-               if (ud->side == USBIP_STUB) {
-                       usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
-               } else {
-                       usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
-                       return -EPIPE;
-               }
-       }
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(usbip_recv_xbuff);
-
-static int __init usbip_core_init(void)
-{
-       pr_info(DRIVER_DESC " v" USBIP_VERSION "\n");
-       return 0;
-}
-
-static void __exit usbip_core_exit(void)
-{
-       return;
-}
-
-module_init(usbip_core_init);
-module_exit(usbip_core_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-MODULE_VERSION(USBIP_VERSION);
diff --git a/drivers/staging/usbip/usbip_common.h b/drivers/staging/usbip/usbip_common.h
deleted file mode 100644 (file)
index 4da3866..0000000
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * Copyright (C) 2003-2008 Takahiro Hirofuchi
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#ifndef __USBIP_COMMON_H
-#define __USBIP_COMMON_H
-
-#include <linux/compiler.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/net.h>
-#include <linux/printk.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-#include <linux/usb.h>
-#include <linux/wait.h>
-#include "uapi/usbip.h"
-
-#define USBIP_VERSION "1.0.0"
-
-#undef pr_fmt
-
-#ifdef DEBUG
-#define pr_fmt(fmt)     KBUILD_MODNAME ": %s:%d: " fmt, __func__, __LINE__
-#else
-#define pr_fmt(fmt)     KBUILD_MODNAME ": " fmt
-#endif
-
-enum {
-       usbip_debug_xmit        = (1 << 0),
-       usbip_debug_sysfs       = (1 << 1),
-       usbip_debug_urb         = (1 << 2),
-       usbip_debug_eh          = (1 << 3),
-
-       usbip_debug_stub_cmp    = (1 << 8),
-       usbip_debug_stub_dev    = (1 << 9),
-       usbip_debug_stub_rx     = (1 << 10),
-       usbip_debug_stub_tx     = (1 << 11),
-
-       usbip_debug_vhci_rh     = (1 << 8),
-       usbip_debug_vhci_hc     = (1 << 9),
-       usbip_debug_vhci_rx     = (1 << 10),
-       usbip_debug_vhci_tx     = (1 << 11),
-       usbip_debug_vhci_sysfs  = (1 << 12)
-};
-
-#define usbip_dbg_flag_xmit    (usbip_debug_flag & usbip_debug_xmit)
-#define usbip_dbg_flag_vhci_rh (usbip_debug_flag & usbip_debug_vhci_rh)
-#define usbip_dbg_flag_vhci_hc (usbip_debug_flag & usbip_debug_vhci_hc)
-#define usbip_dbg_flag_vhci_rx (usbip_debug_flag & usbip_debug_vhci_rx)
-#define usbip_dbg_flag_vhci_tx (usbip_debug_flag & usbip_debug_vhci_tx)
-#define usbip_dbg_flag_stub_rx (usbip_debug_flag & usbip_debug_stub_rx)
-#define usbip_dbg_flag_stub_tx (usbip_debug_flag & usbip_debug_stub_tx)
-#define usbip_dbg_flag_vhci_sysfs  (usbip_debug_flag & usbip_debug_vhci_sysfs)
-
-extern unsigned long usbip_debug_flag;
-extern struct device_attribute dev_attr_usbip_debug;
-
-#define usbip_dbg_with_flag(flag, fmt, args...)                \
-       do {                                            \
-               if (flag & usbip_debug_flag)            \
-                       pr_debug(fmt, ##args);          \
-       } while (0)
-
-#define usbip_dbg_sysfs(fmt, args...) \
-       usbip_dbg_with_flag(usbip_debug_sysfs, fmt , ##args)
-#define usbip_dbg_xmit(fmt, args...) \
-       usbip_dbg_with_flag(usbip_debug_xmit, fmt , ##args)
-#define usbip_dbg_urb(fmt, args...) \
-       usbip_dbg_with_flag(usbip_debug_urb, fmt , ##args)
-#define usbip_dbg_eh(fmt, args...) \
-       usbip_dbg_with_flag(usbip_debug_eh, fmt , ##args)
-
-#define usbip_dbg_vhci_rh(fmt, args...)        \
-       usbip_dbg_with_flag(usbip_debug_vhci_rh, fmt , ##args)
-#define usbip_dbg_vhci_hc(fmt, args...)        \
-       usbip_dbg_with_flag(usbip_debug_vhci_hc, fmt , ##args)
-#define usbip_dbg_vhci_rx(fmt, args...)        \
-       usbip_dbg_with_flag(usbip_debug_vhci_rx, fmt , ##args)
-#define usbip_dbg_vhci_tx(fmt, args...)        \
-       usbip_dbg_with_flag(usbip_debug_vhci_tx, fmt , ##args)
-#define usbip_dbg_vhci_sysfs(fmt, args...) \
-       usbip_dbg_with_flag(usbip_debug_vhci_sysfs, fmt , ##args)
-
-#define usbip_dbg_stub_cmp(fmt, args...) \
-       usbip_dbg_with_flag(usbip_debug_stub_cmp, fmt , ##args)
-#define usbip_dbg_stub_rx(fmt, args...) \
-       usbip_dbg_with_flag(usbip_debug_stub_rx, fmt , ##args)
-#define usbip_dbg_stub_tx(fmt, args...) \
-       usbip_dbg_with_flag(usbip_debug_stub_tx, fmt , ##args)
-
-/*
- * USB/IP request headers
- *
- * Each request is transferred across the network to its counterpart, which
- * facilitates the normal USB communication. The values contained in the headers
- * are basically the same as in a URB. Currently, four request types are
- * defined:
- *
- *  - USBIP_CMD_SUBMIT: a USB request block, corresponds to usb_submit_urb()
- *    (client to server)
- *
- *  - USBIP_RET_SUBMIT: the result of USBIP_CMD_SUBMIT
- *    (server to client)
- *
- *  - USBIP_CMD_UNLINK: an unlink request of a pending USBIP_CMD_SUBMIT,
- *    corresponds to usb_unlink_urb()
- *    (client to server)
- *
- *  - USBIP_RET_UNLINK: the result of USBIP_CMD_UNLINK
- *    (server to client)
- *
- */
-#define USBIP_CMD_SUBMIT       0x0001
-#define USBIP_CMD_UNLINK       0x0002
-#define USBIP_RET_SUBMIT       0x0003
-#define USBIP_RET_UNLINK       0x0004
-
-#define USBIP_DIR_OUT  0x00
-#define USBIP_DIR_IN   0x01
-
-/**
- * struct usbip_header_basic - data pertinent to every request
- * @command: the usbip request type
- * @seqnum: sequential number that identifies requests; incremented per
- *         connection
- * @devid: specifies a remote USB device uniquely instead of busnum and devnum;
- *        in the stub driver, this value is ((busnum << 16) | devnum)
- * @direction: direction of the transfer
- * @ep: endpoint number
- */
-struct usbip_header_basic {
-       __u32 command;
-       __u32 seqnum;
-       __u32 devid;
-       __u32 direction;
-       __u32 ep;
-} __packed;
-
-/**
- * struct usbip_header_cmd_submit - USBIP_CMD_SUBMIT packet header
- * @transfer_flags: URB flags
- * @transfer_buffer_length: the data size for (in) or (out) transfer
- * @start_frame: initial frame for isochronous or interrupt transfers
- * @number_of_packets: number of isochronous packets
- * @interval: maximum time for the request on the server-side host controller
- * @setup: setup data for a control request
- */
-struct usbip_header_cmd_submit {
-       __u32 transfer_flags;
-       __s32 transfer_buffer_length;
-
-       /* it is difficult for usbip to sync frames (reserved only?) */
-       __s32 start_frame;
-       __s32 number_of_packets;
-       __s32 interval;
-
-       unsigned char setup[8];
-} __packed;
-
-/**
- * struct usbip_header_ret_submit - USBIP_RET_SUBMIT packet header
- * @status: return status of a non-iso request
- * @actual_length: number of bytes transferred
- * @start_frame: initial frame for isochronous or interrupt transfers
- * @number_of_packets: number of isochronous packets
- * @error_count: number of errors for isochronous transfers
- */
-struct usbip_header_ret_submit {
-       __s32 status;
-       __s32 actual_length;
-       __s32 start_frame;
-       __s32 number_of_packets;
-       __s32 error_count;
-} __packed;
-
-/**
- * struct usbip_header_cmd_unlink - USBIP_CMD_UNLINK packet header
- * @seqnum: the URB seqnum to unlink
- */
-struct usbip_header_cmd_unlink {
-       __u32 seqnum;
-} __packed;
-
-/**
- * struct usbip_header_ret_unlink - USBIP_RET_UNLINK packet header
- * @status: return status of the request
- */
-struct usbip_header_ret_unlink {
-       __s32 status;
-} __packed;
-
-/**
- * struct usbip_header - common header for all usbip packets
- * @base: the basic header
- * @u: packet type dependent header
- */
-struct usbip_header {
-       struct usbip_header_basic base;
-
-       union {
-               struct usbip_header_cmd_submit  cmd_submit;
-               struct usbip_header_ret_submit  ret_submit;
-               struct usbip_header_cmd_unlink  cmd_unlink;
-               struct usbip_header_ret_unlink  ret_unlink;
-       } u;
-} __packed;
-
-/*
- * This is the same as usb_iso_packet_descriptor but packed for pdu.
- */
-struct usbip_iso_packet_descriptor {
-       __u32 offset;
-       __u32 length;                   /* expected length */
-       __u32 actual_length;
-       __u32 status;
-} __packed;
-
-enum usbip_side {
-       USBIP_VHCI,
-       USBIP_STUB,
-};
-
-/* event handler */
-#define USBIP_EH_SHUTDOWN      (1 << 0)
-#define USBIP_EH_BYE           (1 << 1)
-#define USBIP_EH_RESET         (1 << 2)
-#define USBIP_EH_UNUSABLE      (1 << 3)
-
-#define SDEV_EVENT_REMOVED   (USBIP_EH_SHUTDOWN | USBIP_EH_RESET | USBIP_EH_BYE)
-#define        SDEV_EVENT_DOWN         (USBIP_EH_SHUTDOWN | USBIP_EH_RESET)
-#define        SDEV_EVENT_ERROR_TCP    (USBIP_EH_SHUTDOWN | USBIP_EH_RESET)
-#define        SDEV_EVENT_ERROR_SUBMIT (USBIP_EH_SHUTDOWN | USBIP_EH_RESET)
-#define        SDEV_EVENT_ERROR_MALLOC (USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE)
-
-#define        VDEV_EVENT_REMOVED      (USBIP_EH_SHUTDOWN | USBIP_EH_BYE)
-#define        VDEV_EVENT_DOWN         (USBIP_EH_SHUTDOWN | USBIP_EH_RESET)
-#define        VDEV_EVENT_ERROR_TCP    (USBIP_EH_SHUTDOWN | USBIP_EH_RESET)
-#define        VDEV_EVENT_ERROR_MALLOC (USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE)
-
-/* a common structure for stub_device and vhci_device */
-struct usbip_device {
-       enum usbip_side side;
-       enum usbip_device_status status;
-
-       /* lock for status */
-       spinlock_t lock;
-
-       struct socket *tcp_socket;
-
-       struct task_struct *tcp_rx;
-       struct task_struct *tcp_tx;
-
-       unsigned long event;
-       struct task_struct *eh;
-       wait_queue_head_t eh_waitq;
-
-       struct eh_ops {
-               void (*shutdown)(struct usbip_device *);
-               void (*reset)(struct usbip_device *);
-               void (*unusable)(struct usbip_device *);
-       } eh_ops;
-};
-
-#define kthread_get_run(threadfn, data, namefmt, ...)                     \
-({                                                                        \
-       struct task_struct *__k                                            \
-               = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \
-       if (!IS_ERR(__k)) {                                                \
-               get_task_struct(__k);                                      \
-               wake_up_process(__k);                                      \
-       }                                                                  \
-       __k;                                                               \
-})
-
-#define kthread_stop_put(k)            \
-       do {                            \
-               kthread_stop(k);        \
-               put_task_struct(k);     \
-       } while (0)
-
-/* usbip_common.c */
-void usbip_dump_urb(struct urb *purb);
-void usbip_dump_header(struct usbip_header *pdu);
-
-int usbip_recv(struct socket *sock, void *buf, int size);
-
-void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd,
-                   int pack);
-void usbip_header_correct_endian(struct usbip_header *pdu, int send);
-
-struct usbip_iso_packet_descriptor*
-usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen);
-
-/* some members of urb must be substituted before. */
-int usbip_recv_iso(struct usbip_device *ud, struct urb *urb);
-void usbip_pad_iso(struct usbip_device *ud, struct urb *urb);
-int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb);
-
-/* usbip_event.c */
-int usbip_start_eh(struct usbip_device *ud);
-void usbip_stop_eh(struct usbip_device *ud);
-void usbip_event_add(struct usbip_device *ud, unsigned long event);
-int usbip_event_happened(struct usbip_device *ud);
-
-static inline int interface_to_busnum(struct usb_interface *interface)
-{
-       struct usb_device *udev = interface_to_usbdev(interface);
-
-       return udev->bus->busnum;
-}
-
-static inline int interface_to_devnum(struct usb_interface *interface)
-{
-       struct usb_device *udev = interface_to_usbdev(interface);
-
-       return udev->devnum;
-}
-
-#endif /* __USBIP_COMMON_H */
diff --git a/drivers/staging/usbip/usbip_event.c b/drivers/staging/usbip/usbip_event.c
deleted file mode 100644 (file)
index 64933b9..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2003-2008 Takahiro Hirofuchi
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#include <linux/kthread.h>
-#include <linux/export.h>
-
-#include "usbip_common.h"
-
-static int event_handler(struct usbip_device *ud)
-{
-       usbip_dbg_eh("enter\n");
-
-       /*
-        * Events are handled by only this thread.
-        */
-       while (usbip_event_happened(ud)) {
-               usbip_dbg_eh("pending event %lx\n", ud->event);
-
-               /*
-                * NOTE: shutdown must come first.
-                * Shutdown the device.
-                */
-               if (ud->event & USBIP_EH_SHUTDOWN) {
-                       ud->eh_ops.shutdown(ud);
-                       ud->event &= ~USBIP_EH_SHUTDOWN;
-               }
-
-               /* Reset the device. */
-               if (ud->event & USBIP_EH_RESET) {
-                       ud->eh_ops.reset(ud);
-                       ud->event &= ~USBIP_EH_RESET;
-               }
-
-               /* Mark the device as unusable. */
-               if (ud->event & USBIP_EH_UNUSABLE) {
-                       ud->eh_ops.unusable(ud);
-                       ud->event &= ~USBIP_EH_UNUSABLE;
-               }
-
-               /* Stop the error handler. */
-               if (ud->event & USBIP_EH_BYE)
-                       return -1;
-       }
-
-       return 0;
-}
-
-static int event_handler_loop(void *data)
-{
-       struct usbip_device *ud = data;
-
-       while (!kthread_should_stop()) {
-               wait_event_interruptible(ud->eh_waitq,
-                                        usbip_event_happened(ud) ||
-                                        kthread_should_stop());
-               usbip_dbg_eh("wakeup\n");
-
-               if (event_handler(ud) < 0)
-                       break;
-       }
-
-       return 0;
-}
-
-int usbip_start_eh(struct usbip_device *ud)
-{
-       init_waitqueue_head(&ud->eh_waitq);
-       ud->event = 0;
-
-       ud->eh = kthread_run(event_handler_loop, ud, "usbip_eh");
-       if (IS_ERR(ud->eh)) {
-               pr_warn("Unable to start control thread\n");
-               return PTR_ERR(ud->eh);
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(usbip_start_eh);
-
-void usbip_stop_eh(struct usbip_device *ud)
-{
-       if (ud->eh == current)
-               return; /* do not wait for myself */
-
-       kthread_stop(ud->eh);
-       usbip_dbg_eh("usbip_eh has finished\n");
-}
-EXPORT_SYMBOL_GPL(usbip_stop_eh);
-
-void usbip_event_add(struct usbip_device *ud, unsigned long event)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&ud->lock, flags);
-       ud->event |= event;
-       wake_up(&ud->eh_waitq);
-       spin_unlock_irqrestore(&ud->lock, flags);
-}
-EXPORT_SYMBOL_GPL(usbip_event_add);
-
-int usbip_event_happened(struct usbip_device *ud)
-{
-       int happened = 0;
-
-       spin_lock(&ud->lock);
-       if (ud->event != 0)
-               happened = 1;
-       spin_unlock(&ud->lock);
-
-       return happened;
-}
-EXPORT_SYMBOL_GPL(usbip_event_happened);
diff --git a/drivers/staging/usbip/usbip_protocol.txt b/drivers/staging/usbip/usbip_protocol.txt
deleted file mode 100644 (file)
index 16b6fe2..0000000
+++ /dev/null
@@ -1,358 +0,0 @@
-PRELIMINARY DRAFT, MAY CONTAIN MISTAKES!
-28 Jun 2011
-
-The USB/IP protocol follows a server/client architecture. The server exports the
-USB devices and the clients imports them. The device driver for the exported
-USB device runs on the client machine.
-
-The client may ask for the list of the exported USB devices. To get the list the
-client opens a TCP/IP connection towards the server, and sends an OP_REQ_DEVLIST
-packet on top of the TCP/IP connection (so the actual OP_REQ_DEVLIST may be sent
-in one or more pieces at the low level transport layer). The server sends back
-the OP_REP_DEVLIST packet which lists the exported USB devices. Finally the
-TCP/IP connection is closed.
-
- virtual host controller                                 usb host
-      "client"                                           "server"
-  (imports USB devices)                             (exports USB devices)
-          |                                                 |
-          |                  OP_REQ_DEVLIST                 |
-          | ----------------------------------------------> |
-          |                                                 |
-          |                  OP_REP_DEVLIST                 |
-          | <---------------------------------------------- |
-          |                                                 |
-
-Once the client knows the list of exported USB devices it may decide to use one
-of them. First the client opens a TCP/IP connection towards the server and
-sends an OP_REQ_IMPORT packet. The server replies with OP_REP_IMPORT. If the
-import was successful the TCP/IP connection remains open and will be used
-to transfer the URB traffic between the client and the server. The client may
-send two types of packets: the USBIP_CMD_SUBMIT to submit an URB, and
-USBIP_CMD_UNLINK to unlink a previously submitted URB. The answers of the
-server may be USBIP_RET_SUBMIT and USBIP_RET_UNLINK respectively.
-
- virtual host controller                                 usb host
-      "client"                                           "server"
-  (imports USB devices)                             (exports USB devices)
-          |                                                 |
-          |                  OP_REQ_IMPORT                  |
-          | ----------------------------------------------> |
-          |                                                 |
-          |                  OP_REP_IMPORT                  |
-          | <---------------------------------------------- |
-          |                                                 |
-          |                                                 |
-          |            USBIP_CMD_SUBMIT(seqnum = n)         |
-          | ----------------------------------------------> |
-          |                                                 |
-          |            USBIP_RET_SUBMIT(seqnum = n)         |
-          | <---------------------------------------------- |
-          |                        .                        |
-          |                        :                        |
-          |                                                 |
-          |            USBIP_CMD_SUBMIT(seqnum = m)         |
-          | ----------------------------------------------> |
-          |                                                 |
-          |            USBIP_CMD_SUBMIT(seqnum = m+1)       |
-          | ----------------------------------------------> |
-          |                                                 |
-          |            USBIP_CMD_SUBMIT(seqnum = m+2)       |
-          | ----------------------------------------------> |
-          |                                                 |
-          |            USBIP_RET_SUBMIT(seqnum = m)         |
-          | <---------------------------------------------- |
-          |                                                 |
-          |            USBIP_CMD_SUBMIT(seqnum = m+3)       |
-          | ----------------------------------------------> |
-          |                                                 |
-          |            USBIP_RET_SUBMIT(seqnum = m+1)       |
-          | <---------------------------------------------- |
-          |                                                 |
-          |            USBIP_CMD_SUBMIT(seqnum = m+4)       |
-          | ----------------------------------------------> |
-          |                                                 |
-          |            USBIP_RET_SUBMIT(seqnum = m+2)       |
-          | <---------------------------------------------- |
-          |                        .                        |
-          |                        :                        |
-          |                                                 |
-          |               USBIP_CMD_UNLINK                  |
-          | ----------------------------------------------> |
-          |                                                 |
-          |               USBIP_RET_UNLINK                  |
-          | <---------------------------------------------- |
-          |                                                 |
-
-The fields are in network (big endian) byte order meaning that the most significant
-byte (MSB) is stored at the lowest address.
-
-
-OP_REQ_DEVLIST: Retrieve the list of exported USB devices.
-
- Offset    | Length | Value      | Description
------------+--------+------------+---------------------------------------------------
- 0         | 2      | 0x0100     | Binary-coded decimal USBIP version number: v1.0.0
------------+--------+------------+---------------------------------------------------
- 2         | 2      | 0x8005     | Command code: Retrieve the list of exported USB
-           |        |            |   devices.
------------+--------+------------+---------------------------------------------------
- 4         | 4      | 0x00000000 | Status: unused, shall be set to 0
-
-OP_REP_DEVLIST: Reply with the list of exported USB devices.
-
- Offset    | Length | Value      | Description
------------+--------+------------+---------------------------------------------------
- 0         | 2      | 0x0100     | Binary-coded decimal USBIP version number: v1.0.0.
------------+--------+------------+---------------------------------------------------
- 2         | 2      | 0x0005     | Reply code: The list of exported USB devices.
------------+--------+------------+---------------------------------------------------
- 4         | 4      | 0x00000000 | Status: 0 for OK
------------+--------+------------+---------------------------------------------------
- 8         | 4      | n          | Number of exported devices: 0 means no exported
-           |        |            |   devices.
------------+--------+------------+---------------------------------------------------
- 0x0C      |        |            | From now on the exported n devices are described,
-           |        |            |   if any. If no devices are exported the message
-           |        |            |   ends with the previous "number of exported
-           |        |            |   devices" field.
------------+--------+------------+---------------------------------------------------
-           | 256    |            | path: Path of the device on the host exporting the
-           |        |            |   USB device, string closed with zero byte, e.g.
-           |        |            |   "/sys/devices/pci0000:00/0000:00:1d.1/usb3/3-2"
-           |        |            |   The unused bytes shall be filled with zero
-           |        |            |   bytes.
------------+--------+------------+---------------------------------------------------
- 0x10C     | 32     |            | busid: Bus ID of the exported device, string
-           |        |            |   closed with zero byte, e.g. "3-2". The unused
-           |        |            |   bytes shall be filled with zero bytes.
------------+--------+------------+---------------------------------------------------
- 0x12C     | 4      |            | busnum
------------+--------+------------+---------------------------------------------------
- 0x130     | 4      |            | devnum
------------+--------+------------+---------------------------------------------------
- 0x134     | 4      |            | speed
------------+--------+------------+---------------------------------------------------
- 0x138     | 2      |            | idVendor
------------+--------+------------+---------------------------------------------------
- 0x13A     | 2      |            | idProduct
------------+--------+------------+---------------------------------------------------
- 0x13C     | 2      |            | bcdDevice
------------+--------+------------+---------------------------------------------------
- 0x13E     | 1      |            | bDeviceClass
------------+--------+------------+---------------------------------------------------
- 0x13F     | 1      |            | bDeviceSubClass
------------+--------+------------+---------------------------------------------------
- 0x140     | 1      |            | bDeviceProtocol
------------+--------+------------+---------------------------------------------------
- 0x141     | 1      |            | bConfigurationValue
------------+--------+------------+---------------------------------------------------
- 0x142     | 1      |            | bNumConfigurations
------------+--------+------------+---------------------------------------------------
- 0x143     | 1      |            | bNumInterfaces
------------+--------+------------+---------------------------------------------------
- 0x144     |        | m_0        | From now on each interface is described, all
-           |        |            |   together bNumInterfaces times, with the
-           |        |            |   the following 4 fields:
------------+--------+------------+---------------------------------------------------
-           | 1      |            | bInterfaceClass
------------+--------+------------+---------------------------------------------------
- 0x145     | 1      |            | bInterfaceSubClass
------------+--------+------------+---------------------------------------------------
- 0x146     | 1      |            | bInterfaceProtocol
------------+--------+------------+---------------------------------------------------
- 0x147     | 1      |            | padding byte for alignment, shall be set to zero
------------+--------+------------+---------------------------------------------------
- 0xC +     |        |            | The second exported USB device starts at i=1
- i*0x138 + |        |            | with the busid field.
- m_(i-1)*4 |        |            |
-
-OP_REQ_IMPORT: Request to import (attach) a remote USB device.
-
- Offset    | Length | Value      | Description
------------+--------+------------+---------------------------------------------------
- 0         | 2      | 0x0100     | Binary-coded decimal USBIP version number: v1.0.0
------------+--------+------------+---------------------------------------------------
- 2         | 2      | 0x8003     | Command code: import a remote USB device.
------------+--------+------------+---------------------------------------------------
- 4         | 4      | 0x00000000 | Status: unused, shall be set to 0
------------+--------+------------+---------------------------------------------------
- 8         | 32     |            | busid: the busid of the exported device on the
-           |        |            |   remote host. The possible values are taken
-           |        |            |   from the message field OP_REP_DEVLIST.busid.
-           |        |            |   A string closed with zero, the unused bytes
-           |        |            |   shall be filled with zeros.
------------+--------+------------+---------------------------------------------------
-
-OP_REP_IMPORT: Reply to import (attach) a remote USB device.
-
- Offset    | Length | Value      | Description
------------+--------+------------+---------------------------------------------------
- 0         | 2      | 0x0100     | Binary-coded decimal USBIP version number: v1.0.0
------------+--------+------------+---------------------------------------------------
- 2         | 2      | 0x0003     | Reply code: Reply to import.
------------+--------+------------+---------------------------------------------------
- 4         | 4      | 0x00000000 | Status: 0 for OK
-           |        |            |         1 for error
------------+--------+------------+---------------------------------------------------
- 8         |        |            | From now on comes the details of the imported
-           |        |            |   device, if the previous status field was OK (0),
-           |        |            |   otherwise the reply ends with the status field.
------------+--------+------------+---------------------------------------------------
-           | 256    |            | path: Path of the device on the host exporting the
-           |        |            |   USB device, string closed with zero byte, e.g.
-           |        |            |   "/sys/devices/pci0000:00/0000:00:1d.1/usb3/3-2"
-           |        |            |   The unused bytes shall be filled with zero
-           |        |            |   bytes.
------------+--------+------------+---------------------------------------------------
- 0x108     | 32     |            | busid: Bus ID of the exported device, string
-           |        |            |   closed with zero byte, e.g. "3-2". The unused
-           |        |            |   bytes shall be filled with zero bytes.
------------+--------+------------+---------------------------------------------------
- 0x128     | 4      |            | busnum
------------+--------+------------+---------------------------------------------------
- 0x12C     | 4      |            | devnum
------------+--------+------------+---------------------------------------------------
- 0x130     | 4      |            | speed
------------+--------+------------+---------------------------------------------------
- 0x134     | 2      |            | idVendor
------------+--------+------------+---------------------------------------------------
- 0x136     | 2      |            | idProduct
------------+--------+------------+---------------------------------------------------
- 0x138     | 2      |            | bcdDevice
------------+--------+------------+---------------------------------------------------
- 0x139     | 1      |            | bDeviceClass
------------+--------+------------+---------------------------------------------------
- 0x13A     | 1      |            | bDeviceSubClass
------------+--------+------------+---------------------------------------------------
- 0x13B     | 1      |            | bDeviceProtocol
------------+--------+------------+---------------------------------------------------
- 0x13C     | 1      |            | bConfigurationValue
------------+--------+------------+---------------------------------------------------
- 0x13D     | 1      |            | bNumConfigurations
------------+--------+------------+---------------------------------------------------
- 0x13E     | 1      |            | bNumInterfaces
-
-USBIP_CMD_SUBMIT: Submit an URB
-
- Offset    | Length | Value      | Description
------------+--------+------------+---------------------------------------------------
- 0         | 4      | 0x00000001 | command: Submit an URB
------------+--------+------------+---------------------------------------------------
- 4         | 4      |            | seqnum: the sequence number of the URB to submit
------------+--------+------------+---------------------------------------------------
- 8         | 4      |            | devid
------------+--------+------------+---------------------------------------------------
- 0xC       | 4      |            | direction: 0: USBIP_DIR_OUT
-           |        |            |            1: USBIP_DIR_IN
------------+--------+------------+---------------------------------------------------
- 0x10      | 4      |            | ep: endpoint number, possible values are: 0...15
------------+--------+------------+---------------------------------------------------
- 0x14      | 4      |            | transfer_flags: possible values depend on the
-           |        |            |   URB transfer type, see below
------------+--------+------------+---------------------------------------------------
- 0x18      | 4      |            | transfer_buffer_length
------------+--------+------------+---------------------------------------------------
- 0x1C      | 4      |            | start_frame: specify the selected frame to
-           |        |            |   transmit an ISO frame, ignored if URB_ISO_ASAP
-           |        |            |   is specified at transfer_flags
------------+--------+------------+---------------------------------------------------
- 0x20      | 4      |            | number_of_packets: number of ISO packets
------------+--------+------------+---------------------------------------------------
- 0x24      | 4      |            | interval: maximum time for the request on the
-           |        |            |   server-side host controller
------------+--------+------------+---------------------------------------------------
- 0x28      | 8      |            | setup: data bytes for USB setup, filled with
-           |        |            |   zeros if not used
------------+--------+------------+---------------------------------------------------
- 0x30      |        |            | URB data. For ISO transfers the padding between
-           |        |            |   each ISO packets is not transmitted.
-
-
-  Allowed transfer_flags  | value      | control | interrupt | bulk     | isochronous
- -------------------------+------------+---------+-----------+----------+-------------
-  URB_SHORT_NOT_OK        | 0x00000001 | only in | only in   | only in  | no
-  URB_ISO_ASAP            | 0x00000002 | no      | no        | no       | yes
-  URB_NO_TRANSFER_DMA_MAP | 0x00000004 | yes     | yes       | yes      | yes
-  URB_NO_FSBR             | 0x00000020 | yes     | no        | no       | no
-  URB_ZERO_PACKET         | 0x00000040 | no      | no        | only out | no
-  URB_NO_INTERRUPT        | 0x00000080 | yes     | yes       | yes      | yes
-  URB_FREE_BUFFER         | 0x00000100 | yes     | yes       | yes      | yes
-  URB_DIR_MASK            | 0x00000200 | yes     | yes       | yes      | yes
-
-
-USBIP_RET_SUBMIT: Reply for submitting an URB
-
- Offset    | Length | Value      | Description
------------+--------+------------+---------------------------------------------------
- 0         | 4      | 0x00000003 | command
------------+--------+------------+---------------------------------------------------
- 4         | 4      |            | seqnum: URB sequence number
------------+--------+------------+---------------------------------------------------
- 8         | 4      |            | devid
------------+--------+------------+---------------------------------------------------
- 0xC       | 4      |            | direction: 0: USBIP_DIR_OUT
-           |        |            |            1: USBIP_DIR_IN
------------+--------+------------+---------------------------------------------------
- 0x10      | 4      |            | ep: endpoint number
------------+--------+------------+---------------------------------------------------
- 0x14      | 4      |            | status: zero for successful URB transaction,
-           |        |            |   otherwise some kind of error happened.
------------+--------+------------+---------------------------------------------------
- 0x18      | 4      | n          | actual_length: number of URB data bytes
------------+--------+------------+---------------------------------------------------
- 0x1C      | 4      |            | start_frame: for an ISO frame the actually
-           |        |            |   selected frame for transmit.
------------+--------+------------+---------------------------------------------------
- 0x20      | 4      |            | number_of_packets
------------+--------+------------+---------------------------------------------------
- 0x24      | 4      |            | error_count
------------+--------+------------+---------------------------------------------------
- 0x28      | 8      |            | setup: data bytes for USB setup, filled with
-           |        |            |   zeros if not used
------------+--------+------------+---------------------------------------------------
- 0x30      | n      |            | URB data bytes. For ISO transfers the padding
-           |        |            |   between each ISO packets is not transmitted.
-
-USBIP_CMD_UNLINK: Unlink an URB
-
- Offset    | Length | Value      | Description
------------+--------+------------+---------------------------------------------------
- 0         | 4      | 0x00000002 | command: URB unlink command
------------+--------+------------+---------------------------------------------------
- 4         | 4      |            | seqnum: URB sequence number to unlink: FIXME: is this so?
------------+--------+------------+---------------------------------------------------
- 8         | 4      |            | devid
------------+--------+------------+---------------------------------------------------
- 0xC       | 4      |            | direction: 0: USBIP_DIR_OUT
-           |        |            |            1: USBIP_DIR_IN
------------+--------+------------+---------------------------------------------------
- 0x10      | 4      |            | ep: endpoint number: zero
------------+--------+------------+---------------------------------------------------
- 0x14      | 4      |            | seqnum: the URB sequence number given previously
-           |        |            |   at USBIP_CMD_SUBMIT.seqnum field
------------+--------+------------+---------------------------------------------------
- 0x30      | n      |            | URB data bytes. For ISO transfers the padding
-           |        |            |   between each ISO packets is not transmitted.
-
-USBIP_RET_UNLINK: Reply for URB unlink
-
- Offset    | Length | Value      | Description
------------+--------+------------+---------------------------------------------------
- 0         | 4      | 0x00000004 | command: reply for the URB unlink command
------------+--------+------------+---------------------------------------------------
- 4         | 4      |            | seqnum: the unlinked URB sequence number
------------+--------+------------+---------------------------------------------------
- 8         | 4      |            | devid
------------+--------+------------+---------------------------------------------------
- 0xC       | 4      |            | direction: 0: USBIP_DIR_OUT
-           |        |            |            1: USBIP_DIR_IN
------------+--------+------------+---------------------------------------------------
- 0x10      | 4      |            | ep: endpoint number
------------+--------+------------+---------------------------------------------------
- 0x14      | 4      |            | status: This is the value contained in the
-           |        |            |   urb->status in the URB completition handler.
-           |        |            |   FIXME: a better explanation needed.
------------+--------+------------+---------------------------------------------------
- 0x30      | n      |            | URB data bytes. For ISO transfers the padding
-           |        |            |   between each ISO packets is not transmitted.
diff --git a/drivers/staging/usbip/userspace/.gitignore b/drivers/staging/usbip/userspace/.gitignore
deleted file mode 100644 (file)
index 9aad9e3..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-Makefile
-Makefile.in
-aclocal.m4
-autom4te.cache/
-config.guess
-config.h
-config.h.in
-config.log
-config.status
-config.sub
-configure
-depcomp
-install-sh
-libsrc/Makefile
-libsrc/Makefile.in
-libtool
-ltmain.sh
-missing
-src/Makefile
-src/Makefile.in
-stamp-h1
-libsrc/libusbip.la
-libsrc/libusbip_la-names.lo
-libsrc/libusbip_la-usbip_common.lo
-libsrc/libusbip_la-usbip_host_driver.lo
-libsrc/libusbip_la-vhci_driver.lo
-src/usbip
-src/usbipd
diff --git a/drivers/staging/usbip/userspace/AUTHORS b/drivers/staging/usbip/userspace/AUTHORS
deleted file mode 100644 (file)
index a27ea8d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-Takahiro Hirofuchi
-Robert Leibl
-matt mooney <mfm@muteddisk.com>
diff --git a/drivers/staging/usbip/userspace/COPYING b/drivers/staging/usbip/userspace/COPYING
deleted file mode 100644 (file)
index c5611e4..0000000
+++ /dev/null
@@ -1,340 +0,0 @@
-                   GNU GENERAL PUBLIC LICENSE
-                      Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-                           Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users.  This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
-your programs, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
-  For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have.  You must make sure that they, too, receive or can get the
-source code.  And you must show them these terms so they know their
-rights.
-
-  We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
-  Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software.  If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary.  To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.
-
-                   GNU GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License.  The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language.  (Hereinafter, translation is included without limitation in
-the term "modification".)  Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
-  1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
-  2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) You must cause the modified files to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    b) You must cause any work that you distribute or publish, that in
-    whole or in part contains or is derived from the Program or any
-    part thereof, to be licensed as a whole at no charge to all third
-    parties under the terms of this License.
-
-    c) If the modified program normally reads commands interactively
-    when run, you must cause it, when started running for such
-    interactive use in the most ordinary way, to print or display an
-    announcement including an appropriate copyright notice and a
-    notice that there is no warranty (or else, saying that you provide
-    a warranty) and that users may redistribute the program under
-    these conditions, and telling the user how to view a copy of this
-    License.  (Exception: if the Program itself is interactive but
-    does not normally print such an announcement, your work based on
-    the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
-    a) Accompany it with the complete corresponding machine-readable
-    source code, which must be distributed under the terms of Sections
-    1 and 2 above on a medium customarily used for software interchange; or,
-
-    b) Accompany it with a written offer, valid for at least three
-    years, to give any third party, for a charge no more than your
-    cost of physically performing source distribution, a complete
-    machine-readable copy of the corresponding source code, to be
-    distributed under the terms of Sections 1 and 2 above on a medium
-    customarily used for software interchange; or,
-
-    c) Accompany it with the information you received as to the offer
-    to distribute corresponding source code.  (This alternative is
-    allowed only for noncommercial distribution and only if you
-    received the program in object code or executable form with such
-    an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it.  For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable.  However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License.  Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
-  5. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Program or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
-  6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded.  In such case, this License incorporates
-the limitation as if written in the body of this License.
-
-  9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time.  Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation.  If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
-  10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission.  For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this.  Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
-                           NO WARRANTY
-
-  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
-  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
-                    END OF TERMS AND CONDITIONS
-
-           How to Apply These Terms to Your New Programs
-
-  If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
-  To do so, attach the following notices to the program.  It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
-    Gnomovision version 69, Copyright (C) year  name of author
-    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
-    This is free software, and you are welcome to redistribute it
-    under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License.  Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
-  `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
-  <signature of Ty Coon>, 1 April 1989
-  Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs.  If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/drivers/staging/usbip/userspace/INSTALL b/drivers/staging/usbip/userspace/INSTALL
deleted file mode 100644 (file)
index d3c5b40..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-Installation Instructions
-*************************
-
-Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
-2006, 2007 Free Software Foundation, Inc.
-
-This file is free documentation; the Free Software Foundation gives
-unlimited permission to copy, distribute and modify it.
-
-Basic Installation
-==================
-
-Briefly, the shell commands `./configure; make; make install' should
-configure, build, and install this package.  The following
-more-detailed instructions are generic; see the `README' file for
-instructions specific to this package.
-
-   The `configure' shell script attempts to guess correct values for
-various system-dependent variables used during compilation.  It uses
-those values to create a `Makefile' in each directory of the package.
-It may also create one or more `.h' files containing system-dependent
-definitions.  Finally, it creates a shell script `config.status' that
-you can run in the future to recreate the current configuration, and a
-file `config.log' containing compiler output (useful mainly for
-debugging `configure').
-
-   It can also use an optional file (typically called `config.cache'
-and enabled with `--cache-file=config.cache' or simply `-C') that saves
-the results of its tests to speed up reconfiguring.  Caching is
-disabled by default to prevent problems with accidental use of stale
-cache files.
-
-   If you need to do unusual things to compile the package, please try
-to figure out how `configure' could check whether to do them, and mail
-diffs or instructions to the address given in the `README' so they can
-be considered for the next release.  If you are using the cache, and at
-some point `config.cache' contains results you don't want to keep, you
-may remove or edit it.
-
-   The file `configure.ac' (or `configure.in') is used to create
-`configure' by a program called `autoconf'.  You need `configure.ac' if
-you want to change it or regenerate `configure' using a newer version
-of `autoconf'.
-
-The simplest way to compile this package is:
-
-  1. `cd' to the directory containing the package's source code and type
-     `./configure' to configure the package for your system.
-
-     Running `configure' might take a while.  While running, it prints
-     some messages telling which features it is checking for.
-
-  2. Type `make' to compile the package.
-
-  3. Optionally, type `make check' to run any self-tests that come with
-     the package.
-
-  4. Type `make install' to install the programs and any data files and
-     documentation.
-
-  5. You can remove the program binaries and object files from the
-     source code directory by typing `make clean'.  To also remove the
-     files that `configure' created (so you can compile the package for
-     a different kind of computer), type `make distclean'.  There is
-     also a `make maintainer-clean' target, but that is intended mainly
-     for the package's developers.  If you use it, you may have to get
-     all sorts of other programs in order to regenerate files that came
-     with the distribution.
-
-  6. Often, you can also type `make uninstall' to remove the installed
-     files again.
-
-Compilers and Options
-=====================
-
-Some systems require unusual options for compilation or linking that the
-`configure' script does not know about.  Run `./configure --help' for
-details on some of the pertinent environment variables.
-
-   You can give `configure' initial values for configuration parameters
-by setting variables in the command line or in the environment.  Here
-is an example:
-
-     ./configure CC=c99 CFLAGS=-g LIBS=-lposix
-
-   *Note Defining Variables::, for more details.
-
-Compiling For Multiple Architectures
-====================================
-
-You can compile the package for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory.  To do this, you can use GNU `make'.  `cd' to the
-directory where you want the object files and executables to go and run
-the `configure' script.  `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'.
-
-   With a non-GNU `make', it is safer to compile the package for one
-architecture at a time in the source code directory.  After you have
-installed the package for one architecture, use `make distclean' before
-reconfiguring for another architecture.
-
-Installation Names
-==================
-
-By default, `make install' installs the package's commands under
-`/usr/local/bin', include files under `/usr/local/include', etc.  You
-can specify an installation prefix other than `/usr/local' by giving
-`configure' the option `--prefix=PREFIX'.
-
-   You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files.  If you
-pass the option `--exec-prefix=PREFIX' to `configure', the package uses
-PREFIX as the prefix for installing programs and libraries.
-Documentation and other data files still use the regular prefix.
-
-   In addition, if you use an unusual directory layout you can give
-options like `--bindir=DIR' to specify different values for particular
-kinds of files.  Run `configure --help' for a list of the directories
-you can set and what kinds of files go in them.
-
-   If the package supports it, you can cause programs to be installed
-with an extra prefix or suffix on their names by giving `configure' the
-option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
-
-Optional Features
-=================
-
-Some packages pay attention to `--enable-FEATURE' options to
-`configure', where FEATURE indicates an optional part of the package.
-They may also pay attention to `--with-PACKAGE' options, where PACKAGE
-is something like `gnu-as' or `x' (for the X Window System).  The
-`README' should mention any `--enable-' and `--with-' options that the
-package recognizes.
-
-   For packages that use the X Window System, `configure' can usually
-find the X include and library files automatically, but if it doesn't,
-you can use the `configure' options `--x-includes=DIR' and
-`--x-libraries=DIR' to specify their locations.
-
-Specifying the System Type
-==========================
-
-There may be some features `configure' cannot figure out automatically,
-but needs to determine by the type of machine the package will run on.
-Usually, assuming the package is built to be run on the _same_
-architectures, `configure' can figure that out, but if it prints a
-message saying it cannot guess the machine type, give it the
-`--build=TYPE' option.  TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name which has the form:
-
-     CPU-COMPANY-SYSTEM
-
-where SYSTEM can have one of these forms:
-
-     OS KERNEL-OS
-
-   See the file `config.sub' for the possible values of each field.  If
-`config.sub' isn't included in this package, then this package doesn't
-need to know the machine type.
-
-   If you are _building_ compiler tools for cross-compiling, you should
-use the option `--target=TYPE' to select the type of system they will
-produce code for.
-
-   If you want to _use_ a cross compiler, that generates code for a
-platform different from the build platform, you should specify the
-"host" platform (i.e., that on which the generated programs will
-eventually be run) with `--host=TYPE'.
-
-Sharing Defaults
-================
-
-If you want to set default values for `configure' scripts to share, you
-can create a site shell script called `config.site' that gives default
-values for variables like `CC', `cache_file', and `prefix'.
-`configure' looks for `PREFIX/share/config.site' if it exists, then
-`PREFIX/etc/config.site' if it exists.  Or, you can set the
-`CONFIG_SITE' environment variable to the location of the site script.
-A warning: not all `configure' scripts look for a site script.
-
-Defining Variables
-==================
-
-Variables not defined in a site shell script can be set in the
-environment passed to `configure'.  However, some packages may run
-configure again during the build, and the customized values of these
-variables may be lost.  In order to avoid this problem, you should set
-them in the `configure' command line, using `VAR=value'.  For example:
-
-     ./configure CC=/usr/local2/bin/gcc
-
-causes the specified `gcc' to be used as the C compiler (unless it is
-overridden in the site shell script).
-
-Unfortunately, this technique does not work for `CONFIG_SHELL' due to
-an Autoconf bug.  Until the bug is fixed you can use this workaround:
-
-     CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
-
-`configure' Invocation
-======================
-
-`configure' recognizes the following options to control how it operates.
-
-`--help'
-`-h'
-     Print a summary of the options to `configure', and exit.
-
-`--version'
-`-V'
-     Print the version of Autoconf used to generate the `configure'
-     script, and exit.
-
-`--cache-file=FILE'
-     Enable the cache: use and save the results of the tests in FILE,
-     traditionally `config.cache'.  FILE defaults to `/dev/null' to
-     disable caching.
-
-`--config-cache'
-`-C'
-     Alias for `--cache-file=config.cache'.
-
-`--quiet'
-`--silent'
-`-q'
-     Do not print messages saying which checks are being made.  To
-     suppress all normal output, redirect it to `/dev/null' (any error
-     messages will still be shown).
-
-`--srcdir=DIR'
-     Look for the package's source code in directory DIR.  Usually
-     `configure' can determine that directory automatically.
-
-`configure' also accepts some other, not widely useful, options.  Run
-`configure --help' for more details.
-
diff --git a/drivers/staging/usbip/userspace/Makefile.am b/drivers/staging/usbip/userspace/Makefile.am
deleted file mode 100644 (file)
index 66f8bf0..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-SUBDIRS := libsrc src
-includedir = @includedir@/usbip
-include_HEADERS := $(addprefix libsrc/, \
-                    usbip_common.h vhci_driver.h usbip_host_driver.h)
-
-dist_man_MANS := $(addprefix doc/, usbip.8 usbipd.8)
diff --git a/drivers/staging/usbip/userspace/README b/drivers/staging/usbip/userspace/README
deleted file mode 100644 (file)
index 831f49f..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-#
-# README for usbip-utils
-#
-# Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
-#               2005-2008 Takahiro Hirofuchi
-
-
-[Requirements]
-    - USB/IP device drivers
-       Found in the staging directory of the Linux kernel.
-
-    - libudev >= 2.0
-       libudev library
-
-    - libwrap0-dev
-       tcp wrapper library
-
-    - gcc >= 4.0
-
-    - libtool, automake >= 1.9, autoconf >= 2.5.0, pkg-config
-
-[Optional]
-    - hwdata
-        Contains USB device identification data.
-
-
-[Install]
-    0. Generate configuration scripts.
-       $ ./autogen.sh
-
-    1. Compile & install the userspace utilities.
-       $ ./configure [--with-tcp-wrappers=no] [--with-usbids-dir=<dir>]
-       $ make install
-
-    2. Compile & install USB/IP drivers.
-
-
-[Usage]
-    server:# (Physically attach your USB device.)
-
-    server:# insmod usbip-core.ko
-    server:# insmod usbip-host.ko
-
-    server:# usbipd -D
-       - Start usbip daemon.
-
-    server:# usbip list -l
-       - List driver assignments for USB devices.
-
-    server:# usbip bind --busid 1-2
-       - Bind usbip-host.ko to the device with busid 1-2.
-       - The USB device 1-2 is now exportable to other hosts!
-       - Use `usbip unbind --busid 1-2' to stop exporting the device.
-
-    client:# insmod usbip-core.ko
-    client:# insmod vhci-hcd.ko
-
-    client:# usbip list --remote <host>
-       - List exported USB devices on the <host>.
-
-    client:# usbip attach --remote <host> --busid 1-2
-       - Connect the remote USB device.
-
-    client:# usbip port
-       - Show virtual port status.
-
-    client:# usbip detach --port <port>
-       - Detach the USB device.
-
-
-[Example]
----------------------------
-       SERVER SIDE
----------------------------
-Physically attach your USB devices to this host.
-
-    trois:# insmod path/to/usbip-core.ko
-    trois:# insmod path/to/usbip-host.ko
-    trois:# usbipd -D
-
-In another terminal, let's look up what USB devices are physically
-attached to this host.
-
-    trois:# usbip list -l
-    Local USB devices
-    =================
-     - busid 1-1 (05a9:a511)
-            1-1:1.0 -> ov511
-
-     - busid 3-2 (0711:0902)
-            3-2:1.0 -> none
-
-     - busid 3-3.1 (08bb:2702)
-            3-3.1:1.0 -> snd-usb-audio
-            3-3.1:1.1 -> snd-usb-audio
-
-     - busid 3-3.2 (04bb:0206)
-            3-3.2:1.0 -> usb-storage
-
-     - busid 3-3 (0409:0058)
-            3-3:1.0 -> hub
-
-     - busid 4-1 (046d:08b2)
-            4-1:1.0 -> none
-            4-1:1.1 -> none
-            4-1:1.2 -> none
-
-     - busid 5-2 (058f:9254)
-            5-2:1.0 -> hub
-
-A USB storage device of busid 3-3.2 is now bound to the usb-storage
-driver. To export this device, we first mark the device as
-"exportable"; the device is bound to the usbip-host driver. Please
-remember you can not export a USB hub.
-
-Mark the device of busid 3-3.2 as exportable:
-
-    trois:# usbip --debug bind --busid 3-3.2
-    ...
-    usbip debug: usbip_bind.c:162:[unbind_other] 3-3.2:1.0 -> usb-storage
-    ...
-    bind device on busid 3-3.2: complete
-
-    trois:# usbip list -l
-    Local USB devices
-    =================
-    ...
-
-     - busid 3-3.2 (04bb:0206)
-            3-3.2:1.0 -> usbip-host
-    ...
-
----------------------------
-       CLIENT SIDE
----------------------------
-First, let's list available remote devices that are marked as
-exportable on the host.
-
-    deux:# insmod path/to/usbip-core.ko
-    deux:# insmod path/to/vhci-hcd.ko
-
-    deux:# usbip list --remote 10.0.0.3
-    Exportable USB devices
-    ======================
-     - 10.0.0.3
-           1-1: Prolific Technology, Inc. : unknown product (067b:3507)
-              : /sys/devices/pci0000:00/0000:00:1f.2/usb1/1-1
-              : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
-              :  0 - Mass Storage / SCSI / Bulk (Zip) (08/06/50)
-
-       1-2.2.1: Apple Computer, Inc. : unknown product (05ac:0203)
-              : /sys/devices/pci0000:00/0000:00:1f.2/usb1/1-2/1-2.2/1-2.2.1
-              : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
-              :  0 - Human Interface Devices / Boot Interface Subclass / Keyboard (03/01/01)
-
-       1-2.2.3: OmniVision Technologies, Inc. : OV511+ WebCam (05a9:a511)
-              : /sys/devices/pci0000:00/0000:00:1f.2/usb1/1-2/1-2.2/1-2.2.3
-              : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
-              :  0 - Vendor Specific Class / unknown subclass / unknown protocol (ff/00/00)
-
-           3-1: Logitech, Inc. : QuickCam Pro 4000 (046d:08b2)
-              : /sys/devices/pci0000:00/0000:00:1e.0/0000:02:0a.0/usb3/3-1
-              : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
-              :  0 - Data / unknown subclass / unknown protocol (0a/ff/00)
-              :  1 - Audio / Control Device / unknown protocol (01/01/00)
-              :  2 - Audio / Streaming / unknown protocol (01/02/00)
-
-Attach a remote USB device:
-
-    deux:# usbip attach --remote 10.0.0.3 --busid 1-1
-    port 0 attached
-
-Show the devices attached to this client:
-
-    deux:# usbip port
-    Port 00: <Port in Use> at Full Speed(12Mbps)
-          Prolific Technology, Inc. : unknown product (067b:3507)
-          6-1 -> usbip://10.0.0.3:3240/1-1  (remote bus/dev 001/004)
-          6-1:1.0 used by usb-storage
-                         /sys/class/scsi_device/0:0:0:0/device
-                         /sys/class/scsi_host/host0/device
-                         /sys/block/sda/device
-
-Detach the imported device:
-
-    deux:# usbip detach --port 0
-    port 0 detached
-
-
-[Checklist]
-    - See 'Debug Tips' on the project wiki.
-       - http://usbip.wiki.sourceforge.net/how-to-debug-usbip
-    - usbip-host.ko must be bound to the target device.
-       - See /proc/bus/usb/devices and find "Driver=..." lines of the device.
-    - Shutdown firewall.
-       - usbip now uses TCP port 3240.
-    - Disable SELinux.
-    - Check the kernel and daemon messages.
-
-
-[Contact]
-    Mailing List: linux-usb@vger.kernel.org
diff --git a/drivers/staging/usbip/userspace/autogen.sh b/drivers/staging/usbip/userspace/autogen.sh
deleted file mode 100755 (executable)
index e1112d3..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh -x
-
-#aclocal
-#autoheader
-#libtoolize --copy --force
-#automake-1.9 -acf
-#autoconf
-
-autoreconf -i -f -v
diff --git a/drivers/staging/usbip/userspace/cleanup.sh b/drivers/staging/usbip/userspace/cleanup.sh
deleted file mode 100755 (executable)
index 955c3cc..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh
-
-if [ -r Makefile ]; then
-       make distclean
-fi
-
-FILES="aclocal.m4 autom4te.cache compile config.guess config.h.in config.log \
-       config.status config.sub configure cscope.out depcomp install-sh      \
-       libsrc/Makefile libsrc/Makefile.in libtool ltmain.sh Makefile         \
-       Makefile.in missing src/Makefile src/Makefile.in"
-
-rm -vRf $FILES
diff --git a/drivers/staging/usbip/userspace/configure.ac b/drivers/staging/usbip/userspace/configure.ac
deleted file mode 100644 (file)
index 607d05c..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-dnl Process this file with autoconf to produce a configure script.
-
-AC_PREREQ(2.59)
-AC_INIT([usbip-utils], [2.0], [linux-usb@vger.kernel.org])
-AC_DEFINE([USBIP_VERSION], [0x00000111], [binary-coded decimal version number])
-
-CURRENT=0
-REVISION=1
-AGE=0
-AC_SUBST([LIBUSBIP_VERSION], [$CURRENT:$REVISION:$AGE], [library version])
-
-AC_CONFIG_SRCDIR([src/usbipd.c])
-AC_CONFIG_HEADERS([config.h])
-
-AM_INIT_AUTOMAKE([foreign])
-LT_INIT
-
-# Silent build for automake >= 1.11
-m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
-
-AC_SUBST([EXTRA_CFLAGS], ["-Wall -Werror -Wextra -std=gnu99"])
-
-# Checks for programs.
-AC_PROG_CC
-AC_PROG_INSTALL
-AC_PROG_MAKE_SET
-
-# Checks for header files.
-AC_HEADER_DIRENT
-AC_HEADER_STDC
-AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdint.h stdlib.h dnl
-                 string.h sys/socket.h syslog.h unistd.h])
-
-# Checks for typedefs, structures, and compiler characteristics.
-AC_TYPE_INT32_T
-AC_TYPE_SIZE_T
-AC_TYPE_SSIZE_T
-AC_TYPE_UINT16_T
-AC_TYPE_UINT32_T
-AC_TYPE_UINT8_T
-
-# Checks for library functions.
-AC_FUNC_REALLOC
-AC_CHECK_FUNCS([memset mkdir regcomp socket strchr strerror strstr dnl
-               strtoul])
-
-AC_CHECK_HEADER([libudev.h],
-               [AC_CHECK_LIB([udev], [udev_new],
-                             [LIBS="$LIBS -ludev"],
-                             [AC_MSG_ERROR([Missing udev library!])])],
-               [AC_MSG_ERROR([Missing /usr/include/libudev.h])])
-
-# Checks for libwrap library.
-AC_MSG_CHECKING([whether to use the libwrap (TCP wrappers) library])
-AC_ARG_WITH([tcp-wrappers],
-           [AS_HELP_STRING([--with-tcp-wrappers],
-                           [use the libwrap (TCP wrappers) library])],
-           dnl [ACTION-IF-GIVEN]
-           [if test "$withval" = "yes"; then
-                    AC_MSG_RESULT([yes])
-                    AC_MSG_CHECKING([for hosts_access in -lwrap])
-                    saved_LIBS="$LIBS"
-                    LIBS="-lwrap $saved_LIBS"
-                    AC_TRY_LINK(
-                      [int hosts_access(); int allow_severity, deny_severity;],
-                      [hosts_access()],
-                      [AC_MSG_RESULT([yes]);
-                       AC_DEFINE([HAVE_LIBWRAP], [1],
-                                 [use tcp wrapper]) wrap_LIB="-lwrap"],
-                      [AC_MSG_RESULT([not found]); exit 1])
-            else
-                    AC_MSG_RESULT([no]);
-            fi],
-           dnl [ACTION-IF-NOT-GIVEN]
-           [AC_MSG_RESULT([(default)])
-            AC_MSG_CHECKING([for hosts_access in -lwrap])
-            saved_LIBS="$LIBS"
-            LIBS="-lwrap $saved_LIBS"
-            AC_TRY_LINK(
-              [int hosts_access(); int allow_severity, deny_severity;],
-              [hosts_access()],
-              [AC_MSG_RESULT([yes]);
-               AC_DEFINE([HAVE_LIBWRAP], [1], [use tcp wrapper])],
-              [AC_MSG_RESULT([no]); LIBS="$saved_LIBS"])])
-
-# Sets directory containing usb.ids.
-AC_ARG_WITH([usbids-dir],
-           [AS_HELP_STRING([--with-usbids-dir=DIR],
-              [where usb.ids is found (default /usr/share/hwdata/)])],
-           [USBIDS_DIR=$withval], [USBIDS_DIR="/usr/share/hwdata/"])
-AC_SUBST([USBIDS_DIR])
-
-# use _FORTIFY_SOURCE
-AC_MSG_CHECKING([whether to use fortify])
-AC_ARG_WITH([fortify],
-           [AS_HELP_STRING([--with-fortify],
-                           [use _FORTIFY_SROUCE option when compiling)])],
-                           dnl [ACTION-IF-GIVEN]
-                           [if test "$withval" = "yes"; then
-                               AC_MSG_RESULT([yes])
-                               CFLAGS="$CFLAGS -D_FORTIFY_SOURCE -O"
-                            else
-                               AC_MSG_RESULT([no])
-                               CFLAGS="$CFLAGS -U_FORTIFY_SOURCE"
-                            fi
-                           ],
-                           dnl [ACTION-IF-NOT-GIVEN]
-                           [AC_MSG_RESULT([default])])
-
-AC_CONFIG_FILES([Makefile libsrc/Makefile src/Makefile])
-AC_OUTPUT
diff --git a/drivers/staging/usbip/userspace/doc/usbip.8 b/drivers/staging/usbip/userspace/doc/usbip.8
deleted file mode 100644 (file)
index a6097be..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-.TH USBIP "8" "February 2009" "usbip" "System Administration Utilities"
-.SH NAME
-usbip \- manage USB/IP devices
-.SH SYNOPSIS
-.B usbip
-[\fIoptions\fR] <\fIcommand\fR> <\fIargs\fR>
-
-.SH DESCRIPTION
-On a USB/IP server, devices can be listed, bound, and unbound using
-this program.  On a USB/IP client, devices exported by USB/IP servers
-can be listed, attached and detached.
-
-.SH OPTIONS
-.HP
-\fB\-\-debug\fR
-.IP
-Print debugging information.
-.PP
-
-.HP
-\fB\-\-log\fR
-.IP
-Log to syslog.
-.PP
-
-.HP
-\fB\-\-tcp-port PORT\fR
-.IP
-Connect to PORT on remote host (used for attach and list --remote).
-.PP
-
-.SH COMMANDS
-.HP
-\fBversion\fR
-.IP
-Show version and exit.
-.PP
-
-.HP
-\fBhelp\fR [\fIcommand\fR]
-.IP
-Print the program help message, or help on a specific command, and
-then exit.
-.PP
-
-.HP
-\fBattach\fR \-\-remote=<\fIhost\fR> \-\-busid=<\fIbus_id\fR>
-.IP
-Attach a remote USB device.
-.PP
-
-.HP
-\fBdetach\fR \-\-port=<\fIport\fR>
-.IP
-Detach an imported USB device.
-.PP
-
-.HP
-\fBbind\fR \-\-busid=<\fIbusid\fR>
-.IP
-Make a device exportable.
-.PP
-
-.HP
-\fBunbind\fR \-\-busid=<\fIbusid\fR>
-.IP
-Stop exporting a device so it can be used by a local driver.
-.PP
-
-.HP
-\fBlist\fR \-\-remote=<\fIhost\fR>
-.IP
-List USB devices exported by a remote host.
-.PP
-
-.HP
-\fBlist\fR \-\-local
-.IP
-List local USB devices.
-.PP
-
-
-.SH EXAMPLES
-
-    client:# usbip list --remote=server
-        - List exportable usb devices on the server.
-
-    client:# usbip attach --remote=server --busid=1-2
-        - Connect the remote USB device.
-
-    client:# usbip detach --port=0
-        - Detach the usb device.
-
-.SH "SEE ALSO"
-\fBusbipd\fP\fB(8)\fB\fP
diff --git a/drivers/staging/usbip/userspace/doc/usbipd.8 b/drivers/staging/usbip/userspace/doc/usbipd.8
deleted file mode 100644 (file)
index ac4635d..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-.TH USBIP "8" "February 2009" "usbip" "System Administration Utilities"
-.SH NAME
-usbipd \- USB/IP server daemon
-.SH SYNOPSIS
-.B usbipd
-[\fIoptions\fR]
-
-.SH DESCRIPTION
-.B usbipd
-provides USB/IP clients access to exported USB devices.
-
-Devices have to explicitly be exported using
-.B usbip bind
-before usbipd makes them available to other hosts.
-
-The daemon accepts connections from USB/IP clients
-on TCP port 3240 by default.
-
-.SH OPTIONS
-.HP
-\fB\-4\fR, \fB\-\-ipv4\fR
-.IP
-Bind to IPv4. Default is both.
-.PP
-
-.HP
-\fB\-6\fR, \fB\-\-ipv6\fR
-.IP
-Bind to IPv6. Default is both.
-.PP
-
-.HP
-\fB\-D\fR, \fB\-\-daemon\fR
-.IP
-Run as a daemon process.
-.PP
-
-.HP
-\fB\-d\fR, \fB\-\-debug\fR
-.IP
-Print debugging information.
-.PP
-
-.HP
-\fB\-PFILE\fR, \fB\-\-pid FILE\fR
-.IP
-Write process id to FILE.
-.br
-If no FILE specified, use /var/run/usbipd.pid
-.PP
-
-\fB\-tPORT\fR, \fB\-\-tcp\-port PORT\fR
-.IP
-Listen on TCP/IP port PORT.
-.PP
-
-\fB\-h\fR, \fB\-\-help\fR
-.IP
-Print the program help message and exit.
-.PP
-
-.HP
-\fB\-v\fR, \fB\-\-version\fR
-.IP
-Show version.
-.PP
-
-.SH LIMITATIONS
-
-.B usbipd
-offers no authentication or authorization for USB/IP. Any
-USB/IP client can connect and use exported devices.
-
-.SH EXAMPLES
-
-    server:# modprobe usbip
-
-    server:# usbipd -D
-        - Start usbip daemon.
-
-    server:# usbip list --local
-        - List driver assignments for usb devices.
-
-    server:# usbip bind --busid=1-2
-        - Bind usbip-host.ko to the device of busid 1-2.
-        - A usb device 1-2 is now exportable to other hosts!
-        - Use 'usbip unbind --busid=1-2' when you want to shutdown exporting and use the device locally.
-
-.SH "SEE ALSO"
-\fBusbip\fP\fB(8)\fB\fP
-
diff --git a/drivers/staging/usbip/userspace/libsrc/Makefile.am b/drivers/staging/usbip/userspace/libsrc/Makefile.am
deleted file mode 100644 (file)
index 7c8f8a4..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-libusbip_la_CPPFLAGS = -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"'
-libusbip_la_CFLAGS   = @EXTRA_CFLAGS@
-libusbip_la_LDFLAGS  = -version-info @LIBUSBIP_VERSION@
-
-lib_LTLIBRARIES := libusbip.la
-libusbip_la_SOURCES := names.c names.h usbip_host_driver.c usbip_host_driver.h \
-                      usbip_common.c usbip_common.h vhci_driver.c vhci_driver.h \
-                      sysfs_utils.c sysfs_utils.h
diff --git a/drivers/staging/usbip/userspace/libsrc/list.h b/drivers/staging/usbip/userspace/libsrc/list.h
deleted file mode 100644 (file)
index 8d0c936..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-#ifndef _LIST_H
-#define _LIST_H
-
-/* Stripped down implementation of linked list taken
- * from the Linux Kernel.
- */
-
-/*
- * Simple doubly linked list implementation.
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole lists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
-
-struct list_head {
-       struct list_head *next, *prev;
-};
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
-       struct list_head name = LIST_HEAD_INIT(name)
-
-static inline void INIT_LIST_HEAD(struct list_head *list)
-{
-       list->next = list;
-       list->prev = list;
-}
-
-/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_add(struct list_head *new,
-                             struct list_head *prev,
-                             struct list_head *next)
-{
-       next->prev = new;
-       new->next = next;
-       new->prev = prev;
-       prev->next = new;
-}
-
-/**
- * list_add - add a new entry
- * @new: new entry to be added
- * @head: list head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-static inline void list_add(struct list_head *new, struct list_head *head)
-{
-       __list_add(new, head, head->next);
-}
-
-/*
- * Delete a list entry by making the prev/next entries
- * point to each other.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
- */
-static inline void __list_del(struct list_head * prev, struct list_head * next)
-{
-       next->prev = prev;
-       prev->next = next;
-}
-
-#define POISON_POINTER_DELTA 0
-#define LIST_POISON1  ((void *) 0x00100100 + POISON_POINTER_DELTA)
-#define LIST_POISON2  ((void *) 0x00200200 + POISON_POINTER_DELTA)
-
-/**
- * list_del - deletes entry from list.
- * @entry: the element to delete from the list.
- * Note: list_empty() on entry does not return true after this, the entry is
- * in an undefined state.
- */
-static inline void __list_del_entry(struct list_head *entry)
-{
-       __list_del(entry->prev, entry->next);
-}
-
-static inline void list_del(struct list_head *entry)
-{
-       __list_del(entry->prev, entry->next);
-       entry->next = LIST_POISON1;
-       entry->prev = LIST_POISON2;
-}
-
-/**
- * list_entry - get the struct for this entry
- * @ptr:       the &struct list_head pointer.
- * @type:      the type of the struct this is embedded in.
- * @member:    the name of the list_struct within the struct.
- */
-#define list_entry(ptr, type, member) \
-       container_of(ptr, type, member)
-/**
- * list_for_each       -       iterate over a list
- * @pos:       the &struct list_head to use as a loop cursor.
- * @head:      the head for your list.
- */
-#define list_for_each(pos, head) \
-       for (pos = (head)->next; pos != (head); pos = pos->next)
-
-/**
- * list_for_each_safe - iterate over a list safe against removal of list entry
- * @pos:       the &struct list_head to use as a loop cursor.
- * @n:         another &struct list_head to use as temporary storage
- * @head:      the head for your list.
- */
-#define list_for_each_safe(pos, n, head) \
-       for (pos = (head)->next, n = pos->next; pos != (head); \
-               pos = n, n = pos->next)
-
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
-
-/**
- * container_of - cast a member of a structure out to the containing structure
- * @ptr:       the pointer to the member.
- * @type:      the type of the container struct this is embedded in.
- * @member:    the name of the member within the struct.
- *
- */
-#define container_of(ptr, type, member) ({                     \
-       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
-       (type *)( (char *)__mptr - offsetof(type,member) );})
-
-#endif
diff --git a/drivers/staging/usbip/userspace/libsrc/names.c b/drivers/staging/usbip/userspace/libsrc/names.c
deleted file mode 100644 (file)
index 81ff852..0000000
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
- *      names.c  --  USB name database manipulation routines
- *
- *      Copyright (C) 1999, 2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *
- *
- *
- *     Copyright (C) 2005 Takahiro Hirofuchi
- *             - names_deinit() is added.
- *
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#include "names.h"
-#include "usbip_common.h"
-
-struct vendor {
-       struct vendor *next;
-       u_int16_t vendorid;
-       char name[1];
-};
-
-struct product {
-       struct product *next;
-       u_int16_t vendorid, productid;
-       char name[1];
-};
-
-struct class {
-       struct class *next;
-       u_int8_t classid;
-       char name[1];
-};
-
-struct subclass {
-       struct subclass *next;
-       u_int8_t classid, subclassid;
-       char name[1];
-};
-
-struct protocol {
-       struct protocol *next;
-       u_int8_t classid, subclassid, protocolid;
-       char name[1];
-};
-
-struct genericstrtable {
-       struct genericstrtable *next;
-       unsigned int num;
-       char name[1];
-};
-
-
-#define HASH1  0x10
-#define HASH2  0x02
-#define HASHSZ 16
-
-static unsigned int hashnum(unsigned int num)
-{
-       unsigned int mask1 = HASH1 << 27, mask2 = HASH2 << 27;
-
-       for (; mask1 >= HASH1; mask1 >>= 1, mask2 >>= 1)
-               if (num & mask1)
-                       num ^= mask2;
-       return num & (HASHSZ-1);
-}
-
-
-static struct vendor *vendors[HASHSZ] = { NULL, };
-static struct product *products[HASHSZ] = { NULL, };
-static struct class *classes[HASHSZ] = { NULL, };
-static struct subclass *subclasses[HASHSZ] = { NULL, };
-static struct protocol *protocols[HASHSZ] = { NULL, };
-
-const char *names_vendor(u_int16_t vendorid)
-{
-       struct vendor *v;
-
-       v = vendors[hashnum(vendorid)];
-       for (; v; v = v->next)
-               if (v->vendorid == vendorid)
-                       return v->name;
-       return NULL;
-}
-
-const char *names_product(u_int16_t vendorid, u_int16_t productid)
-{
-       struct product *p;
-
-       p = products[hashnum((vendorid << 16) | productid)];
-       for (; p; p = p->next)
-               if (p->vendorid == vendorid && p->productid == productid)
-                       return p->name;
-       return NULL;
-}
-
-const char *names_class(u_int8_t classid)
-{
-       struct class *c;
-
-       c = classes[hashnum(classid)];
-       for (; c; c = c->next)
-               if (c->classid == classid)
-                       return c->name;
-       return NULL;
-}
-
-const char *names_subclass(u_int8_t classid, u_int8_t subclassid)
-{
-       struct subclass *s;
-
-       s = subclasses[hashnum((classid << 8) | subclassid)];
-       for (; s; s = s->next)
-               if (s->classid == classid && s->subclassid == subclassid)
-                       return s->name;
-       return NULL;
-}
-
-const char *names_protocol(u_int8_t classid, u_int8_t subclassid,
-                          u_int8_t protocolid)
-{
-       struct protocol *p;
-
-       p = protocols[hashnum((classid << 16) | (subclassid << 8)
-                             | protocolid)];
-       for (; p; p = p->next)
-               if (p->classid == classid && p->subclassid == subclassid &&
-                   p->protocolid == protocolid)
-                       return p->name;
-       return NULL;
-}
-
-/* add a cleanup function by takahiro */
-struct pool {
-       struct pool *next;
-       void *mem;
-};
-
-static struct pool *pool_head;
-
-static void *my_malloc(size_t size)
-{
-       struct pool *p;
-
-       p = calloc(1, sizeof(struct pool));
-       if (!p)
-               return NULL;
-
-       p->mem = calloc(1, size);
-       if (!p->mem) {
-               free(p);
-               return NULL;
-       }
-
-       p->next = pool_head;
-       pool_head = p;
-
-       return p->mem;
-}
-
-void names_free(void)
-{
-       struct pool *pool;
-
-       if (!pool_head)
-               return;
-
-       for (pool = pool_head; pool != NULL; ) {
-               struct pool *tmp;
-
-               if (pool->mem)
-                       free(pool->mem);
-
-               tmp = pool;
-               pool = pool->next;
-               free(tmp);
-       }
-}
-
-static int new_vendor(const char *name, u_int16_t vendorid)
-{
-       struct vendor *v;
-       unsigned int h = hashnum(vendorid);
-
-       v = vendors[h];
-       for (; v; v = v->next)
-               if (v->vendorid == vendorid)
-                       return -1;
-       v = my_malloc(sizeof(struct vendor) + strlen(name));
-       if (!v)
-               return -1;
-       strcpy(v->name, name);
-       v->vendorid = vendorid;
-       v->next = vendors[h];
-       vendors[h] = v;
-       return 0;
-}
-
-static int new_product(const char *name, u_int16_t vendorid,
-                      u_int16_t productid)
-{
-       struct product *p;
-       unsigned int h = hashnum((vendorid << 16) | productid);
-
-       p = products[h];
-       for (; p; p = p->next)
-               if (p->vendorid == vendorid && p->productid == productid)
-                       return -1;
-       p = my_malloc(sizeof(struct product) + strlen(name));
-       if (!p)
-               return -1;
-       strcpy(p->name, name);
-       p->vendorid = vendorid;
-       p->productid = productid;
-       p->next = products[h];
-       products[h] = p;
-       return 0;
-}
-
-static int new_class(const char *name, u_int8_t classid)
-{
-       struct class *c;
-       unsigned int h = hashnum(classid);
-
-       c = classes[h];
-       for (; c; c = c->next)
-               if (c->classid == classid)
-                       return -1;
-       c = my_malloc(sizeof(struct class) + strlen(name));
-       if (!c)
-               return -1;
-       strcpy(c->name, name);
-       c->classid = classid;
-       c->next = classes[h];
-       classes[h] = c;
-       return 0;
-}
-
-static int new_subclass(const char *name, u_int8_t classid, u_int8_t subclassid)
-{
-       struct subclass *s;
-       unsigned int h = hashnum((classid << 8) | subclassid);
-
-       s = subclasses[h];
-       for (; s; s = s->next)
-               if (s->classid == classid && s->subclassid == subclassid)
-                       return -1;
-       s = my_malloc(sizeof(struct subclass) + strlen(name));
-       if (!s)
-               return -1;
-       strcpy(s->name, name);
-       s->classid = classid;
-       s->subclassid = subclassid;
-       s->next = subclasses[h];
-       subclasses[h] = s;
-       return 0;
-}
-
-static int new_protocol(const char *name, u_int8_t classid, u_int8_t subclassid,
-                       u_int8_t protocolid)
-{
-       struct protocol *p;
-       unsigned int h = hashnum((classid << 16) | (subclassid << 8)
-                                | protocolid);
-
-       p = protocols[h];
-       for (; p; p = p->next)
-               if (p->classid == classid && p->subclassid == subclassid
-                   && p->protocolid == protocolid)
-                       return -1;
-       p = my_malloc(sizeof(struct protocol) + strlen(name));
-       if (!p)
-               return -1;
-       strcpy(p->name, name);
-       p->classid = classid;
-       p->subclassid = subclassid;
-       p->protocolid = protocolid;
-       p->next = protocols[h];
-       protocols[h] = p;
-       return 0;
-}
-
-static void parse(FILE *f)
-{
-       char buf[512], *cp;
-       unsigned int linectr = 0;
-       int lastvendor = -1;
-       int lastclass = -1;
-       int lastsubclass = -1;
-       int lasthut = -1;
-       int lastlang = -1;
-       unsigned int u;
-
-       while (fgets(buf, sizeof(buf), f)) {
-               linectr++;
-               /* remove line ends */
-               cp = strchr(buf, '\r');
-               if (cp)
-                       *cp = 0;
-               cp = strchr(buf, '\n');
-               if (cp)
-                       *cp = 0;
-               if (buf[0] == '#' || !buf[0])
-                       continue;
-               cp = buf;
-               if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' &&
-                   buf[3] == 'S' && buf[4] == 'D' &&
-                   buf[5] == 'E' && buf[6] == 'S' && /*isspace(buf[7])*/
-                   buf[7] == ' ') {
-                       continue;
-               }
-               if (buf[0] == 'P' && buf[1] == 'H' &&
-                   buf[2] == 'Y' && /*isspace(buf[3])*/ buf[3] == ' ') {
-                       continue;
-               }
-               if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A' &&
-                   buf[3] == 'S' && /*isspace(buf[4])*/ buf[4] == ' ') {
-                       continue;
-               }
-               if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') {
-                       lasthut = lastclass = lastvendor = lastsubclass = -1;
-                       /*
-                        * set 1 as pseudo-id to indicate that the parser is
-                        * in a `L' section.
-                        */
-                       lastlang = 1;
-                       continue;
-               }
-               if (buf[0] == 'C' && /*isspace(buf[1])*/ buf[1] == ' ') {
-                       /* class spec */
-                       cp = buf+2;
-                       while (isspace(*cp))
-                               cp++;
-                       if (!isxdigit(*cp)) {
-                               err("Invalid class spec at line %u", linectr);
-                               continue;
-                       }
-                       u = strtoul(cp, &cp, 16);
-                       while (isspace(*cp))
-                               cp++;
-                       if (!*cp) {
-                               err("Invalid class spec at line %u", linectr);
-                               continue;
-                       }
-                       if (new_class(cp, u))
-                               err("Duplicate class spec at line %u class %04x %s",
-                                   linectr, u, cp);
-                       dbg("line %5u class %02x %s", linectr, u, cp);
-                       lasthut = lastlang = lastvendor = lastsubclass = -1;
-                       lastclass = u;
-                       continue;
-               }
-               if (buf[0] == 'A' && buf[1] == 'T' && isspace(buf[2])) {
-                       /* audio terminal type spec */
-                       continue;
-               }
-               if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C'
-                   && isspace(buf[3])) {
-                       /* HID Descriptor bCountryCode */
-                       continue;
-               }
-               if (isxdigit(*cp)) {
-                       /* vendor */
-                       u = strtoul(cp, &cp, 16);
-                       while (isspace(*cp))
-                               cp++;
-                       if (!*cp) {
-                               err("Invalid vendor spec at line %u", linectr);
-                               continue;
-                       }
-                       if (new_vendor(cp, u))
-                               err("Duplicate vendor spec at line %u vendor %04x %s",
-                                   linectr, u, cp);
-                       dbg("line %5u vendor %04x %s", linectr, u, cp);
-                       lastvendor = u;
-                       lasthut = lastlang = lastclass = lastsubclass = -1;
-                       continue;
-               }
-               if (buf[0] == '\t' && isxdigit(buf[1])) {
-                       /* product or subclass spec */
-                       u = strtoul(buf+1, &cp, 16);
-                       while (isspace(*cp))
-                               cp++;
-                       if (!*cp) {
-                               err("Invalid product/subclass spec at line %u",
-                                   linectr);
-                               continue;
-                       }
-                       if (lastvendor != -1) {
-                               if (new_product(cp, lastvendor, u))
-                                       err("Duplicate product spec at line %u product %04x:%04x %s",
-                                           linectr, lastvendor, u, cp);
-                               dbg("line %5u product %04x:%04x %s", linectr,
-                                   lastvendor, u, cp);
-                               continue;
-                       }
-                       if (lastclass != -1) {
-                               if (new_subclass(cp, lastclass, u))
-                                       err("Duplicate subclass spec at line %u class %02x:%02x %s",
-                                           linectr, lastclass, u, cp);
-                               dbg("line %5u subclass %02x:%02x %s", linectr,
-                                   lastclass, u, cp);
-                               lastsubclass = u;
-                               continue;
-                       }
-                       if (lasthut != -1) {
-                               /* do not store hut */
-                               continue;
-                       }
-                       if (lastlang != -1) {
-                               /* do not store langid */
-                               continue;
-                       }
-                       err("Product/Subclass spec without prior Vendor/Class spec at line %u",
-                           linectr);
-                       continue;
-               }
-               if (buf[0] == '\t' && buf[1] == '\t' && isxdigit(buf[2])) {
-                       /* protocol spec */
-                       u = strtoul(buf+2, &cp, 16);
-                       while (isspace(*cp))
-                               cp++;
-                       if (!*cp) {
-                               err("Invalid protocol spec at line %u",
-                                   linectr);
-                               continue;
-                       }
-                       if (lastclass != -1 && lastsubclass != -1) {
-                               if (new_protocol(cp, lastclass, lastsubclass,
-                                                u))
-                                       err("Duplicate protocol spec at line %u class %02x:%02x:%02x %s",
-                                           linectr, lastclass, lastsubclass,
-                                           u, cp);
-                               dbg("line %5u protocol %02x:%02x:%02x %s",
-                                   linectr, lastclass, lastsubclass, u, cp);
-                               continue;
-                       }
-                       err("Protocol spec without prior Class and Subclass spec at line %u",
-                           linectr);
-                       continue;
-               }
-               if (buf[0] == 'H' && buf[1] == 'I' &&
-                   buf[2] == 'D' && /*isspace(buf[3])*/ buf[3] == ' ') {
-                       continue;
-               }
-               if (buf[0] == 'H' && buf[1] == 'U' &&
-                   buf[2] == 'T' && /*isspace(buf[3])*/ buf[3] == ' ') {
-                       lastlang = lastclass = lastvendor = lastsubclass = -1;
-                       /*
-                        * set 1 as pseudo-id to indicate that the parser is
-                        * in a `HUT' section.
-                        */
-                       lasthut = 1;
-                       continue;
-               }
-               if (buf[0] == 'R' && buf[1] == ' ')
-                       continue;
-
-               if (buf[0] == 'V' && buf[1] == 'T')
-                       continue;
-
-               err("Unknown line at line %u", linectr);
-       }
-}
-
-
-int names_init(char *n)
-{
-       FILE *f;
-
-       f = fopen(n, "r");
-       if (!f)
-               return errno;
-
-       parse(f);
-       fclose(f);
-       return 0;
-}
diff --git a/drivers/staging/usbip/userspace/libsrc/names.h b/drivers/staging/usbip/userspace/libsrc/names.h
deleted file mode 100644 (file)
index 6809265..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *      names.h  --  USB name database manipulation routines
- *
- *      Copyright (C) 1999, 2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *      This program is distributed in the hope that it will be useful,
- *      but WITHOUT ANY WARRANTY; without even the implied warranty of
- *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *      GNU General Public License for more details.
- *
- *      You should have received a copy of the GNU General Public License
- *      along with this program; if not, write to the Free Software
- *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- *
- *     Copyright (C) 2005 Takahiro Hirofuchi
- *            - names_free() is added.
- */
-
-#ifndef _NAMES_H
-#define _NAMES_H
-
-#include <sys/types.h>
-
-/* used by usbip_common.c */
-extern const char *names_vendor(u_int16_t vendorid);
-extern const char *names_product(u_int16_t vendorid, u_int16_t productid);
-extern const char *names_class(u_int8_t classid);
-extern const char *names_subclass(u_int8_t classid, u_int8_t subclassid);
-extern const char *names_protocol(u_int8_t classid, u_int8_t subclassid,
-                                 u_int8_t protocolid);
-extern int  names_init(char *n);
-extern void names_free(void);
-
-#endif /* _NAMES_H */
diff --git a/drivers/staging/usbip/userspace/libsrc/sysfs_utils.c b/drivers/staging/usbip/userspace/libsrc/sysfs_utils.c
deleted file mode 100644 (file)
index 36ac88e..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#include "sysfs_utils.h"
-#include "usbip_common.h"
-
-int write_sysfs_attribute(const char *attr_path, const char *new_value,
-                         size_t len)
-{
-       int fd;
-       int length;
-
-       fd = open(attr_path, O_WRONLY);
-       if (fd < 0) {
-               dbg("error opening attribute %s", attr_path);
-               return -1;
-       }
-
-       length = write(fd, new_value, len);
-       if (length < 0) {
-               dbg("error writing to attribute %s", attr_path);
-               close(fd);
-               return -1;
-       }
-
-       close(fd);
-
-       return 0;
-}
diff --git a/drivers/staging/usbip/userspace/libsrc/sysfs_utils.h b/drivers/staging/usbip/userspace/libsrc/sysfs_utils.h
deleted file mode 100644 (file)
index 32ac1d1..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-
-#ifndef __SYSFS_UTILS_H
-#define __SYSFS_UTILS_H
-
-int write_sysfs_attribute(const char *attr_path, const char *new_value,
-                         size_t len);
-
-#endif
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_common.c b/drivers/staging/usbip/userspace/libsrc/usbip_common.c
deleted file mode 100644 (file)
index ac73710..0000000
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright (C) 2005-2007 Takahiro Hirofuchi
- */
-
-#include <libudev.h>
-#include "usbip_common.h"
-#include "names.h"
-
-#undef  PROGNAME
-#define PROGNAME "libusbip"
-
-int usbip_use_syslog;
-int usbip_use_stderr;
-int usbip_use_debug;
-
-extern struct udev *udev_context;
-
-struct speed_string {
-       int num;
-       char *speed;
-       char *desc;
-};
-
-static const struct speed_string speed_strings[] = {
-       { USB_SPEED_UNKNOWN, "unknown", "Unknown Speed"},
-       { USB_SPEED_LOW,  "1.5", "Low Speed(1.5Mbps)"  },
-       { USB_SPEED_FULL, "12",  "Full Speed(12Mbps)" },
-       { USB_SPEED_HIGH, "480", "High Speed(480Mbps)" },
-       { USB_SPEED_WIRELESS, "53.3-480", "Wireless"},
-       { USB_SPEED_SUPER, "5000", "Super Speed(5000Mbps)" },
-       { 0, NULL, NULL }
-};
-
-struct portst_string {
-       int num;
-       char *desc;
-};
-
-static struct portst_string portst_strings[] = {
-       { SDEV_ST_AVAILABLE,    "Device Available" },
-       { SDEV_ST_USED,         "Device in Use" },
-       { SDEV_ST_ERROR,        "Device Error"},
-       { VDEV_ST_NULL,         "Port Available"},
-       { VDEV_ST_NOTASSIGNED,  "Port Initializing"},
-       { VDEV_ST_USED,         "Port in Use"},
-       { VDEV_ST_ERROR,        "Port Error"},
-       { 0, NULL}
-};
-
-const char *usbip_status_string(int32_t status)
-{
-       for (int i = 0; portst_strings[i].desc != NULL; i++)
-               if (portst_strings[i].num == status)
-                       return portst_strings[i].desc;
-
-       return "Unknown Status";
-}
-
-const char *usbip_speed_string(int num)
-{
-       for (int i = 0; speed_strings[i].speed != NULL; i++)
-               if (speed_strings[i].num == num)
-                       return speed_strings[i].desc;
-
-       return "Unknown Speed";
-}
-
-
-#define DBG_UDEV_INTEGER(name)\
-       dbg("%-20s = %x", to_string(name), (int) udev->name)
-
-#define DBG_UINF_INTEGER(name)\
-       dbg("%-20s = %x", to_string(name), (int) uinf->name)
-
-void dump_usb_interface(struct usbip_usb_interface *uinf)
-{
-       char buff[100];
-
-       usbip_names_get_class(buff, sizeof(buff),
-                       uinf->bInterfaceClass,
-                       uinf->bInterfaceSubClass,
-                       uinf->bInterfaceProtocol);
-       dbg("%-20s = %s", "Interface(C/SC/P)", buff);
-}
-
-void dump_usb_device(struct usbip_usb_device *udev)
-{
-       char buff[100];
-
-       dbg("%-20s = %s", "path",  udev->path);
-       dbg("%-20s = %s", "busid", udev->busid);
-
-       usbip_names_get_class(buff, sizeof(buff),
-                       udev->bDeviceClass,
-                       udev->bDeviceSubClass,
-                       udev->bDeviceProtocol);
-       dbg("%-20s = %s", "Device(C/SC/P)", buff);
-
-       DBG_UDEV_INTEGER(bcdDevice);
-
-       usbip_names_get_product(buff, sizeof(buff),
-                       udev->idVendor,
-                       udev->idProduct);
-       dbg("%-20s = %s", "Vendor/Product", buff);
-
-       DBG_UDEV_INTEGER(bNumConfigurations);
-       DBG_UDEV_INTEGER(bNumInterfaces);
-
-       dbg("%-20s = %s", "speed",
-                       usbip_speed_string(udev->speed));
-
-       DBG_UDEV_INTEGER(busnum);
-       DBG_UDEV_INTEGER(devnum);
-}
-
-
-int read_attr_value(struct udev_device *dev, const char *name,
-                   const char *format)
-{
-       const char *attr;
-       int num = 0;
-       int ret;
-
-       attr = udev_device_get_sysattr_value(dev, name);
-       if (!attr) {
-               err("udev_device_get_sysattr_value failed");
-               goto err;
-       }
-
-       /* The client chooses the device configuration
-        * when attaching it so right after being bound
-        * to usbip-host on the server the device will
-        * have no configuration.
-        * Therefore, attributes such as bConfigurationValue
-        * and bNumInterfaces will not exist and sscanf will
-        * fail. Check for these cases and don't treat them
-        * as errors.
-        */
-
-       ret = sscanf(attr, format, &num);
-       if (ret < 1) {
-               if (strcmp(name, "bConfigurationValue") &&
-                               strcmp(name, "bNumInterfaces")) {
-                       err("sscanf failed for attribute %s", name);
-                       goto err;
-               }
-       }
-
-err:
-
-       return num;
-}
-
-
-int read_attr_speed(struct udev_device *dev)
-{
-       const char *speed;
-
-       speed = udev_device_get_sysattr_value(dev, "speed");
-       if (!speed) {
-               err("udev_device_get_sysattr_value failed");
-               goto err;
-       }
-
-       for (int i = 0; speed_strings[i].speed != NULL; i++) {
-               if (!strcmp(speed, speed_strings[i].speed))
-                       return speed_strings[i].num;
-       }
-
-err:
-
-       return USB_SPEED_UNKNOWN;
-}
-
-#define READ_ATTR(object, type, dev, name, format)                           \
-       do {                                                                  \
-               (object)->name = (type) read_attr_value(dev, to_string(name), \
-                                                       format);              \
-       } while (0)
-
-
-int read_usb_device(struct udev_device *sdev, struct usbip_usb_device *udev)
-{
-       uint32_t busnum, devnum;
-       const char *path, *name;
-
-       READ_ATTR(udev, uint8_t,  sdev, bDeviceClass,           "%02x\n");
-       READ_ATTR(udev, uint8_t,  sdev, bDeviceSubClass,        "%02x\n");
-       READ_ATTR(udev, uint8_t,  sdev, bDeviceProtocol,        "%02x\n");
-
-       READ_ATTR(udev, uint16_t, sdev, idVendor,               "%04x\n");
-       READ_ATTR(udev, uint16_t, sdev, idProduct,              "%04x\n");
-       READ_ATTR(udev, uint16_t, sdev, bcdDevice,              "%04x\n");
-
-       READ_ATTR(udev, uint8_t,  sdev, bConfigurationValue,    "%02x\n");
-       READ_ATTR(udev, uint8_t,  sdev, bNumConfigurations,     "%02x\n");
-       READ_ATTR(udev, uint8_t,  sdev, bNumInterfaces,         "%02x\n");
-
-       READ_ATTR(udev, uint8_t,  sdev, devnum,                 "%d\n");
-       udev->speed = read_attr_speed(sdev);
-
-       path = udev_device_get_syspath(sdev);
-       name = udev_device_get_sysname(sdev);
-
-       strncpy(udev->path,  path,  SYSFS_PATH_MAX);
-       strncpy(udev->busid, name, SYSFS_BUS_ID_SIZE);
-
-       sscanf(name, "%u-%u", &busnum, &devnum);
-       udev->busnum = busnum;
-
-       return 0;
-}
-
-int read_usb_interface(struct usbip_usb_device *udev, int i,
-                      struct usbip_usb_interface *uinf)
-{
-       char busid[SYSFS_BUS_ID_SIZE];
-       struct udev_device *sif;
-
-       sprintf(busid, "%s:%d.%d", udev->busid, udev->bConfigurationValue, i);
-
-       sif = udev_device_new_from_subsystem_sysname(udev_context, "usb", busid);
-       if (!sif) {
-               err("udev_device_new_from_subsystem_sysname %s failed", busid);
-               return -1;
-       }
-
-       READ_ATTR(uinf, uint8_t,  sif, bInterfaceClass,         "%02x\n");
-       READ_ATTR(uinf, uint8_t,  sif, bInterfaceSubClass,      "%02x\n");
-       READ_ATTR(uinf, uint8_t,  sif, bInterfaceProtocol,      "%02x\n");
-
-       return 0;
-}
-
-int usbip_names_init(char *f)
-{
-       return names_init(f);
-}
-
-void usbip_names_free(void)
-{
-       names_free();
-}
-
-void usbip_names_get_product(char *buff, size_t size, uint16_t vendor,
-                            uint16_t product)
-{
-       const char *prod, *vend;
-
-       prod = names_product(vendor, product);
-       if (!prod)
-               prod = "unknown product";
-
-
-       vend = names_vendor(vendor);
-       if (!vend)
-               vend = "unknown vendor";
-
-       snprintf(buff, size, "%s : %s (%04x:%04x)", vend, prod, vendor, product);
-}
-
-void usbip_names_get_class(char *buff, size_t size, uint8_t class,
-                          uint8_t subclass, uint8_t protocol)
-{
-       const char *c, *s, *p;
-
-       if (class == 0 && subclass == 0 && protocol == 0) {
-               snprintf(buff, size, "(Defined at Interface level) (%02x/%02x/%02x)", class, subclass, protocol);
-               return;
-       }
-
-       p = names_protocol(class, subclass, protocol);
-       if (!p)
-               p = "unknown protocol";
-
-       s = names_subclass(class, subclass);
-       if (!s)
-               s = "unknown subclass";
-
-       c = names_class(class);
-       if (!c)
-               c = "unknown class";
-
-       snprintf(buff, size, "%s / %s / %s (%02x/%02x/%02x)", c, s, p, class, subclass, protocol);
-}
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_common.h b/drivers/staging/usbip/userspace/libsrc/usbip_common.h
deleted file mode 100644 (file)
index 5a0e95e..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2005-2007 Takahiro Hirofuchi
- */
-
-#ifndef __USBIP_COMMON_H
-#define __USBIP_COMMON_H
-
-#include <libudev.h>
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <syslog.h>
-#include <unistd.h>
-#include <linux/usb/ch9.h>
-#include "../../uapi/usbip.h"
-
-#ifndef USBIDS_FILE
-#define USBIDS_FILE "/usr/share/hwdata/usb.ids"
-#endif
-
-#ifndef VHCI_STATE_PATH
-#define VHCI_STATE_PATH "/var/run/vhci_hcd"
-#endif
-
-/* kernel module names */
-#define USBIP_CORE_MOD_NAME    "usbip-core"
-#define USBIP_HOST_DRV_NAME    "usbip-host"
-#define USBIP_VHCI_DRV_NAME    "vhci_hcd"
-
-/* sysfs constants */
-#define SYSFS_MNT_PATH         "/sys"
-#define SYSFS_BUS_NAME         "bus"
-#define SYSFS_BUS_TYPE         "usb"
-#define SYSFS_DRIVERS_NAME     "drivers"
-
-#define SYSFS_PATH_MAX         256
-#define SYSFS_BUS_ID_SIZE      32
-
-extern int usbip_use_syslog;
-extern int usbip_use_stderr;
-extern int usbip_use_debug ;
-
-#define PROGNAME "usbip"
-
-#define pr_fmt(fmt)    "%s: %s: " fmt "\n", PROGNAME
-#define dbg_fmt(fmt)   pr_fmt("%s:%d:[%s] " fmt), "debug",     \
-                       __FILE__, __LINE__, __func__
-
-#define err(fmt, args...)                                              \
-       do {                                                            \
-               if (usbip_use_syslog) {                                 \
-                       syslog(LOG_ERR, pr_fmt(fmt), "error", ##args);  \
-               }                                                       \
-               if (usbip_use_stderr) {                                 \
-                       fprintf(stderr, pr_fmt(fmt), "error", ##args);  \
-               }                                                       \
-       } while (0)
-
-#define info(fmt, args...)                                             \
-       do {                                                            \
-               if (usbip_use_syslog) {                                 \
-                       syslog(LOG_INFO, pr_fmt(fmt), "info", ##args);  \
-               }                                                       \
-               if (usbip_use_stderr) {                                 \
-                       fprintf(stderr, pr_fmt(fmt), "info", ##args);   \
-               }                                                       \
-       } while (0)
-
-#define dbg(fmt, args...)                                              \
-       do {                                                            \
-       if (usbip_use_debug) {                                          \
-               if (usbip_use_syslog) {                                 \
-                       syslog(LOG_DEBUG, dbg_fmt(fmt), ##args);        \
-               }                                                       \
-               if (usbip_use_stderr) {                                 \
-                       fprintf(stderr, dbg_fmt(fmt), ##args);          \
-               }                                                       \
-       }                                                               \
-       } while (0)
-
-#define BUG()                                          \
-       do {                                            \
-               err("sorry, it's a bug!");              \
-               abort();                                \
-       } while (0)
-
-struct usbip_usb_interface {
-       uint8_t bInterfaceClass;
-       uint8_t bInterfaceSubClass;
-       uint8_t bInterfaceProtocol;
-       uint8_t padding;        /* alignment */
-} __attribute__((packed));
-
-struct usbip_usb_device {
-       char path[SYSFS_PATH_MAX];
-       char busid[SYSFS_BUS_ID_SIZE];
-
-       uint32_t busnum;
-       uint32_t devnum;
-       uint32_t speed;
-
-       uint16_t idVendor;
-       uint16_t idProduct;
-       uint16_t bcdDevice;
-
-       uint8_t bDeviceClass;
-       uint8_t bDeviceSubClass;
-       uint8_t bDeviceProtocol;
-       uint8_t bConfigurationValue;
-       uint8_t bNumConfigurations;
-       uint8_t bNumInterfaces;
-} __attribute__((packed));
-
-#define to_string(s)   #s
-
-void dump_usb_interface(struct usbip_usb_interface *);
-void dump_usb_device(struct usbip_usb_device *);
-int read_usb_device(struct udev_device *sdev, struct usbip_usb_device *udev);
-int read_attr_value(struct udev_device *dev, const char *name,
-                   const char *format);
-int read_usb_interface(struct usbip_usb_device *udev, int i,
-                      struct usbip_usb_interface *uinf);
-
-const char *usbip_speed_string(int num);
-const char *usbip_status_string(int32_t status);
-
-int usbip_names_init(char *);
-void usbip_names_free(void);
-void usbip_names_get_product(char *buff, size_t size, uint16_t vendor,
-                            uint16_t product);
-void usbip_names_get_class(char *buff, size_t size, uint8_t class,
-                          uint8_t subclass, uint8_t protocol);
-
-#endif /* __USBIP_COMMON_H */
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c
deleted file mode 100644 (file)
index bef08d5..0000000
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
- *               2005-2007 Takahiro Hirofuchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <errno.h>
-#include <unistd.h>
-
-#include <libudev.h>
-
-#include "usbip_common.h"
-#include "usbip_host_driver.h"
-#include "list.h"
-#include "sysfs_utils.h"
-
-#undef  PROGNAME
-#define PROGNAME "libusbip"
-
-struct usbip_host_driver *host_driver;
-struct udev *udev_context;
-
-static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
-{
-       char status_attr_path[SYSFS_PATH_MAX];
-       int fd;
-       int length;
-       char status;
-       int value = 0;
-
-       snprintf(status_attr_path, SYSFS_PATH_MAX, "%s/usbip_status",
-                udev->path);
-
-       fd = open(status_attr_path, O_RDONLY);
-       if (fd < 0) {
-               err("error opening attribute %s", status_attr_path);
-               return -1;
-       }
-
-       length = read(fd, &status, 1);
-       if (length < 0) {
-               err("error reading attribute %s", status_attr_path);
-               close(fd);
-               return -1;
-       }
-
-       value = atoi(&status);
-
-       return value;
-}
-
-static
-struct usbip_exported_device *usbip_exported_device_new(const char *sdevpath)
-{
-       struct usbip_exported_device *edev = NULL;
-       struct usbip_exported_device *edev_old;
-       size_t size;
-       int i;
-
-       edev = calloc(1, sizeof(struct usbip_exported_device));
-
-       edev->sudev = udev_device_new_from_syspath(udev_context, sdevpath);
-       if (!edev->sudev) {
-               err("udev_device_new_from_syspath: %s", sdevpath);
-               goto err;
-       }
-
-       read_usb_device(edev->sudev, &edev->udev);
-
-       edev->status = read_attr_usbip_status(&edev->udev);
-       if (edev->status < 0)
-               goto err;
-
-       /* reallocate buffer to include usb interface data */
-       size = sizeof(struct usbip_exported_device) +
-               edev->udev.bNumInterfaces * sizeof(struct usbip_usb_interface);
-
-       edev_old = edev;
-       edev = realloc(edev, size);
-       if (!edev) {
-               edev = edev_old;
-               dbg("realloc failed");
-               goto err;
-       }
-
-       for (i = 0; i < edev->udev.bNumInterfaces; i++)
-               read_usb_interface(&edev->udev, i, &edev->uinf[i]);
-
-       return edev;
-err:
-       if (edev->sudev)
-               udev_device_unref(edev->sudev);
-       if (edev)
-               free(edev);
-
-       return NULL;
-}
-
-static int refresh_exported_devices(void)
-{
-       struct usbip_exported_device *edev;
-       struct udev_enumerate *enumerate;
-       struct udev_list_entry *devices, *dev_list_entry;
-       struct udev_device *dev;
-       const char *path;
-       const char *driver;
-
-       enumerate = udev_enumerate_new(udev_context);
-       udev_enumerate_add_match_subsystem(enumerate, "usb");
-       udev_enumerate_scan_devices(enumerate);
-
-       devices = udev_enumerate_get_list_entry(enumerate);
-
-       udev_list_entry_foreach(dev_list_entry, devices) {
-               path = udev_list_entry_get_name(dev_list_entry);
-               dev = udev_device_new_from_syspath(udev_context, path);
-               if (dev == NULL)
-                       continue;
-
-               /* Check whether device uses usbip-host driver. */
-               driver = udev_device_get_driver(dev);
-               if (driver != NULL && !strcmp(driver, USBIP_HOST_DRV_NAME)) {
-                       edev = usbip_exported_device_new(path);
-                       if (!edev) {
-                               dbg("usbip_exported_device_new failed");
-                               continue;
-                       }
-
-                       list_add(&edev->node, &host_driver->edev_list);
-                       host_driver->ndevs++;
-               }
-       }
-
-       return 0;
-}
-
-static void usbip_exported_device_destroy(void)
-{
-       struct list_head *i, *tmp;
-       struct usbip_exported_device *edev;
-
-       list_for_each_safe(i, tmp, &host_driver->edev_list) {
-               edev = list_entry(i, struct usbip_exported_device, node);
-               list_del(i);
-               free(edev);
-       }
-}
-
-int usbip_host_driver_open(void)
-{
-       int rc;
-
-       udev_context = udev_new();
-       if (!udev_context) {
-               err("udev_new failed");
-               return -1;
-       }
-
-       host_driver = calloc(1, sizeof(*host_driver));
-
-       host_driver->ndevs = 0;
-       INIT_LIST_HEAD(&host_driver->edev_list);
-
-       rc = refresh_exported_devices();
-       if (rc < 0)
-               goto err_free_host_driver;
-
-       return 0;
-
-err_free_host_driver:
-       free(host_driver);
-       host_driver = NULL;
-
-       udev_unref(udev_context);
-
-       return -1;
-}
-
-void usbip_host_driver_close(void)
-{
-       if (!host_driver)
-               return;
-
-       usbip_exported_device_destroy();
-
-       free(host_driver);
-       host_driver = NULL;
-
-       udev_unref(udev_context);
-}
-
-int usbip_host_refresh_device_list(void)
-{
-       int rc;
-
-       usbip_exported_device_destroy();
-
-       host_driver->ndevs = 0;
-       INIT_LIST_HEAD(&host_driver->edev_list);
-
-       rc = refresh_exported_devices();
-       if (rc < 0)
-               return -1;
-
-       return 0;
-}
-
-int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd)
-{
-       char attr_name[] = "usbip_sockfd";
-       char sockfd_attr_path[SYSFS_PATH_MAX];
-       char sockfd_buff[30];
-       int ret;
-
-       if (edev->status != SDEV_ST_AVAILABLE) {
-               dbg("device not available: %s", edev->udev.busid);
-               switch (edev->status) {
-               case SDEV_ST_ERROR:
-                       dbg("status SDEV_ST_ERROR");
-                       break;
-               case SDEV_ST_USED:
-                       dbg("status SDEV_ST_USED");
-                       break;
-               default:
-                       dbg("status unknown: 0x%x", edev->status);
-               }
-               return -1;
-       }
-
-       /* only the first interface is true */
-       snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s",
-                edev->udev.path, attr_name);
-
-       snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd);
-
-       ret = write_sysfs_attribute(sockfd_attr_path, sockfd_buff,
-                                   strlen(sockfd_buff));
-       if (ret < 0) {
-               err("write_sysfs_attribute failed: sockfd %s to %s",
-                   sockfd_buff, sockfd_attr_path);
-               return ret;
-       }
-
-       info("connect: %s", edev->udev.busid);
-
-       return ret;
-}
-
-struct usbip_exported_device *usbip_host_get_device(int num)
-{
-       struct list_head *i;
-       struct usbip_exported_device *edev;
-       int cnt = 0;
-
-       list_for_each(i, &host_driver->edev_list) {
-               edev = list_entry(i, struct usbip_exported_device, node);
-               if (num == cnt)
-                       return edev;
-               else
-                       cnt++;
-       }
-
-       return NULL;
-}
diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.h b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.h
deleted file mode 100644 (file)
index 2a31f85..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
- *               2005-2007 Takahiro Hirofuchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __USBIP_HOST_DRIVER_H
-#define __USBIP_HOST_DRIVER_H
-
-#include <stdint.h>
-#include "usbip_common.h"
-#include "list.h"
-
-struct usbip_host_driver {
-       int ndevs;
-       /* list of exported device */
-       struct list_head edev_list;
-};
-
-struct usbip_exported_device {
-       struct udev_device *sudev;
-       int32_t status;
-       struct usbip_usb_device udev;
-       struct list_head node;
-       struct usbip_usb_interface uinf[];
-};
-
-extern struct usbip_host_driver *host_driver;
-
-int usbip_host_driver_open(void);
-void usbip_host_driver_close(void);
-
-int usbip_host_refresh_device_list(void);
-int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd);
-struct usbip_exported_device *usbip_host_get_device(int num);
-
-#endif /* __USBIP_HOST_DRIVER_H */
diff --git a/drivers/staging/usbip/userspace/libsrc/vhci_driver.c b/drivers/staging/usbip/userspace/libsrc/vhci_driver.c
deleted file mode 100644 (file)
index ad92047..0000000
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * Copyright (C) 2005-2007 Takahiro Hirofuchi
- */
-
-#include "usbip_common.h"
-#include "vhci_driver.h"
-#include <limits.h>
-#include <netdb.h>
-#include <libudev.h>
-#include "sysfs_utils.h"
-
-#undef  PROGNAME
-#define PROGNAME "libusbip"
-
-struct usbip_vhci_driver *vhci_driver;
-struct udev *udev_context;
-
-static struct usbip_imported_device *
-imported_device_init(struct usbip_imported_device *idev, char *busid)
-{
-       struct udev_device *sudev;
-
-       sudev = udev_device_new_from_subsystem_sysname(udev_context,
-                                                      "usb", busid);
-       if (!sudev) {
-               dbg("udev_device_new_from_subsystem_sysname failed: %s", busid);
-               goto err;
-       }
-       read_usb_device(sudev, &idev->udev);
-       udev_device_unref(sudev);
-
-       return idev;
-
-err:
-       return NULL;
-}
-
-
-
-static int parse_status(const char *value)
-{
-       int ret = 0;
-       char *c;
-
-
-       for (int i = 0; i < vhci_driver->nports; i++)
-               memset(&vhci_driver->idev[i], 0, sizeof(vhci_driver->idev[i]));
-
-
-       /* skip a header line */
-       c = strchr(value, '\n');
-       if (!c)
-               return -1;
-       c++;
-
-       while (*c != '\0') {
-               int port, status, speed, devid;
-               unsigned long socket;
-               char lbusid[SYSFS_BUS_ID_SIZE];
-
-               ret = sscanf(c, "%d %d %d %x %lx %31s\n",
-                               &port, &status, &speed,
-                               &devid, &socket, lbusid);
-
-               if (ret < 5) {
-                       dbg("sscanf failed: %d", ret);
-                       BUG();
-               }
-
-               dbg("port %d status %d speed %d devid %x",
-                               port, status, speed, devid);
-               dbg("socket %lx lbusid %s", socket, lbusid);
-
-
-               /* if a device is connected, look at it */
-               {
-                       struct usbip_imported_device *idev = &vhci_driver->idev[port];
-
-                       idev->port      = port;
-                       idev->status    = status;
-
-                       idev->devid     = devid;
-
-                       idev->busnum    = (devid >> 16);
-                       idev->devnum    = (devid & 0x0000ffff);
-
-                       if (idev->status != VDEV_ST_NULL
-                           && idev->status != VDEV_ST_NOTASSIGNED) {
-                               idev = imported_device_init(idev, lbusid);
-                               if (!idev) {
-                                       dbg("imported_device_init failed");
-                                       return -1;
-                               }
-                       }
-               }
-
-
-               /* go to the next line */
-               c = strchr(c, '\n');
-               if (!c)
-                       break;
-               c++;
-       }
-
-       dbg("exit");
-
-       return 0;
-}
-
-static int refresh_imported_device_list(void)
-{
-       const char *attr_status;
-
-       attr_status = udev_device_get_sysattr_value(vhci_driver->hc_device,
-                                              "status");
-       if (!attr_status) {
-               err("udev_device_get_sysattr_value failed");
-               return -1;
-       }
-
-       return parse_status(attr_status);
-}
-
-static int get_nports(void)
-{
-       char *c;
-       int nports = 0;
-       const char *attr_status;
-
-       attr_status = udev_device_get_sysattr_value(vhci_driver->hc_device,
-                                              "status");
-       if (!attr_status) {
-               err("udev_device_get_sysattr_value failed");
-               return -1;
-       }
-
-       /* skip a header line */
-       c = strchr(attr_status, '\n');
-       if (!c)
-               return 0;
-       c++;
-
-       while (*c != '\0') {
-               /* go to the next line */
-               c = strchr(c, '\n');
-               if (!c)
-                       return nports;
-               c++;
-               nports += 1;
-       }
-
-       return nports;
-}
-
-/*
- * Read the given port's record.
- *
- * To avoid buffer overflow we will read the entire line and
- * validate each part's size. The initial buffer is padded by 4 to
- * accommodate the 2 spaces, 1 newline and an additional character
- * which is needed to properly validate the 3rd part without it being
- * truncated to an acceptable length.
- */
-static int read_record(int rhport, char *host, unsigned long host_len,
-               char *port, unsigned long port_len, char *busid)
-{
-       int part;
-       FILE *file;
-       char path[PATH_MAX+1];
-       char *buffer, *start, *end;
-       char delim[] = {' ', ' ', '\n'};
-       int max_len[] = {(int)host_len, (int)port_len, SYSFS_BUS_ID_SIZE};
-       size_t buffer_len = host_len + port_len + SYSFS_BUS_ID_SIZE + 4;
-
-       buffer = malloc(buffer_len);
-       if (!buffer)
-               return -1;
-
-       snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport);
-
-       file = fopen(path, "r");
-       if (!file) {
-               err("fopen");
-               free(buffer);
-               return -1;
-       }
-
-       if (fgets(buffer, buffer_len, file) == NULL) {
-               err("fgets");
-               free(buffer);
-               fclose(file);
-               return -1;
-       }
-       fclose(file);
-
-       /* validate the length of each of the 3 parts */
-       start = buffer;
-       for (part = 0; part < 3; part++) {
-               end = strchr(start, delim[part]);
-               if (end == NULL || (end - start) > max_len[part]) {
-                       free(buffer);
-                       return -1;
-               }
-               start = end + 1;
-       }
-
-       if (sscanf(buffer, "%s %s %s\n", host, port, busid) != 3) {
-               err("sscanf");
-               free(buffer);
-               return -1;
-       }
-
-       free(buffer);
-
-       return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-int usbip_vhci_driver_open(void)
-{
-       udev_context = udev_new();
-       if (!udev_context) {
-               err("udev_new failed");
-               return -1;
-       }
-
-       vhci_driver = calloc(1, sizeof(struct usbip_vhci_driver));
-
-       /* will be freed in usbip_driver_close() */
-       vhci_driver->hc_device =
-               udev_device_new_from_subsystem_sysname(udev_context,
-                                                      USBIP_VHCI_BUS_TYPE,
-                                                      USBIP_VHCI_DRV_NAME);
-       if (!vhci_driver->hc_device) {
-               err("udev_device_new_from_subsystem_sysname failed");
-               goto err;
-       }
-
-       vhci_driver->nports = get_nports();
-
-       dbg("available ports: %d", vhci_driver->nports);
-
-       if (refresh_imported_device_list())
-               goto err;
-
-       return 0;
-
-err:
-       udev_device_unref(vhci_driver->hc_device);
-
-       if (vhci_driver)
-               free(vhci_driver);
-
-       vhci_driver = NULL;
-
-       udev_unref(udev_context);
-
-       return -1;
-}
-
-
-void usbip_vhci_driver_close(void)
-{
-       if (!vhci_driver)
-               return;
-
-       udev_device_unref(vhci_driver->hc_device);
-
-       free(vhci_driver);
-
-       vhci_driver = NULL;
-
-       udev_unref(udev_context);
-}
-
-
-int usbip_vhci_refresh_device_list(void)
-{
-
-       if (refresh_imported_device_list())
-               goto err;
-
-       return 0;
-err:
-       dbg("failed to refresh device list");
-       return -1;
-}
-
-
-int usbip_vhci_get_free_port(void)
-{
-       for (int i = 0; i < vhci_driver->nports; i++) {
-               if (vhci_driver->idev[i].status == VDEV_ST_NULL)
-                       return i;
-       }
-
-       return -1;
-}
-
-int usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid,
-               uint32_t speed) {
-       char buff[200]; /* what size should be ? */
-       char attach_attr_path[SYSFS_PATH_MAX];
-       char attr_attach[] = "attach";
-       const char *path;
-       int ret;
-
-       snprintf(buff, sizeof(buff), "%u %d %u %u",
-                       port, sockfd, devid, speed);
-       dbg("writing: %s", buff);
-
-       path = udev_device_get_syspath(vhci_driver->hc_device);
-       snprintf(attach_attr_path, sizeof(attach_attr_path), "%s/%s",
-                path, attr_attach);
-       dbg("attach attribute path: %s", attach_attr_path);
-
-       ret = write_sysfs_attribute(attach_attr_path, buff, strlen(buff));
-       if (ret < 0) {
-               dbg("write_sysfs_attribute failed");
-               return -1;
-       }
-
-       dbg("attached port: %d", port);
-
-       return 0;
-}
-
-static unsigned long get_devid(uint8_t busnum, uint8_t devnum)
-{
-       return (busnum << 16) | devnum;
-}
-
-/* will be removed */
-int usbip_vhci_attach_device(uint8_t port, int sockfd, uint8_t busnum,
-               uint8_t devnum, uint32_t speed)
-{
-       int devid = get_devid(busnum, devnum);
-
-       return usbip_vhci_attach_device2(port, sockfd, devid, speed);
-}
-
-int usbip_vhci_detach_device(uint8_t port)
-{
-       char detach_attr_path[SYSFS_PATH_MAX];
-       char attr_detach[] = "detach";
-       char buff[200]; /* what size should be ? */
-       const char *path;
-       int ret;
-
-       snprintf(buff, sizeof(buff), "%u", port);
-       dbg("writing: %s", buff);
-
-       path = udev_device_get_syspath(vhci_driver->hc_device);
-       snprintf(detach_attr_path, sizeof(detach_attr_path), "%s/%s",
-                path, attr_detach);
-       dbg("detach attribute path: %s", detach_attr_path);
-
-       ret = write_sysfs_attribute(detach_attr_path, buff, strlen(buff));
-       if (ret < 0) {
-               dbg("write_sysfs_attribute failed");
-               return -1;
-       }
-
-       dbg("detached port: %d", port);
-
-       return 0;
-}
-
-int usbip_vhci_imported_device_dump(struct usbip_imported_device *idev)
-{
-       char product_name[100];
-       char host[NI_MAXHOST] = "unknown host";
-       char serv[NI_MAXSERV] = "unknown port";
-       char remote_busid[SYSFS_BUS_ID_SIZE];
-       int ret;
-       int read_record_error = 0;
-
-       if (idev->status == VDEV_ST_NULL || idev->status == VDEV_ST_NOTASSIGNED)
-               return 0;
-
-       ret = read_record(idev->port, host, sizeof(host), serv, sizeof(serv),
-                         remote_busid);
-       if (ret) {
-               err("read_record");
-               read_record_error = 1;
-       }
-
-       printf("Port %02d: <%s> at %s\n", idev->port,
-              usbip_status_string(idev->status),
-              usbip_speed_string(idev->udev.speed));
-
-       usbip_names_get_product(product_name, sizeof(product_name),
-                               idev->udev.idVendor, idev->udev.idProduct);
-
-       printf("       %s\n",  product_name);
-
-       if (!read_record_error) {
-               printf("%10s -> usbip://%s:%s/%s\n", idev->udev.busid,
-                      host, serv, remote_busid);
-               printf("%10s -> remote bus/dev %03d/%03d\n", " ",
-                      idev->busnum, idev->devnum);
-       } else {
-               printf("%10s -> unknown host, remote port and remote busid\n",
-                      idev->udev.busid);
-               printf("%10s -> remote bus/dev %03d/%03d\n", " ",
-                      idev->busnum, idev->devnum);
-       }
-
-       return 0;
-}
diff --git a/drivers/staging/usbip/userspace/libsrc/vhci_driver.h b/drivers/staging/usbip/userspace/libsrc/vhci_driver.h
deleted file mode 100644 (file)
index fa2316c..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2005-2007 Takahiro Hirofuchi
- */
-
-#ifndef __VHCI_DRIVER_H
-#define __VHCI_DRIVER_H
-
-#include <libudev.h>
-#include <stdint.h>
-
-#include "usbip_common.h"
-
-#define USBIP_VHCI_BUS_TYPE "platform"
-#define MAXNPORT 128
-
-struct usbip_imported_device {
-       uint8_t port;
-       uint32_t status;
-
-       uint32_t devid;
-
-       uint8_t busnum;
-       uint8_t devnum;
-
-       /* usbip_class_device list */
-       struct usbip_usb_device udev;
-};
-
-struct usbip_vhci_driver {
-
-       /* /sys/devices/platform/vhci_hcd */
-       struct udev_device *hc_device;
-
-       int nports;
-       struct usbip_imported_device idev[MAXNPORT];
-};
-
-
-extern struct usbip_vhci_driver *vhci_driver;
-
-int usbip_vhci_driver_open(void);
-void usbip_vhci_driver_close(void);
-
-int  usbip_vhci_refresh_device_list(void);
-
-
-int usbip_vhci_get_free_port(void);
-int usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid,
-               uint32_t speed);
-
-/* will be removed */
-int usbip_vhci_attach_device(uint8_t port, int sockfd, uint8_t busnum,
-               uint8_t devnum, uint32_t speed);
-
-int usbip_vhci_detach_device(uint8_t port);
-
-int usbip_vhci_imported_device_dump(struct usbip_imported_device *idev);
-
-#endif /* __VHCI_DRIVER_H */
diff --git a/drivers/staging/usbip/userspace/src/Makefile.am b/drivers/staging/usbip/userspace/src/Makefile.am
deleted file mode 100644 (file)
index e81a4eb..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-AM_CPPFLAGS = -I$(top_srcdir)/libsrc -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"'
-AM_CFLAGS   = @EXTRA_CFLAGS@
-LDADD       = $(top_builddir)/libsrc/libusbip.la
-
-sbin_PROGRAMS := usbip usbipd
-
-usbip_SOURCES := usbip.h utils.h usbip.c utils.c usbip_network.c \
-                usbip_attach.c usbip_detach.c usbip_list.c \
-                usbip_bind.c usbip_unbind.c usbip_port.c
-
-usbipd_SOURCES := usbip_network.h usbipd.c usbip_network.c
diff --git a/drivers/staging/usbip/userspace/src/usbip.c b/drivers/staging/usbip/userspace/src/usbip.c
deleted file mode 100644 (file)
index d7599d9..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * command structure borrowed from udev
- * (git://git.kernel.org/pub/scm/linux/hotplug/udev.git)
- *
- * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
- *               2005-2007 Takahiro Hirofuchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <getopt.h>
-#include <syslog.h>
-
-#include "usbip_common.h"
-#include "usbip_network.h"
-#include "usbip.h"
-
-static int usbip_help(int argc, char *argv[]);
-static int usbip_version(int argc, char *argv[]);
-
-static const char usbip_version_string[] = PACKAGE_STRING;
-
-static const char usbip_usage_string[] =
-       "usbip [--debug] [--log] [--tcp-port PORT] [version]\n"
-       "             [help] <command> <args>\n";
-
-static void usbip_usage(void)
-{
-       printf("usage: %s", usbip_usage_string);
-}
-
-struct command {
-       const char *name;
-       int (*fn)(int argc, char *argv[]);
-       const char *help;
-       void (*usage)(void);
-};
-
-static const struct command cmds[] = {
-       {
-               .name  = "help",
-               .fn    = usbip_help,
-               .help  = NULL,
-               .usage = NULL
-       },
-       {
-               .name  = "version",
-               .fn    = usbip_version,
-               .help  = NULL,
-               .usage = NULL
-       },
-       {
-               .name  = "attach",
-               .fn    = usbip_attach,
-               .help  = "Attach a remote USB device",
-               .usage = usbip_attach_usage
-       },
-       {
-               .name  = "detach",
-               .fn    = usbip_detach,
-               .help  = "Detach a remote USB device",
-               .usage = usbip_detach_usage
-       },
-       {
-               .name  = "list",
-               .fn    = usbip_list,
-               .help  = "List exportable or local USB devices",
-               .usage = usbip_list_usage
-       },
-       {
-               .name  = "bind",
-               .fn    = usbip_bind,
-               .help  = "Bind device to " USBIP_HOST_DRV_NAME ".ko",
-               .usage = usbip_bind_usage
-       },
-       {
-               .name  = "unbind",
-               .fn    = usbip_unbind,
-               .help  = "Unbind device from " USBIP_HOST_DRV_NAME ".ko",
-               .usage = usbip_unbind_usage
-       },
-       {
-               .name  = "port",
-               .fn    = usbip_port_show,
-               .help  = "Show imported USB devices",
-               .usage = NULL
-       },
-       { NULL, NULL, NULL, NULL }
-};
-
-static int usbip_help(int argc, char *argv[])
-{
-       const struct command *cmd;
-       int i;
-       int ret = 0;
-
-       if (argc > 1 && argv++) {
-               for (i = 0; cmds[i].name != NULL; i++)
-                       if (!strcmp(cmds[i].name, argv[0]) && cmds[i].usage) {
-                               cmds[i].usage();
-                               goto done;
-                       }
-               ret = -1;
-       }
-
-       usbip_usage();
-       printf("\n");
-       for (cmd = cmds; cmd->name != NULL; cmd++)
-               if (cmd->help != NULL)
-                       printf("  %-10s %s\n", cmd->name, cmd->help);
-       printf("\n");
-done:
-       return ret;
-}
-
-static int usbip_version(int argc, char *argv[])
-{
-       (void) argc;
-       (void) argv;
-
-       printf(PROGNAME " (%s)\n", usbip_version_string);
-       return 0;
-}
-
-static int run_command(const struct command *cmd, int argc, char *argv[])
-{
-       dbg("running command: `%s'", cmd->name);
-       return cmd->fn(argc, argv);
-}
-
-int main(int argc, char *argv[])
-{
-       static const struct option opts[] = {
-               { "debug",    no_argument,       NULL, 'd' },
-               { "log",      no_argument,       NULL, 'l' },
-               { "tcp-port", required_argument, NULL, 't' },
-               { NULL,       0,                 NULL,  0  }
-       };
-
-       char *cmd;
-       int opt;
-       int i, rc = -1;
-
-       usbip_use_stderr = 1;
-       opterr = 0;
-       for (;;) {
-               opt = getopt_long(argc, argv, "+dlt:", opts, NULL);
-
-               if (opt == -1)
-                       break;
-
-               switch (opt) {
-               case 'd':
-                       usbip_use_debug = 1;
-                       break;
-               case 'l':
-                       usbip_use_syslog = 1;
-                       openlog("", LOG_PID, LOG_USER);
-                       break;
-               case 't':
-                       usbip_setup_port_number(optarg);
-                       break;
-               case '?':
-                       printf("usbip: invalid option\n");
-               default:
-                       usbip_usage();
-                       goto out;
-               }
-       }
-
-       cmd = argv[optind];
-       if (cmd) {
-               for (i = 0; cmds[i].name != NULL; i++)
-                       if (!strcmp(cmds[i].name, cmd)) {
-                               argc -= optind;
-                               argv += optind;
-                               optind = 0;
-                               rc = run_command(&cmds[i], argc, argv);
-                               goto out;
-                       }
-       }
-
-       /* invalid command */
-       usbip_help(0, NULL);
-out:
-       return (rc > -1 ? EXIT_SUCCESS : EXIT_FAILURE);
-}
diff --git a/drivers/staging/usbip/userspace/src/usbip.h b/drivers/staging/usbip/userspace/src/usbip.h
deleted file mode 100644 (file)
index 84fe66a..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
- *               2005-2007 Takahiro Hirofuchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __USBIP_H
-#define __USBIP_H
-
-#ifdef HAVE_CONFIG_H
-#include "../config.h"
-#endif
-
-/* usbip commands */
-int usbip_attach(int argc, char *argv[]);
-int usbip_detach(int argc, char *argv[]);
-int usbip_list(int argc, char *argv[]);
-int usbip_bind(int argc, char *argv[]);
-int usbip_unbind(int argc, char *argv[]);
-int usbip_port_show(int argc, char *argv[]);
-
-void usbip_attach_usage(void);
-void usbip_detach_usage(void);
-void usbip_list_usage(void);
-void usbip_bind_usage(void);
-void usbip_unbind_usage(void);
-
-#endif /* __USBIP_H */
diff --git a/drivers/staging/usbip/userspace/src/usbip_attach.c b/drivers/staging/usbip/userspace/src/usbip_attach.c
deleted file mode 100644 (file)
index d58a14d..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
- *               2005-2007 Takahiro Hirofuchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <sys/stat.h>
-
-#include <limits.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <fcntl.h>
-#include <getopt.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include "vhci_driver.h"
-#include "usbip_common.h"
-#include "usbip_network.h"
-#include "usbip.h"
-
-static const char usbip_attach_usage_string[] =
-       "usbip attach <args>\n"
-       "    -r, --remote=<host>      The machine with exported USB devices\n"
-       "    -b, --busid=<busid>    Busid of the device on <host>\n";
-
-void usbip_attach_usage(void)
-{
-       printf("usage: %s", usbip_attach_usage_string);
-}
-
-#define MAX_BUFF 100
-static int record_connection(char *host, char *port, char *busid, int rhport)
-{
-       int fd;
-       char path[PATH_MAX+1];
-       char buff[MAX_BUFF+1];
-       int ret;
-
-       ret = mkdir(VHCI_STATE_PATH, 0700);
-       if (ret < 0) {
-               /* if VHCI_STATE_PATH exists, then it better be a directory */
-               if (errno == EEXIST) {
-                       struct stat s;
-
-                       ret = stat(VHCI_STATE_PATH, &s);
-                       if (ret < 0)
-                               return -1;
-                       if (!(s.st_mode & S_IFDIR))
-                               return -1;
-               } else
-                       return -1;
-       }
-
-       snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport);
-
-       fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
-       if (fd < 0)
-               return -1;
-
-       snprintf(buff, MAX_BUFF, "%s %s %s\n",
-                       host, port, busid);
-
-       ret = write(fd, buff, strlen(buff));
-       if (ret != (ssize_t) strlen(buff)) {
-               close(fd);
-               return -1;
-       }
-
-       close(fd);
-
-       return 0;
-}
-
-static int import_device(int sockfd, struct usbip_usb_device *udev)
-{
-       int rc;
-       int port;
-
-       rc = usbip_vhci_driver_open();
-       if (rc < 0) {
-               err("open vhci_driver");
-               return -1;
-       }
-
-       port = usbip_vhci_get_free_port();
-       if (port < 0) {
-               err("no free port");
-               usbip_vhci_driver_close();
-               return -1;
-       }
-
-       rc = usbip_vhci_attach_device(port, sockfd, udev->busnum,
-                                     udev->devnum, udev->speed);
-       if (rc < 0) {
-               err("import device");
-               usbip_vhci_driver_close();
-               return -1;
-       }
-
-       usbip_vhci_driver_close();
-
-       return port;
-}
-
-static int query_import_device(int sockfd, char *busid)
-{
-       int rc;
-       struct op_import_request request;
-       struct op_import_reply   reply;
-       uint16_t code = OP_REP_IMPORT;
-
-       memset(&request, 0, sizeof(request));
-       memset(&reply, 0, sizeof(reply));
-
-       /* send a request */
-       rc = usbip_net_send_op_common(sockfd, OP_REQ_IMPORT, 0);
-       if (rc < 0) {
-               err("send op_common");
-               return -1;
-       }
-
-       strncpy(request.busid, busid, SYSFS_BUS_ID_SIZE-1);
-
-       PACK_OP_IMPORT_REQUEST(0, &request);
-
-       rc = usbip_net_send(sockfd, (void *) &request, sizeof(request));
-       if (rc < 0) {
-               err("send op_import_request");
-               return -1;
-       }
-
-       /* receive a reply */
-       rc = usbip_net_recv_op_common(sockfd, &code);
-       if (rc < 0) {
-               err("recv op_common");
-               return -1;
-       }
-
-       rc = usbip_net_recv(sockfd, (void *) &reply, sizeof(reply));
-       if (rc < 0) {
-               err("recv op_import_reply");
-               return -1;
-       }
-
-       PACK_OP_IMPORT_REPLY(0, &reply);
-
-       /* check the reply */
-       if (strncmp(reply.udev.busid, busid, SYSFS_BUS_ID_SIZE)) {
-               err("recv different busid %s", reply.udev.busid);
-               return -1;
-       }
-
-       /* import a device */
-       return import_device(sockfd, &reply.udev);
-}
-
-static int attach_device(char *host, char *busid)
-{
-       int sockfd;
-       int rc;
-       int rhport;
-
-       sockfd = usbip_net_tcp_connect(host, usbip_port_string);
-       if (sockfd < 0) {
-               err("tcp connect");
-               return -1;
-       }
-
-       rhport = query_import_device(sockfd, busid);
-       if (rhport < 0) {
-               err("query");
-               return -1;
-       }
-
-       close(sockfd);
-
-       rc = record_connection(host, usbip_port_string, busid, rhport);
-       if (rc < 0) {
-               err("record connection");
-               return -1;
-       }
-
-       return 0;
-}
-
-int usbip_attach(int argc, char *argv[])
-{
-       static const struct option opts[] = {
-               { "remote", required_argument, NULL, 'r' },
-               { "busid",  required_argument, NULL, 'b' },
-               { NULL, 0,  NULL, 0 }
-       };
-       char *host = NULL;
-       char *busid = NULL;
-       int opt;
-       int ret = -1;
-
-       for (;;) {
-               opt = getopt_long(argc, argv, "r:b:", opts, NULL);
-
-               if (opt == -1)
-                       break;
-
-               switch (opt) {
-               case 'r':
-                       host = optarg;
-                       break;
-               case 'b':
-                       busid = optarg;
-                       break;
-               default:
-                       goto err_out;
-               }
-       }
-
-       if (!host || !busid)
-               goto err_out;
-
-       ret = attach_device(host, busid);
-       goto out;
-
-err_out:
-       usbip_attach_usage();
-out:
-       return ret;
-}
diff --git a/drivers/staging/usbip/userspace/src/usbip_bind.c b/drivers/staging/usbip/userspace/src/usbip_bind.c
deleted file mode 100644 (file)
index fa46141..0000000
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
- *               2005-2007 Takahiro Hirofuchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <libudev.h>
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <getopt.h>
-
-#include "usbip_common.h"
-#include "utils.h"
-#include "usbip.h"
-#include "sysfs_utils.h"
-
-enum unbind_status {
-       UNBIND_ST_OK,
-       UNBIND_ST_USBIP_HOST,
-       UNBIND_ST_FAILED
-};
-
-static const char usbip_bind_usage_string[] =
-       "usbip bind <args>\n"
-       "    -b, --busid=<busid>    Bind " USBIP_HOST_DRV_NAME ".ko to device "
-       "on <busid>\n";
-
-void usbip_bind_usage(void)
-{
-       printf("usage: %s", usbip_bind_usage_string);
-}
-
-/* call at unbound state */
-static int bind_usbip(char *busid)
-{
-       char attr_name[] = "bind";
-       char bind_attr_path[SYSFS_PATH_MAX];
-       int rc = -1;
-
-       snprintf(bind_attr_path, sizeof(bind_attr_path), "%s/%s/%s/%s/%s/%s",
-                SYSFS_MNT_PATH, SYSFS_BUS_NAME, SYSFS_BUS_TYPE,
-                SYSFS_DRIVERS_NAME, USBIP_HOST_DRV_NAME, attr_name);
-
-       rc = write_sysfs_attribute(bind_attr_path, busid, strlen(busid));
-       if (rc < 0) {
-               err("error binding device %s to driver: %s", busid,
-                   strerror(errno));
-               return -1;
-       }
-
-       return 0;
-}
-
-/* buggy driver may cause dead lock */
-static int unbind_other(char *busid)
-{
-       enum unbind_status status = UNBIND_ST_OK;
-
-       char attr_name[] = "unbind";
-       char unbind_attr_path[SYSFS_PATH_MAX];
-       int rc = -1;
-
-       struct udev *udev;
-       struct udev_device *dev;
-       const char *driver;
-       const char *bDevClass;
-
-       /* Create libudev context. */
-       udev = udev_new();
-
-       /* Get the device. */
-       dev = udev_device_new_from_subsystem_sysname(udev, "usb", busid);
-       if (!dev) {
-               dbg("unable to find device with bus ID %s", busid);
-               goto err_close_busid_dev;
-       }
-
-       /* Check what kind of device it is. */
-       bDevClass  = udev_device_get_sysattr_value(dev, "bDeviceClass");
-       if (!bDevClass) {
-               dbg("unable to get bDevClass device attribute");
-               goto err_close_busid_dev;
-       }
-
-       if (!strncmp(bDevClass, "09", strlen(bDevClass))) {
-               dbg("skip unbinding of hub");
-               goto err_close_busid_dev;
-       }
-
-       /* Get the device driver. */
-       driver = udev_device_get_driver(dev);
-       if (!driver) {
-               /* No driver bound to this device. */
-               goto out;
-       }
-
-       if (!strncmp(USBIP_HOST_DRV_NAME, driver,
-                               strlen(USBIP_HOST_DRV_NAME))) {
-               /* Already bound to usbip-host. */
-               status = UNBIND_ST_USBIP_HOST;
-               goto out;
-       }
-
-       /* Unbind device from driver. */
-       snprintf(unbind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",
-                SYSFS_MNT_PATH, SYSFS_BUS_NAME, SYSFS_BUS_TYPE,
-                SYSFS_DRIVERS_NAME, driver, attr_name);
-
-       rc = write_sysfs_attribute(unbind_attr_path, busid, strlen(busid));
-       if (rc < 0) {
-               err("error unbinding device %s from driver", busid);
-               goto err_close_busid_dev;
-       }
-
-       goto out;
-
-err_close_busid_dev:
-       status = UNBIND_ST_FAILED;
-out:
-       udev_device_unref(dev);
-       udev_unref(udev);
-
-       return status;
-}
-
-static int bind_device(char *busid)
-{
-       int rc;
-       struct udev *udev;
-       struct udev_device *dev;
-
-       /* Check whether the device with this bus ID exists. */
-       udev = udev_new();
-       dev = udev_device_new_from_subsystem_sysname(udev, "usb", busid);
-       if (!dev) {
-               err("device with the specified bus ID does not exist");
-               return -1;
-       }
-       udev_unref(udev);
-
-       rc = unbind_other(busid);
-       if (rc == UNBIND_ST_FAILED) {
-               err("could not unbind driver from device on busid %s", busid);
-               return -1;
-       } else if (rc == UNBIND_ST_USBIP_HOST) {
-               err("device on busid %s is already bound to %s", busid,
-                   USBIP_HOST_DRV_NAME);
-               return -1;
-       }
-
-       rc = modify_match_busid(busid, 1);
-       if (rc < 0) {
-               err("unable to bind device on %s", busid);
-               return -1;
-       }
-
-       rc = bind_usbip(busid);
-       if (rc < 0) {
-               err("could not bind device to %s", USBIP_HOST_DRV_NAME);
-               modify_match_busid(busid, 0);
-               return -1;
-       }
-
-       info("bind device on busid %s: complete", busid);
-
-       return 0;
-}
-
-int usbip_bind(int argc, char *argv[])
-{
-       static const struct option opts[] = {
-               { "busid", required_argument, NULL, 'b' },
-               { NULL,    0,                 NULL,  0  }
-       };
-
-       int opt;
-       int ret = -1;
-
-       for (;;) {
-               opt = getopt_long(argc, argv, "b:", opts, NULL);
-
-               if (opt == -1)
-                       break;
-
-               switch (opt) {
-               case 'b':
-                       ret = bind_device(optarg);
-                       goto out;
-               default:
-                       goto err_out;
-               }
-       }
-
-err_out:
-       usbip_bind_usage();
-out:
-       return ret;
-}
diff --git a/drivers/staging/usbip/userspace/src/usbip_detach.c b/drivers/staging/usbip/userspace/src/usbip_detach.c
deleted file mode 100644 (file)
index 05c6d15..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
- *               2005-2007 Takahiro Hirofuchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <ctype.h>
-#include <limits.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <getopt.h>
-#include <unistd.h>
-
-#include "vhci_driver.h"
-#include "usbip_common.h"
-#include "usbip_network.h"
-#include "usbip.h"
-
-static const char usbip_detach_usage_string[] =
-       "usbip detach <args>\n"
-       "    -p, --port=<port>    " USBIP_VHCI_DRV_NAME
-       " port the device is on\n";
-
-void usbip_detach_usage(void)
-{
-       printf("usage: %s", usbip_detach_usage_string);
-}
-
-static int detach_port(char *port)
-{
-       int ret;
-       uint8_t portnum;
-       char path[PATH_MAX+1];
-
-       for (unsigned int i = 0; i < strlen(port); i++)
-               if (!isdigit(port[i])) {
-                       err("invalid port %s", port);
-                       return -1;
-               }
-
-       /* check max port */
-
-       portnum = atoi(port);
-
-       /* remove the port state file */
-
-       snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", portnum);
-
-       remove(path);
-       rmdir(VHCI_STATE_PATH);
-
-       ret = usbip_vhci_driver_open();
-       if (ret < 0) {
-               err("open vhci_driver");
-               return -1;
-       }
-
-       ret = usbip_vhci_detach_device(portnum);
-       if (ret < 0)
-               return -1;
-
-       usbip_vhci_driver_close();
-
-       return ret;
-}
-
-int usbip_detach(int argc, char *argv[])
-{
-       static const struct option opts[] = {
-               { "port", required_argument, NULL, 'p' },
-               { NULL, 0, NULL, 0 }
-       };
-       int opt;
-       int ret = -1;
-
-       for (;;) {
-               opt = getopt_long(argc, argv, "p:", opts, NULL);
-
-               if (opt == -1)
-                       break;
-
-               switch (opt) {
-               case 'p':
-                       ret = detach_port(optarg);
-                       goto out;
-               default:
-                       goto err_out;
-               }
-       }
-
-err_out:
-       usbip_detach_usage();
-out:
-       return ret;
-}
diff --git a/drivers/staging/usbip/userspace/src/usbip_list.c b/drivers/staging/usbip/userspace/src/usbip_list.c
deleted file mode 100644 (file)
index d5ce34a..0000000
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
- *               2005-2007 Takahiro Hirofuchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <sys/types.h>
-#include <libudev.h>
-
-#include <errno.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <getopt.h>
-#include <netdb.h>
-#include <unistd.h>
-
-#include "usbip_common.h"
-#include "usbip_network.h"
-#include "usbip.h"
-
-static const char usbip_list_usage_string[] =
-       "usbip list [-p|--parsable] <args>\n"
-       "    -p, --parsable         Parsable list format\n"
-       "    -r, --remote=<host>    List the exportable USB devices on <host>\n"
-       "    -l, --local            List the local USB devices\n";
-
-void usbip_list_usage(void)
-{
-       printf("usage: %s", usbip_list_usage_string);
-}
-
-static int get_exported_devices(char *host, int sockfd)
-{
-       char product_name[100];
-       char class_name[100];
-       struct op_devlist_reply reply;
-       uint16_t code = OP_REP_DEVLIST;
-       struct usbip_usb_device udev;
-       struct usbip_usb_interface uintf;
-       unsigned int i;
-       int rc, j;
-
-       rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0);
-       if (rc < 0) {
-               dbg("usbip_net_send_op_common failed");
-               return -1;
-       }
-
-       rc = usbip_net_recv_op_common(sockfd, &code);
-       if (rc < 0) {
-               dbg("usbip_net_recv_op_common failed");
-               return -1;
-       }
-
-       memset(&reply, 0, sizeof(reply));
-       rc = usbip_net_recv(sockfd, &reply, sizeof(reply));
-       if (rc < 0) {
-               dbg("usbip_net_recv_op_devlist failed");
-               return -1;
-       }
-       PACK_OP_DEVLIST_REPLY(0, &reply);
-       dbg("exportable devices: %d\n", reply.ndev);
-
-       if (reply.ndev == 0) {
-               info("no exportable devices found on %s", host);
-               return 0;
-       }
-
-       printf("Exportable USB devices\n");
-       printf("======================\n");
-       printf(" - %s\n", host);
-
-       for (i = 0; i < reply.ndev; i++) {
-               memset(&udev, 0, sizeof(udev));
-               rc = usbip_net_recv(sockfd, &udev, sizeof(udev));
-               if (rc < 0) {
-                       dbg("usbip_net_recv failed: usbip_usb_device[%d]", i);
-                       return -1;
-               }
-               usbip_net_pack_usb_device(0, &udev);
-
-               usbip_names_get_product(product_name, sizeof(product_name),
-                                       udev.idVendor, udev.idProduct);
-               usbip_names_get_class(class_name, sizeof(class_name),
-                                     udev.bDeviceClass, udev.bDeviceSubClass,
-                                     udev.bDeviceProtocol);
-               printf("%11s: %s\n", udev.busid, product_name);
-               printf("%11s: %s\n", "", udev.path);
-               printf("%11s: %s\n", "", class_name);
-
-               for (j = 0; j < udev.bNumInterfaces; j++) {
-                       rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf));
-                       if (rc < 0) {
-                               err("usbip_net_recv failed: usbip_usb_intf[%d]",
-                                               j);
-
-                               return -1;
-                       }
-                       usbip_net_pack_usb_interface(0, &uintf);
-
-                       usbip_names_get_class(class_name, sizeof(class_name),
-                                       uintf.bInterfaceClass,
-                                       uintf.bInterfaceSubClass,
-                                       uintf.bInterfaceProtocol);
-                       printf("%11s: %2d - %s\n", "", j, class_name);
-               }
-
-               printf("\n");
-       }
-
-       return 0;
-}
-
-static int list_exported_devices(char *host)
-{
-       int rc;
-       int sockfd;
-
-       sockfd = usbip_net_tcp_connect(host, usbip_port_string);
-       if (sockfd < 0) {
-               err("could not connect to %s:%s: %s", host,
-                   usbip_port_string, gai_strerror(sockfd));
-               return -1;
-       }
-       dbg("connected to %s:%s", host, usbip_port_string);
-
-       rc = get_exported_devices(host, sockfd);
-       if (rc < 0) {
-               err("failed to get device list from %s", host);
-               return -1;
-       }
-
-       close(sockfd);
-
-       return 0;
-}
-
-static void print_device(const char *busid, const char *vendor,
-                        const char *product, bool parsable)
-{
-       if (parsable)
-               printf("busid=%s#usbid=%.4s:%.4s#", busid, vendor, product);
-       else
-               printf(" - busid %s (%.4s:%.4s)\n", busid, vendor, product);
-}
-
-static void print_product_name(char *product_name, bool parsable)
-{
-       if (!parsable)
-               printf("   %s\n", product_name);
-}
-
-static int list_devices(bool parsable)
-{
-       struct udev *udev;
-       struct udev_enumerate *enumerate;
-       struct udev_list_entry *devices, *dev_list_entry;
-       struct udev_device *dev;
-       const char *path;
-       const char *idVendor;
-       const char *idProduct;
-       const char *bConfValue;
-       const char *bNumIntfs;
-       const char *busid;
-       char product_name[128];
-       int ret = -1;
-
-       /* Create libudev context. */
-       udev = udev_new();
-
-       /* Create libudev device enumeration. */
-       enumerate = udev_enumerate_new(udev);
-
-       /* Take only USB devices that are not hubs and do not have
-        * the bInterfaceNumber attribute, i.e. are not interfaces.
-        */
-       udev_enumerate_add_match_subsystem(enumerate, "usb");
-       udev_enumerate_add_nomatch_sysattr(enumerate, "bDeviceClass", "09");
-       udev_enumerate_add_nomatch_sysattr(enumerate, "bInterfaceNumber", NULL);
-       udev_enumerate_scan_devices(enumerate);
-
-       devices = udev_enumerate_get_list_entry(enumerate);
-
-       /* Show information about each device. */
-       udev_list_entry_foreach(dev_list_entry, devices) {
-               path = udev_list_entry_get_name(dev_list_entry);
-               dev = udev_device_new_from_syspath(udev, path);
-
-               /* Get device information. */
-               idVendor = udev_device_get_sysattr_value(dev, "idVendor");
-               idProduct = udev_device_get_sysattr_value(dev, "idProduct");
-               bConfValue = udev_device_get_sysattr_value(dev, "bConfigurationValue");
-               bNumIntfs = udev_device_get_sysattr_value(dev, "bNumInterfaces");
-               busid = udev_device_get_sysname(dev);
-               if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) {
-                       err("problem getting device attributes: %s",
-                           strerror(errno));
-                       goto err_out;
-               }
-
-               /* Get product name. */
-               usbip_names_get_product(product_name, sizeof(product_name),
-                                       strtol(idVendor, NULL, 16),
-                                       strtol(idProduct, NULL, 16));
-
-               /* Print information. */
-               print_device(busid, idVendor, idProduct, parsable);
-               print_product_name(product_name, parsable);
-
-               printf("\n");
-
-               udev_device_unref(dev);
-       }
-
-       ret = 0;
-
-err_out:
-       udev_enumerate_unref(enumerate);
-       udev_unref(udev);
-
-       return ret;
-}
-
-int usbip_list(int argc, char *argv[])
-{
-       static const struct option opts[] = {
-               { "parsable", no_argument,       NULL, 'p' },
-               { "remote",   required_argument, NULL, 'r' },
-               { "local",    no_argument,       NULL, 'l' },
-               { NULL,       0,                 NULL,  0  }
-       };
-
-       bool parsable = false;
-       int opt;
-       int ret = -1;
-
-       if (usbip_names_init(USBIDS_FILE))
-               err("failed to open %s", USBIDS_FILE);
-
-       for (;;) {
-               opt = getopt_long(argc, argv, "pr:l", opts, NULL);
-
-               if (opt == -1)
-                       break;
-
-               switch (opt) {
-               case 'p':
-                       parsable = true;
-                       break;
-               case 'r':
-                       ret = list_exported_devices(optarg);
-                       goto out;
-               case 'l':
-                       ret = list_devices(parsable);
-                       goto out;
-               default:
-                       goto err_out;
-               }
-       }
-
-err_out:
-       usbip_list_usage();
-out:
-       usbip_names_free();
-
-       return ret;
-}
diff --git a/drivers/staging/usbip/userspace/src/usbip_network.c b/drivers/staging/usbip/userspace/src/usbip_network.c
deleted file mode 100644 (file)
index b4c37e7..0000000
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
- *               2005-2007 Takahiro Hirofuchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <sys/socket.h>
-
-#include <string.h>
-
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <netinet/tcp.h>
-#include <unistd.h>
-
-#ifdef HAVE_LIBWRAP
-#include <tcpd.h>
-#endif
-
-#include "usbip_common.h"
-#include "usbip_network.h"
-
-int usbip_port = 3240;
-char *usbip_port_string = "3240";
-
-void usbip_setup_port_number(char *arg)
-{
-       dbg("parsing port arg '%s'", arg);
-       char *end;
-       unsigned long int port = strtoul(arg, &end, 10);
-
-       if (end == arg) {
-               err("port: could not parse '%s' as a decimal integer", arg);
-               return;
-       }
-
-       if (*end != '\0') {
-               err("port: garbage at end of '%s'", arg);
-               return;
-       }
-
-       if (port > UINT16_MAX) {
-               err("port: %s too high (max=%d)",
-                   arg, UINT16_MAX);
-               return;
-       }
-
-       usbip_port = port;
-       usbip_port_string = arg;
-       info("using port %d (\"%s\")", usbip_port, usbip_port_string);
-}
-
-void usbip_net_pack_uint32_t(int pack, uint32_t *num)
-{
-       uint32_t i;
-
-       if (pack)
-               i = htonl(*num);
-       else
-               i = ntohl(*num);
-
-       *num = i;
-}
-
-void usbip_net_pack_uint16_t(int pack, uint16_t *num)
-{
-       uint16_t i;
-
-       if (pack)
-               i = htons(*num);
-       else
-               i = ntohs(*num);
-
-       *num = i;
-}
-
-void usbip_net_pack_usb_device(int pack, struct usbip_usb_device *udev)
-{
-       usbip_net_pack_uint32_t(pack, &udev->busnum);
-       usbip_net_pack_uint32_t(pack, &udev->devnum);
-       usbip_net_pack_uint32_t(pack, &udev->speed);
-
-       usbip_net_pack_uint16_t(pack, &udev->idVendor);
-       usbip_net_pack_uint16_t(pack, &udev->idProduct);
-       usbip_net_pack_uint16_t(pack, &udev->bcdDevice);
-}
-
-void usbip_net_pack_usb_interface(int pack __attribute__((unused)),
-                                 struct usbip_usb_interface *udev
-                                 __attribute__((unused)))
-{
-       /* uint8_t members need nothing */
-}
-
-static ssize_t usbip_net_xmit(int sockfd, void *buff, size_t bufflen,
-                             int sending)
-{
-       ssize_t nbytes;
-       ssize_t total = 0;
-
-       if (!bufflen)
-               return 0;
-
-       do {
-               if (sending)
-                       nbytes = send(sockfd, buff, bufflen, 0);
-               else
-                       nbytes = recv(sockfd, buff, bufflen, MSG_WAITALL);
-
-               if (nbytes <= 0)
-                       return -1;
-
-               buff     = (void *)((intptr_t) buff + nbytes);
-               bufflen -= nbytes;
-               total   += nbytes;
-
-       } while (bufflen > 0);
-
-       return total;
-}
-
-ssize_t usbip_net_recv(int sockfd, void *buff, size_t bufflen)
-{
-       return usbip_net_xmit(sockfd, buff, bufflen, 0);
-}
-
-ssize_t usbip_net_send(int sockfd, void *buff, size_t bufflen)
-{
-       return usbip_net_xmit(sockfd, buff, bufflen, 1);
-}
-
-int usbip_net_send_op_common(int sockfd, uint32_t code, uint32_t status)
-{
-       struct op_common op_common;
-       int rc;
-
-       memset(&op_common, 0, sizeof(op_common));
-
-       op_common.version = USBIP_VERSION;
-       op_common.code    = code;
-       op_common.status  = status;
-
-       PACK_OP_COMMON(1, &op_common);
-
-       rc = usbip_net_send(sockfd, &op_common, sizeof(op_common));
-       if (rc < 0) {
-               dbg("usbip_net_send failed: %d", rc);
-               return -1;
-       }
-
-       return 0;
-}
-
-int usbip_net_recv_op_common(int sockfd, uint16_t *code)
-{
-       struct op_common op_common;
-       int rc;
-
-       memset(&op_common, 0, sizeof(op_common));
-
-       rc = usbip_net_recv(sockfd, &op_common, sizeof(op_common));
-       if (rc < 0) {
-               dbg("usbip_net_recv failed: %d", rc);
-               goto err;
-       }
-
-       PACK_OP_COMMON(0, &op_common);
-
-       if (op_common.version != USBIP_VERSION) {
-               dbg("version mismatch: %d %d", op_common.version,
-                   USBIP_VERSION);
-               goto err;
-       }
-
-       switch (*code) {
-       case OP_UNSPEC:
-               break;
-       default:
-               if (op_common.code != *code) {
-                       dbg("unexpected pdu %#0x for %#0x", op_common.code,
-                           *code);
-                       goto err;
-               }
-       }
-
-       if (op_common.status != ST_OK) {
-               dbg("request failed at peer: %d", op_common.status);
-               goto err;
-       }
-
-       *code = op_common.code;
-
-       return 0;
-err:
-       return -1;
-}
-
-int usbip_net_set_reuseaddr(int sockfd)
-{
-       const int val = 1;
-       int ret;
-
-       ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
-       if (ret < 0)
-               dbg("setsockopt: SO_REUSEADDR");
-
-       return ret;
-}
-
-int usbip_net_set_nodelay(int sockfd)
-{
-       const int val = 1;
-       int ret;
-
-       ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
-       if (ret < 0)
-               dbg("setsockopt: TCP_NODELAY");
-
-       return ret;
-}
-
-int usbip_net_set_keepalive(int sockfd)
-{
-       const int val = 1;
-       int ret;
-
-       ret = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
-       if (ret < 0)
-               dbg("setsockopt: SO_KEEPALIVE");
-
-       return ret;
-}
-
-int usbip_net_set_v6only(int sockfd)
-{
-       const int val = 1;
-       int ret;
-
-       ret = setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val));
-       if (ret < 0)
-               dbg("setsockopt: IPV6_V6ONLY");
-
-       return ret;
-}
-
-/*
- * IPv6 Ready
- */
-int usbip_net_tcp_connect(char *hostname, char *service)
-{
-       struct addrinfo hints, *res, *rp;
-       int sockfd;
-       int ret;
-
-       memset(&hints, 0, sizeof(hints));
-       hints.ai_family = AF_UNSPEC;
-       hints.ai_socktype = SOCK_STREAM;
-
-       /* get all possible addresses */
-       ret = getaddrinfo(hostname, service, &hints, &res);
-       if (ret < 0) {
-               dbg("getaddrinfo: %s service %s: %s", hostname, service,
-                   gai_strerror(ret));
-               return ret;
-       }
-
-       /* try the addresses */
-       for (rp = res; rp; rp = rp->ai_next) {
-               sockfd = socket(rp->ai_family, rp->ai_socktype,
-                               rp->ai_protocol);
-               if (sockfd < 0)
-                       continue;
-
-               /* should set TCP_NODELAY for usbip */
-               usbip_net_set_nodelay(sockfd);
-               /* TODO: write code for heartbeat */
-               usbip_net_set_keepalive(sockfd);
-
-               if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) == 0)
-                       break;
-
-               close(sockfd);
-       }
-
-       freeaddrinfo(res);
-
-       if (!rp)
-               return EAI_SYSTEM;
-
-       return sockfd;
-}
diff --git a/drivers/staging/usbip/userspace/src/usbip_network.h b/drivers/staging/usbip/userspace/src/usbip_network.h
deleted file mode 100644 (file)
index c1e875c..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2005-2007 Takahiro Hirofuchi
- */
-
-#ifndef __USBIP_NETWORK_H
-#define __USBIP_NETWORK_H
-
-#ifdef HAVE_CONFIG_H
-#include "../config.h"
-#endif
-
-#include <sys/types.h>
-
-#include <stdint.h>
-
-extern int usbip_port;
-extern char *usbip_port_string;
-void usbip_setup_port_number(char *arg);
-
-/* ---------------------------------------------------------------------- */
-/* Common header for all the kinds of PDUs. */
-struct op_common {
-       uint16_t version;
-
-#define OP_REQUEST     (0x80 << 8)
-#define OP_REPLY       (0x00 << 8)
-       uint16_t code;
-
-       /* add more error code */
-#define ST_OK  0x00
-#define ST_NA  0x01
-       uint32_t status; /* op_code status (for reply) */
-
-} __attribute__((packed));
-
-#define PACK_OP_COMMON(pack, op_common)  do {\
-       usbip_net_pack_uint16_t(pack, &(op_common)->version);\
-       usbip_net_pack_uint16_t(pack, &(op_common)->code);\
-       usbip_net_pack_uint32_t(pack, &(op_common)->status);\
-} while (0)
-
-/* ---------------------------------------------------------------------- */
-/* Dummy Code */
-#define OP_UNSPEC      0x00
-#define OP_REQ_UNSPEC  OP_UNSPEC
-#define OP_REP_UNSPEC  OP_UNSPEC
-
-/* ---------------------------------------------------------------------- */
-/* Retrieve USB device information. (still not used) */
-#define OP_DEVINFO     0x02
-#define OP_REQ_DEVINFO (OP_REQUEST | OP_DEVINFO)
-#define OP_REP_DEVINFO (OP_REPLY   | OP_DEVINFO)
-
-struct op_devinfo_request {
-       char busid[SYSFS_BUS_ID_SIZE];
-} __attribute__((packed));
-
-struct op_devinfo_reply {
-       struct usbip_usb_device udev;
-       struct usbip_usb_interface uinf[];
-} __attribute__((packed));
-
-/* ---------------------------------------------------------------------- */
-/* Import a remote USB device. */
-#define OP_IMPORT      0x03
-#define OP_REQ_IMPORT  (OP_REQUEST | OP_IMPORT)
-#define OP_REP_IMPORT   (OP_REPLY   | OP_IMPORT)
-
-struct op_import_request {
-       char busid[SYSFS_BUS_ID_SIZE];
-} __attribute__((packed));
-
-struct op_import_reply {
-       struct usbip_usb_device udev;
-//     struct usbip_usb_interface uinf[];
-} __attribute__((packed));
-
-#define PACK_OP_IMPORT_REQUEST(pack, request)  do {\
-} while (0)
-
-#define PACK_OP_IMPORT_REPLY(pack, reply)  do {\
-       usbip_net_pack_usb_device(pack, &(reply)->udev);\
-} while (0)
-
-/* ---------------------------------------------------------------------- */
-/* Export a USB device to a remote host. */
-#define OP_EXPORT      0x06
-#define OP_REQ_EXPORT  (OP_REQUEST | OP_EXPORT)
-#define OP_REP_EXPORT  (OP_REPLY   | OP_EXPORT)
-
-struct op_export_request {
-       struct usbip_usb_device udev;
-} __attribute__((packed));
-
-struct op_export_reply {
-       int returncode;
-} __attribute__((packed));
-
-
-#define PACK_OP_EXPORT_REQUEST(pack, request)  do {\
-       usbip_net_pack_usb_device(pack, &(request)->udev);\
-} while (0)
-
-#define PACK_OP_EXPORT_REPLY(pack, reply)  do {\
-} while (0)
-
-/* ---------------------------------------------------------------------- */
-/* un-Export a USB device from a remote host. */
-#define OP_UNEXPORT    0x07
-#define OP_REQ_UNEXPORT        (OP_REQUEST | OP_UNEXPORT)
-#define OP_REP_UNEXPORT        (OP_REPLY   | OP_UNEXPORT)
-
-struct op_unexport_request {
-       struct usbip_usb_device udev;
-} __attribute__((packed));
-
-struct op_unexport_reply {
-       int returncode;
-} __attribute__((packed));
-
-#define PACK_OP_UNEXPORT_REQUEST(pack, request)  do {\
-       usbip_net_pack_usb_device(pack, &(request)->udev);\
-} while (0)
-
-#define PACK_OP_UNEXPORT_REPLY(pack, reply)  do {\
-} while (0)
-
-/* ---------------------------------------------------------------------- */
-/* Negotiate IPSec encryption key. (still not used) */
-#define OP_CRYPKEY     0x04
-#define OP_REQ_CRYPKEY (OP_REQUEST | OP_CRYPKEY)
-#define OP_REP_CRYPKEY (OP_REPLY   | OP_CRYPKEY)
-
-struct op_crypkey_request {
-       /* 128bit key */
-       uint32_t key[4];
-} __attribute__((packed));
-
-struct op_crypkey_reply {
-       uint32_t __reserved;
-} __attribute__((packed));
-
-
-/* ---------------------------------------------------------------------- */
-/* Retrieve the list of exported USB devices. */
-#define OP_DEVLIST     0x05
-#define OP_REQ_DEVLIST (OP_REQUEST | OP_DEVLIST)
-#define OP_REP_DEVLIST (OP_REPLY   | OP_DEVLIST)
-
-struct op_devlist_request {
-} __attribute__((packed));
-
-struct op_devlist_reply {
-       uint32_t ndev;
-       /* followed by reply_extra[] */
-} __attribute__((packed));
-
-struct op_devlist_reply_extra {
-       struct usbip_usb_device    udev;
-       struct usbip_usb_interface uinf[];
-} __attribute__((packed));
-
-#define PACK_OP_DEVLIST_REQUEST(pack, request)  do {\
-} while (0)
-
-#define PACK_OP_DEVLIST_REPLY(pack, reply)  do {\
-       usbip_net_pack_uint32_t(pack, &(reply)->ndev);\
-} while (0)
-
-void usbip_net_pack_uint32_t(int pack, uint32_t *num);
-void usbip_net_pack_uint16_t(int pack, uint16_t *num);
-void usbip_net_pack_usb_device(int pack, struct usbip_usb_device *udev);
-void usbip_net_pack_usb_interface(int pack, struct usbip_usb_interface *uinf);
-
-ssize_t usbip_net_recv(int sockfd, void *buff, size_t bufflen);
-ssize_t usbip_net_send(int sockfd, void *buff, size_t bufflen);
-int usbip_net_send_op_common(int sockfd, uint32_t code, uint32_t status);
-int usbip_net_recv_op_common(int sockfd, uint16_t *code);
-int usbip_net_set_reuseaddr(int sockfd);
-int usbip_net_set_nodelay(int sockfd);
-int usbip_net_set_keepalive(int sockfd);
-int usbip_net_set_v6only(int sockfd);
-int usbip_net_tcp_connect(char *hostname, char *port);
-
-#endif /* __USBIP_NETWORK_H */
diff --git a/drivers/staging/usbip/userspace/src/usbip_port.c b/drivers/staging/usbip/userspace/src/usbip_port.c
deleted file mode 100644 (file)
index a2e884f..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
- *               2005-2007 Takahiro Hirofuchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "vhci_driver.h"
-#include "usbip_common.h"
-
-static int list_imported_devices(void)
-{
-       int i;
-       struct usbip_imported_device *idev;
-       int ret;
-
-       ret = usbip_vhci_driver_open();
-       if (ret < 0) {
-               err("open vhci_driver");
-               return -1;
-       }
-
-       printf("Imported USB devices\n");
-       printf("====================\n");
-
-       for (i = 0; i < vhci_driver->nports; i++) {
-               idev = &vhci_driver->idev[i];
-
-               if (usbip_vhci_imported_device_dump(idev) < 0)
-                       ret = -1;
-       }
-
-       usbip_vhci_driver_close();
-
-       return ret;
-
-}
-
-int usbip_port_show(__attribute__((unused)) int argc,
-                   __attribute__((unused)) char *argv[])
-{
-       int ret;
-
-       ret = list_imported_devices();
-       if (ret < 0)
-               err("list imported devices");
-
-       return ret;
-}
diff --git a/drivers/staging/usbip/userspace/src/usbip_unbind.c b/drivers/staging/usbip/userspace/src/usbip_unbind.c
deleted file mode 100644 (file)
index a4a496c..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
- *               2005-2007 Takahiro Hirofuchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <libudev.h>
-
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <getopt.h>
-
-#include "usbip_common.h"
-#include "utils.h"
-#include "usbip.h"
-#include "sysfs_utils.h"
-
-static const char usbip_unbind_usage_string[] =
-       "usbip unbind <args>\n"
-       "    -b, --busid=<busid>    Unbind " USBIP_HOST_DRV_NAME ".ko from "
-       "device on <busid>\n";
-
-void usbip_unbind_usage(void)
-{
-       printf("usage: %s", usbip_unbind_usage_string);
-}
-
-static int unbind_device(char *busid)
-{
-       char bus_type[] = "usb";
-       int rc, ret = -1;
-
-       char unbind_attr_name[] = "unbind";
-       char unbind_attr_path[SYSFS_PATH_MAX];
-       char rebind_attr_name[] = "rebind";
-       char rebind_attr_path[SYSFS_PATH_MAX];
-
-       struct udev *udev;
-       struct udev_device *dev;
-       const char *driver;
-
-       /* Create libudev context. */
-       udev = udev_new();
-
-       /* Check whether the device with this bus ID exists. */
-       dev = udev_device_new_from_subsystem_sysname(udev, "usb", busid);
-       if (!dev) {
-               err("device with the specified bus ID does not exist");
-               goto err_close_udev;
-       }
-
-       /* Check whether the device is using usbip-host driver. */
-       driver = udev_device_get_driver(dev);
-       if (!driver || strcmp(driver, "usbip-host")) {
-               err("device is not bound to usbip-host driver");
-               goto err_close_udev;
-       }
-
-       /* Unbind device from driver. */
-       snprintf(unbind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",
-                SYSFS_MNT_PATH, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME,
-                USBIP_HOST_DRV_NAME, unbind_attr_name);
-
-       rc = write_sysfs_attribute(unbind_attr_path, busid, strlen(busid));
-       if (rc < 0) {
-               err("error unbinding device %s from driver", busid);
-               goto err_close_udev;
-       }
-
-       /* Notify driver of unbind. */
-       rc = modify_match_busid(busid, 0);
-       if (rc < 0) {
-               err("unable to unbind device on %s", busid);
-               goto err_close_udev;
-       }
-
-       /* Trigger new probing. */
-       snprintf(rebind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",
-                       SYSFS_MNT_PATH, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME,
-                       USBIP_HOST_DRV_NAME, rebind_attr_name);
-
-       rc = write_sysfs_attribute(rebind_attr_path, busid, strlen(busid));
-       if (rc < 0) {
-               err("error rebinding");
-               goto err_close_udev;
-       }
-
-       ret = 0;
-       info("unbind device on busid %s: complete", busid);
-
-err_close_udev:
-       udev_device_unref(dev);
-       udev_unref(udev);
-
-       return ret;
-}
-
-int usbip_unbind(int argc, char *argv[])
-{
-       static const struct option opts[] = {
-               { "busid", required_argument, NULL, 'b' },
-               { NULL,    0,                 NULL,  0  }
-       };
-
-       int opt;
-       int ret = -1;
-
-       for (;;) {
-               opt = getopt_long(argc, argv, "b:", opts, NULL);
-
-               if (opt == -1)
-                       break;
-
-               switch (opt) {
-               case 'b':
-                       ret = unbind_device(optarg);
-                       goto out;
-               default:
-                       goto err_out;
-               }
-       }
-
-err_out:
-       usbip_unbind_usage();
-out:
-       return ret;
-}
diff --git a/drivers/staging/usbip/userspace/src/usbipd.c b/drivers/staging/usbip/userspace/src/usbipd.c
deleted file mode 100644 (file)
index 2f87f2d..0000000
+++ /dev/null
@@ -1,679 +0,0 @@
-/*
- * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
- *               2005-2007 Takahiro Hirofuchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "../config.h"
-#endif
-
-#define _GNU_SOURCE
-#include <errno.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-#ifdef HAVE_LIBWRAP
-#include <tcpd.h>
-#endif
-
-#include <getopt.h>
-#include <signal.h>
-#include <poll.h>
-
-#include "usbip_host_driver.h"
-#include "usbip_common.h"
-#include "usbip_network.h"
-#include "list.h"
-
-#undef  PROGNAME
-#define PROGNAME "usbipd"
-#define MAXSOCKFD 20
-
-#define MAIN_LOOP_TIMEOUT 10
-
-#define DEFAULT_PID_FILE "/var/run/" PROGNAME ".pid"
-
-static const char usbip_version_string[] = PACKAGE_STRING;
-
-static const char usbipd_help_string[] =
-       "usage: usbipd [options]\n"
-       "\n"
-       "       -4, --ipv4\n"
-       "               Bind to IPv4. Default is both.\n"
-       "\n"
-       "       -6, --ipv6\n"
-       "               Bind to IPv6. Default is both.\n"
-       "\n"
-       "       -D, --daemon\n"
-       "               Run as a daemon process.\n"
-       "\n"
-       "       -d, --debug\n"
-       "               Print debugging information.\n"
-       "\n"
-       "       -PFILE, --pid FILE\n"
-       "               Write process id to FILE.\n"
-       "               If no FILE specified, use " DEFAULT_PID_FILE "\n"
-       "\n"
-       "       -tPORT, --tcp-port PORT\n"
-       "               Listen on TCP/IP port PORT.\n"
-       "\n"
-       "       -h, --help\n"
-       "               Print this help.\n"
-       "\n"
-       "       -v, --version\n"
-       "               Show version.\n";
-
-static void usbipd_help(void)
-{
-       printf("%s\n", usbipd_help_string);
-}
-
-static int recv_request_import(int sockfd)
-{
-       struct op_import_request req;
-       struct op_common reply;
-       struct usbip_exported_device *edev;
-       struct usbip_usb_device pdu_udev;
-       struct list_head *i;
-       int found = 0;
-       int error = 0;
-       int rc;
-
-       memset(&req, 0, sizeof(req));
-       memset(&reply, 0, sizeof(reply));
-
-       rc = usbip_net_recv(sockfd, &req, sizeof(req));
-       if (rc < 0) {
-               dbg("usbip_net_recv failed: import request");
-               return -1;
-       }
-       PACK_OP_IMPORT_REQUEST(0, &req);
-
-       list_for_each(i, &host_driver->edev_list) {
-               edev = list_entry(i, struct usbip_exported_device, node);
-               if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) {
-                       info("found requested device: %s", req.busid);
-                       found = 1;
-                       break;
-               }
-       }
-
-       if (found) {
-               /* should set TCP_NODELAY for usbip */
-               usbip_net_set_nodelay(sockfd);
-
-               /* export device needs a TCP/IP socket descriptor */
-               rc = usbip_host_export_device(edev, sockfd);
-               if (rc < 0)
-                       error = 1;
-       } else {
-               info("requested device not found: %s", req.busid);
-               error = 1;
-       }
-
-       rc = usbip_net_send_op_common(sockfd, OP_REP_IMPORT,
-                                     (!error ? ST_OK : ST_NA));
-       if (rc < 0) {
-               dbg("usbip_net_send_op_common failed: %#0x", OP_REP_IMPORT);
-               return -1;
-       }
-
-       if (error) {
-               dbg("import request busid %s: failed", req.busid);
-               return -1;
-       }
-
-       memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev));
-       usbip_net_pack_usb_device(1, &pdu_udev);
-
-       rc = usbip_net_send(sockfd, &pdu_udev, sizeof(pdu_udev));
-       if (rc < 0) {
-               dbg("usbip_net_send failed: devinfo");
-               return -1;
-       }
-
-       dbg("import request busid %s: complete", req.busid);
-
-       return 0;
-}
-
-static int send_reply_devlist(int connfd)
-{
-       struct usbip_exported_device *edev;
-       struct usbip_usb_device pdu_udev;
-       struct usbip_usb_interface pdu_uinf;
-       struct op_devlist_reply reply;
-       struct list_head *j;
-       int rc, i;
-
-       reply.ndev = 0;
-       /* number of exported devices */
-       list_for_each(j, &host_driver->edev_list) {
-               reply.ndev += 1;
-       }
-       info("exportable devices: %d", reply.ndev);
-
-       rc = usbip_net_send_op_common(connfd, OP_REP_DEVLIST, ST_OK);
-       if (rc < 0) {
-               dbg("usbip_net_send_op_common failed: %#0x", OP_REP_DEVLIST);
-               return -1;
-       }
-       PACK_OP_DEVLIST_REPLY(1, &reply);
-
-       rc = usbip_net_send(connfd, &reply, sizeof(reply));
-       if (rc < 0) {
-               dbg("usbip_net_send failed: %#0x", OP_REP_DEVLIST);
-               return -1;
-       }
-
-       list_for_each(j, &host_driver->edev_list) {
-               edev = list_entry(j, struct usbip_exported_device, node);
-               dump_usb_device(&edev->udev);
-               memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev));
-               usbip_net_pack_usb_device(1, &pdu_udev);
-
-               rc = usbip_net_send(connfd, &pdu_udev, sizeof(pdu_udev));
-               if (rc < 0) {
-                       dbg("usbip_net_send failed: pdu_udev");
-                       return -1;
-               }
-
-               for (i = 0; i < edev->udev.bNumInterfaces; i++) {
-                       dump_usb_interface(&edev->uinf[i]);
-                       memcpy(&pdu_uinf, &edev->uinf[i], sizeof(pdu_uinf));
-                       usbip_net_pack_usb_interface(1, &pdu_uinf);
-
-                       rc = usbip_net_send(connfd, &pdu_uinf,
-                                       sizeof(pdu_uinf));
-                       if (rc < 0) {
-                               err("usbip_net_send failed: pdu_uinf");
-                               return -1;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-static int recv_request_devlist(int connfd)
-{
-       struct op_devlist_request req;
-       int rc;
-
-       memset(&req, 0, sizeof(req));
-
-       rc = usbip_net_recv(connfd, &req, sizeof(req));
-       if (rc < 0) {
-               dbg("usbip_net_recv failed: devlist request");
-               return -1;
-       }
-
-       rc = send_reply_devlist(connfd);
-       if (rc < 0) {
-               dbg("send_reply_devlist failed");
-               return -1;
-       }
-
-       return 0;
-}
-
-static int recv_pdu(int connfd)
-{
-       uint16_t code = OP_UNSPEC;
-       int ret;
-
-       ret = usbip_net_recv_op_common(connfd, &code);
-       if (ret < 0) {
-               dbg("could not receive opcode: %#0x", code);
-               return -1;
-       }
-
-       ret = usbip_host_refresh_device_list();
-       if (ret < 0) {
-               dbg("could not refresh device list: %d", ret);
-               return -1;
-       }
-
-       info("received request: %#0x(%d)", code, connfd);
-       switch (code) {
-       case OP_REQ_DEVLIST:
-               ret = recv_request_devlist(connfd);
-               break;
-       case OP_REQ_IMPORT:
-               ret = recv_request_import(connfd);
-               break;
-       case OP_REQ_DEVINFO:
-       case OP_REQ_CRYPKEY:
-       default:
-               err("received an unknown opcode: %#0x", code);
-               ret = -1;
-       }
-
-       if (ret == 0)
-               info("request %#0x(%d): complete", code, connfd);
-       else
-               info("request %#0x(%d): failed", code, connfd);
-
-       return ret;
-}
-
-#ifdef HAVE_LIBWRAP
-static int tcpd_auth(int connfd)
-{
-       struct request_info request;
-       int rc;
-
-       request_init(&request, RQ_DAEMON, PROGNAME, RQ_FILE, connfd, 0);
-       fromhost(&request);
-       rc = hosts_access(&request);
-       if (rc == 0)
-               return -1;
-
-       return 0;
-}
-#endif
-
-static int do_accept(int listenfd)
-{
-       int connfd;
-       struct sockaddr_storage ss;
-       socklen_t len = sizeof(ss);
-       char host[NI_MAXHOST], port[NI_MAXSERV];
-       int rc;
-
-       memset(&ss, 0, sizeof(ss));
-
-       connfd = accept(listenfd, (struct sockaddr *)&ss, &len);
-       if (connfd < 0) {
-               err("failed to accept connection");
-               return -1;
-       }
-
-       rc = getnameinfo((struct sockaddr *)&ss, len, host, sizeof(host),
-                        port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
-       if (rc)
-               err("getnameinfo: %s", gai_strerror(rc));
-
-#ifdef HAVE_LIBWRAP
-       rc = tcpd_auth(connfd);
-       if (rc < 0) {
-               info("denied access from %s", host);
-               close(connfd);
-               return -1;
-       }
-#endif
-       info("connection from %s:%s", host, port);
-
-       return connfd;
-}
-
-int process_request(int listenfd)
-{
-       pid_t childpid;
-       int connfd;
-
-       connfd = do_accept(listenfd);
-       if (connfd < 0)
-               return -1;
-       childpid = fork();
-       if (childpid == 0) {
-               close(listenfd);
-               recv_pdu(connfd);
-               exit(0);
-       }
-       close(connfd);
-       return 0;
-}
-
-static void addrinfo_to_text(struct addrinfo *ai, char buf[],
-                            const size_t buf_size)
-{
-       char hbuf[NI_MAXHOST];
-       char sbuf[NI_MAXSERV];
-       int rc;
-
-       buf[0] = '\0';
-
-       rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf),
-                        sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
-       if (rc)
-               err("getnameinfo: %s", gai_strerror(rc));
-
-       snprintf(buf, buf_size, "%s:%s", hbuf, sbuf);
-}
-
-static int listen_all_addrinfo(struct addrinfo *ai_head, int sockfdlist[],
-                            int maxsockfd)
-{
-       struct addrinfo *ai;
-       int ret, nsockfd = 0;
-       const size_t ai_buf_size = NI_MAXHOST + NI_MAXSERV + 2;
-       char ai_buf[ai_buf_size];
-
-       for (ai = ai_head; ai && nsockfd < maxsockfd; ai = ai->ai_next) {
-               int sock;
-
-               addrinfo_to_text(ai, ai_buf, ai_buf_size);
-               dbg("opening %s", ai_buf);
-               sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
-               if (sock < 0) {
-                       err("socket: %s: %d (%s)",
-                           ai_buf, errno, strerror(errno));
-                       continue;
-               }
-
-               usbip_net_set_reuseaddr(sock);
-               usbip_net_set_nodelay(sock);
-               /* We use seperate sockets for IPv4 and IPv6
-                * (see do_standalone_mode()) */
-               usbip_net_set_v6only(sock);
-
-               if (sock >= FD_SETSIZE) {
-                       err("FD_SETSIZE: %s: sock=%d, max=%d",
-                           ai_buf, sock, FD_SETSIZE);
-                       close(sock);
-                       continue;
-               }
-
-               ret = bind(sock, ai->ai_addr, ai->ai_addrlen);
-               if (ret < 0) {
-                       err("bind: %s: %d (%s)",
-                           ai_buf, errno, strerror(errno));
-                       close(sock);
-                       continue;
-               }
-
-               ret = listen(sock, SOMAXCONN);
-               if (ret < 0) {
-                       err("listen: %s: %d (%s)",
-                           ai_buf, errno, strerror(errno));
-                       close(sock);
-                       continue;
-               }
-
-               info("listening on %s", ai_buf);
-               sockfdlist[nsockfd++] = sock;
-       }
-
-       return nsockfd;
-}
-
-static struct addrinfo *do_getaddrinfo(char *host, int ai_family)
-{
-       struct addrinfo hints, *ai_head;
-       int rc;
-
-       memset(&hints, 0, sizeof(hints));
-       hints.ai_family   = ai_family;
-       hints.ai_socktype = SOCK_STREAM;
-       hints.ai_flags    = AI_PASSIVE;
-
-       rc = getaddrinfo(host, usbip_port_string, &hints, &ai_head);
-       if (rc) {
-               err("failed to get a network address %s: %s", usbip_port_string,
-                   gai_strerror(rc));
-               return NULL;
-       }
-
-       return ai_head;
-}
-
-static void signal_handler(int i)
-{
-       dbg("received '%s' signal", strsignal(i));
-}
-
-static void set_signal(void)
-{
-       struct sigaction act;
-
-       memset(&act, 0, sizeof(act));
-       act.sa_handler = signal_handler;
-       sigemptyset(&act.sa_mask);
-       sigaction(SIGTERM, &act, NULL);
-       sigaction(SIGINT, &act, NULL);
-       act.sa_handler = SIG_IGN;
-       sigaction(SIGCLD, &act, NULL);
-}
-
-static const char *pid_file;
-
-static void write_pid_file(void)
-{
-       if (pid_file) {
-               dbg("creating pid file %s", pid_file);
-               FILE *fp;
-
-               fp = fopen(pid_file, "w");
-               if (!fp) {
-                       err("pid_file: %s: %d (%s)",
-                           pid_file, errno, strerror(errno));
-                       return;
-               }
-               fprintf(fp, "%d\n", getpid());
-               fclose(fp);
-       }
-}
-
-static void remove_pid_file(void)
-{
-       if (pid_file) {
-               dbg("removing pid file %s", pid_file);
-               unlink(pid_file);
-       }
-}
-
-static int do_standalone_mode(int daemonize, int ipv4, int ipv6)
-{
-       struct addrinfo *ai_head;
-       int sockfdlist[MAXSOCKFD];
-       int nsockfd, family;
-       int i, terminate;
-       struct pollfd *fds;
-       struct timespec timeout;
-       sigset_t sigmask;
-
-       if (usbip_host_driver_open()) {
-               err("please load " USBIP_CORE_MOD_NAME ".ko and "
-                   USBIP_HOST_DRV_NAME ".ko!");
-               return -1;
-       }
-
-       if (daemonize) {
-               if (daemon(0, 0) < 0) {
-                       err("daemonizing failed: %s", strerror(errno));
-                       usbip_host_driver_close();
-                       return -1;
-               }
-               umask(0);
-               usbip_use_syslog = 1;
-       }
-       set_signal();
-       write_pid_file();
-
-       info("starting " PROGNAME " (%s)", usbip_version_string);
-
-       /*
-        * To suppress warnings on systems with bindv6only disabled
-        * (default), we use seperate sockets for IPv6 and IPv4 and set
-        * IPV6_V6ONLY on the IPv6 sockets.
-        */
-       if (ipv4 && ipv6)
-               family = AF_UNSPEC;
-       else if (ipv4)
-               family = AF_INET;
-       else
-               family = AF_INET6;
-
-       ai_head = do_getaddrinfo(NULL, family);
-       if (!ai_head) {
-               usbip_host_driver_close();
-               return -1;
-       }
-       nsockfd = listen_all_addrinfo(ai_head, sockfdlist,
-               sizeof(sockfdlist) / sizeof(*sockfdlist));
-       freeaddrinfo(ai_head);
-       if (nsockfd <= 0) {
-               err("failed to open a listening socket");
-               usbip_host_driver_close();
-               return -1;
-       }
-
-       dbg("listening on %d address%s", nsockfd, (nsockfd == 1) ? "" : "es");
-
-       fds = calloc(nsockfd, sizeof(struct pollfd));
-       for (i = 0; i < nsockfd; i++) {
-               fds[i].fd = sockfdlist[i];
-               fds[i].events = POLLIN;
-       }
-       timeout.tv_sec = MAIN_LOOP_TIMEOUT;
-       timeout.tv_nsec = 0;
-
-       sigfillset(&sigmask);
-       sigdelset(&sigmask, SIGTERM);
-       sigdelset(&sigmask, SIGINT);
-
-       terminate = 0;
-       while (!terminate) {
-               int r;
-
-               r = ppoll(fds, nsockfd, &timeout, &sigmask);
-               if (r < 0) {
-                       dbg("%s", strerror(errno));
-                       terminate = 1;
-               } else if (r) {
-                       for (i = 0; i < nsockfd; i++) {
-                               if (fds[i].revents & POLLIN) {
-                                       dbg("read event on fd[%d]=%d",
-                                           i, sockfdlist[i]);
-                                       process_request(sockfdlist[i]);
-                               }
-                       }
-               } else {
-                       dbg("heartbeat timeout on ppoll()");
-               }
-       }
-
-       info("shutting down " PROGNAME);
-       free(fds);
-       usbip_host_driver_close();
-
-       return 0;
-}
-
-int main(int argc, char *argv[])
-{
-       static const struct option longopts[] = {
-               { "ipv4",     no_argument,       NULL, '4' },
-               { "ipv6",     no_argument,       NULL, '6' },
-               { "daemon",   no_argument,       NULL, 'D' },
-               { "daemon",   no_argument,       NULL, 'D' },
-               { "debug",    no_argument,       NULL, 'd' },
-               { "pid",      optional_argument, NULL, 'P' },
-               { "tcp-port", required_argument, NULL, 't' },
-               { "help",     no_argument,       NULL, 'h' },
-               { "version",  no_argument,       NULL, 'v' },
-               { NULL,       0,                 NULL,  0  }
-       };
-
-       enum {
-               cmd_standalone_mode = 1,
-               cmd_help,
-               cmd_version
-       } cmd;
-
-       int daemonize = 0;
-       int ipv4 = 0, ipv6 = 0;
-       int opt, rc = -1;
-
-       pid_file = NULL;
-
-       usbip_use_stderr = 1;
-       usbip_use_syslog = 0;
-
-       if (geteuid() != 0)
-               err("not running as root?");
-
-       cmd = cmd_standalone_mode;
-       for (;;) {
-               opt = getopt_long(argc, argv, "46DdP::t:hv", longopts, NULL);
-
-               if (opt == -1)
-                       break;
-
-               switch (opt) {
-               case '4':
-                       ipv4 = 1;
-                       break;
-               case '6':
-                       ipv6 = 1;
-                       break;
-               case 'D':
-                       daemonize = 1;
-                       break;
-               case 'd':
-                       usbip_use_debug = 1;
-                       break;
-               case 'h':
-                       cmd = cmd_help;
-                       break;
-               case 'P':
-                       pid_file = optarg ? optarg : DEFAULT_PID_FILE;
-                       break;
-               case 't':
-                       usbip_setup_port_number(optarg);
-                       break;
-               case 'v':
-                       cmd = cmd_version;
-                       break;
-               case '?':
-                       usbipd_help();
-               default:
-                       goto err_out;
-               }
-       }
-
-       if (!ipv4 && !ipv6)
-               ipv4 = ipv6 = 1;
-
-       switch (cmd) {
-       case cmd_standalone_mode:
-               rc = do_standalone_mode(daemonize, ipv4, ipv6);
-               remove_pid_file();
-               break;
-       case cmd_version:
-               printf(PROGNAME " (%s)\n", usbip_version_string);
-               rc = 0;
-               break;
-       case cmd_help:
-               usbipd_help();
-               rc = 0;
-               break;
-       default:
-               usbipd_help();
-               goto err_out;
-       }
-
-err_out:
-       return (rc > -1 ? EXIT_SUCCESS : EXIT_FAILURE);
-}
diff --git a/drivers/staging/usbip/userspace/src/utils.c b/drivers/staging/usbip/userspace/src/utils.c
deleted file mode 100644 (file)
index 2b3d6d2..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
- *               2005-2007 Takahiro Hirofuchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "usbip_common.h"
-#include "utils.h"
-#include "sysfs_utils.h"
-
-int modify_match_busid(char *busid, int add)
-{
-       char attr_name[] = "match_busid";
-       char command[SYSFS_BUS_ID_SIZE + 4];
-       char match_busid_attr_path[SYSFS_PATH_MAX];
-       int rc;
-
-       snprintf(match_busid_attr_path, sizeof(match_busid_attr_path),
-                "%s/%s/%s/%s/%s/%s", SYSFS_MNT_PATH, SYSFS_BUS_NAME,
-                SYSFS_BUS_TYPE, SYSFS_DRIVERS_NAME, USBIP_HOST_DRV_NAME,
-                attr_name);
-
-       if (add)
-               snprintf(command, SYSFS_BUS_ID_SIZE + 4, "add %s", busid);
-       else
-               snprintf(command, SYSFS_BUS_ID_SIZE + 4, "del %s", busid);
-
-       rc = write_sysfs_attribute(match_busid_attr_path, command,
-                                  sizeof(command));
-       if (rc < 0) {
-               dbg("failed to write match_busid: %s", strerror(errno));
-               return -1;
-       }
-
-       return 0;
-}
diff --git a/drivers/staging/usbip/userspace/src/utils.h b/drivers/staging/usbip/userspace/src/utils.h
deleted file mode 100644 (file)
index 5916fd3..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
- *               2005-2007 Takahiro Hirofuchi
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __UTILS_H
-#define __UTILS_H
-
-int modify_match_busid(char *busid, int add);
-
-#endif /* __UTILS_H */
-
diff --git a/drivers/staging/usbip/vhci.h b/drivers/staging/usbip/vhci.h
deleted file mode 100644 (file)
index a863a98..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2003-2008 Takahiro Hirofuchi
- *
- * This 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.
- *
- */
-
-#ifndef __USBIP_VHCI_H
-#define __USBIP_VHCI_H
-
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/sysfs.h>
-#include <linux/types.h>
-#include <linux/usb.h>
-#include <linux/usb/hcd.h>
-#include <linux/wait.h>
-
-struct vhci_device {
-       struct usb_device *udev;
-
-       /*
-        * devid specifies a remote usb device uniquely instead
-        * of combination of busnum and devnum.
-        */
-       __u32 devid;
-
-       /* speed of a remote device */
-       enum usb_device_speed speed;
-
-       /* vhci root-hub port to which this device is attached */
-       __u32 rhport;
-
-       struct usbip_device ud;
-
-       /* lock for the below link lists */
-       spinlock_t priv_lock;
-
-       /* vhci_priv is linked to one of them. */
-       struct list_head priv_tx;
-       struct list_head priv_rx;
-
-       /* vhci_unlink is linked to one of them */
-       struct list_head unlink_tx;
-       struct list_head unlink_rx;
-
-       /* vhci_tx thread sleeps for this queue */
-       wait_queue_head_t waitq_tx;
-};
-
-/* urb->hcpriv, use container_of() */
-struct vhci_priv {
-       unsigned long seqnum;
-       struct list_head list;
-
-       struct vhci_device *vdev;
-       struct urb *urb;
-};
-
-struct vhci_unlink {
-       /* seqnum of this request */
-       unsigned long seqnum;
-
-       struct list_head list;
-
-       /* seqnum of the unlink target */
-       unsigned long unlink_seqnum;
-};
-
-/* Number of supported ports. Value has an upperbound of USB_MAXCHILDREN */
-#define VHCI_NPORTS 8
-
-/* for usb_bus.hcpriv */
-struct vhci_hcd {
-       spinlock_t lock;
-
-       u32 port_status[VHCI_NPORTS];
-
-       unsigned resuming:1;
-       unsigned long re_timeout;
-
-       atomic_t seqnum;
-
-       /*
-        * NOTE:
-        * wIndex shows the port number and begins from 1.
-        * But, the index of this array begins from 0.
-        */
-       struct vhci_device vdev[VHCI_NPORTS];
-};
-
-extern struct vhci_hcd *the_controller;
-extern const struct attribute_group dev_attr_group;
-
-/* vhci_hcd.c */
-void rh_port_connect(int rhport, enum usb_device_speed speed);
-
-/* vhci_rx.c */
-struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, __u32 seqnum);
-int vhci_rx_loop(void *data);
-
-/* vhci_tx.c */
-int vhci_tx_loop(void *data);
-
-static inline struct vhci_device *port_to_vdev(__u32 port)
-{
-       return &the_controller->vdev[port];
-}
-
-static inline struct vhci_hcd *hcd_to_vhci(struct usb_hcd *hcd)
-{
-       return (struct vhci_hcd *) (hcd->hcd_priv);
-}
-
-static inline struct usb_hcd *vhci_to_hcd(struct vhci_hcd *vhci)
-{
-       return container_of((void *) vhci, struct usb_hcd, hcd_priv);
-}
-
-static inline struct device *vhci_dev(struct vhci_hcd *vhci)
-{
-       return vhci_to_hcd(vhci)->self.controller;
-}
-
-#endif /* __USBIP_VHCI_H */
diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c
deleted file mode 100644 (file)
index c02374b..0000000
+++ /dev/null
@@ -1,1171 +0,0 @@
-/*
- * Copyright (C) 2003-2008 Takahiro Hirofuchi
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#include <linux/init.h>
-#include <linux/file.h>
-#include <linux/kernel.h>
-#include <linux/kthread.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include "usbip_common.h"
-#include "vhci.h"
-
-#define DRIVER_AUTHOR "Takahiro Hirofuchi"
-#define DRIVER_DESC "USB/IP 'Virtual' Host Controller (VHCI) Driver"
-
-/*
- * TODO
- *     - update root hub emulation
- *     - move the emulation code to userland ?
- *             porting to other operating systems
- *             minimize kernel code
- *     - add suspend/resume code
- *     - clean up everything
- */
-
-/* See usb gadget dummy hcd */
-
-static int vhci_hub_status(struct usb_hcd *hcd, char *buff);
-static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
-                           u16 wIndex, char *buff, u16 wLength);
-static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
-                           gfp_t mem_flags);
-static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
-static int vhci_start(struct usb_hcd *vhci_hcd);
-static void vhci_stop(struct usb_hcd *hcd);
-static int vhci_get_frame_number(struct usb_hcd *hcd);
-
-static const char driver_name[] = "vhci_hcd";
-static const char driver_desc[] = "USB/IP Virtual Host Controller";
-
-struct vhci_hcd *the_controller;
-
-static const char * const bit_desc[] = {
-       "CONNECTION",           /*0*/
-       "ENABLE",               /*1*/
-       "SUSPEND",              /*2*/
-       "OVER_CURRENT",         /*3*/
-       "RESET",                /*4*/
-       "R5",                   /*5*/
-       "R6",                   /*6*/
-       "R7",                   /*7*/
-       "POWER",                /*8*/
-       "LOWSPEED",             /*9*/
-       "HIGHSPEED",            /*10*/
-       "PORT_TEST",            /*11*/
-       "INDICATOR",            /*12*/
-       "R13",                  /*13*/
-       "R14",                  /*14*/
-       "R15",                  /*15*/
-       "C_CONNECTION",         /*16*/
-       "C_ENABLE",             /*17*/
-       "C_SUSPEND",            /*18*/
-       "C_OVER_CURRENT",       /*19*/
-       "C_RESET",              /*20*/
-       "R21",                  /*21*/
-       "R22",                  /*22*/
-       "R23",                  /*23*/
-       "R24",                  /*24*/
-       "R25",                  /*25*/
-       "R26",                  /*26*/
-       "R27",                  /*27*/
-       "R28",                  /*28*/
-       "R29",                  /*29*/
-       "R30",                  /*30*/
-       "R31",                  /*31*/
-};
-
-static void dump_port_status_diff(u32 prev_status, u32 new_status)
-{
-       int i = 0;
-       u32 bit = 1;
-
-       pr_debug("status prev -> new: %08x -> %08x\n", prev_status, new_status);
-       while (bit) {
-               u32 prev = prev_status & bit;
-               u32 new = new_status & bit;
-               char change;
-
-               if (!prev && new)
-                       change = '+';
-               else if (prev && !new)
-                       change = '-';
-               else
-                       change = ' ';
-
-               if (prev || new)
-                       pr_debug(" %c%s\n", change, bit_desc[i]);
-               bit <<= 1;
-               i++;
-       }
-       pr_debug("\n");
-}
-
-void rh_port_connect(int rhport, enum usb_device_speed speed)
-{
-       usbip_dbg_vhci_rh("rh_port_connect %d\n", rhport);
-
-       spin_lock(&the_controller->lock);
-
-       the_controller->port_status[rhport] |= USB_PORT_STAT_CONNECTION
-               | (1 << USB_PORT_FEAT_C_CONNECTION);
-
-       switch (speed) {
-       case USB_SPEED_HIGH:
-               the_controller->port_status[rhport] |= USB_PORT_STAT_HIGH_SPEED;
-               break;
-       case USB_SPEED_LOW:
-               the_controller->port_status[rhport] |= USB_PORT_STAT_LOW_SPEED;
-               break;
-       default:
-               break;
-       }
-
-       spin_unlock(&the_controller->lock);
-
-       usb_hcd_poll_rh_status(vhci_to_hcd(the_controller));
-}
-
-static void rh_port_disconnect(int rhport)
-{
-       usbip_dbg_vhci_rh("rh_port_disconnect %d\n", rhport);
-
-       spin_lock(&the_controller->lock);
-
-       the_controller->port_status[rhport] &= ~USB_PORT_STAT_CONNECTION;
-       the_controller->port_status[rhport] |=
-                                       (1 << USB_PORT_FEAT_C_CONNECTION);
-
-       spin_unlock(&the_controller->lock);
-       usb_hcd_poll_rh_status(vhci_to_hcd(the_controller));
-}
-
-#define PORT_C_MASK                            \
-       ((USB_PORT_STAT_C_CONNECTION            \
-         | USB_PORT_STAT_C_ENABLE              \
-         | USB_PORT_STAT_C_SUSPEND             \
-         | USB_PORT_STAT_C_OVERCURRENT         \
-         | USB_PORT_STAT_C_RESET) << 16)
-
-/*
- * Returns 0 if the status hasn't changed, or the number of bytes in buf.
- * Ports are 0-indexed from the HCD point of view,
- * and 1-indexed from the USB core pointer of view.
- *
- * @buf: a bitmap to show which port status has been changed.
- *  bit  0: reserved
- *  bit  1: the status of port 0 has been changed.
- *  bit  2: the status of port 1 has been changed.
- *  ...
- */
-static int vhci_hub_status(struct usb_hcd *hcd, char *buf)
-{
-       struct vhci_hcd *vhci;
-       int             retval;
-       int             rhport;
-       int             changed = 0;
-
-       retval = DIV_ROUND_UP(VHCI_NPORTS + 1, 8);
-       memset(buf, 0, retval);
-
-       vhci = hcd_to_vhci(hcd);
-
-       spin_lock(&vhci->lock);
-       if (!HCD_HW_ACCESSIBLE(hcd)) {
-               usbip_dbg_vhci_rh("hw accessible flag not on?\n");
-               goto done;
-       }
-
-       /* check pseudo status register for each port */
-       for (rhport = 0; rhport < VHCI_NPORTS; rhport++) {
-               if ((vhci->port_status[rhport] & PORT_C_MASK)) {
-                       /* The status of a port has been changed, */
-                       usbip_dbg_vhci_rh("port %d status changed\n", rhport);
-
-                       buf[(rhport + 1) / 8] |= 1 << (rhport + 1) % 8;
-                       changed = 1;
-               }
-       }
-
-       if ((hcd->state == HC_STATE_SUSPENDED) && (changed == 1))
-               usb_hcd_resume_root_hub(hcd);
-
-done:
-       spin_unlock(&vhci->lock);
-       return changed ? retval : 0;
-}
-
-static inline void hub_descriptor(struct usb_hub_descriptor *desc)
-{
-       memset(desc, 0, sizeof(*desc));
-       desc->bDescriptorType = 0x29;
-       desc->bDescLength = 9;
-       desc->wHubCharacteristics = (__constant_cpu_to_le16(0x0001));
-       desc->bNbrPorts = VHCI_NPORTS;
-       desc->u.hs.DeviceRemovable[0] = 0xff;
-       desc->u.hs.DeviceRemovable[1] = 0xff;
-}
-
-static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
-                           u16 wIndex, char *buf, u16 wLength)
-{
-       struct vhci_hcd *dum;
-       int             retval = 0;
-       int             rhport;
-
-       u32 prev_port_status[VHCI_NPORTS];
-
-       if (!HCD_HW_ACCESSIBLE(hcd))
-               return -ETIMEDOUT;
-
-       /*
-        * NOTE:
-        * wIndex shows the port number and begins from 1.
-        */
-       usbip_dbg_vhci_rh("typeReq %x wValue %x wIndex %x\n", typeReq, wValue,
-                         wIndex);
-       if (wIndex > VHCI_NPORTS)
-               pr_err("invalid port number %d\n", wIndex);
-       rhport = ((__u8)(wIndex & 0x00ff)) - 1;
-
-       dum = hcd_to_vhci(hcd);
-
-       spin_lock(&dum->lock);
-
-       /* store old status and compare now and old later */
-       if (usbip_dbg_flag_vhci_rh) {
-               memcpy(prev_port_status, dum->port_status,
-                       sizeof(prev_port_status));
-       }
-
-       switch (typeReq) {
-       case ClearHubFeature:
-               usbip_dbg_vhci_rh(" ClearHubFeature\n");
-               break;
-       case ClearPortFeature:
-               switch (wValue) {
-               case USB_PORT_FEAT_SUSPEND:
-                       if (dum->port_status[rhport] & USB_PORT_STAT_SUSPEND) {
-                               /* 20msec signaling */
-                               dum->resuming = 1;
-                               dum->re_timeout =
-                                       jiffies + msecs_to_jiffies(20);
-                       }
-                       break;
-               case USB_PORT_FEAT_POWER:
-                       usbip_dbg_vhci_rh(
-                               " ClearPortFeature: USB_PORT_FEAT_POWER\n");
-                       dum->port_status[rhport] = 0;
-                       dum->resuming = 0;
-                       break;
-               case USB_PORT_FEAT_C_RESET:
-                       usbip_dbg_vhci_rh(
-                               " ClearPortFeature: USB_PORT_FEAT_C_RESET\n");
-                       switch (dum->vdev[rhport].speed) {
-                       case USB_SPEED_HIGH:
-                               dum->port_status[rhport] |=
-                                       USB_PORT_STAT_HIGH_SPEED;
-                               break;
-                       case USB_SPEED_LOW:
-                               dum->port_status[rhport] |=
-                                       USB_PORT_STAT_LOW_SPEED;
-                               break;
-                       default:
-                               break;
-                       }
-               default:
-                       usbip_dbg_vhci_rh(" ClearPortFeature: default %x\n",
-                                         wValue);
-                       dum->port_status[rhport] &= ~(1 << wValue);
-                       break;
-               }
-               break;
-       case GetHubDescriptor:
-               usbip_dbg_vhci_rh(" GetHubDescriptor\n");
-               hub_descriptor((struct usb_hub_descriptor *) buf);
-               break;
-       case GetHubStatus:
-               usbip_dbg_vhci_rh(" GetHubStatus\n");
-               *(__le32 *) buf = cpu_to_le32(0);
-               break;
-       case GetPortStatus:
-               usbip_dbg_vhci_rh(" GetPortStatus port %x\n", wIndex);
-               if (wIndex > VHCI_NPORTS || wIndex < 1) {
-                       pr_err("invalid port number %d\n", wIndex);
-                       retval = -EPIPE;
-               }
-
-               /* we do not care about resume. */
-
-               /* whoever resets or resumes must GetPortStatus to
-                * complete it!!
-                */
-               if (dum->resuming && time_after(jiffies, dum->re_timeout)) {
-                       dum->port_status[rhport] |=
-                               (1 << USB_PORT_FEAT_C_SUSPEND);
-                       dum->port_status[rhport] &=
-                               ~(1 << USB_PORT_FEAT_SUSPEND);
-                       dum->resuming = 0;
-                       dum->re_timeout = 0;
-               }
-
-               if ((dum->port_status[rhport] & (1 << USB_PORT_FEAT_RESET)) !=
-                   0 && time_after(jiffies, dum->re_timeout)) {
-                       dum->port_status[rhport] |=
-                               (1 << USB_PORT_FEAT_C_RESET);
-                       dum->port_status[rhport] &=
-                               ~(1 << USB_PORT_FEAT_RESET);
-                       dum->re_timeout = 0;
-
-                       if (dum->vdev[rhport].ud.status ==
-                           VDEV_ST_NOTASSIGNED) {
-                               usbip_dbg_vhci_rh(
-                                       " enable rhport %d (status %u)\n",
-                                       rhport,
-                                       dum->vdev[rhport].ud.status);
-                               dum->port_status[rhport] |=
-                                       USB_PORT_STAT_ENABLE;
-                       }
-               }
-               ((__le16 *) buf)[0] = cpu_to_le16(dum->port_status[rhport]);
-               ((__le16 *) buf)[1] =
-                       cpu_to_le16(dum->port_status[rhport] >> 16);
-
-               usbip_dbg_vhci_rh(" GetPortStatus bye %x %x\n", ((u16 *)buf)[0],
-                                 ((u16 *)buf)[1]);
-               break;
-       case SetHubFeature:
-               usbip_dbg_vhci_rh(" SetHubFeature\n");
-               retval = -EPIPE;
-               break;
-       case SetPortFeature:
-               switch (wValue) {
-               case USB_PORT_FEAT_SUSPEND:
-                       usbip_dbg_vhci_rh(
-                               " SetPortFeature: USB_PORT_FEAT_SUSPEND\n");
-                       break;
-               case USB_PORT_FEAT_RESET:
-                       usbip_dbg_vhci_rh(
-                               " SetPortFeature: USB_PORT_FEAT_RESET\n");
-                       /* if it's already running, disconnect first */
-                       if (dum->port_status[rhport] & USB_PORT_STAT_ENABLE) {
-                               dum->port_status[rhport] &=
-                                       ~(USB_PORT_STAT_ENABLE |
-                                         USB_PORT_STAT_LOW_SPEED |
-                                         USB_PORT_STAT_HIGH_SPEED);
-                               /* FIXME test that code path! */
-                       }
-                       /* 50msec reset signaling */
-                       dum->re_timeout = jiffies + msecs_to_jiffies(50);
-
-                       /* FALLTHROUGH */
-               default:
-                       usbip_dbg_vhci_rh(" SetPortFeature: default %d\n",
-                                         wValue);
-                       dum->port_status[rhport] |= (1 << wValue);
-                       break;
-               }
-               break;
-
-       default:
-               pr_err("default: no such request\n");
-
-               /* "protocol stall" on error */
-               retval = -EPIPE;
-       }
-
-       if (usbip_dbg_flag_vhci_rh) {
-               pr_debug("port %d\n", rhport);
-               /* Only dump valid port status */
-               if (rhport >= 0) {
-                       dump_port_status_diff(prev_port_status[rhport],
-                                             dum->port_status[rhport]);
-               }
-       }
-       usbip_dbg_vhci_rh(" bye\n");
-
-       spin_unlock(&dum->lock);
-
-       return retval;
-}
-
-static struct vhci_device *get_vdev(struct usb_device *udev)
-{
-       int i;
-
-       if (!udev)
-               return NULL;
-
-       for (i = 0; i < VHCI_NPORTS; i++)
-               if (the_controller->vdev[i].udev == udev)
-                       return port_to_vdev(i);
-
-       return NULL;
-}
-
-static void vhci_tx_urb(struct urb *urb)
-{
-       struct vhci_device *vdev = get_vdev(urb->dev);
-       struct vhci_priv *priv;
-
-       if (!vdev) {
-               pr_err("could not get virtual device");
-               return;
-       }
-
-       priv = kzalloc(sizeof(struct vhci_priv), GFP_ATOMIC);
-       if (!priv) {
-               usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC);
-               return;
-       }
-
-       spin_lock(&vdev->priv_lock);
-
-       priv->seqnum = atomic_inc_return(&the_controller->seqnum);
-       if (priv->seqnum == 0xffff)
-               dev_info(&urb->dev->dev, "seqnum max\n");
-
-       priv->vdev = vdev;
-       priv->urb = urb;
-
-       urb->hcpriv = (void *) priv;
-
-       list_add_tail(&priv->list, &vdev->priv_tx);
-
-       wake_up(&vdev->waitq_tx);
-       spin_unlock(&vdev->priv_lock);
-}
-
-static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
-                           gfp_t mem_flags)
-{
-       struct device *dev = &urb->dev->dev;
-       int ret = 0;
-       struct vhci_device *vdev;
-
-       usbip_dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n",
-                         hcd, urb, mem_flags);
-
-       /* patch to usb_sg_init() is in 2.5.60 */
-       BUG_ON(!urb->transfer_buffer && urb->transfer_buffer_length);
-
-       spin_lock(&the_controller->lock);
-
-       if (urb->status != -EINPROGRESS) {
-               dev_err(dev, "URB already unlinked!, status %d\n", urb->status);
-               spin_unlock(&the_controller->lock);
-               return urb->status;
-       }
-
-       vdev = port_to_vdev(urb->dev->portnum-1);
-
-       /* refuse enqueue for dead connection */
-       spin_lock(&vdev->ud.lock);
-       if (vdev->ud.status == VDEV_ST_NULL ||
-           vdev->ud.status == VDEV_ST_ERROR) {
-               dev_err(dev, "enqueue for inactive port %d\n", vdev->rhport);
-               spin_unlock(&vdev->ud.lock);
-               spin_unlock(&the_controller->lock);
-               return -ENODEV;
-       }
-       spin_unlock(&vdev->ud.lock);
-
-       ret = usb_hcd_link_urb_to_ep(hcd, urb);
-       if (ret)
-               goto no_need_unlink;
-
-       /*
-        * The enumeration process is as follows;
-        *
-        *  1. Get_Descriptor request to DevAddrs(0) EndPoint(0)
-        *     to get max packet length of default pipe
-        *
-        *  2. Set_Address request to DevAddr(0) EndPoint(0)
-        *
-        */
-       if (usb_pipedevice(urb->pipe) == 0) {
-               __u8 type = usb_pipetype(urb->pipe);
-               struct usb_ctrlrequest *ctrlreq =
-                       (struct usb_ctrlrequest *) urb->setup_packet;
-
-               if (type != PIPE_CONTROL || !ctrlreq) {
-                       dev_err(dev, "invalid request to devnum 0\n");
-                       ret = -EINVAL;
-                       goto no_need_xmit;
-               }
-
-               switch (ctrlreq->bRequest) {
-               case USB_REQ_SET_ADDRESS:
-                       /* set_address may come when a device is reset */
-                       dev_info(dev, "SetAddress Request (%d) to port %d\n",
-                                ctrlreq->wValue, vdev->rhport);
-
-                       if (vdev->udev)
-                               usb_put_dev(vdev->udev);
-                       vdev->udev = usb_get_dev(urb->dev);
-
-                       spin_lock(&vdev->ud.lock);
-                       vdev->ud.status = VDEV_ST_USED;
-                       spin_unlock(&vdev->ud.lock);
-
-                       if (urb->status == -EINPROGRESS) {
-                               /* This request is successfully completed. */
-                               /* If not -EINPROGRESS, possibly unlinked. */
-                               urb->status = 0;
-                       }
-
-                       goto no_need_xmit;
-
-               case USB_REQ_GET_DESCRIPTOR:
-                       if (ctrlreq->wValue == cpu_to_le16(USB_DT_DEVICE << 8))
-                               usbip_dbg_vhci_hc(
-                                       "Not yet?:Get_Descriptor to device 0 (get max pipe size)\n");
-
-                       if (vdev->udev)
-                               usb_put_dev(vdev->udev);
-                       vdev->udev = usb_get_dev(urb->dev);
-                       goto out;
-
-               default:
-                       /* NOT REACHED */
-                       dev_err(dev,
-                               "invalid request to devnum 0 bRequest %u, wValue %u\n",
-                               ctrlreq->bRequest,
-                               ctrlreq->wValue);
-                       ret =  -EINVAL;
-                       goto no_need_xmit;
-               }
-
-       }
-
-out:
-       vhci_tx_urb(urb);
-       spin_unlock(&the_controller->lock);
-
-       return 0;
-
-no_need_xmit:
-       usb_hcd_unlink_urb_from_ep(hcd, urb);
-no_need_unlink:
-       spin_unlock(&the_controller->lock);
-       usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status);
-       return ret;
-}
-
-/*
- * vhci_rx gives back the urb after receiving the reply of the urb.  If an
- * unlink pdu is sent or not, vhci_rx receives a normal return pdu and gives
- * back its urb. For the driver unlinking the urb, the content of the urb is
- * not important, but the calling to its completion handler is important; the
- * completion of unlinking is notified by the completion handler.
- *
- *
- * CLIENT SIDE
- *
- * - When vhci_hcd receives RET_SUBMIT,
- *
- *     - case 1a). the urb of the pdu is not unlinking.
- *             - normal case
- *             => just give back the urb
- *
- *     - case 1b). the urb of the pdu is unlinking.
- *             - usbip.ko will return a reply of the unlinking request.
- *             => give back the urb now and go to case 2b).
- *
- * - When vhci_hcd receives RET_UNLINK,
- *
- *     - case 2a). a submit request is still pending in vhci_hcd.
- *             - urb was really pending in usbip.ko and urb_unlink_urb() was
- *               completed there.
- *             => free a pending submit request
- *             => notify unlink completeness by giving back the urb
- *
- *     - case 2b). a submit request is *not* pending in vhci_hcd.
- *             - urb was already given back to the core driver.
- *             => do not give back the urb
- *
- *
- * SERVER SIDE
- *
- * - When usbip receives CMD_UNLINK,
- *
- *     - case 3a). the urb of the unlink request is now in submission.
- *             => do usb_unlink_urb().
- *             => after the unlink is completed, send RET_UNLINK.
- *
- *     - case 3b). the urb of the unlink request is not in submission.
- *             - may be already completed or never be received
- *             => send RET_UNLINK
- *
- */
-static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
-{
-       struct vhci_priv *priv;
-       struct vhci_device *vdev;
-
-       pr_info("dequeue a urb %p\n", urb);
-
-       spin_lock(&the_controller->lock);
-
-       priv = urb->hcpriv;
-       if (!priv) {
-               /* URB was never linked! or will be soon given back by
-                * vhci_rx. */
-               spin_unlock(&the_controller->lock);
-               return 0;
-       }
-
-       {
-               int ret = 0;
-
-               ret = usb_hcd_check_unlink_urb(hcd, urb, status);
-               if (ret) {
-                       spin_unlock(&the_controller->lock);
-                       return ret;
-               }
-       }
-
-        /* send unlink request here? */
-       vdev = priv->vdev;
-
-       if (!vdev->ud.tcp_socket) {
-               /* tcp connection is closed */
-               spin_lock(&vdev->priv_lock);
-
-               pr_info("device %p seems to be disconnected\n", vdev);
-               list_del(&priv->list);
-               kfree(priv);
-               urb->hcpriv = NULL;
-
-               spin_unlock(&vdev->priv_lock);
-
-               /*
-                * If tcp connection is alive, we have sent CMD_UNLINK.
-                * vhci_rx will receive RET_UNLINK and give back the URB.
-                * Otherwise, we give back it here.
-                */
-               pr_info("gives back urb %p\n", urb);
-
-               usb_hcd_unlink_urb_from_ep(hcd, urb);
-
-               spin_unlock(&the_controller->lock);
-               usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
-                                    urb->status);
-               spin_lock(&the_controller->lock);
-
-       } else {
-               /* tcp connection is alive */
-               struct vhci_unlink *unlink;
-
-               spin_lock(&vdev->priv_lock);
-
-               /* setup CMD_UNLINK pdu */
-               unlink = kzalloc(sizeof(struct vhci_unlink), GFP_ATOMIC);
-               if (!unlink) {
-                       spin_unlock(&vdev->priv_lock);
-                       spin_unlock(&the_controller->lock);
-                       usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC);
-                       return -ENOMEM;
-               }
-
-               unlink->seqnum = atomic_inc_return(&the_controller->seqnum);
-               if (unlink->seqnum == 0xffff)
-                       pr_info("seqnum max\n");
-
-               unlink->unlink_seqnum = priv->seqnum;
-
-               pr_info("device %p seems to be still connected\n", vdev);
-
-               /* send cmd_unlink and try to cancel the pending URB in the
-                * peer */
-               list_add_tail(&unlink->list, &vdev->unlink_tx);
-               wake_up(&vdev->waitq_tx);
-
-               spin_unlock(&vdev->priv_lock);
-       }
-
-       spin_unlock(&the_controller->lock);
-
-       usbip_dbg_vhci_hc("leave\n");
-       return 0;
-}
-
-static void vhci_device_unlink_cleanup(struct vhci_device *vdev)
-{
-       struct vhci_unlink *unlink, *tmp;
-
-       spin_lock(&the_controller->lock);
-       spin_lock(&vdev->priv_lock);
-
-       list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) {
-               pr_info("unlink cleanup tx %lu\n", unlink->unlink_seqnum);
-               list_del(&unlink->list);
-               kfree(unlink);
-       }
-
-       while (!list_empty(&vdev->unlink_rx)) {
-               struct urb *urb;
-
-               unlink = list_first_entry(&vdev->unlink_rx, struct vhci_unlink,
-                       list);
-
-               /* give back URB of unanswered unlink request */
-               pr_info("unlink cleanup rx %lu\n", unlink->unlink_seqnum);
-
-               urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum);
-               if (!urb) {
-                       pr_info("the urb (seqnum %lu) was already given back\n",
-                               unlink->unlink_seqnum);
-                       list_del(&unlink->list);
-                       kfree(unlink);
-                       continue;
-               }
-
-               urb->status = -ENODEV;
-
-               usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
-
-               list_del(&unlink->list);
-
-               spin_unlock(&vdev->priv_lock);
-               spin_unlock(&the_controller->lock);
-
-               usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
-                                    urb->status);
-
-               spin_lock(&the_controller->lock);
-               spin_lock(&vdev->priv_lock);
-
-               kfree(unlink);
-       }
-
-       spin_unlock(&vdev->priv_lock);
-       spin_unlock(&the_controller->lock);
-}
-
-/*
- * The important thing is that only one context begins cleanup.
- * This is why error handling and cleanup become simple.
- * We do not want to consider race condition as possible.
- */
-static void vhci_shutdown_connection(struct usbip_device *ud)
-{
-       struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
-
-       /* need this? see stub_dev.c */
-       if (ud->tcp_socket) {
-               pr_debug("shutdown tcp_socket %p\n", ud->tcp_socket);
-               kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR);
-       }
-
-       /* kill threads related to this sdev */
-       if (vdev->ud.tcp_rx) {
-               kthread_stop_put(vdev->ud.tcp_rx);
-               vdev->ud.tcp_rx = NULL;
-       }
-       if (vdev->ud.tcp_tx) {
-               kthread_stop_put(vdev->ud.tcp_tx);
-               vdev->ud.tcp_tx = NULL;
-       }
-       pr_info("stop threads\n");
-
-       /* active connection is closed */
-       if (vdev->ud.tcp_socket) {
-               sockfd_put(vdev->ud.tcp_socket);
-               vdev->ud.tcp_socket = NULL;
-       }
-       pr_info("release socket\n");
-
-       vhci_device_unlink_cleanup(vdev);
-
-       /*
-        * rh_port_disconnect() is a trigger of ...
-        *   usb_disable_device():
-        *      disable all the endpoints for a USB device.
-        *   usb_disable_endpoint():
-        *      disable endpoints. pending urbs are unlinked(dequeued).
-        *
-        * NOTE: After calling rh_port_disconnect(), the USB device drivers of a
-        * detached device should release used urbs in a cleanup function (i.e.
-        * xxx_disconnect()). Therefore, vhci_hcd does not need to release
-        * pushed urbs and their private data in this function.
-        *
-        * NOTE: vhci_dequeue() must be considered carefully. When shutting down
-        * a connection, vhci_shutdown_connection() expects vhci_dequeue()
-        * gives back pushed urbs and frees their private data by request of
-        * the cleanup function of a USB driver. When unlinking a urb with an
-        * active connection, vhci_dequeue() does not give back the urb which
-        * is actually given back by vhci_rx after receiving its return pdu.
-        *
-        */
-       rh_port_disconnect(vdev->rhport);
-
-       pr_info("disconnect device\n");
-}
-
-
-static void vhci_device_reset(struct usbip_device *ud)
-{
-       struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
-
-       spin_lock(&ud->lock);
-
-       vdev->speed  = 0;
-       vdev->devid  = 0;
-
-       if (vdev->udev)
-               usb_put_dev(vdev->udev);
-       vdev->udev = NULL;
-
-       if (ud->tcp_socket) {
-               sockfd_put(ud->tcp_socket);
-               ud->tcp_socket = NULL;
-       }
-       ud->status = VDEV_ST_NULL;
-
-       spin_unlock(&ud->lock);
-}
-
-static void vhci_device_unusable(struct usbip_device *ud)
-{
-       spin_lock(&ud->lock);
-       ud->status = VDEV_ST_ERROR;
-       spin_unlock(&ud->lock);
-}
-
-static void vhci_device_init(struct vhci_device *vdev)
-{
-       memset(vdev, 0, sizeof(*vdev));
-
-       vdev->ud.side   = USBIP_VHCI;
-       vdev->ud.status = VDEV_ST_NULL;
-       spin_lock_init(&vdev->ud.lock);
-
-       INIT_LIST_HEAD(&vdev->priv_rx);
-       INIT_LIST_HEAD(&vdev->priv_tx);
-       INIT_LIST_HEAD(&vdev->unlink_tx);
-       INIT_LIST_HEAD(&vdev->unlink_rx);
-       spin_lock_init(&vdev->priv_lock);
-
-       init_waitqueue_head(&vdev->waitq_tx);
-
-       vdev->ud.eh_ops.shutdown = vhci_shutdown_connection;
-       vdev->ud.eh_ops.reset = vhci_device_reset;
-       vdev->ud.eh_ops.unusable = vhci_device_unusable;
-
-       usbip_start_eh(&vdev->ud);
-}
-
-static int vhci_start(struct usb_hcd *hcd)
-{
-       struct vhci_hcd *vhci = hcd_to_vhci(hcd);
-       int rhport;
-       int err = 0;
-
-       usbip_dbg_vhci_hc("enter vhci_start\n");
-
-       /* initialize private data of usb_hcd */
-
-       for (rhport = 0; rhport < VHCI_NPORTS; rhport++) {
-               struct vhci_device *vdev = &vhci->vdev[rhport];
-
-               vhci_device_init(vdev);
-               vdev->rhport = rhport;
-       }
-
-       atomic_set(&vhci->seqnum, 0);
-       spin_lock_init(&vhci->lock);
-
-       hcd->power_budget = 0; /* no limit */
-       hcd->uses_new_polling = 1;
-
-       /* vhci_hcd is now ready to be controlled through sysfs */
-       err = sysfs_create_group(&vhci_dev(vhci)->kobj, &dev_attr_group);
-       if (err) {
-               pr_err("create sysfs files\n");
-               return err;
-       }
-
-       return 0;
-}
-
-static void vhci_stop(struct usb_hcd *hcd)
-{
-       struct vhci_hcd *vhci = hcd_to_vhci(hcd);
-       int rhport = 0;
-
-       usbip_dbg_vhci_hc("stop VHCI controller\n");
-
-       /* 1. remove the userland interface of vhci_hcd */
-       sysfs_remove_group(&vhci_dev(vhci)->kobj, &dev_attr_group);
-
-       /* 2. shutdown all the ports of vhci_hcd */
-       for (rhport = 0; rhport < VHCI_NPORTS; rhport++) {
-               struct vhci_device *vdev = &vhci->vdev[rhport];
-
-               usbip_event_add(&vdev->ud, VDEV_EVENT_REMOVED);
-               usbip_stop_eh(&vdev->ud);
-       }
-}
-
-static int vhci_get_frame_number(struct usb_hcd *hcd)
-{
-       pr_err("Not yet implemented\n");
-       return 0;
-}
-
-#ifdef CONFIG_PM
-
-/* FIXME: suspend/resume */
-static int vhci_bus_suspend(struct usb_hcd *hcd)
-{
-       struct vhci_hcd *vhci = hcd_to_vhci(hcd);
-
-       dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
-
-       spin_lock(&vhci->lock);
-       hcd->state = HC_STATE_SUSPENDED;
-       spin_unlock(&vhci->lock);
-
-       return 0;
-}
-
-static int vhci_bus_resume(struct usb_hcd *hcd)
-{
-       struct vhci_hcd *vhci = hcd_to_vhci(hcd);
-       int rc = 0;
-
-       dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
-
-       spin_lock(&vhci->lock);
-       if (!HCD_HW_ACCESSIBLE(hcd))
-               rc = -ESHUTDOWN;
-       else
-               hcd->state = HC_STATE_RUNNING;
-       spin_unlock(&vhci->lock);
-
-       return rc;
-}
-
-#else
-
-#define vhci_bus_suspend      NULL
-#define vhci_bus_resume       NULL
-#endif
-
-static struct hc_driver vhci_hc_driver = {
-       .description    = driver_name,
-       .product_desc   = driver_desc,
-       .hcd_priv_size  = sizeof(struct vhci_hcd),
-
-       .flags          = HCD_USB2,
-
-       .start          = vhci_start,
-       .stop           = vhci_stop,
-
-       .urb_enqueue    = vhci_urb_enqueue,
-       .urb_dequeue    = vhci_urb_dequeue,
-
-       .get_frame_number = vhci_get_frame_number,
-
-       .hub_status_data = vhci_hub_status,
-       .hub_control    = vhci_hub_control,
-       .bus_suspend    = vhci_bus_suspend,
-       .bus_resume     = vhci_bus_resume,
-};
-
-static int vhci_hcd_probe(struct platform_device *pdev)
-{
-       struct usb_hcd          *hcd;
-       int                     ret;
-
-       usbip_dbg_vhci_hc("name %s id %d\n", pdev->name, pdev->id);
-
-       /*
-        * Allocate and initialize hcd.
-        * Our private data is also allocated automatically.
-        */
-       hcd = usb_create_hcd(&vhci_hc_driver, &pdev->dev, dev_name(&pdev->dev));
-       if (!hcd) {
-               pr_err("create hcd failed\n");
-               return -ENOMEM;
-       }
-       hcd->has_tt = 1;
-
-       /* this is private data for vhci_hcd */
-       the_controller = hcd_to_vhci(hcd);
-
-       /*
-        * Finish generic HCD structure initialization and register.
-        * Call the driver's reset() and start() routines.
-        */
-       ret = usb_add_hcd(hcd, 0, 0);
-       if (ret != 0) {
-               pr_err("usb_add_hcd failed %d\n", ret);
-               usb_put_hcd(hcd);
-               the_controller = NULL;
-               return ret;
-       }
-
-       usbip_dbg_vhci_hc("bye\n");
-       return 0;
-}
-
-static int vhci_hcd_remove(struct platform_device *pdev)
-{
-       struct usb_hcd  *hcd;
-
-       hcd = platform_get_drvdata(pdev);
-       if (!hcd)
-               return 0;
-
-       /*
-        * Disconnects the root hub,
-        * then reverses the effects of usb_add_hcd(),
-        * invoking the HCD's stop() methods.
-        */
-       usb_remove_hcd(hcd);
-       usb_put_hcd(hcd);
-       the_controller = NULL;
-
-       return 0;
-}
-
-#ifdef CONFIG_PM
-
-/* what should happen for USB/IP under suspend/resume? */
-static int vhci_hcd_suspend(struct platform_device *pdev, pm_message_t state)
-{
-       struct usb_hcd *hcd;
-       int rhport = 0;
-       int connected = 0;
-       int ret = 0;
-
-       hcd = platform_get_drvdata(pdev);
-
-       spin_lock(&the_controller->lock);
-
-       for (rhport = 0; rhport < VHCI_NPORTS; rhport++)
-               if (the_controller->port_status[rhport] &
-                   USB_PORT_STAT_CONNECTION)
-                       connected += 1;
-
-       spin_unlock(&the_controller->lock);
-
-       if (connected > 0) {
-               dev_info(&pdev->dev,
-                        "We have %d active connection%s. Do not suspend.\n",
-                        connected, (connected == 1 ? "" : "s"));
-               ret =  -EBUSY;
-       } else {
-               dev_info(&pdev->dev, "suspend vhci_hcd");
-               clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-       }
-
-       return ret;
-}
-
-static int vhci_hcd_resume(struct platform_device *pdev)
-{
-       struct usb_hcd *hcd;
-
-       dev_dbg(&pdev->dev, "%s\n", __func__);
-
-       hcd = platform_get_drvdata(pdev);
-       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-       usb_hcd_poll_rh_status(hcd);
-
-       return 0;
-}
-
-#else
-
-#define vhci_hcd_suspend       NULL
-#define vhci_hcd_resume                NULL
-
-#endif
-
-static struct platform_driver vhci_driver = {
-       .probe  = vhci_hcd_probe,
-       .remove = vhci_hcd_remove,
-       .suspend = vhci_hcd_suspend,
-       .resume = vhci_hcd_resume,
-       .driver = {
-               .name = driver_name,
-               .owner = THIS_MODULE,
-       },
-};
-
-/*
- * The VHCI 'device' is 'virtual'; not a real plug&play hardware.
- * We need to add this virtual device as a platform device arbitrarily:
- *     1. platform_device_register()
- */
-static void the_pdev_release(struct device *dev)
-{
-}
-
-static struct platform_device the_pdev = {
-       /* should be the same name as driver_name */
-       .name = driver_name,
-       .id = -1,
-       .dev = {
-               .release = the_pdev_release,
-       },
-};
-
-static int __init vhci_hcd_init(void)
-{
-       int ret;
-
-       if (usb_disabled())
-               return -ENODEV;
-
-       ret = platform_driver_register(&vhci_driver);
-       if (ret)
-               goto err_driver_register;
-
-       ret = platform_device_register(&the_pdev);
-       if (ret)
-               goto err_platform_device_register;
-
-       pr_info(DRIVER_DESC " v" USBIP_VERSION "\n");
-       return ret;
-
-err_platform_device_register:
-       platform_driver_unregister(&vhci_driver);
-err_driver_register:
-       return ret;
-}
-
-static void __exit vhci_hcd_exit(void)
-{
-       platform_device_unregister(&the_pdev);
-       platform_driver_unregister(&vhci_driver);
-}
-
-module_init(vhci_hcd_init);
-module_exit(vhci_hcd_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-MODULE_VERSION(USBIP_VERSION);
diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c
deleted file mode 100644 (file)
index 00e4a54..0000000
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright (C) 2003-2008 Takahiro Hirofuchi
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#include <linux/kthread.h>
-#include <linux/slab.h>
-
-#include "usbip_common.h"
-#include "vhci.h"
-
-/* get URB from transmitted urb queue. caller must hold vdev->priv_lock */
-struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, __u32 seqnum)
-{
-       struct vhci_priv *priv, *tmp;
-       struct urb *urb = NULL;
-       int status;
-
-       list_for_each_entry_safe(priv, tmp, &vdev->priv_rx, list) {
-               if (priv->seqnum != seqnum)
-                       continue;
-
-               urb = priv->urb;
-               status = urb->status;
-
-               usbip_dbg_vhci_rx("find urb %p vurb %p seqnum %u\n",
-                               urb, priv, seqnum);
-
-               switch (status) {
-               case -ENOENT:
-                       /* fall through */
-               case -ECONNRESET:
-                       dev_info(&urb->dev->dev,
-                                "urb %p was unlinked %ssynchronuously.\n", urb,
-                                status == -ENOENT ? "" : "a");
-                       break;
-               case -EINPROGRESS:
-                       /* no info output */
-                       break;
-               default:
-                       dev_info(&urb->dev->dev,
-                                "urb %p may be in a error, status %d\n", urb,
-                                status);
-               }
-
-               list_del(&priv->list);
-               kfree(priv);
-               urb->hcpriv = NULL;
-
-               break;
-       }
-
-       return urb;
-}
-
-static void vhci_recv_ret_submit(struct vhci_device *vdev,
-                                struct usbip_header *pdu)
-{
-       struct usbip_device *ud = &vdev->ud;
-       struct urb *urb;
-
-       spin_lock(&vdev->priv_lock);
-       urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum);
-       spin_unlock(&vdev->priv_lock);
-
-       if (!urb) {
-               pr_err("cannot find a urb of seqnum %u\n", pdu->base.seqnum);
-               pr_info("max seqnum %d\n",
-                       atomic_read(&the_controller->seqnum));
-               usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
-               return;
-       }
-
-       /* unpack the pdu to a urb */
-       usbip_pack_pdu(pdu, urb, USBIP_RET_SUBMIT, 0);
-
-       /* recv transfer buffer */
-       if (usbip_recv_xbuff(ud, urb) < 0)
-               return;
-
-       /* recv iso_packet_descriptor */
-       if (usbip_recv_iso(ud, urb) < 0)
-               return;
-
-       /* restore the padding in iso packets */
-       usbip_pad_iso(ud, urb);
-
-       if (usbip_dbg_flag_vhci_rx)
-               usbip_dump_urb(urb);
-
-       usbip_dbg_vhci_rx("now giveback urb %p\n", urb);
-
-       spin_lock(&the_controller->lock);
-       usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
-       spin_unlock(&the_controller->lock);
-
-       usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status);
-
-       usbip_dbg_vhci_rx("Leave\n");
-}
-
-static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev,
-                                                 struct usbip_header *pdu)
-{
-       struct vhci_unlink *unlink, *tmp;
-
-       spin_lock(&vdev->priv_lock);
-
-       list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) {
-               pr_info("unlink->seqnum %lu\n", unlink->seqnum);
-               if (unlink->seqnum == pdu->base.seqnum) {
-                       usbip_dbg_vhci_rx("found pending unlink, %lu\n",
-                                         unlink->seqnum);
-                       list_del(&unlink->list);
-
-                       spin_unlock(&vdev->priv_lock);
-                       return unlink;
-               }
-       }
-
-       spin_unlock(&vdev->priv_lock);
-
-       return NULL;
-}
-
-static void vhci_recv_ret_unlink(struct vhci_device *vdev,
-                                struct usbip_header *pdu)
-{
-       struct vhci_unlink *unlink;
-       struct urb *urb;
-
-       usbip_dump_header(pdu);
-
-       unlink = dequeue_pending_unlink(vdev, pdu);
-       if (!unlink) {
-               pr_info("cannot find the pending unlink %u\n",
-                       pdu->base.seqnum);
-               return;
-       }
-
-       spin_lock(&vdev->priv_lock);
-       urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum);
-       spin_unlock(&vdev->priv_lock);
-
-       if (!urb) {
-               /*
-                * I get the result of a unlink request. But, it seems that I
-                * already received the result of its submit result and gave
-                * back the URB.
-                */
-               pr_info("the urb (seqnum %d) was already given back\n",
-                       pdu->base.seqnum);
-       } else {
-               usbip_dbg_vhci_rx("now giveback urb %p\n", urb);
-
-               /* If unlink is successful, status is -ECONNRESET */
-               urb->status = pdu->u.ret_unlink.status;
-               pr_info("urb->status %d\n", urb->status);
-
-               spin_lock(&the_controller->lock);
-               usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
-               spin_unlock(&the_controller->lock);
-
-               usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
-                                    urb->status);
-       }
-
-       kfree(unlink);
-}
-
-static int vhci_priv_tx_empty(struct vhci_device *vdev)
-{
-       int empty = 0;
-
-       spin_lock(&vdev->priv_lock);
-       empty = list_empty(&vdev->priv_rx);
-       spin_unlock(&vdev->priv_lock);
-
-       return empty;
-}
-
-/* recv a pdu */
-static void vhci_rx_pdu(struct usbip_device *ud)
-{
-       int ret;
-       struct usbip_header pdu;
-       struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
-
-       usbip_dbg_vhci_rx("Enter\n");
-
-       memset(&pdu, 0, sizeof(pdu));
-
-       /* receive a pdu header */
-       ret = usbip_recv(ud->tcp_socket, &pdu, sizeof(pdu));
-       if (ret < 0) {
-               if (ret == -ECONNRESET)
-                       pr_info("connection reset by peer\n");
-               else if (ret == -EAGAIN) {
-                       /* ignore if connection was idle */
-                       if (vhci_priv_tx_empty(vdev))
-                               return;
-                       pr_info("connection timed out with pending urbs\n");
-               } else if (ret != -ERESTARTSYS)
-                       pr_info("xmit failed %d\n", ret);
-
-               usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
-               return;
-       }
-       if (ret == 0) {
-               pr_info("connection closed");
-               usbip_event_add(ud, VDEV_EVENT_DOWN);
-               return;
-       }
-       if (ret != sizeof(pdu)) {
-               pr_err("received pdu size is %d, should be %d\n", ret,
-                      (unsigned int)sizeof(pdu));
-               usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
-               return;
-       }
-
-       usbip_header_correct_endian(&pdu, 0);
-
-       if (usbip_dbg_flag_vhci_rx)
-               usbip_dump_header(&pdu);
-
-       switch (pdu.base.command) {
-       case USBIP_RET_SUBMIT:
-               vhci_recv_ret_submit(vdev, &pdu);
-               break;
-       case USBIP_RET_UNLINK:
-               vhci_recv_ret_unlink(vdev, &pdu);
-               break;
-       default:
-               /* NOT REACHED */
-               pr_err("unknown pdu %u\n", pdu.base.command);
-               usbip_dump_header(&pdu);
-               usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
-               break;
-       }
-}
-
-int vhci_rx_loop(void *data)
-{
-       struct usbip_device *ud = data;
-
-       while (!kthread_should_stop()) {
-               if (usbip_event_happened(ud))
-                       break;
-
-               vhci_rx_pdu(ud);
-       }
-
-       return 0;
-}
diff --git a/drivers/staging/usbip/vhci_sysfs.c b/drivers/staging/usbip/vhci_sysfs.c
deleted file mode 100644 (file)
index 211f43f..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright (C) 2003-2008 Takahiro Hirofuchi
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#include <linux/kthread.h>
-#include <linux/file.h>
-#include <linux/net.h>
-
-#include "usbip_common.h"
-#include "vhci.h"
-
-/* TODO: refine locking ?*/
-
-/* Sysfs entry to show port status */
-static ssize_t status_show(struct device *dev, struct device_attribute *attr,
-                          char *out)
-{
-       char *s = out;
-       int i = 0;
-
-       BUG_ON(!the_controller || !out);
-
-       spin_lock(&the_controller->lock);
-
-       /*
-        * output example:
-        * prt sta spd dev socket           local_busid
-        * 000 004 000 000         c5a7bb80 1-2.3
-        * 001 004 000 000         d8cee980 2-3.4
-        *
-        * IP address can be retrieved from a socket pointer address by looking
-        * up /proc/net/{tcp,tcp6}. Also, a userland program may remember a
-        * port number and its peer IP address.
-        */
-       out += sprintf(out,
-                      "prt sta spd bus dev socket           local_busid\n");
-
-       for (i = 0; i < VHCI_NPORTS; i++) {
-               struct vhci_device *vdev = port_to_vdev(i);
-
-               spin_lock(&vdev->ud.lock);
-               out += sprintf(out, "%03u %03u ", i, vdev->ud.status);
-
-               if (vdev->ud.status == VDEV_ST_USED) {
-                       out += sprintf(out, "%03u %08x ",
-                                      vdev->speed, vdev->devid);
-                       out += sprintf(out, "%16p ", vdev->ud.tcp_socket);
-                       out += sprintf(out, "%s", dev_name(&vdev->udev->dev));
-
-               } else {
-                       out += sprintf(out, "000 000 000 0000000000000000 0-0");
-               }
-
-               out += sprintf(out, "\n");
-               spin_unlock(&vdev->ud.lock);
-       }
-
-       spin_unlock(&the_controller->lock);
-
-       return out - s;
-}
-static DEVICE_ATTR_RO(status);
-
-/* Sysfs entry to shutdown a virtual connection */
-static int vhci_port_disconnect(__u32 rhport)
-{
-       struct vhci_device *vdev;
-
-       usbip_dbg_vhci_sysfs("enter\n");
-
-       /* lock */
-       spin_lock(&the_controller->lock);
-
-       vdev = port_to_vdev(rhport);
-
-       spin_lock(&vdev->ud.lock);
-       if (vdev->ud.status == VDEV_ST_NULL) {
-               pr_err("not connected %d\n", vdev->ud.status);
-
-               /* unlock */
-               spin_unlock(&vdev->ud.lock);
-               spin_unlock(&the_controller->lock);
-
-               return -EINVAL;
-       }
-
-       /* unlock */
-       spin_unlock(&vdev->ud.lock);
-       spin_unlock(&the_controller->lock);
-
-       usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN);
-
-       return 0;
-}
-
-static ssize_t store_detach(struct device *dev, struct device_attribute *attr,
-                           const char *buf, size_t count)
-{
-       int err;
-       __u32 rhport = 0;
-
-       if (sscanf(buf, "%u", &rhport) != 1)
-               return -EINVAL;
-
-       /* check rhport */
-       if (rhport >= VHCI_NPORTS) {
-               dev_err(dev, "invalid port %u\n", rhport);
-               return -EINVAL;
-       }
-
-       err = vhci_port_disconnect(rhport);
-       if (err < 0)
-               return -EINVAL;
-
-       usbip_dbg_vhci_sysfs("Leave\n");
-
-       return count;
-}
-static DEVICE_ATTR(detach, S_IWUSR, NULL, store_detach);
-
-/* Sysfs entry to establish a virtual connection */
-static int valid_args(__u32 rhport, enum usb_device_speed speed)
-{
-       /* check rhport */
-       if (rhport >= VHCI_NPORTS) {
-               pr_err("port %u\n", rhport);
-               return -EINVAL;
-       }
-
-       /* check speed */
-       switch (speed) {
-       case USB_SPEED_LOW:
-       case USB_SPEED_FULL:
-       case USB_SPEED_HIGH:
-       case USB_SPEED_WIRELESS:
-               break;
-       default:
-               pr_err("Failed attach request for unsupported USB speed: %s\n",
-                       usb_speed_string(speed));
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/*
- * To start a new USB/IP attachment, a userland program needs to setup a TCP
- * connection and then write its socket descriptor with remote device
- * information into this sysfs file.
- *
- * A remote device is virtually attached to the root-hub port of @rhport with
- * @speed. @devid is embedded into a request to specify the remote device in a
- * server host.
- *
- * write() returns 0 on success, else negative errno.
- */
-static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
-                           const char *buf, size_t count)
-{
-       struct vhci_device *vdev;
-       struct socket *socket;
-       int sockfd = 0;
-       __u32 rhport = 0, devid = 0, speed = 0;
-       int err;
-
-       /*
-        * @rhport: port number of vhci_hcd
-        * @sockfd: socket descriptor of an established TCP connection
-        * @devid: unique device identifier in a remote host
-        * @speed: usb device speed in a remote host
-        */
-       if (sscanf(buf, "%u %u %u %u", &rhport, &sockfd, &devid, &speed) != 4)
-               return -EINVAL;
-
-       usbip_dbg_vhci_sysfs("rhport(%u) sockfd(%u) devid(%u) speed(%u)\n",
-                            rhport, sockfd, devid, speed);
-
-       /* check received parameters */
-       if (valid_args(rhport, speed) < 0)
-               return -EINVAL;
-
-       /* Extract socket from fd. */
-       socket = sockfd_lookup(sockfd, &err);
-       if (!socket)
-               return -EINVAL;
-
-       /* now need lock until setting vdev status as used */
-
-       /* begin a lock */
-       spin_lock(&the_controller->lock);
-       vdev = port_to_vdev(rhport);
-       spin_lock(&vdev->ud.lock);
-
-       if (vdev->ud.status != VDEV_ST_NULL) {
-               /* end of the lock */
-               spin_unlock(&vdev->ud.lock);
-               spin_unlock(&the_controller->lock);
-
-               sockfd_put(socket);
-
-               dev_err(dev, "port %d already used\n", rhport);
-               return -EINVAL;
-       }
-
-       dev_info(dev,
-                "rhport(%u) sockfd(%d) devid(%u) speed(%u) speed_str(%s)\n",
-                rhport, sockfd, devid, speed, usb_speed_string(speed));
-
-       vdev->devid         = devid;
-       vdev->speed         = speed;
-       vdev->ud.tcp_socket = socket;
-       vdev->ud.status     = VDEV_ST_NOTASSIGNED;
-
-       spin_unlock(&vdev->ud.lock);
-       spin_unlock(&the_controller->lock);
-       /* end the lock */
-
-       vdev->ud.tcp_rx = kthread_get_run(vhci_rx_loop, &vdev->ud, "vhci_rx");
-       vdev->ud.tcp_tx = kthread_get_run(vhci_tx_loop, &vdev->ud, "vhci_tx");
-
-       rh_port_connect(rhport, speed);
-
-       return count;
-}
-static DEVICE_ATTR(attach, S_IWUSR, NULL, store_attach);
-
-static struct attribute *dev_attrs[] = {
-       &dev_attr_status.attr,
-       &dev_attr_detach.attr,
-       &dev_attr_attach.attr,
-       &dev_attr_usbip_debug.attr,
-       NULL,
-};
-
-const struct attribute_group dev_attr_group = {
-       .attrs = dev_attrs,
-};
diff --git a/drivers/staging/usbip/vhci_tx.c b/drivers/staging/usbip/vhci_tx.c
deleted file mode 100644 (file)
index 409fd99..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * Copyright (C) 2003-2008 Takahiro Hirofuchi
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-#include <linux/kthread.h>
-#include <linux/slab.h>
-
-#include "usbip_common.h"
-#include "vhci.h"
-
-static void setup_cmd_submit_pdu(struct usbip_header *pdup,  struct urb *urb)
-{
-       struct vhci_priv *priv = ((struct vhci_priv *)urb->hcpriv);
-       struct vhci_device *vdev = priv->vdev;
-
-       usbip_dbg_vhci_tx("URB, local devnum %u, remote devid %u\n",
-                         usb_pipedevice(urb->pipe), vdev->devid);
-
-       pdup->base.command   = USBIP_CMD_SUBMIT;
-       pdup->base.seqnum    = priv->seqnum;
-       pdup->base.devid     = vdev->devid;
-       pdup->base.direction = usb_pipein(urb->pipe) ?
-               USBIP_DIR_IN : USBIP_DIR_OUT;
-       pdup->base.ep        = usb_pipeendpoint(urb->pipe);
-
-       usbip_pack_pdu(pdup, urb, USBIP_CMD_SUBMIT, 1);
-
-       if (urb->setup_packet)
-               memcpy(pdup->u.cmd_submit.setup, urb->setup_packet, 8);
-}
-
-static struct vhci_priv *dequeue_from_priv_tx(struct vhci_device *vdev)
-{
-       struct vhci_priv *priv, *tmp;
-
-       spin_lock(&vdev->priv_lock);
-
-       list_for_each_entry_safe(priv, tmp, &vdev->priv_tx, list) {
-               list_move_tail(&priv->list, &vdev->priv_rx);
-               spin_unlock(&vdev->priv_lock);
-               return priv;
-       }
-
-       spin_unlock(&vdev->priv_lock);
-
-       return NULL;
-}
-
-static int vhci_send_cmd_submit(struct vhci_device *vdev)
-{
-       struct vhci_priv *priv = NULL;
-
-       struct msghdr msg;
-       struct kvec iov[3];
-       size_t txsize;
-
-       size_t total_size = 0;
-
-       while ((priv = dequeue_from_priv_tx(vdev)) != NULL) {
-               int ret;
-               struct urb *urb = priv->urb;
-               struct usbip_header pdu_header;
-               struct usbip_iso_packet_descriptor *iso_buffer = NULL;
-
-               txsize = 0;
-               memset(&pdu_header, 0, sizeof(pdu_header));
-               memset(&msg, 0, sizeof(msg));
-               memset(&iov, 0, sizeof(iov));
-
-               usbip_dbg_vhci_tx("setup txdata urb %p\n", urb);
-
-               /* 1. setup usbip_header */
-               setup_cmd_submit_pdu(&pdu_header, urb);
-               usbip_header_correct_endian(&pdu_header, 1);
-
-               iov[0].iov_base = &pdu_header;
-               iov[0].iov_len  = sizeof(pdu_header);
-               txsize += sizeof(pdu_header);
-
-               /* 2. setup transfer buffer */
-               if (!usb_pipein(urb->pipe) && urb->transfer_buffer_length > 0) {
-                       iov[1].iov_base = urb->transfer_buffer;
-                       iov[1].iov_len  = urb->transfer_buffer_length;
-                       txsize += urb->transfer_buffer_length;
-               }
-
-               /* 3. setup iso_packet_descriptor */
-               if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
-                       ssize_t len = 0;
-
-                       iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len);
-                       if (!iso_buffer) {
-                               usbip_event_add(&vdev->ud,
-                                               SDEV_EVENT_ERROR_MALLOC);
-                               return -1;
-                       }
-
-                       iov[2].iov_base = iso_buffer;
-                       iov[2].iov_len  = len;
-                       txsize += len;
-               }
-
-               ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, iov, 3, txsize);
-               if (ret != txsize) {
-                       pr_err("sendmsg failed!, ret=%d for %zd\n", ret,
-                              txsize);
-                       kfree(iso_buffer);
-                       usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP);
-                       return -1;
-               }
-
-               kfree(iso_buffer);
-               usbip_dbg_vhci_tx("send txdata\n");
-
-               total_size += txsize;
-       }
-
-       return total_size;
-}
-
-static struct vhci_unlink *dequeue_from_unlink_tx(struct vhci_device *vdev)
-{
-       struct vhci_unlink *unlink, *tmp;
-
-       spin_lock(&vdev->priv_lock);
-
-       list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) {
-               list_move_tail(&unlink->list, &vdev->unlink_rx);
-               spin_unlock(&vdev->priv_lock);
-               return unlink;
-       }
-
-       spin_unlock(&vdev->priv_lock);
-
-       return NULL;
-}
-
-static int vhci_send_cmd_unlink(struct vhci_device *vdev)
-{
-       struct vhci_unlink *unlink = NULL;
-
-       struct msghdr msg;
-       struct kvec iov[3];
-       size_t txsize;
-
-       size_t total_size = 0;
-
-       while ((unlink = dequeue_from_unlink_tx(vdev)) != NULL) {
-               int ret;
-               struct usbip_header pdu_header;
-
-               txsize = 0;
-               memset(&pdu_header, 0, sizeof(pdu_header));
-               memset(&msg, 0, sizeof(msg));
-               memset(&iov, 0, sizeof(iov));
-
-               usbip_dbg_vhci_tx("setup cmd unlink, %lu\n", unlink->seqnum);
-
-               /* 1. setup usbip_header */
-               pdu_header.base.command = USBIP_CMD_UNLINK;
-               pdu_header.base.seqnum  = unlink->seqnum;
-               pdu_header.base.devid   = vdev->devid;
-               pdu_header.base.ep      = 0;
-               pdu_header.u.cmd_unlink.seqnum = unlink->unlink_seqnum;
-
-               usbip_header_correct_endian(&pdu_header, 1);
-
-               iov[0].iov_base = &pdu_header;
-               iov[0].iov_len  = sizeof(pdu_header);
-               txsize += sizeof(pdu_header);
-
-               ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, iov, 1, txsize);
-               if (ret != txsize) {
-                       pr_err("sendmsg failed!, ret=%d for %zd\n", ret,
-                              txsize);
-                       usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP);
-                       return -1;
-               }
-
-               usbip_dbg_vhci_tx("send txdata\n");
-
-               total_size += txsize;
-       }
-
-       return total_size;
-}
-
-int vhci_tx_loop(void *data)
-{
-       struct usbip_device *ud = data;
-       struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
-
-       while (!kthread_should_stop()) {
-               if (vhci_send_cmd_submit(vdev) < 0)
-                       break;
-
-               if (vhci_send_cmd_unlink(vdev) < 0)
-                       break;
-
-               wait_event_interruptible(vdev->waitq_tx,
-                                        (!list_empty(&vdev->priv_tx) ||
-                                         !list_empty(&vdev->unlink_tx) ||
-                                         kthread_should_stop()));
-
-               usbip_dbg_vhci_tx("pending urbs ?, now wake up\n");
-       }
-
-       return 0;
-}
index 8fcf8a7b6c2264d75f98d919b4bc88e7b1a3e4ae..9562cd026dc01754144edab74f981313f837b507 100644 (file)
@@ -150,7 +150,26 @@ int tb_path_activate(struct tb_path *path)
 
        /* Activate hops. */
        for (i = path->path_length - 1; i >= 0; i--) {
-               struct tb_regs_hop hop;
+               struct tb_regs_hop hop = { 0 };
+
+               /*
+                * We do (currently) not tear down paths setup by the firmeware.
+                * If a firmware device is unplugged and plugged in again then
+                * it can happen that we reuse some of the hops from the (now
+                * defunct) firmeware path. This causes the hotplug operation to
+                * fail (the pci device does not show up). Clearing the hop
+                * before overwriting it fixes the problem.
+                *
+                * Should be removed once we discover and tear down firmeware
+                * paths.
+                */
+               res = tb_port_write(path->hops[i].in_port, &hop, TB_CFG_HOPS,
+                                   2 * path->hops[i].in_hop_index, 2);
+               if (res) {
+                       __tb_path_deactivate_hops(path, i);
+                       __tb_path_deallocate_nfc(path, 0);
+                       goto err;
+               }
 
                /* dword 0 */
                hop.next_hop = path->hops[i].next_hop_index;
index 4db7987ec225f4d345efbb3249f0005897f95b2e..57d9df84ce5d7aca4fe25c557988742fbbb986bc 100644 (file)
@@ -540,6 +540,7 @@ static const struct acpi_device_id dw8250_acpi_match[] = {
        { "INT3434", 0 },
        { "INT3435", 0 },
        { "80860F0A", 0 },
+       { "8086228A", 0 },
        { },
 };
 MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
index 7b63677475c1f0cc57f9a5f947d74d66cf9aad81..d7d4584549a5d77e84b02f567085bcc77da5526a 100644 (file)
@@ -526,6 +526,45 @@ static void atmel_enable_ms(struct uart_port *port)
        UART_PUT_IER(port, ier);
 }
 
+/*
+ * Disable modem status interrupts
+ */
+static void atmel_disable_ms(struct uart_port *port)
+{
+       struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+       uint32_t idr = 0;
+
+       /*
+        * Interrupt should not be disabled twice
+        */
+       if (!atmel_port->ms_irq_enabled)
+               return;
+
+       atmel_port->ms_irq_enabled = false;
+
+       if (atmel_port->gpio_irq[UART_GPIO_CTS] >= 0)
+               disable_irq(atmel_port->gpio_irq[UART_GPIO_CTS]);
+       else
+               idr |= ATMEL_US_CTSIC;
+
+       if (atmel_port->gpio_irq[UART_GPIO_DSR] >= 0)
+               disable_irq(atmel_port->gpio_irq[UART_GPIO_DSR]);
+       else
+               idr |= ATMEL_US_DSRIC;
+
+       if (atmel_port->gpio_irq[UART_GPIO_RI] >= 0)
+               disable_irq(atmel_port->gpio_irq[UART_GPIO_RI]);
+       else
+               idr |= ATMEL_US_RIIC;
+
+       if (atmel_port->gpio_irq[UART_GPIO_DCD] >= 0)
+               disable_irq(atmel_port->gpio_irq[UART_GPIO_DCD]);
+       else
+               idr |= ATMEL_US_DCDIC;
+
+       UART_PUT_IDR(port, idr);
+}
+
 /*
  * Control the transmission of a break signal
  */
@@ -1993,7 +2032,9 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 
        /* CTS flow-control and modem-status interrupts */
        if (UART_ENABLE_MS(port, termios->c_cflag))
-               port->ops->enable_ms(port);
+               atmel_enable_ms(port);
+       else
+               atmel_disable_ms(port);
 
        spin_unlock_irqrestore(&port->lock, flags);
 }
index 01951d27cc03c8a4801dd66083c9a90c079b0332..806e4bcadbd7ee6d2d7e543798fb8a621b4e21cb 100644 (file)
@@ -581,7 +581,7 @@ static unsigned int cdns_uart_tx_empty(struct uart_port *port)
 {
        unsigned int status;
 
-       status = cdns_uart_readl(CDNS_UART_ISR_OFFSET) & CDNS_UART_IXR_TXEMPTY;
+       status = cdns_uart_readl(CDNS_UART_SR_OFFSET) & CDNS_UART_SR_TXEMPTY;
        return status ? TIOCSER_TEMT : 0;
 }
 
index e0cad4418085c5c136c1e8db3852803d74d3b822..cf1b19bca3064621a8d772b76a37f504346bb848 100644 (file)
@@ -92,6 +92,8 @@ source "drivers/usb/storage/Kconfig"
 
 source "drivers/usb/image/Kconfig"
 
+source "drivers/usb/usbip/Kconfig"
+
 endif
 
 source "drivers/usb/musb/Kconfig"
index 3cba892b83a2f5b29ec0e03e69a5393a2bb3e875..d7be717780598ec5668506a5c0e2e33a224b0ce3 100644 (file)
@@ -60,3 +60,5 @@ obj-$(CONFIG_USB_RENESAS_USBHS)       += renesas_usbhs/
 obj-$(CONFIG_USB_GADGET)       += gadget/
 
 obj-$(CONFIG_USB_COMMON)       += common/
+
+obj-$(CONFIG_USBIP_CORE)       += usbip/
index d72b9d2de2c5f828be33ea965c6ad87617722859..4935ac38fd008d17a51ed866e9fc002cddf021f5 100644 (file)
 static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
 {
        struct device *dev = ci->gadget.dev.parent;
-       int val;
 
        switch (event) {
        case CI_HDRC_CONTROLLER_RESET_EVENT:
                dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
                writel(0, USB_AHBBURST);
                writel(0, USB_AHBMODE);
+               usb_phy_init(ci->transceiver);
                break;
        case CI_HDRC_CONTROLLER_STOPPED_EVENT:
                dev_dbg(dev, "CI_HDRC_CONTROLLER_STOPPED_EVENT received\n");
@@ -34,10 +34,7 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
                 * Put the transceiver in non-driving mode. Otherwise host
                 * may not detect soft-disconnection.
                 */
-               val = usb_phy_io_read(ci->transceiver, ULPI_FUNC_CTRL);
-               val &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
-               val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
-               usb_phy_io_write(ci->transceiver, val, ULPI_FUNC_CTRL);
+               usb_phy_notify_disconnect(ci->transceiver, USB_SPEED_UNKNOWN);
                break;
        default:
                dev_dbg(dev, "unknown ci_hdrc event\n");
index 8a4dcbc7a75fb7f1f6a780af6fa65698af952bf2..d481c99a20d7b13adc9b9ec5c00565fd7d0ecc60 100644 (file)
@@ -1728,8 +1728,14 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
         * - Change autosuspend delay of hub can avoid unnecessary auto
         *   suspend timer for hub, also may decrease power consumption
         *   of USB bus.
+        *
+        * - If user has indicated to prevent autosuspend by passing
+        *   usbcore.autosuspend = -1 then keep autosuspend disabled.
         */
-       pm_runtime_set_autosuspend_delay(&hdev->dev, 0);
+#ifdef CONFIG_PM_RUNTIME
+       if (hdev->dev.power.autosuspend_delay >= 0)
+               pm_runtime_set_autosuspend_delay(&hdev->dev, 0);
+#endif
 
        /*
         * Hubs have proper suspend/resume support, except for root hubs
@@ -2107,8 +2113,8 @@ void usb_disconnect(struct usb_device **pdev)
 {
        struct usb_port *port_dev = NULL;
        struct usb_device *udev = *pdev;
-       struct usb_hub *hub;
-       int port1;
+       struct usb_hub *hub = NULL;
+       int port1 = 1;
 
        /* mark the device as inactive, so any further urb submissions for
         * this device (and any of its children) will fail immediately.
@@ -4631,9 +4637,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
                        if (status != -ENODEV &&
                                port1 != unreliable_port &&
                                printk_ratelimit())
-                               dev_err(&udev->dev, "connect-debounce failed, port %d disabled\n",
-                                       port1);
-
+                               dev_err(&port_dev->dev, "connect-debounce failed\n");
                        portstatus &= ~USB_PORT_STAT_CONNECTION;
                        unreliable_port = port1;
                } else {
@@ -5020,9 +5024,10 @@ static void hub_events(void)
 
                hub = list_entry(tmp, struct usb_hub, event_list);
                kref_get(&hub->kref);
+               hdev = hub->hdev;
+               usb_get_dev(hdev);
                spin_unlock_irq(&hub_event_lock);
 
-               hdev = hub->hdev;
                hub_dev = hub->intfdev;
                intf = to_usb_interface(hub_dev);
                dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
@@ -5135,6 +5140,7 @@ static void hub_events(void)
                usb_autopm_put_interface(intf);
  loop_disconnected:
                usb_unlock_device(hdev);
+               usb_put_dev(hdev);
                kref_put(&hub->kref, hub_release);
 
        } /* end while (1) */
index 0ba9c335b5849d4960fe4deced4a21b20076fdc0..ce6071d65d510696ebb4d428cd7240dd51a95b3e 100644 (file)
@@ -1649,6 +1649,7 @@ static void s3c_hsotg_txfifo_flush(struct s3c_hsotg *hsotg, unsigned int idx)
                        dev_err(hsotg->dev,
                                "%s: timeout flushing fifo (GRSTCTL=%08x)\n",
                                __func__, val);
+                       break;
                }
 
                udelay(1);
@@ -1901,7 +1902,7 @@ static void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx,
 static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg)
 {
        u32 dsts = readl(hsotg->regs + DSTS);
-       int ep0_mps = 0, ep_mps;
+       int ep0_mps = 0, ep_mps = 8;
 
        /*
         * This should signal the finish of the enumeration phase
@@ -2747,13 +2748,14 @@ static void s3c_hsotg_phy_enable(struct s3c_hsotg *hsotg)
 
        dev_dbg(hsotg->dev, "pdev 0x%p\n", pdev);
 
-       if (hsotg->phy) {
-               phy_init(hsotg->phy);
-               phy_power_on(hsotg->phy);
-       } else if (hsotg->uphy)
+       if (hsotg->uphy)
                usb_phy_init(hsotg->uphy);
-       else if (hsotg->plat->phy_init)
+       else if (hsotg->plat && hsotg->plat->phy_init)
                hsotg->plat->phy_init(pdev, hsotg->plat->phy_type);
+       else {
+               phy_init(hsotg->phy);
+               phy_power_on(hsotg->phy);
+       }
 }
 
 /**
@@ -2767,13 +2769,14 @@ static void s3c_hsotg_phy_disable(struct s3c_hsotg *hsotg)
 {
        struct platform_device *pdev = to_platform_device(hsotg->dev);
 
-       if (hsotg->phy) {
-               phy_power_off(hsotg->phy);
-               phy_exit(hsotg->phy);
-       } else if (hsotg->uphy)
+       if (hsotg->uphy)
                usb_phy_shutdown(hsotg->uphy);
-       else if (hsotg->plat->phy_exit)
+       else if (hsotg->plat && hsotg->plat->phy_exit)
                hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
+       else {
+               phy_power_off(hsotg->phy);
+               phy_exit(hsotg->phy);
+       }
 }
 
 /**
@@ -2892,13 +2895,11 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget,
                return -ENODEV;
 
        /* all endpoints should be shutdown */
-       for (ep = 0; ep < hsotg->num_of_eps; ep++)
+       for (ep = 1; ep < hsotg->num_of_eps; ep++)
                s3c_hsotg_ep_disable(&hsotg->eps[ep].ep);
 
        spin_lock_irqsave(&hsotg->lock, flags);
 
-       s3c_hsotg_phy_disable(hsotg);
-
        if (!driver)
                hsotg->driver = NULL;
 
@@ -2941,7 +2942,6 @@ static int s3c_hsotg_pullup(struct usb_gadget *gadget, int is_on)
                s3c_hsotg_phy_enable(hsotg);
                s3c_hsotg_core_init(hsotg);
        } else {
-               s3c_hsotg_disconnect(hsotg);
                s3c_hsotg_phy_disable(hsotg);
        }
 
@@ -3441,13 +3441,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
 
        hsotg->irq = ret;
 
-       ret = devm_request_irq(&pdev->dev, hsotg->irq, s3c_hsotg_irq, 0,
-                               dev_name(dev), hsotg);
-       if (ret < 0) {
-               dev_err(dev, "cannot claim IRQ\n");
-               goto err_clk;
-       }
-
        dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq);
 
        hsotg->gadget.max_speed = USB_SPEED_HIGH;
@@ -3488,9 +3481,6 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
        if (hsotg->phy && (phy_get_bus_width(phy) == 8))
                hsotg->phyif = GUSBCFG_PHYIF8;
 
-       if (hsotg->phy)
-               phy_init(hsotg->phy);
-
        /* usb phy enable */
        s3c_hsotg_phy_enable(hsotg);
 
@@ -3498,6 +3488,17 @@ static int s3c_hsotg_probe(struct platform_device *pdev)
        s3c_hsotg_init(hsotg);
        s3c_hsotg_hw_cfg(hsotg);
 
+       ret = devm_request_irq(&pdev->dev, hsotg->irq, s3c_hsotg_irq, 0,
+                               dev_name(dev), hsotg);
+       if (ret < 0) {
+               s3c_hsotg_phy_disable(hsotg);
+               clk_disable_unprepare(hsotg->clk);
+               regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
+                                      hsotg->supplies);
+               dev_err(dev, "cannot claim IRQ\n");
+               goto err_clk;
+       }
+
        /* hsotg->num_of_eps holds number of EPs other than ep0 */
 
        if (hsotg->num_of_eps == 0) {
@@ -3582,9 +3583,6 @@ static int s3c_hsotg_remove(struct platform_device *pdev)
                usb_gadget_unregister_driver(hsotg->driver);
        }
 
-       s3c_hsotg_phy_disable(hsotg);
-       if (hsotg->phy)
-               phy_exit(hsotg->phy);
        clk_disable_unprepare(hsotg->clk);
 
        return 0;
index b769c1faaf0385dff2543592e2fe68745d1fc7c5..9069984fe5cf0eae313a0dfb5faa2fe06ba9766c 100644 (file)
@@ -799,20 +799,21 @@ static int dwc3_remove(struct platform_device *pdev)
 {
        struct dwc3     *dwc = platform_get_drvdata(pdev);
 
+       dwc3_debugfs_exit(dwc);
+       dwc3_core_exit_mode(dwc);
+       dwc3_event_buffers_cleanup(dwc);
+       dwc3_free_event_buffers(dwc);
+
        usb_phy_set_suspend(dwc->usb2_phy, 1);
        usb_phy_set_suspend(dwc->usb3_phy, 1);
        phy_power_off(dwc->usb2_generic_phy);
        phy_power_off(dwc->usb3_generic_phy);
 
+       dwc3_core_exit(dwc);
+
        pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
 
-       dwc3_debugfs_exit(dwc);
-       dwc3_core_exit_mode(dwc);
-       dwc3_event_buffers_cleanup(dwc);
-       dwc3_free_event_buffers(dwc);
-       dwc3_core_exit(dwc);
-
        return 0;
 }
 
index ef4936ff626c3cdea2bd0bc6e0a7e7328481a3a7..fc0de3753648187ab9f1fd68ac121a83cd808e91 100644 (file)
@@ -425,7 +425,7 @@ static void dwc3_omap_set_utmi_mode(struct dwc3_omap *omap)
 
 static int dwc3_omap_extcon_register(struct dwc3_omap *omap)
 {
-       u32                     ret;
+       int                     ret;
        struct device_node      *node = omap->dev->of_node;
        struct extcon_dev       *edev;
 
@@ -576,9 +576,9 @@ static int dwc3_omap_remove(struct platform_device *pdev)
        if (omap->extcon_id_dev.edev)
                extcon_unregister_interest(&omap->extcon_id_dev);
        dwc3_omap_disable_irqs(omap);
+       device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
        pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
-       device_for_each_child(&pdev->dev, NULL, dwc3_omap_remove_core);
 
        return 0;
 }
index 349cacc577d81a679cacd4494bb7ead82f11cfa4..490a6ca0073369844b40eff51f88b2cbfd353bce 100644 (file)
@@ -527,7 +527,7 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep,
                dep->stream_capable = true;
        }
 
-       if (usb_endpoint_xfer_isoc(desc))
+       if (!usb_endpoint_xfer_control(desc))
                params.param1 |= DWC3_DEPCFG_XFER_IN_PROGRESS_EN;
 
        /*
@@ -1225,16 +1225,17 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, struct usb_request *request,
 
        int                             ret;
 
+       spin_lock_irqsave(&dwc->lock, flags);
        if (!dep->endpoint.desc) {
                dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n",
                                request, ep->name);
+               spin_unlock_irqrestore(&dwc->lock, flags);
                return -ESHUTDOWN;
        }
 
        dev_vdbg(dwc->dev, "queing request %p to %s length %d\n",
                        request, ep->name, request->length);
 
-       spin_lock_irqsave(&dwc->lock, flags);
        ret = __dwc3_gadget_ep_queue(dep, req);
        spin_unlock_irqrestore(&dwc->lock, flags);
 
@@ -2041,12 +2042,6 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
                dwc3_endpoint_transfer_complete(dwc, dep, event);
                break;
        case DWC3_DEPEVT_XFERINPROGRESS:
-               if (!usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
-                       dev_dbg(dwc->dev, "%s is not an Isochronous endpoint\n",
-                                       dep->name);
-                       return;
-               }
-
                dwc3_endpoint_transfer_complete(dwc, dep, event);
                break;
        case DWC3_DEPEVT_XFERNOTREADY:
index a186afeaa7001f3f81abb4f95d9edd3099477867..9add915d41f73521d369279bdbcd443d9d552fa2 100644 (file)
@@ -3,7 +3,7 @@
 #
 subdir-ccflags-$(CONFIG_USB_GADGET_DEBUG)      := -DDEBUG
 subdir-ccflags-$(CONFIG_USB_GADGET_VERBOSE)    += -DVERBOSE_DEBUG
-ccflags-y                              += -I$(PWD)/drivers/usb/gadget/udc
+ccflags-y                              += -Idrivers/usb/gadget/udc
 
 obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o
 libcomposite-y                 := usbstring.o config.o epautoconf.o
index 6d91f21b52a6301c303aac0a4f62e572d83c02aa..83ae1065149d3dd21f91bef6902168b9908f73ff 100644 (file)
@@ -2,8 +2,8 @@
 # USB peripheral controller drivers
 #
 
-ccflags-y                      := -I$(PWD)/drivers/usb/gadget/
-ccflags-y                      += -I$(PWD)/drivers/usb/gadget/udc/
+ccflags-y                      := -Idrivers/usb/gadget/
+ccflags-y                      += -Idrivers/usb/gadget/udc/
 
 # USB Functions
 usb_f_acm-y                    := f_acm.o
index dc30adf15a01d22cbde3c3a195a146373e302ef0..0dc3552d13603282d3d631aa1a7d06078bec0c3b 100644 (file)
@@ -155,6 +155,12 @@ struct ffs_io_data {
        struct usb_request *req;
 };
 
+struct ffs_desc_helper {
+       struct ffs_data *ffs;
+       unsigned interfaces_count;
+       unsigned eps_count;
+};
+
 static int  __must_check ffs_epfiles_create(struct ffs_data *ffs);
 static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count);
 
@@ -1830,7 +1836,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
                                u8 *valuep, struct usb_descriptor_header *desc,
                                void *priv)
 {
-       struct ffs_data *ffs = priv;
+       struct ffs_desc_helper *helper = priv;
+       struct usb_endpoint_descriptor *d;
 
        ENTER();
 
@@ -1844,8 +1851,8 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
                 * encountered interface "n" then there are at least
                 * "n+1" interfaces.
                 */
-               if (*valuep >= ffs->interfaces_count)
-                       ffs->interfaces_count = *valuep + 1;
+               if (*valuep >= helper->interfaces_count)
+                       helper->interfaces_count = *valuep + 1;
                break;
 
        case FFS_STRING:
@@ -1853,14 +1860,22 @@ static int __ffs_data_do_entity(enum ffs_entity_type type,
                 * Strings are indexed from 1 (0 is magic ;) reserved
                 * for languages list or some such)
                 */
-               if (*valuep > ffs->strings_count)
-                       ffs->strings_count = *valuep;
+               if (*valuep > helper->ffs->strings_count)
+                       helper->ffs->strings_count = *valuep;
                break;
 
        case FFS_ENDPOINT:
-               /* Endpoints are indexed from 1 as well. */
-               if ((*valuep & USB_ENDPOINT_NUMBER_MASK) > ffs->eps_count)
-                       ffs->eps_count = (*valuep & USB_ENDPOINT_NUMBER_MASK);
+               d = (void *)desc;
+               helper->eps_count++;
+               if (helper->eps_count >= 15)
+                       return -EINVAL;
+               /* Check if descriptors for any speed were already parsed */
+               if (!helper->ffs->eps_count && !helper->ffs->interfaces_count)
+                       helper->ffs->eps_addrmap[helper->eps_count] =
+                               d->bEndpointAddress;
+               else if (helper->ffs->eps_addrmap[helper->eps_count] !=
+                               d->bEndpointAddress)
+                       return -EINVAL;
                break;
        }
 
@@ -2053,6 +2068,7 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
        char *data = _data, *raw_descs;
        unsigned os_descs_count = 0, counts[3], flags;
        int ret = -EINVAL, i;
+       struct ffs_desc_helper helper;
 
        ENTER();
 
@@ -2101,13 +2117,29 @@ static int __ffs_data_got_descs(struct ffs_data *ffs,
 
        /* Read descriptors */
        raw_descs = data;
+       helper.ffs = ffs;
        for (i = 0; i < 3; ++i) {
                if (!counts[i])
                        continue;
+               helper.interfaces_count = 0;
+               helper.eps_count = 0;
                ret = ffs_do_descs(counts[i], data, len,
-                                  __ffs_data_do_entity, ffs);
+                                  __ffs_data_do_entity, &helper);
                if (ret < 0)
                        goto error;
+               if (!ffs->eps_count && !ffs->interfaces_count) {
+                       ffs->eps_count = helper.eps_count;
+                       ffs->interfaces_count = helper.interfaces_count;
+               } else {
+                       if (ffs->eps_count != helper.eps_count) {
+                               ret = -EINVAL;
+                               goto error;
+                       }
+                       if (ffs->interfaces_count != helper.interfaces_count) {
+                               ret = -EINVAL;
+                               goto error;
+                       }
+               }
                data += ret;
                len  -= ret;
        }
@@ -2342,9 +2374,18 @@ static void ffs_event_add(struct ffs_data *ffs,
        spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags);
 }
 
-
 /* Bind/unbind USB function hooks *******************************************/
 
+static int ffs_ep_addr2idx(struct ffs_data *ffs, u8 endpoint_address)
+{
+       int i;
+
+       for (i = 1; i < ARRAY_SIZE(ffs->eps_addrmap); ++i)
+               if (ffs->eps_addrmap[i] == endpoint_address)
+                       return i;
+       return -ENOENT;
+}
+
 static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
                                    struct usb_descriptor_header *desc,
                                    void *priv)
@@ -2378,7 +2419,10 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
        if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT)
                return 0;
 
-       idx = (ds->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) - 1;
+       idx = ffs_ep_addr2idx(func->ffs, ds->bEndpointAddress) - 1;
+       if (idx < 0)
+               return idx;
+
        ffs_ep = func->eps + idx;
 
        if (unlikely(ffs_ep->descs[ep_desc_id])) {
index d50adda913cfa6d57e1e6191ab5444d6981af47a..6e6f87656e7b0f5795caa17f387aa6cf89de2d41 100644 (file)
@@ -1127,10 +1127,7 @@ void gether_disconnect(struct gether *link)
 
        DBG(dev, "%s\n", __func__);
 
-       netif_tx_lock(dev->net);
        netif_stop_queue(dev->net);
-       netif_tx_unlock(dev->net);
-
        netif_carrier_off(dev->net);
 
        /* disable endpoints, forcing (synchronous) completion
index 63d6e71569c18d7ddcf26e92586798d30a97cbd2..d48897e8ffebf03db2f39ec77ba695364b4174a2 100644 (file)
@@ -224,6 +224,8 @@ struct ffs_data {
        void                            *ms_os_descs_ext_prop_name_avail;
        void                            *ms_os_descs_ext_prop_data_avail;
 
+       u8                              eps_addrmap[15];
+
        unsigned short                  strings_count;
        unsigned short                  interfaces_count;
        unsigned short                  eps_count;
index 71e896d4c5ae481d189e582609d8cb456a8187c3..a5eb9a3fbb7a3c7c40306e516abfd5244986f436 100644 (file)
@@ -195,6 +195,7 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
                printk(KERN_INFO "Failed to queue request (%d).\n", ret);
                usb_ep_set_halt(ep);
                spin_unlock_irqrestore(&video->queue.irqlock, flags);
+               uvc_queue_cancel(queue, 0);
                goto requeue;
        }
        spin_unlock_irqrestore(&video->queue.irqlock, flags);
@@ -281,6 +282,7 @@ error:
 static int
 uvc_video_pump(struct uvc_video *video)
 {
+       struct uvc_video_queue *queue = &video->queue;
        struct usb_request *req;
        struct uvc_buffer *buf;
        unsigned long flags;
@@ -322,6 +324,7 @@ uvc_video_pump(struct uvc_video *video)
                        printk(KERN_INFO "Failed to queue request (%d)\n", ret);
                        usb_ep_set_halt(video->ep);
                        spin_unlock_irqrestore(&video->queue.irqlock, flags);
+                       uvc_queue_cancel(queue, 0);
                        break;
                }
                spin_unlock_irqrestore(&video->queue.irqlock, flags);
index a11aad5635df415422feb5f0a32d8d269cc14b6d..edba2d1ee0f3fc65e2af5366b503245857080bf8 100644 (file)
@@ -2,9 +2,9 @@
 # USB gadget drivers
 #
 
-ccflags-y                      := -I$(PWD)/drivers/usb/gadget/
-ccflags-y                      += -I$(PWD)/drivers/usb/gadget/udc/
-ccflags-y                      += -I$(PWD)/drivers/usb/gadget/function/
+ccflags-y                      := -Idrivers/usb/gadget/
+ccflags-y                      += -Idrivers/usb/gadget/udc/
+ccflags-y                      += -Idrivers/usb/gadget/function/
 
 g_zero-y                       := zero.o
 g_audio-y                      := audio.o
index 986fc511a2edcdab4afc6a09780d2b1632159f75..225e385a616009747a42b5117769e316c7638fc6 100644 (file)
@@ -222,10 +222,12 @@ static void dbgp_unbind(struct usb_gadget *gadget)
 {
 #ifdef CONFIG_USB_G_DBGP_SERIAL
        kfree(dbgp.serial);
+       dbgp.serial = NULL;
 #endif
        if (dbgp.req) {
                kfree(dbgp.req->buf);
                usb_ep_free_request(gadget->ep0, dbgp.req);
+               dbgp.req = NULL;
        }
 
        gadget->ep0->driver_data = NULL;
index 2e4ce7704908bc78e4ed2385842a1e6dbec1d59c..e96077b8bf7922b89b5feda9a9c34b3de843ab55 100644 (file)
@@ -440,7 +440,7 @@ ep_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
 
        value = -ENOMEM;
        kbuf = memdup_user(buf, len);
-       if (!kbuf) {
+       if (IS_ERR(kbuf)) {
                value = PTR_ERR(kbuf);
                goto free1;
        }
index 5151f947a4f56119e56c9e6d445df29b4f1a6314..34ebaa68504c1b68c5e697ccfe0ed74524f1a4fc 100644 (file)
@@ -332,7 +332,7 @@ config USB_GOKU
           gadget drivers to also be dynamically linked.
 
 config USB_EG20T
-       tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
+       tristate "Intel QUARK X1000/EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
        depends on PCI
        help
          This is a USB device driver for EG20T PCH.
@@ -353,6 +353,7 @@ config USB_EG20T
          ML7213/ML7831 is companion chip for Intel Atom E6xx series.
          ML7213/ML7831 is completely compatible for Intel EG20T PCH.
 
+         This driver can be used with Intel's Quark X1000 SOC platform
 #
 # LAST -- dummy/emulated controller
 #
index 906e65f0e4fa7b8c225e4c75ad80666b6dd78085..c9fe67e29d35fcbe420b04a79f6797d531b852e9 100644 (file)
@@ -1661,7 +1661,7 @@ static irqreturn_t usba_udc_irq(int irq, void *devid)
        if (dma_status) {
                int i;
 
-               for (i = 1; i < USBA_NR_DMAS; i++)
+               for (i = 1; i <= USBA_NR_DMAS; i++)
                        if (dma_status & (1 << i))
                                usba_dma_irq(udc, &udc->usba_ep[i]);
        }
index d40255f784df6824d4d3a6d00ca58bf15f319292..5c5d1adda7eb23c1a57e4ee8ea5d8696c361ebbb 100644 (file)
@@ -1398,13 +1398,17 @@ static int fusb300_probe(struct platform_device *pdev)
 
        /* initialize udc */
        fusb300 = kzalloc(sizeof(struct fusb300), GFP_KERNEL);
-       if (fusb300 == NULL)
+       if (fusb300 == NULL) {
+               ret = -ENOMEM;
                goto clean_up;
+       }
 
        for (i = 0; i < FUSB300_MAX_NUM_EP; i++) {
                _ep[i] = kzalloc(sizeof(struct fusb300_ep), GFP_KERNEL);
-               if (_ep[i] == NULL)
+               if (_ep[i] == NULL) {
+                       ret = -ENOMEM;
                        goto clean_up;
+               }
                fusb300->ep[i] = _ep[i];
        }
 
index ae811d8d38b435d9cd198369b399b1cf58bda63c..ad39f892d20099a5047fc5a815fd9d33a03b1e65 100644 (file)
@@ -12,7 +12,7 @@
 
 
 #ifndef __FUSB300_UDC_H__
-#define __FUSB300_UDC_H_
+#define __FUSB300_UDC_H__
 
 #include <linux/kernel.h>
 
index f4eac113690ebd2e164e4768113aec6319b68290..2e95715b50c0967f02550dbe11e88c159dbd5b5c 100644 (file)
@@ -3320,7 +3320,7 @@ static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
        if (stat & tmp) {
                writel(tmp, &dev->regs->irqstat1);
                if ((((stat & BIT(ROOT_PORT_RESET_INTERRUPT)) &&
-                               (readl(&dev->usb->usbstat) & mask)) ||
+                               ((readl(&dev->usb->usbstat) & mask) == 0)) ||
                                ((readl(&dev->usb->usbctl) &
                                        BIT(VBUS_PIN)) == 0)) &&
                                (dev->gadget.speed != USB_SPEED_UNKNOWN)) {
index eb8c3bedb57abc20e7a9ccd4913700406b1958d5..460d953c91b6c9b540d2af185b3f2664ea39613b 100644 (file)
@@ -343,6 +343,7 @@ struct pch_vbus_gpio_data {
  * @setup_data:                Received setup data
  * @phys_addr:         of device memory
  * @base_addr:         for mapped device memory
+ * @bar:               Indicates which PCI BAR for USB regs
  * @irq:               IRQ line for the device
  * @cfg_data:          current cfg, intf, and alt in use
  * @vbus_gpio:         GPIO informaton for detecting VBUS
@@ -370,14 +371,17 @@ struct pch_udc_dev {
        struct usb_ctrlrequest          setup_data;
        unsigned long                   phys_addr;
        void __iomem                    *base_addr;
+       unsigned                        bar;
        unsigned                        irq;
        struct pch_udc_cfg_data         cfg_data;
        struct pch_vbus_gpio_data       vbus_gpio;
 };
 #define to_pch_udc(g)  (container_of((g), struct pch_udc_dev, gadget))
 
+#define PCH_UDC_PCI_BAR_QUARK_X1000    0
 #define PCH_UDC_PCI_BAR                        1
 #define PCI_DEVICE_ID_INTEL_EG20T_UDC  0x8808
+#define PCI_DEVICE_ID_INTEL_QUARK_X1000_UDC    0x0939
 #define PCI_VENDOR_ID_ROHM             0x10DB
 #define PCI_DEVICE_ID_ML7213_IOH_UDC   0x801D
 #define PCI_DEVICE_ID_ML7831_IOH_UDC   0x8808
@@ -3076,7 +3080,7 @@ static void pch_udc_remove(struct pci_dev *pdev)
                iounmap(dev->base_addr);
        if (dev->mem_region)
                release_mem_region(dev->phys_addr,
-                                  pci_resource_len(pdev, PCH_UDC_PCI_BAR));
+                                  pci_resource_len(pdev, dev->bar));
        if (dev->active)
                pci_disable_device(pdev);
        kfree(dev);
@@ -3144,9 +3148,15 @@ static int pch_udc_probe(struct pci_dev *pdev,
        dev->active = 1;
        pci_set_drvdata(pdev, dev);
 
+       /* Determine BAR based on PCI ID */
+       if (id->device == PCI_DEVICE_ID_INTEL_QUARK_X1000_UDC)
+               dev->bar = PCH_UDC_PCI_BAR_QUARK_X1000;
+       else
+               dev->bar = PCH_UDC_PCI_BAR;
+
        /* PCI resource allocation */
-       resource = pci_resource_start(pdev, 1);
-       len = pci_resource_len(pdev, 1);
+       resource = pci_resource_start(pdev, dev->bar);
+       len = pci_resource_len(pdev, dev->bar);
 
        if (!request_mem_region(resource, len, KBUILD_MODNAME)) {
                dev_err(&pdev->dev, "%s: pci device used already\n", __func__);
@@ -3211,6 +3221,12 @@ finished:
 }
 
 static const struct pci_device_id pch_udc_pcidev_id[] = {
+       {
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL,
+                          PCI_DEVICE_ID_INTEL_QUARK_X1000_UDC),
+               .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+               .class_mask = 0xffffffff,
+       },
        {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EG20T_UDC),
                .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
index 46008421c1ec8fad66dca295174460255150e51b..de2a8713b42884994cafda67990e06a2e93fcb23 100644 (file)
@@ -1868,8 +1868,8 @@ static int r8a66597_probe(struct platform_device *pdev)
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        reg = devm_ioremap_resource(&pdev->dev, res);
-       if (!reg)
-               return -ENODEV;
+       if (IS_ERR(reg))
+               return PTR_ERR(reg);
 
        ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        irq = ires->start;
index cc305c71ac3d489d469ec4ca34a03c7861bf122f..6130b757490893a471dd3cbfa33026e8b8738071 100644 (file)
@@ -1230,7 +1230,7 @@ int ehci_hub_control(
                        if (selector == EHSET_TEST_SINGLE_STEP_SET_FEATURE) {
                                spin_unlock_irqrestore(&ehci->lock, flags);
                                retval = ehset_single_step_set_feature(hcd,
-                                                                       wIndex);
+                                                               wIndex + 1);
                                spin_lock_irqsave(&ehci->lock, flags);
                                break;
                        }
index aa79e8749040b783281ec6f968620fc41ad41876..69aece31143a12d965af1014b0c133f773ffafcf 100644 (file)
@@ -468,7 +468,8 @@ static void xhci_hub_report_usb2_link_state(u32 *status, u32 status_reg)
 }
 
 /* Updates Link Status for super Speed port */
-static void xhci_hub_report_usb3_link_state(u32 *status, u32 status_reg)
+static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci,
+               u32 *status, u32 status_reg)
 {
        u32 pls = status_reg & PORT_PLS_MASK;
 
@@ -507,7 +508,8 @@ static void xhci_hub_report_usb3_link_state(u32 *status, u32 status_reg)
                 * in which sometimes the port enters compliance mode
                 * caused by a delay on the host-device negotiation.
                 */
-               if (pls == USB_SS_PORT_LS_COMP_MOD)
+               if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
+                               (pls == USB_SS_PORT_LS_COMP_MOD))
                        pls |= USB_PORT_STAT_CONNECTION;
        }
 
@@ -666,7 +668,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
        }
        /* Update Port Link State */
        if (hcd->speed == HCD_USB3) {
-               xhci_hub_report_usb3_link_state(&status, raw_port_status);
+               xhci_hub_report_usb3_link_state(xhci, &status, raw_port_status);
                /*
                 * Verify if all USB3 Ports Have entered U0 already.
                 * Delete Compliance Mode Timer if so.
index 8056d90690ee1bff397b0fa689f3ab9175622a6b..8936211b161d3ed6b0a2989359707287f2721b21 100644 (file)
@@ -1812,6 +1812,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
 
        if (xhci->lpm_command)
                xhci_free_command(xhci, xhci->lpm_command);
+       xhci->lpm_command = NULL;
        if (xhci->cmd_ring)
                xhci_ring_free(xhci, xhci->cmd_ring);
        xhci->cmd_ring = NULL;
@@ -1819,7 +1820,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
        xhci_cleanup_command_queue(xhci);
 
        num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
-       for (i = 0; i < num_ports; i++) {
+       for (i = 0; i < num_ports && xhci->rh_bw; i++) {
                struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table;
                for (j = 0; j < XHCI_MAX_INTERVAL; j++) {
                        struct list_head *ep = &bwt->interval_bw[j].endpoints;
index 687d366081557589ad2fa9e33b1a51a0c4499c3e..c22a3e15a16e77b3543921ab8bb4ba2a84268f80 100644 (file)
@@ -101,6 +101,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
        /* AMD PLL quirk */
        if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_find_chipset_info())
                xhci->quirks |= XHCI_AMD_PLL_FIX;
+
+       if (pdev->vendor == PCI_VENDOR_ID_AMD)
+               xhci->quirks |= XHCI_TRUST_TX_LENGTH;
+
        if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
                xhci->quirks |= XHCI_LPM_SUPPORT;
                xhci->quirks |= XHCI_INTEL_HOST;
@@ -151,6 +155,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
        if (pdev->vendor == PCI_VENDOR_ID_VIA)
                xhci->quirks |= XHCI_RESET_ON_RESUME;
 
+       /* See https://bugzilla.kernel.org/show_bug.cgi?id=79511 */
+       if (pdev->vendor == PCI_VENDOR_ID_VIA &&
+                       pdev->device == 0x3432)
+               xhci->quirks |= XHCI_BROKEN_STREAMS;
+
        if (xhci->quirks & XHCI_RESET_ON_RESUME)
                xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
                                "QUIRK: Resetting on resume");
index 60fb52ae864b0ed15066d6073647224df7fd32ec..abed30b82905737e5565515ca9c7fe8b5e508303 100644 (file)
@@ -364,32 +364,6 @@ static void ring_doorbell_for_active_rings(struct xhci_hcd *xhci,
        }
 }
 
-/*
- * Find the segment that trb is in.  Start searching in start_seg.
- * If we must move past a segment that has a link TRB with a toggle cycle state
- * bit set, then we will toggle the value pointed at by cycle_state.
- */
-static struct xhci_segment *find_trb_seg(
-               struct xhci_segment *start_seg,
-               union xhci_trb  *trb, int *cycle_state)
-{
-       struct xhci_segment *cur_seg = start_seg;
-       struct xhci_generic_trb *generic_trb;
-
-       while (cur_seg->trbs > trb ||
-                       &cur_seg->trbs[TRBS_PER_SEGMENT - 1] < trb) {
-               generic_trb = &cur_seg->trbs[TRBS_PER_SEGMENT - 1].generic;
-               if (generic_trb->field[3] & cpu_to_le32(LINK_TOGGLE))
-                       *cycle_state ^= 0x1;
-               cur_seg = cur_seg->next;
-               if (cur_seg == start_seg)
-                       /* Looped over the entire list.  Oops! */
-                       return NULL;
-       }
-       return cur_seg;
-}
-
-
 static struct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci,
                unsigned int slot_id, unsigned int ep_index,
                unsigned int stream_id)
@@ -459,9 +433,12 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
        struct xhci_virt_device *dev = xhci->devs[slot_id];
        struct xhci_virt_ep *ep = &dev->eps[ep_index];
        struct xhci_ring *ep_ring;
-       struct xhci_generic_trb *trb;
+       struct xhci_segment *new_seg;
+       union xhci_trb *new_deq;
        dma_addr_t addr;
        u64 hw_dequeue;
+       bool cycle_found = false;
+       bool td_last_trb_found = false;
 
        ep_ring = xhci_triad_to_transfer_ring(xhci, slot_id,
                        ep_index, stream_id);
@@ -486,45 +463,45 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
                hw_dequeue = le64_to_cpu(ep_ctx->deq);
        }
 
-       /* Find virtual address and segment of hardware dequeue pointer */
-       state->new_deq_seg = ep_ring->deq_seg;
-       state->new_deq_ptr = ep_ring->dequeue;
-       while (xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr)
-                       != (dma_addr_t)(hw_dequeue & ~0xf)) {
-               next_trb(xhci, ep_ring, &state->new_deq_seg,
-                                       &state->new_deq_ptr);
-               if (state->new_deq_ptr == ep_ring->dequeue) {
-                       WARN_ON(1);
-                       return;
-               }
-       }
+       new_seg = ep_ring->deq_seg;
+       new_deq = ep_ring->dequeue;
+       state->new_cycle_state = hw_dequeue & 0x1;
+
        /*
-        * Find cycle state for last_trb, starting at old cycle state of
-        * hw_dequeue. If there is only one segment ring, find_trb_seg() will
-        * return immediately and cannot toggle the cycle state if this search
-        * wraps around, so add one more toggle manually in that case.
+        * We want to find the pointer, segment and cycle state of the new trb
+        * (the one after current TD's last_trb). We know the cycle state at
+        * hw_dequeue, so walk the ring until both hw_dequeue and last_trb are
+        * found.
         */
-       state->new_cycle_state = hw_dequeue & 0x1;
-       if (ep_ring->first_seg == ep_ring->first_seg->next &&
-                       cur_td->last_trb < state->new_deq_ptr)
-               state->new_cycle_state ^= 0x1;
+       do {
+               if (!cycle_found && xhci_trb_virt_to_dma(new_seg, new_deq)
+                   == (dma_addr_t)(hw_dequeue & ~0xf)) {
+                       cycle_found = true;
+                       if (td_last_trb_found)
+                               break;
+               }
+               if (new_deq == cur_td->last_trb)
+                       td_last_trb_found = true;
 
-       state->new_deq_ptr = cur_td->last_trb;
-       xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
-                       "Finding segment containing last TRB in TD.");
-       state->new_deq_seg = find_trb_seg(state->new_deq_seg,
-                       state->new_deq_ptr, &state->new_cycle_state);
-       if (!state->new_deq_seg) {
-               WARN_ON(1);
-               return;
-       }
+               if (cycle_found &&
+                   TRB_TYPE_LINK_LE32(new_deq->generic.field[3]) &&
+                   new_deq->generic.field[3] & cpu_to_le32(LINK_TOGGLE))
+                       state->new_cycle_state ^= 0x1;
+
+               next_trb(xhci, ep_ring, &new_seg, &new_deq);
+
+               /* Search wrapped around, bail out */
+               if (new_deq == ep->ring->dequeue) {
+                       xhci_err(xhci, "Error: Failed finding new dequeue state\n");
+                       state->new_deq_seg = NULL;
+                       state->new_deq_ptr = NULL;
+                       return;
+               }
+
+       } while (!cycle_found || !td_last_trb_found);
 
-       /* Increment to find next TRB after last_trb. Cycle if appropriate. */
-       trb = &state->new_deq_ptr->generic;
-       if (TRB_TYPE_LINK_LE32(trb->field[3]) &&
-           (trb->field[3] & cpu_to_le32(LINK_TOGGLE)))
-               state->new_cycle_state ^= 0x1;
-       next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr);
+       state->new_deq_seg = new_seg;
+       state->new_deq_ptr = new_deq;
 
        /* Don't update the ring cycle state for the producer (us). */
        xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
@@ -2487,7 +2464,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                 * last TRB of the previous TD. The command completion handle
                 * will take care the rest.
                 */
-               if (!event_seg && trb_comp_code == COMP_STOP_INVAL) {
+               if (!event_seg && (trb_comp_code == COMP_STOP ||
+                                  trb_comp_code == COMP_STOP_INVAL)) {
                        ret = 0;
                        goto cleanup;
                }
index b6f21175b872fd0d300968a55e2750e0fd9c69c5..c4a8fca8ae939f4fefeca3498bf967ce7aabcb9f 100644 (file)
@@ -2880,6 +2880,9 @@ void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci,
                        ep_index, ep->stopped_stream, ep->stopped_td,
                        &deq_state);
 
+       if (!deq_state.new_deq_ptr || !deq_state.new_deq_seg)
+               return;
+
        /* HW with the reset endpoint quirk will use the saved dequeue state to
         * issue a configure endpoint command later.
         */
@@ -3968,13 +3971,21 @@ static int __maybe_unused xhci_change_max_exit_latency(struct xhci_hcd *xhci,
        int ret;
 
        spin_lock_irqsave(&xhci->lock, flags);
-       if (max_exit_latency == xhci->devs[udev->slot_id]->current_mel) {
+
+       virt_dev = xhci->devs[udev->slot_id];
+
+       /*
+        * virt_dev might not exists yet if xHC resumed from hibernate (S4) and
+        * xHC was re-initialized. Exit latency will be set later after
+        * hub_port_finish_reset() is done and xhci->devs[] are re-allocated
+        */
+
+       if (!virt_dev || max_exit_latency == virt_dev->current_mel) {
                spin_unlock_irqrestore(&xhci->lock, flags);
                return 0;
        }
 
        /* Attempt to issue an Evaluate Context command to change the MEL. */
-       virt_dev = xhci->devs[udev->slot_id];
        command = xhci->lpm_command;
        ctrl_ctx = xhci_get_input_control_ctx(xhci, command->in_ctx);
        if (!ctrl_ctx) {
index 06b5d77cd9ade2aba61d5e79d308ae6afdc7e45b..633caf64312232bb7e73954357f1efb66313597a 100644 (file)
@@ -3250,6 +3250,7 @@ static const struct usb_device_id sisusb_table[] = {
        { USB_DEVICE(0x0711, 0x0918) },
        { USB_DEVICE(0x0711, 0x0920) },
        { USB_DEVICE(0x0711, 0x0950) },
+       { USB_DEVICE(0x0711, 0x5200) },
        { USB_DEVICE(0x182d, 0x021c) },
        { USB_DEVICE(0x182d, 0x0269) },
        { }
index 47ae6455d0733c2d3ef4093aa4408e98969b3644..3ee133f675abee3e9c6921c4fa034855f57efba8 100644 (file)
@@ -39,6 +39,7 @@ struct cppi41_dma_channel {
        u32 transferred;
        u32 packet_sz;
        struct list_head tx_check;
+       int tx_zlp;
 };
 
 #define MUSB_DMA_NUM_CHANNELS 15
@@ -122,6 +123,8 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
 {
        struct musb_hw_ep *hw_ep = cppi41_channel->hw_ep;
        struct musb *musb = hw_ep->musb;
+       void __iomem *epio = hw_ep->regs;
+       u16 csr;
 
        if (!cppi41_channel->prog_len ||
            (cppi41_channel->channel.status == MUSB_DMA_STATUS_FREE)) {
@@ -131,15 +134,24 @@ static void cppi41_trans_done(struct cppi41_dma_channel *cppi41_channel)
                        cppi41_channel->transferred;
                cppi41_channel->channel.status = MUSB_DMA_STATUS_FREE;
                cppi41_channel->channel.rx_packet_done = true;
+
+               /*
+                * transmit ZLP using PIO mode for transfers which size is
+                * multiple of EP packet size.
+                */
+               if (cppi41_channel->tx_zlp && (cppi41_channel->transferred %
+                                       cppi41_channel->packet_sz) == 0) {
+                       musb_ep_select(musb->mregs, hw_ep->epnum);
+                       csr = MUSB_TXCSR_MODE | MUSB_TXCSR_TXPKTRDY;
+                       musb_writew(epio, MUSB_TXCSR, csr);
+               }
                musb_dma_completion(musb, hw_ep->epnum, cppi41_channel->is_tx);
        } else {
                /* next iteration, reload */
                struct dma_chan *dc = cppi41_channel->dc;
                struct dma_async_tx_descriptor *dma_desc;
                enum dma_transfer_direction direction;
-               u16 csr;
                u32 remain_bytes;
-               void __iomem *epio = cppi41_channel->hw_ep->regs;
 
                cppi41_channel->buf_addr += cppi41_channel->packet_sz;
 
@@ -363,6 +375,7 @@ static bool cppi41_configure_channel(struct dma_channel *channel,
        cppi41_channel->total_len = len;
        cppi41_channel->transferred = 0;
        cppi41_channel->packet_sz = packet_sz;
+       cppi41_channel->tx_zlp = (cppi41_channel->is_tx && mode) ? 1 : 0;
 
        /*
         * Due to AM335x' Advisory 1.0.13 we are not allowed to transfer more
index 9aad00f11bd5e81fb16a4930c1ba9b0efe951acd..221faed9f07408d5881d1dd6c43270a1a5f1c240 100644 (file)
@@ -96,7 +96,7 @@ static bool ux500_configure_channel(struct dma_channel *channel,
        struct musb *musb = ux500_channel->controller->private_data;
 
        dev_dbg(musb->controller,
-               "packet_sz=%d, mode=%d, dma_addr=0x%llu, len=%d is_tx=%d\n",
+               "packet_sz=%d, mode=%d, dma_addr=0x%llx, len=%d is_tx=%d\n",
                packet_sz, mode, (unsigned long long) dma_addr,
                len, ux500_channel->is_tx);
 
index ea9e705555df67cb32cc9d67f89ef734872ac39d..f4b14bd97e1442a586371943d3bd39897e5b997f 100644 (file)
@@ -260,10 +260,8 @@ static int gpio_vbus_probe(struct platform_device *pdev)
 
        gpio_vbus->phy.otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg),
                                          GFP_KERNEL);
-       if (!gpio_vbus->phy.otg) {
-               kfree(gpio_vbus);
+       if (!gpio_vbus->phy.otg)
                return -ENOMEM;
-       }
 
        platform_set_drvdata(pdev, gpio_vbus);
        gpio_vbus->dev = &pdev->dev;
index e4108eec5ef4153c7370f405040618cd1df41114..afc09087ec3630217079dd074f6da406ab3eed68 100644 (file)
@@ -1601,8 +1601,8 @@ static int msm_otg_probe(struct platform_device *pdev)
         */
        if (motg->phy_number) {
                phy_select = devm_ioremap_nocache(&pdev->dev, USB2_PHY_SEL, 4);
-               if (IS_ERR(phy_select))
-                       return PTR_ERR(phy_select);
+               if (!phy_select)
+                       return -ENOMEM;
                /* Enable second PHY with the OTG port */
                writel(0x1, phy_select);
        }
index c42bdf0c4a1f7322eed6ba4f7ce6b058f7c16fd9..00972eca04e7f5d4965f32fd0944c453f5291f07 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2012-2013 Freescale Semiconductor, Inc.
+ * Copyright 2012-2014 Freescale Semiconductor, Inc.
  * Copyright (C) 2012 Marek Vasut <marex@denx.de>
  * on behalf of DENX Software Engineering GmbH
  *
@@ -125,7 +125,13 @@ static const struct mxs_phy_data imx6sl_phy_data = {
                MXS_PHY_NEED_IP_FIX,
 };
 
+static const struct mxs_phy_data imx6sx_phy_data = {
+       .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
+               MXS_PHY_NEED_IP_FIX,
+};
+
 static const struct of_device_id mxs_phy_dt_ids[] = {
+       { .compatible = "fsl,imx6sx-usbphy", .data = &imx6sx_phy_data, },
        { .compatible = "fsl,imx6sl-usbphy", .data = &imx6sl_phy_data, },
        { .compatible = "fsl,imx6q-usbphy", .data = &imx6q_phy_data, },
        { .compatible = "fsl,imx23-usbphy", .data = &imx23_phy_data, },
index 68771bfd18253df19dd2f999086611d0314d4b90..80eedd45a20aed05417066229040ccfaf4381b21 100644 (file)
 
 #define EXYNOS5_DRD_PHYPARAM1                  (0x20)
 
-#define PHYPARAM1_PCS_TXDEEMPH_MASK            (0x1f << 0)
+#define PHYPARAM1_PCS_TXDEEMPH_MASK            (0x3f << 0)
 #define PHYPARAM1_PCS_TXDEEMPH                 (0x1c)
 
 #define EXYNOS5_DRD_PHYTERM                    (0x24)
index 13b4fa287da8aff05739a657fb9c24b3f5541ea7..886f1807a67bbdcb8fe5e17e91b45e382507db14 100644 (file)
@@ -878,8 +878,8 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy,
                return -ENOMEM;
        }
 
-       tegra_phy->config = devm_kzalloc(&pdev->dev,
-               sizeof(*tegra_phy->config), GFP_KERNEL);
+       tegra_phy->config = devm_kzalloc(&pdev->dev, sizeof(*config),
+                                        GFP_KERNEL);
        if (!tegra_phy->config) {
                dev_err(&pdev->dev,
                        "unable to allocate memory for USB UTMIP config\n");
index 6d0f6080eceb309201abb2afae10080c6b67ba84..045cd309367ae7e9df8bbb9726ddb4b99de23ea1 100644 (file)
@@ -232,6 +232,9 @@ struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index)
        phy = __usb_find_phy_dev(dev, &phy_bind_list, index);
        if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
                dev_dbg(dev, "unable to find transceiver\n");
+               if (!IS_ERR(phy))
+                       phy = ERR_PTR(-ENODEV);
+
                goto err0;
        }
 
index 4fd36530bfa35dfb9a83b89f7d02abd04b17fbea..b0c97a3f1bfed74e262c3aa818817259f31e987e 100644 (file)
@@ -108,19 +108,45 @@ static struct usbhs_pkt *__usbhsf_pkt_get(struct usbhs_pipe *pipe)
        return list_first_entry(&pipe->list, struct usbhs_pkt, node);
 }
 
+static void usbhsf_fifo_clear(struct usbhs_pipe *pipe,
+                             struct usbhs_fifo *fifo);
+static void usbhsf_fifo_unselect(struct usbhs_pipe *pipe,
+                                struct usbhs_fifo *fifo);
+static struct dma_chan *usbhsf_dma_chan_get(struct usbhs_fifo *fifo,
+                                           struct usbhs_pkt *pkt);
+#define usbhsf_dma_map(p)      __usbhsf_dma_map_ctrl(p, 1)
+#define usbhsf_dma_unmap(p)    __usbhsf_dma_map_ctrl(p, 0)
+static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map);
 struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt)
 {
        struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
+       struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe);
        unsigned long flags;
 
        /********************  spin lock ********************/
        usbhs_lock(priv, flags);
 
+       usbhs_pipe_disable(pipe);
+
        if (!pkt)
                pkt = __usbhsf_pkt_get(pipe);
 
-       if (pkt)
+       if (pkt) {
+               struct dma_chan *chan = NULL;
+
+               if (fifo)
+                       chan = usbhsf_dma_chan_get(fifo, pkt);
+               if (chan) {
+                       dmaengine_terminate_all(chan);
+                       usbhsf_fifo_clear(pipe, fifo);
+                       usbhsf_dma_unmap(pkt);
+               }
+
                __usbhsf_pkt_del(pkt);
+       }
+
+       if (fifo)
+               usbhsf_fifo_unselect(pipe, fifo);
 
        usbhs_unlock(priv, flags);
        /********************  spin unlock ******************/
@@ -544,6 +570,7 @@ static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done)
                usbhsf_send_terminator(pipe, fifo);
 
        usbhsf_tx_irq_ctrl(pipe, !*is_done);
+       usbhs_pipe_running(pipe, !*is_done);
        usbhs_pipe_enable(pipe);
 
        dev_dbg(dev, "  send %d (%d/ %d/ %d/ %d)\n",
@@ -570,12 +597,21 @@ usbhs_fifo_write_busy:
         * retry in interrupt
         */
        usbhsf_tx_irq_ctrl(pipe, 1);
+       usbhs_pipe_running(pipe, 1);
 
        return ret;
 }
 
+static int usbhsf_pio_prepare_push(struct usbhs_pkt *pkt, int *is_done)
+{
+       if (usbhs_pipe_is_running(pkt->pipe))
+               return 0;
+
+       return usbhsf_pio_try_push(pkt, is_done);
+}
+
 struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = {
-       .prepare = usbhsf_pio_try_push,
+       .prepare = usbhsf_pio_prepare_push,
        .try_run = usbhsf_pio_try_push,
 };
 
@@ -589,6 +625,9 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done)
        if (usbhs_pipe_is_busy(pipe))
                return 0;
 
+       if (usbhs_pipe_is_running(pipe))
+               return 0;
+
        /*
         * pipe enable to prepare packet receive
         */
@@ -597,6 +636,7 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done)
 
        usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length);
        usbhs_pipe_enable(pipe);
+       usbhs_pipe_running(pipe, 1);
        usbhsf_rx_irq_ctrl(pipe, 1);
 
        return 0;
@@ -642,6 +682,7 @@ static int usbhsf_pio_try_pop(struct usbhs_pkt *pkt, int *is_done)
            (total_len < maxp)) {               /* short packet */
                *is_done = 1;
                usbhsf_rx_irq_ctrl(pipe, 0);
+               usbhs_pipe_running(pipe, 0);
                usbhs_pipe_disable(pipe);       /* disable pipe first */
        }
 
@@ -763,8 +804,6 @@ static void __usbhsf_dma_ctrl(struct usbhs_pipe *pipe,
        usbhs_bset(priv, fifo->sel, DREQE, dreqe);
 }
 
-#define usbhsf_dma_map(p)      __usbhsf_dma_map_ctrl(p, 1)
-#define usbhsf_dma_unmap(p)    __usbhsf_dma_map_ctrl(p, 0)
 static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
 {
        struct usbhs_pipe *pipe = pkt->pipe;
@@ -805,6 +844,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_running(pipe, 1);
        usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans);
        usbhs_pipe_enable(pipe);
        usbhsf_dma_start(pipe, fifo);
@@ -836,6 +876,10 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
        if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */
                goto usbhsf_pio_prepare_push;
 
+       /* return at this time if the pipe is running */
+       if (usbhs_pipe_is_running(pipe))
+               return 0;
+
        /* get enable DMA fifo */
        fifo = usbhsf_get_dma_fifo(priv, pkt);
        if (!fifo)
@@ -869,15 +913,29 @@ usbhsf_pio_prepare_push:
 static int usbhsf_dma_push_done(struct usbhs_pkt *pkt, int *is_done)
 {
        struct usbhs_pipe *pipe = pkt->pipe;
+       int is_short = pkt->trans % usbhs_pipe_get_maxpacket(pipe);
+
+       pkt->actual += pkt->trans;
 
-       pkt->actual = pkt->trans;
+       if (pkt->actual < pkt->length)
+               *is_done = 0;           /* there are remainder data */
+       else if (is_short)
+               *is_done = 1;           /* short packet */
+       else
+               *is_done = !pkt->zero;  /* send zero packet? */
 
-       *is_done = !pkt->zero;  /* send zero packet ? */
+       usbhs_pipe_running(pipe, !*is_done);
 
        usbhsf_dma_stop(pipe, pipe->fifo);
        usbhsf_dma_unmap(pkt);
        usbhsf_fifo_unselect(pipe, pipe->fifo);
 
+       if (!*is_done) {
+               /* change handler to PIO */
+               pkt->handler = &usbhs_fifo_pio_push_handler;
+               return pkt->handler->try_run(pkt, is_done);
+       }
+
        return 0;
 }
 
@@ -972,8 +1030,10 @@ static int usbhsf_dma_pop_done(struct usbhs_pkt *pkt, int *is_done)
        if ((pkt->actual == pkt->length) ||     /* receive all data */
            (pkt->trans < maxp)) {              /* short packet */
                *is_done = 1;
+               usbhs_pipe_running(pipe, 0);
        } else {
                /* re-enable */
+               usbhs_pipe_running(pipe, 0);
                usbhsf_prepare_pop(pkt, is_done);
        }
 
index 6a030b931a3b71d721870181d1170ba451dacc8b..9a705b15b3a1528b733c9eebac04e0d2f7ef2ee9 100644 (file)
@@ -213,7 +213,10 @@ static int usbhs_status_get_each_irq(struct usbhs_priv *priv,
 {
        struct usbhs_mod *mod = usbhs_mod_get_current(priv);
        u16 intenb0, intenb1;
+       unsigned long flags;
 
+       /********************  spin lock ********************/
+       usbhs_lock(priv, flags);
        state->intsts0 = usbhs_read(priv, INTSTS0);
        state->intsts1 = usbhs_read(priv, INTSTS1);
 
@@ -229,6 +232,8 @@ static int usbhs_status_get_each_irq(struct usbhs_priv *priv,
                state->bempsts &= mod->irq_bempsts;
                state->brdysts &= mod->irq_brdysts;
        }
+       usbhs_unlock(priv, flags);
+       /********************  spin unlock ******************/
 
        /*
         * Check whether the irq enable registers and the irq status are set
index 75fbcf6b102e86f8678434bd75188e71005d2504..040bcefcb0402c80116b917ea6595e1d01ed0a4d 100644 (file)
@@ -578,6 +578,19 @@ int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe)
        return usbhsp_flags_has(pipe, IS_DIR_HOST);
 }
 
+int usbhs_pipe_is_running(struct usbhs_pipe *pipe)
+{
+       return usbhsp_flags_has(pipe, IS_RUNNING);
+}
+
+void usbhs_pipe_running(struct usbhs_pipe *pipe, int running)
+{
+       if (running)
+               usbhsp_flags_set(pipe, IS_RUNNING);
+       else
+               usbhsp_flags_clr(pipe, IS_RUNNING);
+}
+
 void usbhs_pipe_data_sequence(struct usbhs_pipe *pipe, int sequence)
 {
        u16 mask = (SQCLR | SQSET);
index 406f36d050e4facf2c24b04fc254e2cbd639c623..d24a059723704cbae9c09c501f580c3ff0a450b7 100644 (file)
@@ -36,6 +36,7 @@ struct usbhs_pipe {
 #define USBHS_PIPE_FLAGS_IS_USED               (1 << 0)
 #define USBHS_PIPE_FLAGS_IS_DIR_IN             (1 << 1)
 #define USBHS_PIPE_FLAGS_IS_DIR_HOST           (1 << 2)
+#define USBHS_PIPE_FLAGS_IS_RUNNING            (1 << 3)
 
        struct usbhs_pkt_handle *handler;
 
@@ -80,6 +81,9 @@ int usbhs_pipe_probe(struct usbhs_priv *priv);
 void usbhs_pipe_remove(struct usbhs_priv *priv);
 int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe);
 int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe);
+int usbhs_pipe_is_running(struct usbhs_pipe *pipe);
+void usbhs_pipe_running(struct usbhs_pipe *pipe, int running);
+
 void usbhs_pipe_init(struct usbhs_priv *priv,
                     int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map));
 int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe);
index 216ce30782704d29a922a4a0e7d5df380768cd5d..dc72b924c399e955e8cd94f68c8337f1b7e3facd 100644 (file)
@@ -146,6 +146,7 @@ static const struct usb_device_id id_table_combined[] = {
        { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_BM_ATOM_NANO_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_NXTCAM_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_EV3CON_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) },
@@ -727,6 +728,7 @@ static const struct usb_device_id id_table_combined[] = {
        { USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID),
                .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk },
        { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) },
+       { USB_DEVICE(NOVITUS_VID, NOVITUS_BONO_E_PID) },
        { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S03_PID) },
        { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_59_PID) },
        { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_57A_PID) },
@@ -934,8 +936,12 @@ static const struct usb_device_id id_table_combined[] = {
        { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_2_PID) },
        { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_3_PID) },
        { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_4_PID) },
+       /* ekey Devices */
+       { USB_DEVICE(FTDI_VID, FTDI_EKEY_CONV_USB_PID) },
        /* Infineon Devices */
        { USB_DEVICE_INTERFACE_NUMBER(INFINEON_VID, INFINEON_TRIBOARD_PID, 1) },
+       /* GE Healthcare devices */
+       { USB_DEVICE(GE_HEALTHCARE_VID, GE_HEALTHCARE_NEMO_TRACKER_PID) },
        { }                                     /* Terminating entry */
 };
 
index 1e58d90a0b6c974197de3d138cced219bf201a27..5937b2d242f28c14064d56b073dbbda5fb737093 100644 (file)
@@ -42,6 +42,8 @@
 /* www.candapter.com Ewert Energy Systems CANdapter device */
 #define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */
 
+#define FTDI_BM_ATOM_NANO_PID  0xa559  /* Basic Micro ATOM Nano USB2Serial */
+
 /*
  * Texas Instruments XDS100v2 JTAG / BeagleBone A3
  * http://processors.wiki.ti.com/index.php/XDS100
 #define TELLDUS_VID                    0x1781  /* Vendor ID */
 #define TELLDUS_TELLSTICK_PID          0x0C30  /* RF control dongle 433 MHz using FT232RL */
 
+/*
+ * NOVITUS printers
+ */
+#define NOVITUS_VID                    0x1a28
+#define NOVITUS_BONO_E_PID             0x6010
+
 /*
  * RT Systems programming cables for various ham radios
  */
 #define BRAINBOXES_US_160_6_PID                0x9006 /* US-160 16xRS232 1Mbaud Port 11 and 12 */
 #define BRAINBOXES_US_160_7_PID                0x9007 /* US-160 16xRS232 1Mbaud Port 13 and 14 */
 #define BRAINBOXES_US_160_8_PID                0x9008 /* US-160 16xRS232 1Mbaud Port 15 and 16 */
+
+/*
+ * ekey biometric systems GmbH (http://ekey.net/)
+ */
+#define FTDI_EKEY_CONV_USB_PID         0xCB08  /* Converter USB */
+
+/*
+ * GE Healthcare devices
+ */
+#define GE_HEALTHCARE_VID              0x1901
+#define GE_HEALTHCARE_NEMO_TRACKER_PID 0x0015
index a9688940543d78d1724f28dae75a0929919e4f25..54a8120897a67f4783df9e3f525fb41359076734 100644 (file)
@@ -275,8 +275,12 @@ static void option_instat_callback(struct urb *urb);
 #define ZTE_PRODUCT_MF622                      0x0001
 #define ZTE_PRODUCT_MF628                      0x0015
 #define ZTE_PRODUCT_MF626                      0x0031
-#define ZTE_PRODUCT_MC2718                     0xffe8
 #define ZTE_PRODUCT_AC2726                     0xfff1
+#define ZTE_PRODUCT_CDMA_TECH                  0xfffe
+#define ZTE_PRODUCT_AC8710T                    0xffff
+#define ZTE_PRODUCT_MC2718                     0xffe8
+#define ZTE_PRODUCT_AD3812                     0xffeb
+#define ZTE_PRODUCT_MC2716                     0xffed
 
 #define BENQ_VENDOR_ID                         0x04a5
 #define BENQ_PRODUCT_H10                       0x4068
@@ -494,6 +498,10 @@ static void option_instat_callback(struct urb *urb);
 #define INOVIA_VENDOR_ID                       0x20a6
 #define INOVIA_SEW858                          0x1105
 
+/* VIA Telecom */
+#define VIATELECOM_VENDOR_ID                   0x15eb
+#define VIATELECOM_PRODUCT_CDS7                        0x0001
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
                OPTION_BLACKLIST_NONE = 0,
@@ -527,10 +535,18 @@ static const struct option_blacklist_info zte_k3765_z_blacklist = {
        .reserved = BIT(4),
 };
 
+static const struct option_blacklist_info zte_ad3812_z_blacklist = {
+       .sendsetup = BIT(0) | BIT(1) | BIT(2),
+};
+
 static const struct option_blacklist_info zte_mc2718_z_blacklist = {
        .sendsetup = BIT(1) | BIT(2) | BIT(3) | BIT(4),
 };
 
+static const struct option_blacklist_info zte_mc2716_z_blacklist = {
+       .sendsetup = BIT(1) | BIT(2) | BIT(3),
+};
+
 static const struct option_blacklist_info huawei_cdc12_blacklist = {
        .reserved = BIT(1) | BIT(2),
 };
@@ -1070,6 +1086,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_INTERFACE_CLASS(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_1012, 0xff) },
        { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC650) },
        { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) },
+       { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
        { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
@@ -1544,13 +1561,18 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff93, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff94, 0xff, 0xff, 0xff) },
 
-       /* NOTE: most ZTE CDMA devices should be driven by zte_ev, not option */
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710T, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2718, 0xff, 0xff, 0xff),
         .driver_info = (kernel_ulong_t)&zte_mc2718_z_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AD3812, 0xff, 0xff, 0xff),
+        .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff),
+        .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) },
        { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
 
        { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
        { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
@@ -1724,6 +1746,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */
        { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */
        { USB_DEVICE(INOVIA_VENDOR_ID, INOVIA_SEW858) },
+       { USB_DEVICE(VIATELECOM_VENDOR_ID, VIATELECOM_PRODUCT_CDS7) },
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
@@ -1916,6 +1939,8 @@ static void option_instat_callback(struct urb *urb)
                        dev_dbg(dev, "%s: type %x req %x\n", __func__,
                                req_pkt->bRequestType, req_pkt->bRequest);
                }
+       } else if (status == -ENOENT || status == -ESHUTDOWN) {
+               dev_dbg(dev, "%s: urb stopped: %d\n", __func__, status);
        } else
                dev_err(dev, "%s: error %d\n", __func__, status);
 
index b3d5a35c0d4b2e09ee3b0aea7fda1763d510c6a4..e9bad928039fd39ef00b73e898efa6a807e5b858 100644 (file)
@@ -45,6 +45,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_GPRS) },
        { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) },
        { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) },
+       { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ZTEK) },
        { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
        { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
        { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
index 42bc082896ac8e9d8f913168a0f209a7bebb673e..71fd9da1d6e7ac6e36ecdf38e8f8192c60fbbc39 100644 (file)
@@ -22,6 +22,7 @@
 #define PL2303_PRODUCT_ID_GPRS         0x0609
 #define PL2303_PRODUCT_ID_HCR331       0x331a
 #define PL2303_PRODUCT_ID_MOTOROLA     0x0307
+#define PL2303_PRODUCT_ID_ZTEK         0xe1f1
 
 #define ATEN_VENDOR_ID         0x0557
 #define ATEN_VENDOR_ID2                0x0547
index 6f7f01eb556a3af29634ce6e8a3e0745d6815e2e..46179a0828ebcbad9a78c11dad8044edff27664a 100644 (file)
@@ -282,14 +282,19 @@ static const struct usb_device_id id_table[] = {
        /* Sierra Wireless HSPA Non-Composite Device */
        { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)},
        { USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */
-       { USB_DEVICE(0x1199, 0x68A3),   /* Sierra Wireless Direct IP modems */
+       /* Sierra Wireless Direct IP modems */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68A3, 0xFF, 0xFF, 0xFF),
+         .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
+       },
+       { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68AA, 0xFF, 0xFF, 0xFF),
          .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
        },
        /* AT&T Direct IP LTE modems */
        { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68AA, 0xFF, 0xFF, 0xFF),
          .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
        },
-       { USB_DEVICE(0x0f3d, 0x68A3),   /* Airprime/Sierra Wireless Direct IP modems */
+       /* Airprime/Sierra Wireless Direct IP modems */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68A3, 0xFF, 0xFF, 0xFF),
          .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
        },
 
index 02de3110fe940e63308e7707a966c539bb620403..475723c006f955923d255be9abc408c7fd29027d 100644 (file)
@@ -764,29 +764,39 @@ static int usb_serial_probe(struct usb_interface *interface,
                if (usb_endpoint_is_bulk_in(endpoint)) {
                        /* we found a bulk in endpoint */
                        dev_dbg(ddev, "found bulk in on endpoint %d\n", i);
-                       bulk_in_endpoint[num_bulk_in] = endpoint;
-                       ++num_bulk_in;
+                       if (num_bulk_in < MAX_NUM_PORTS) {
+                               bulk_in_endpoint[num_bulk_in] = endpoint;
+                               ++num_bulk_in;
+                       }
                }
 
                if (usb_endpoint_is_bulk_out(endpoint)) {
                        /* we found a bulk out endpoint */
                        dev_dbg(ddev, "found bulk out on endpoint %d\n", i);
-                       bulk_out_endpoint[num_bulk_out] = endpoint;
-                       ++num_bulk_out;
+                       if (num_bulk_out < MAX_NUM_PORTS) {
+                               bulk_out_endpoint[num_bulk_out] = endpoint;
+                               ++num_bulk_out;
+                       }
                }
 
                if (usb_endpoint_is_int_in(endpoint)) {
                        /* we found a interrupt in endpoint */
                        dev_dbg(ddev, "found interrupt in on endpoint %d\n", i);
-                       interrupt_in_endpoint[num_interrupt_in] = endpoint;
-                       ++num_interrupt_in;
+                       if (num_interrupt_in < MAX_NUM_PORTS) {
+                               interrupt_in_endpoint[num_interrupt_in] =
+                                               endpoint;
+                               ++num_interrupt_in;
+                       }
                }
 
                if (usb_endpoint_is_int_out(endpoint)) {
                        /* we found an interrupt out endpoint */
                        dev_dbg(ddev, "found interrupt out on endpoint %d\n", i);
-                       interrupt_out_endpoint[num_interrupt_out] = endpoint;
-                       ++num_interrupt_out;
+                       if (num_interrupt_out < MAX_NUM_PORTS) {
+                               interrupt_out_endpoint[num_interrupt_out] =
+                                               endpoint;
+                               ++num_interrupt_out;
+                       }
                }
        }
 
@@ -809,8 +819,10 @@ static int usb_serial_probe(struct usb_interface *interface,
                                if (usb_endpoint_is_int_in(endpoint)) {
                                        /* we found a interrupt in endpoint */
                                        dev_dbg(ddev, "found interrupt in for Prolific device on separate interface\n");
-                                       interrupt_in_endpoint[num_interrupt_in] = endpoint;
-                                       ++num_interrupt_in;
+                                       if (num_interrupt_in < MAX_NUM_PORTS) {
+                                               interrupt_in_endpoint[num_interrupt_in] = endpoint;
+                                               ++num_interrupt_in;
+                                       }
                                }
                        }
                }
@@ -850,6 +862,11 @@ static int usb_serial_probe(struct usb_interface *interface,
                        num_ports = type->num_ports;
        }
 
+       if (num_ports > MAX_NUM_PORTS) {
+               dev_warn(ddev, "too many ports requested: %d\n", num_ports);
+               num_ports = MAX_NUM_PORTS;
+       }
+
        serial->num_ports = num_ports;
        serial->num_bulk_in = num_bulk_in;
        serial->num_bulk_out = num_bulk_out;
index e62f2dff8b7df6db65e684ef01dbbccced3a6066..6c3734d2b45a7a9ca24557a586ba10135b7cadb3 100644 (file)
@@ -514,6 +514,10 @@ static void command_port_read_callback(struct urb *urb)
                dev_dbg(&urb->dev->dev, "%s - command_info is NULL, exiting.\n", __func__);
                return;
        }
+       if (!urb->actual_length) {
+               dev_dbg(&urb->dev->dev, "%s - empty response, exiting.\n", __func__);
+               return;
+       }
        if (status) {
                dev_dbg(&urb->dev->dev, "%s - nonzero urb status: %d\n", __func__, status);
                if (status != -ENOENT)
@@ -534,7 +538,8 @@ static void command_port_read_callback(struct urb *urb)
                /* These are unsolicited reports from the firmware, hence no
                   waiting command to wakeup */
                dev_dbg(&urb->dev->dev, "%s - event received\n", __func__);
-       } else if (data[0] == WHITEHEAT_GET_DTR_RTS) {
+       } else if ((data[0] == WHITEHEAT_GET_DTR_RTS) &&
+               (urb->actual_length - 1 <= sizeof(command_info->result_buffer))) {
                memcpy(command_info->result_buffer, &data[1],
                                                urb->actual_length - 1);
                command_info->command_finished = WHITEHEAT_CMD_COMPLETE;
index e40ab739c4a6eb227f4704f75daee65a5f13f0be..c9bb107d5e5ccae2ffaa7823f70872c0de86d419 100644 (file)
@@ -272,28 +272,16 @@ static void zte_ev_usb_serial_close(struct usb_serial_port *port)
 }
 
 static const struct usb_device_id id_table[] = {
-       /* AC8710, AC8710T */
-       { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffff, 0xff, 0xff, 0xff) },
-        /* AC8700 */
-       { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xfffe, 0xff, 0xff, 0xff) },
-       /* MG880 */
-       { USB_DEVICE(0x19d2, 0xfffd) },
-       { USB_DEVICE(0x19d2, 0xfffc) },
-       { USB_DEVICE(0x19d2, 0xfffb) },
-       /* AC8710_V3 */
+       { USB_DEVICE(0x19d2, 0xffec) },
+       { USB_DEVICE(0x19d2, 0xffee) },
        { USB_DEVICE(0x19d2, 0xfff6) },
        { USB_DEVICE(0x19d2, 0xfff7) },
        { USB_DEVICE(0x19d2, 0xfff8) },
        { USB_DEVICE(0x19d2, 0xfff9) },
-       { USB_DEVICE(0x19d2, 0xffee) },
-       /* AC2716, MC2716 */
-       { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffed, 0xff, 0xff, 0xff) },
-       /* AD3812 */
-       { USB_DEVICE_AND_INTERFACE_INFO(0x19d2, 0xffeb, 0xff, 0xff, 0xff) },
-       { USB_DEVICE(0x19d2, 0xffec) },
-       { USB_DEVICE(0x05C6, 0x3197) },
-       { USB_DEVICE(0x05C6, 0x6000) },
-       { USB_DEVICE(0x05C6, 0x9008) },
+       { USB_DEVICE(0x19d2, 0xfffb) },
+       { USB_DEVICE(0x19d2, 0xfffc) },
+       /* MG880 */
+       { USB_DEVICE(0x19d2, 0xfffd) },
        { },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
index 503ac5c8d80f7bb7bcb87832df78a71d8c14587f..8a6f371ed6e77e3ccdc99632c3cd41ebeb155213 100644 (file)
@@ -59,10 +59,6 @@ static int uas_use_uas_driver(struct usb_interface *intf,
        unsigned long flags = id->driver_info;
        int r, alt;
 
-       usb_stor_adjust_quirks(udev, &flags);
-
-       if (flags & US_FL_IGNORE_UAS)
-               return 0;
 
        alt = uas_find_uas_alt_setting(intf);
        if (alt < 0)
@@ -72,6 +68,29 @@ static int uas_use_uas_driver(struct usb_interface *intf,
        if (r < 0)
                return 0;
 
+       /*
+        * ASM1051 and older ASM1053 devices have the same usb-id, and UAS is
+        * broken on the ASM1051, use the number of streams to differentiate.
+        * New ASM1053-s also support 32 streams, but have a different prod-id.
+        */
+       if (le16_to_cpu(udev->descriptor.idVendor) == 0x174c &&
+                       le16_to_cpu(udev->descriptor.idProduct) == 0x55aa) {
+               if (udev->speed < USB_SPEED_SUPER) {
+                       /* No streams info, assume ASM1051 */
+                       flags |= US_FL_IGNORE_UAS;
+               } else if (usb_ss_max_streams(&eps[1]->ss_ep_comp) == 32) {
+                       flags |= US_FL_IGNORE_UAS;
+               }
+       }
+
+       usb_stor_adjust_quirks(udev, &flags);
+
+       if (flags & US_FL_IGNORE_UAS) {
+               dev_warn(&udev->dev,
+                       "UAS is blacklisted for this device, using usb-storage instead\n");
+               return 0;
+       }
+
        if (udev->bus->sg_tablesize == 0) {
                dev_warn(&udev->dev,
                        "The driver for the USB controller %s does not support scatter-gather which is\n",
index 80a5b366255fb8acb812cadfe0ff6d63d5329ece..60cfcbc78552ceef5e9876610d30647d1aa67884 100644 (file)
@@ -741,6 +741,12 @@ UNUSUAL_DEV(  0x059b, 0x0001, 0x0100, 0x0100,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_SINGLE_LUN ),
 
+UNUSUAL_DEV(  0x059b, 0x0040, 0x0100, 0x0100,
+               "Iomega",
+               "Jaz USB Adapter",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_SINGLE_LUN ),
+
 /* Reported by <Hendryk.Pfeiffer@gmx.de> */
 UNUSUAL_DEV(  0x059f, 0x0643, 0x0000, 0x0000,
                "LaCie",
@@ -922,6 +928,12 @@ UNUSUAL_DEV(  0x069b, 0x3004, 0x0001, 0x0001,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_FIX_CAPACITY ),
 
+UNUSUAL_DEV(  0x06ca, 0x2003, 0x0100, 0x0100,
+               "Newer Technology",
+               "uSCSI",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_euscsi_init,
+               US_FL_SCM_MULT_TARG ),
+
 /* Reported by Adrian Pilchowiec <adi1981@epf.pl> */
 UNUSUAL_DEV(  0x071b, 0x3203, 0x0000, 0x0000,
                "RockChip",
diff --git a/drivers/usb/usbip/Kconfig b/drivers/usb/usbip/Kconfig
new file mode 100644 (file)
index 0000000..bd99e9e
--- /dev/null
@@ -0,0 +1,41 @@
+config USBIP_CORE
+       tristate "USB/IP support"
+       depends on USB && NET
+       ---help---
+         This enables pushing USB packets over IP to allow remote
+         machines direct access to USB devices. It provides the
+         USB/IP core that is required by both drivers.
+
+         For more details, and to get the userspace utility
+         programs, please see <http://usbip.sourceforge.net/>.
+
+         To compile this as a module, choose M here: the module will
+         be called usbip-core.
+
+         If unsure, say N.
+
+config USBIP_VHCI_HCD
+       tristate "VHCI hcd"
+       depends on USBIP_CORE
+       ---help---
+         This enables the USB/IP virtual host controller driver,
+         which is run on the remote machine.
+
+         To compile this driver as a module, choose M here: the
+         module will be called vhci-hcd.
+
+config USBIP_HOST
+       tristate "Host driver"
+       depends on USBIP_CORE
+       ---help---
+         This enables the USB/IP host driver, which is run on the
+         machine that is sharing the USB devices.
+
+         To compile this driver as a module, choose M here: the
+         module will be called usbip-host.
+
+config USBIP_DEBUG
+       bool "Debug messages for USB/IP"
+       depends on USBIP_CORE
+       ---help---
+         This enables the debug messages from the USB/IP drivers.
diff --git a/drivers/usb/usbip/Makefile b/drivers/usb/usbip/Makefile
new file mode 100644 (file)
index 0000000..9ecd615
--- /dev/null
@@ -0,0 +1,10 @@
+ccflags-$(CONFIG_USBIP_DEBUG) := -DDEBUG
+
+obj-$(CONFIG_USBIP_CORE) += usbip-core.o
+usbip-core-y := usbip_common.o usbip_event.o
+
+obj-$(CONFIG_USBIP_VHCI_HCD) += vhci-hcd.o
+vhci-hcd-y := vhci_sysfs.o vhci_tx.o vhci_rx.o vhci_hcd.o
+
+obj-$(CONFIG_USBIP_HOST) += usbip-host.o
+usbip-host-y := stub_dev.o stub_main.o stub_rx.o stub_tx.o
diff --git a/drivers/usb/usbip/README b/drivers/usb/usbip/README
new file mode 100644 (file)
index 0000000..41a2cf2
--- /dev/null
@@ -0,0 +1,7 @@
+TODO:
+       - more discussion about the protocol
+       - testing
+       - review of the userspace interface
+       - document the protocol
+
+Please send patches for this code to Greg Kroah-Hartman <greg@kroah.com>
diff --git a/drivers/usb/usbip/stub.h b/drivers/usb/usbip/stub.h
new file mode 100644 (file)
index 0000000..266e2b0
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef __USBIP_STUB_H
+#define __USBIP_STUB_H
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/usb.h>
+#include <linux/wait.h>
+
+#define STUB_BUSID_OTHER 0
+#define STUB_BUSID_REMOV 1
+#define STUB_BUSID_ADDED 2
+#define STUB_BUSID_ALLOC 3
+
+struct stub_device {
+       struct usb_interface *interface;
+       struct usb_device *udev;
+
+       struct usbip_device ud;
+       __u32 devid;
+
+       /*
+        * stub_priv preserves private data of each urb.
+        * It is allocated as stub_priv_cache and assigned to urb->context.
+        *
+        * stub_priv is always linked to any one of 3 lists;
+        *      priv_init: linked to this until the comletion of a urb.
+        *      priv_tx  : linked to this after the completion of a urb.
+        *      priv_free: linked to this after the sending of the result.
+        *
+        * Any of these list operations should be locked by priv_lock.
+        */
+       spinlock_t priv_lock;
+       struct list_head priv_init;
+       struct list_head priv_tx;
+       struct list_head priv_free;
+
+       /* see comments for unlinking in stub_rx.c */
+       struct list_head unlink_tx;
+       struct list_head unlink_free;
+
+       wait_queue_head_t tx_waitq;
+};
+
+/* private data into urb->priv */
+struct stub_priv {
+       unsigned long seqnum;
+       struct list_head list;
+       struct stub_device *sdev;
+       struct urb *urb;
+
+       int unlinking;
+};
+
+struct stub_unlink {
+       unsigned long seqnum;
+       struct list_head list;
+       __u32 status;
+};
+
+/* same as SYSFS_BUS_ID_SIZE */
+#define BUSID_SIZE 32
+
+struct bus_id_priv {
+       char name[BUSID_SIZE];
+       char status;
+       int interf_count;
+       struct stub_device *sdev;
+       struct usb_device *udev;
+       char shutdown_busid;
+};
+
+/* stub_priv is allocated from stub_priv_cache */
+extern struct kmem_cache *stub_priv_cache;
+
+/* stub_dev.c */
+extern struct usb_device_driver stub_driver;
+
+/* stub_main.c */
+struct bus_id_priv *get_busid_priv(const char *busid);
+int del_match_busid(char *busid);
+void stub_device_cleanup_urbs(struct stub_device *sdev);
+
+/* stub_rx.c */
+int stub_rx_loop(void *data);
+
+/* stub_tx.c */
+void stub_enqueue_ret_unlink(struct stub_device *sdev, __u32 seqnum,
+                            __u32 status);
+void stub_complete(struct urb *urb);
+int stub_tx_loop(void *data);
+
+#endif /* __USBIP_STUB_H */
diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c
new file mode 100644 (file)
index 0000000..fac20e0
--- /dev/null
@@ -0,0 +1,498 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <linux/device.h>
+#include <linux/file.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+
+#include "usbip_common.h"
+#include "stub.h"
+
+/*
+ * usbip_status shows the status of usbip-host as long as this driver is bound
+ * to the target device.
+ */
+static ssize_t usbip_status_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       struct stub_device *sdev = dev_get_drvdata(dev);
+       int status;
+
+       if (!sdev) {
+               dev_err(dev, "sdev is null\n");
+               return -ENODEV;
+       }
+
+       spin_lock_irq(&sdev->ud.lock);
+       status = sdev->ud.status;
+       spin_unlock_irq(&sdev->ud.lock);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", status);
+}
+static DEVICE_ATTR_RO(usbip_status);
+
+/*
+ * usbip_sockfd gets a socket descriptor of an established TCP connection that
+ * is used to transfer usbip requests by kernel threads. -1 is a magic number
+ * by which usbip connection is finished.
+ */
+static ssize_t store_sockfd(struct device *dev, struct device_attribute *attr,
+                           const char *buf, size_t count)
+{
+       struct stub_device *sdev = dev_get_drvdata(dev);
+       int sockfd = 0;
+       struct socket *socket;
+       int rv;
+
+       if (!sdev) {
+               dev_err(dev, "sdev is null\n");
+               return -ENODEV;
+       }
+
+       rv = sscanf(buf, "%d", &sockfd);
+       if (rv != 1)
+               return -EINVAL;
+
+       if (sockfd != -1) {
+               int err;
+
+               dev_info(dev, "stub up\n");
+
+               spin_lock_irq(&sdev->ud.lock);
+
+               if (sdev->ud.status != SDEV_ST_AVAILABLE) {
+                       dev_err(dev, "not ready\n");
+                       goto err;
+               }
+
+               socket = sockfd_lookup(sockfd, &err);
+               if (!socket)
+                       goto err;
+
+               sdev->ud.tcp_socket = socket;
+
+               spin_unlock_irq(&sdev->ud.lock);
+
+               sdev->ud.tcp_rx = kthread_get_run(stub_rx_loop, &sdev->ud,
+                                                 "stub_rx");
+               sdev->ud.tcp_tx = kthread_get_run(stub_tx_loop, &sdev->ud,
+                                                 "stub_tx");
+
+               spin_lock_irq(&sdev->ud.lock);
+               sdev->ud.status = SDEV_ST_USED;
+               spin_unlock_irq(&sdev->ud.lock);
+
+       } else {
+               dev_info(dev, "stub down\n");
+
+               spin_lock_irq(&sdev->ud.lock);
+               if (sdev->ud.status != SDEV_ST_USED)
+                       goto err;
+
+               spin_unlock_irq(&sdev->ud.lock);
+
+               usbip_event_add(&sdev->ud, SDEV_EVENT_DOWN);
+       }
+
+       return count;
+
+err:
+       spin_unlock_irq(&sdev->ud.lock);
+       return -EINVAL;
+}
+static DEVICE_ATTR(usbip_sockfd, S_IWUSR, NULL, store_sockfd);
+
+static int stub_add_files(struct device *dev)
+{
+       int err = 0;
+
+       err = device_create_file(dev, &dev_attr_usbip_status);
+       if (err)
+               goto err_status;
+
+       err = device_create_file(dev, &dev_attr_usbip_sockfd);
+       if (err)
+               goto err_sockfd;
+
+       err = device_create_file(dev, &dev_attr_usbip_debug);
+       if (err)
+               goto err_debug;
+
+       return 0;
+
+err_debug:
+       device_remove_file(dev, &dev_attr_usbip_sockfd);
+err_sockfd:
+       device_remove_file(dev, &dev_attr_usbip_status);
+err_status:
+       return err;
+}
+
+static void stub_remove_files(struct device *dev)
+{
+       device_remove_file(dev, &dev_attr_usbip_status);
+       device_remove_file(dev, &dev_attr_usbip_sockfd);
+       device_remove_file(dev, &dev_attr_usbip_debug);
+}
+
+static void stub_shutdown_connection(struct usbip_device *ud)
+{
+       struct stub_device *sdev = container_of(ud, struct stub_device, ud);
+
+       /*
+        * When removing an exported device, kernel panic sometimes occurred
+        * and then EIP was sk_wait_data of stub_rx thread. Is this because
+        * sk_wait_data returned though stub_rx thread was already finished by
+        * step 1?
+        */
+       if (ud->tcp_socket) {
+               dev_dbg(&sdev->udev->dev, "shutdown tcp_socket %p\n",
+                       ud->tcp_socket);
+               kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR);
+       }
+
+       /* 1. stop threads */
+       if (ud->tcp_rx) {
+               kthread_stop_put(ud->tcp_rx);
+               ud->tcp_rx = NULL;
+       }
+       if (ud->tcp_tx) {
+               kthread_stop_put(ud->tcp_tx);
+               ud->tcp_tx = NULL;
+       }
+
+       /*
+        * 2. close the socket
+        *
+        * tcp_socket is freed after threads are killed so that usbip_xmit does
+        * not touch NULL socket.
+        */
+       if (ud->tcp_socket) {
+               sockfd_put(ud->tcp_socket);
+               ud->tcp_socket = NULL;
+       }
+
+       /* 3. free used data */
+       stub_device_cleanup_urbs(sdev);
+
+       /* 4. free stub_unlink */
+       {
+               unsigned long flags;
+               struct stub_unlink *unlink, *tmp;
+
+               spin_lock_irqsave(&sdev->priv_lock, flags);
+               list_for_each_entry_safe(unlink, tmp, &sdev->unlink_tx, list) {
+                       list_del(&unlink->list);
+                       kfree(unlink);
+               }
+               list_for_each_entry_safe(unlink, tmp, &sdev->unlink_free,
+                                        list) {
+                       list_del(&unlink->list);
+                       kfree(unlink);
+               }
+               spin_unlock_irqrestore(&sdev->priv_lock, flags);
+       }
+}
+
+static void stub_device_reset(struct usbip_device *ud)
+{
+       struct stub_device *sdev = container_of(ud, struct stub_device, ud);
+       struct usb_device *udev = sdev->udev;
+       int ret;
+
+       dev_dbg(&udev->dev, "device reset");
+
+       ret = usb_lock_device_for_reset(udev, sdev->interface);
+       if (ret < 0) {
+               dev_err(&udev->dev, "lock for reset\n");
+               spin_lock_irq(&ud->lock);
+               ud->status = SDEV_ST_ERROR;
+               spin_unlock_irq(&ud->lock);
+               return;
+       }
+
+       /* try to reset the device */
+       ret = usb_reset_device(udev);
+       usb_unlock_device(udev);
+
+       spin_lock_irq(&ud->lock);
+       if (ret) {
+               dev_err(&udev->dev, "device reset\n");
+               ud->status = SDEV_ST_ERROR;
+       } else {
+               dev_info(&udev->dev, "device reset\n");
+               ud->status = SDEV_ST_AVAILABLE;
+       }
+       spin_unlock_irq(&ud->lock);
+}
+
+static void stub_device_unusable(struct usbip_device *ud)
+{
+       spin_lock_irq(&ud->lock);
+       ud->status = SDEV_ST_ERROR;
+       spin_unlock_irq(&ud->lock);
+}
+
+/**
+ * stub_device_alloc - allocate a new stub_device struct
+ * @interface: usb_interface of a new device
+ *
+ * Allocates and initializes a new stub_device struct.
+ */
+static struct stub_device *stub_device_alloc(struct usb_device *udev)
+{
+       struct stub_device *sdev;
+       int busnum = udev->bus->busnum;
+       int devnum = udev->devnum;
+
+       dev_dbg(&udev->dev, "allocating stub device");
+
+       /* yes, it's a new device */
+       sdev = kzalloc(sizeof(struct stub_device), GFP_KERNEL);
+       if (!sdev)
+               return NULL;
+
+       sdev->udev = usb_get_dev(udev);
+
+       /*
+        * devid is defined with devnum when this driver is first allocated.
+        * devnum may change later if a device is reset. However, devid never
+        * changes during a usbip connection.
+        */
+       sdev->devid             = (busnum << 16) | devnum;
+       sdev->ud.side           = USBIP_STUB;
+       sdev->ud.status         = SDEV_ST_AVAILABLE;
+       spin_lock_init(&sdev->ud.lock);
+       sdev->ud.tcp_socket     = NULL;
+
+       INIT_LIST_HEAD(&sdev->priv_init);
+       INIT_LIST_HEAD(&sdev->priv_tx);
+       INIT_LIST_HEAD(&sdev->priv_free);
+       INIT_LIST_HEAD(&sdev->unlink_free);
+       INIT_LIST_HEAD(&sdev->unlink_tx);
+       spin_lock_init(&sdev->priv_lock);
+
+       init_waitqueue_head(&sdev->tx_waitq);
+
+       sdev->ud.eh_ops.shutdown = stub_shutdown_connection;
+       sdev->ud.eh_ops.reset    = stub_device_reset;
+       sdev->ud.eh_ops.unusable = stub_device_unusable;
+
+       usbip_start_eh(&sdev->ud);
+
+       dev_dbg(&udev->dev, "register new device\n");
+
+       return sdev;
+}
+
+static void stub_device_free(struct stub_device *sdev)
+{
+       kfree(sdev);
+}
+
+static int stub_probe(struct usb_device *udev)
+{
+       struct stub_device *sdev = NULL;
+       const char *udev_busid = dev_name(&udev->dev);
+       int err = 0;
+       struct bus_id_priv *busid_priv;
+       int rc;
+
+       dev_dbg(&udev->dev, "Enter\n");
+
+       /* check we should claim or not by busid_table */
+       busid_priv = get_busid_priv(udev_busid);
+       if (!busid_priv || (busid_priv->status == STUB_BUSID_REMOV) ||
+           (busid_priv->status == STUB_BUSID_OTHER)) {
+               dev_info(&udev->dev,
+                       "%s is not in match_busid table... skip!\n",
+                       udev_busid);
+
+               /*
+                * Return value should be ENODEV or ENOXIO to continue trying
+                * other matched drivers by the driver core.
+                * See driver_probe_device() in driver/base/dd.c
+                */
+               return -ENODEV;
+       }
+
+       if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) {
+               dev_dbg(&udev->dev, "%s is a usb hub device... skip!\n",
+                        udev_busid);
+               return -ENODEV;
+       }
+
+       if (!strcmp(udev->bus->bus_name, "vhci_hcd")) {
+               dev_dbg(&udev->dev,
+                       "%s is attached on vhci_hcd... skip!\n",
+                       udev_busid);
+
+               return -ENODEV;
+       }
+
+       /* ok, this is my device */
+       sdev = stub_device_alloc(udev);
+       if (!sdev)
+               return -ENOMEM;
+
+       dev_info(&udev->dev,
+               "usbip-host: register new device (bus %u dev %u)\n",
+               udev->bus->busnum, udev->devnum);
+
+       busid_priv->shutdown_busid = 0;
+
+       /* set private data to usb_device */
+       dev_set_drvdata(&udev->dev, sdev);
+       busid_priv->sdev = sdev;
+       busid_priv->udev = udev;
+
+       /*
+        * Claim this hub port.
+        * It doesn't matter what value we pass as owner
+        * (struct dev_state) as long as it is unique.
+        */
+       rc = usb_hub_claim_port(udev->parent, udev->portnum,
+                       (struct usb_dev_state *) udev);
+       if (rc) {
+               dev_dbg(&udev->dev, "unable to claim port\n");
+               return rc;
+       }
+
+       err = stub_add_files(&udev->dev);
+       if (err) {
+               dev_err(&udev->dev, "stub_add_files for %s\n", udev_busid);
+               dev_set_drvdata(&udev->dev, NULL);
+               usb_put_dev(udev);
+               kthread_stop_put(sdev->ud.eh);
+
+               busid_priv->sdev = NULL;
+               stub_device_free(sdev);
+               return err;
+       }
+       busid_priv->status = STUB_BUSID_ALLOC;
+
+       return 0;
+}
+
+static void shutdown_busid(struct bus_id_priv *busid_priv)
+{
+       if (busid_priv->sdev && !busid_priv->shutdown_busid) {
+               busid_priv->shutdown_busid = 1;
+               usbip_event_add(&busid_priv->sdev->ud, SDEV_EVENT_REMOVED);
+
+               /* wait for the stop of the event handler */
+               usbip_stop_eh(&busid_priv->sdev->ud);
+       }
+}
+
+/*
+ * called in usb_disconnect() or usb_deregister()
+ * but only if actconfig(active configuration) exists
+ */
+static void stub_disconnect(struct usb_device *udev)
+{
+       struct stub_device *sdev;
+       const char *udev_busid = dev_name(&udev->dev);
+       struct bus_id_priv *busid_priv;
+       int rc;
+
+       dev_dbg(&udev->dev, "Enter\n");
+
+       busid_priv = get_busid_priv(udev_busid);
+       if (!busid_priv) {
+               BUG();
+               return;
+       }
+
+       sdev = dev_get_drvdata(&udev->dev);
+
+       /* get stub_device */
+       if (!sdev) {
+               dev_err(&udev->dev, "could not get device");
+               return;
+       }
+
+       dev_set_drvdata(&udev->dev, NULL);
+
+       /*
+        * NOTE: rx/tx threads are invoked for each usb_device.
+        */
+       stub_remove_files(&udev->dev);
+
+       /* release port */
+       rc = usb_hub_release_port(udev->parent, udev->portnum,
+                                 (struct usb_dev_state *) udev);
+       if (rc) {
+               dev_dbg(&udev->dev, "unable to release port\n");
+               return;
+       }
+
+       /* If usb reset is called from event handler */
+       if (busid_priv->sdev->ud.eh == current)
+               return;
+
+       /* shutdown the current connection */
+       shutdown_busid(busid_priv);
+
+       usb_put_dev(sdev->udev);
+
+       /* free sdev */
+       busid_priv->sdev = NULL;
+       stub_device_free(sdev);
+
+       if (busid_priv->status == STUB_BUSID_ALLOC) {
+               busid_priv->status = STUB_BUSID_ADDED;
+       } else {
+               busid_priv->status = STUB_BUSID_OTHER;
+               del_match_busid((char *)udev_busid);
+       }
+}
+
+#ifdef CONFIG_PM
+
+/* These functions need usb_port_suspend and usb_port_resume,
+ * which reside in drivers/usb/core/usb.h. Skip for now. */
+
+static int stub_suspend(struct usb_device *udev, pm_message_t message)
+{
+       dev_dbg(&udev->dev, "stub_suspend\n");
+
+       return 0;
+}
+
+static int stub_resume(struct usb_device *udev, pm_message_t message)
+{
+       dev_dbg(&udev->dev, "stub_resume\n");
+
+       return 0;
+}
+
+#endif /* CONFIG_PM */
+
+struct usb_device_driver stub_driver = {
+       .name           = "usbip-host",
+       .probe          = stub_probe,
+       .disconnect     = stub_disconnect,
+#ifdef CONFIG_PM
+       .suspend        = stub_suspend,
+       .resume         = stub_resume,
+#endif
+       .supports_autosuspend   =       0,
+};
diff --git a/drivers/usb/usbip/stub_main.c b/drivers/usb/usbip/stub_main.c
new file mode 100644 (file)
index 0000000..44ab43f
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/device.h>
+
+#include "usbip_common.h"
+#include "stub.h"
+
+#define DRIVER_AUTHOR "Takahiro Hirofuchi"
+#define DRIVER_DESC "USB/IP Host Driver"
+
+struct kmem_cache *stub_priv_cache;
+/*
+ * busid_tables defines matching busids that usbip can grab. A user can change
+ * dynamically what device is locally used and what device is exported to a
+ * remote host.
+ */
+#define MAX_BUSID 16
+static struct bus_id_priv busid_table[MAX_BUSID];
+static spinlock_t busid_table_lock;
+
+static void init_busid_table(void)
+{
+       /*
+        * This also sets the bus_table[i].status to
+        * STUB_BUSID_OTHER, which is 0.
+        */
+       memset(busid_table, 0, sizeof(busid_table));
+
+       spin_lock_init(&busid_table_lock);
+}
+
+/*
+ * Find the index of the busid by name.
+ * Must be called with busid_table_lock held.
+ */
+static int get_busid_idx(const char *busid)
+{
+       int i;
+       int idx = -1;
+
+       for (i = 0; i < MAX_BUSID; i++)
+               if (busid_table[i].name[0])
+                       if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
+                               idx = i;
+                               break;
+                       }
+       return idx;
+}
+
+struct bus_id_priv *get_busid_priv(const char *busid)
+{
+       int idx;
+       struct bus_id_priv *bid = NULL;
+
+       spin_lock(&busid_table_lock);
+       idx = get_busid_idx(busid);
+       if (idx >= 0)
+               bid = &(busid_table[idx]);
+       spin_unlock(&busid_table_lock);
+
+       return bid;
+}
+
+static int add_match_busid(char *busid)
+{
+       int i;
+       int ret = -1;
+
+       spin_lock(&busid_table_lock);
+       /* already registered? */
+       if (get_busid_idx(busid) >= 0) {
+               ret = 0;
+               goto out;
+       }
+
+       for (i = 0; i < MAX_BUSID; i++)
+               if (!busid_table[i].name[0]) {
+                       strlcpy(busid_table[i].name, busid, BUSID_SIZE);
+                       if ((busid_table[i].status != STUB_BUSID_ALLOC) &&
+                           (busid_table[i].status != STUB_BUSID_REMOV))
+                               busid_table[i].status = STUB_BUSID_ADDED;
+                       ret = 0;
+                       break;
+               }
+
+out:
+       spin_unlock(&busid_table_lock);
+
+       return ret;
+}
+
+int del_match_busid(char *busid)
+{
+       int idx;
+       int ret = -1;
+
+       spin_lock(&busid_table_lock);
+       idx = get_busid_idx(busid);
+       if (idx < 0)
+               goto out;
+
+       /* found */
+       ret = 0;
+
+       if (busid_table[idx].status == STUB_BUSID_OTHER)
+               memset(busid_table[idx].name, 0, BUSID_SIZE);
+
+       if ((busid_table[idx].status != STUB_BUSID_OTHER) &&
+           (busid_table[idx].status != STUB_BUSID_ADDED))
+               busid_table[idx].status = STUB_BUSID_REMOV;
+
+out:
+       spin_unlock(&busid_table_lock);
+
+       return ret;
+}
+
+static ssize_t show_match_busid(struct device_driver *drv, char *buf)
+{
+       int i;
+       char *out = buf;
+
+       spin_lock(&busid_table_lock);
+       for (i = 0; i < MAX_BUSID; i++)
+               if (busid_table[i].name[0])
+                       out += sprintf(out, "%s ", busid_table[i].name);
+       spin_unlock(&busid_table_lock);
+       out += sprintf(out, "\n");
+
+       return out - buf;
+}
+
+static ssize_t store_match_busid(struct device_driver *dev, const char *buf,
+                                size_t count)
+{
+       int len;
+       char busid[BUSID_SIZE];
+
+       if (count < 5)
+               return -EINVAL;
+
+       /* busid needs to include \0 termination */
+       len = strlcpy(busid, buf + 4, BUSID_SIZE);
+       if (sizeof(busid) <= len)
+               return -EINVAL;
+
+       if (!strncmp(buf, "add ", 4)) {
+               if (add_match_busid(busid) < 0)
+                       return -ENOMEM;
+
+               pr_debug("add busid %s\n", busid);
+               return count;
+       }
+
+       if (!strncmp(buf, "del ", 4)) {
+               if (del_match_busid(busid) < 0)
+                       return -ENODEV;
+
+               pr_debug("del busid %s\n", busid);
+               return count;
+       }
+
+       return -EINVAL;
+}
+static DRIVER_ATTR(match_busid, S_IRUSR | S_IWUSR, show_match_busid,
+                  store_match_busid);
+
+static ssize_t rebind_store(struct device_driver *dev, const char *buf,
+                                size_t count)
+{
+       int ret;
+       int len;
+       struct bus_id_priv *bid;
+
+       /* buf length should be less that BUSID_SIZE */
+       len = strnlen(buf, BUSID_SIZE);
+
+       if (!(len < BUSID_SIZE))
+               return -EINVAL;
+
+       bid = get_busid_priv(buf);
+       if (!bid)
+               return -ENODEV;
+
+       ret = device_attach(&bid->udev->dev);
+       if (ret < 0) {
+               dev_err(&bid->udev->dev, "rebind failed\n");
+               return ret;
+       }
+
+       return count;
+}
+
+static DRIVER_ATTR_WO(rebind);
+
+static struct stub_priv *stub_priv_pop_from_listhead(struct list_head *listhead)
+{
+       struct stub_priv *priv, *tmp;
+
+       list_for_each_entry_safe(priv, tmp, listhead, list) {
+               list_del(&priv->list);
+               return priv;
+       }
+
+       return NULL;
+}
+
+static struct stub_priv *stub_priv_pop(struct stub_device *sdev)
+{
+       unsigned long flags;
+       struct stub_priv *priv;
+
+       spin_lock_irqsave(&sdev->priv_lock, flags);
+
+       priv = stub_priv_pop_from_listhead(&sdev->priv_init);
+       if (priv)
+               goto done;
+
+       priv = stub_priv_pop_from_listhead(&sdev->priv_tx);
+       if (priv)
+               goto done;
+
+       priv = stub_priv_pop_from_listhead(&sdev->priv_free);
+
+done:
+       spin_unlock_irqrestore(&sdev->priv_lock, flags);
+
+       return priv;
+}
+
+void stub_device_cleanup_urbs(struct stub_device *sdev)
+{
+       struct stub_priv *priv;
+       struct urb *urb;
+
+       dev_dbg(&sdev->udev->dev, "free sdev %p\n", sdev);
+
+       while ((priv = stub_priv_pop(sdev))) {
+               urb = priv->urb;
+               dev_dbg(&sdev->udev->dev, "free urb %p\n", urb);
+               usb_kill_urb(urb);
+
+               kmem_cache_free(stub_priv_cache, priv);
+
+               kfree(urb->transfer_buffer);
+               kfree(urb->setup_packet);
+               usb_free_urb(urb);
+       }
+}
+
+static int __init usbip_host_init(void)
+{
+       int ret;
+
+       init_busid_table();
+
+       stub_priv_cache = KMEM_CACHE(stub_priv, SLAB_HWCACHE_ALIGN);
+       if (!stub_priv_cache) {
+               pr_err("kmem_cache_create failed\n");
+               return -ENOMEM;
+       }
+
+       ret = usb_register_device_driver(&stub_driver, THIS_MODULE);
+       if (ret) {
+               pr_err("usb_register failed %d\n", ret);
+               goto err_usb_register;
+       }
+
+       ret = driver_create_file(&stub_driver.drvwrap.driver,
+                                &driver_attr_match_busid);
+       if (ret) {
+               pr_err("driver_create_file failed\n");
+               goto err_create_file;
+       }
+
+       ret = driver_create_file(&stub_driver.drvwrap.driver,
+                                &driver_attr_rebind);
+       if (ret) {
+               pr_err("driver_create_file failed\n");
+               goto err_create_file;
+       }
+
+       pr_info(DRIVER_DESC " v" USBIP_VERSION "\n");
+       return ret;
+
+err_create_file:
+       usb_deregister_device_driver(&stub_driver);
+err_usb_register:
+       kmem_cache_destroy(stub_priv_cache);
+       return ret;
+}
+
+static void __exit usbip_host_exit(void)
+{
+       driver_remove_file(&stub_driver.drvwrap.driver,
+                          &driver_attr_match_busid);
+
+       driver_remove_file(&stub_driver.drvwrap.driver,
+                          &driver_attr_rebind);
+
+       /*
+        * deregister() calls stub_disconnect() for all devices. Device
+        * specific data is cleared in stub_disconnect().
+        */
+       usb_deregister_device_driver(&stub_driver);
+
+       kmem_cache_destroy(stub_priv_cache);
+}
+
+module_init(usbip_host_init);
+module_exit(usbip_host_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_VERSION(USBIP_VERSION);
diff --git a/drivers/usb/usbip/stub_rx.c b/drivers/usb/usbip/stub_rx.c
new file mode 100644 (file)
index 0000000..00e475c
--- /dev/null
@@ -0,0 +1,594 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <asm/byteorder.h>
+#include <linux/kthread.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+
+#include "usbip_common.h"
+#include "stub.h"
+
+static int is_clear_halt_cmd(struct urb *urb)
+{
+       struct usb_ctrlrequest *req;
+
+       req = (struct usb_ctrlrequest *) urb->setup_packet;
+
+        return (req->bRequest == USB_REQ_CLEAR_FEATURE) &&
+                (req->bRequestType == USB_RECIP_ENDPOINT) &&
+                (req->wValue == USB_ENDPOINT_HALT);
+}
+
+static int is_set_interface_cmd(struct urb *urb)
+{
+       struct usb_ctrlrequest *req;
+
+       req = (struct usb_ctrlrequest *) urb->setup_packet;
+
+       return (req->bRequest == USB_REQ_SET_INTERFACE) &&
+               (req->bRequestType == USB_RECIP_INTERFACE);
+}
+
+static int is_set_configuration_cmd(struct urb *urb)
+{
+       struct usb_ctrlrequest *req;
+
+       req = (struct usb_ctrlrequest *) urb->setup_packet;
+
+       return (req->bRequest == USB_REQ_SET_CONFIGURATION) &&
+               (req->bRequestType == USB_RECIP_DEVICE);
+}
+
+static int is_reset_device_cmd(struct urb *urb)
+{
+       struct usb_ctrlrequest *req;
+       __u16 value;
+       __u16 index;
+
+       req = (struct usb_ctrlrequest *) urb->setup_packet;
+       value = le16_to_cpu(req->wValue);
+       index = le16_to_cpu(req->wIndex);
+
+       if ((req->bRequest == USB_REQ_SET_FEATURE) &&
+           (req->bRequestType == USB_RT_PORT) &&
+           (value == USB_PORT_FEAT_RESET)) {
+               usbip_dbg_stub_rx("reset_device_cmd, port %u\n", index);
+               return 1;
+       } else
+               return 0;
+}
+
+static int tweak_clear_halt_cmd(struct urb *urb)
+{
+       struct usb_ctrlrequest *req;
+       int target_endp;
+       int target_dir;
+       int target_pipe;
+       int ret;
+
+       req = (struct usb_ctrlrequest *) urb->setup_packet;
+
+       /*
+        * The stalled endpoint is specified in the wIndex value. The endpoint
+        * of the urb is the target of this clear_halt request (i.e., control
+        * endpoint).
+        */
+       target_endp = le16_to_cpu(req->wIndex) & 0x000f;
+
+       /* the stalled endpoint direction is IN or OUT?. USB_DIR_IN is 0x80.  */
+       target_dir = le16_to_cpu(req->wIndex) & 0x0080;
+
+       if (target_dir)
+               target_pipe = usb_rcvctrlpipe(urb->dev, target_endp);
+       else
+               target_pipe = usb_sndctrlpipe(urb->dev, target_endp);
+
+       ret = usb_clear_halt(urb->dev, target_pipe);
+       if (ret < 0)
+               dev_err(&urb->dev->dev,
+                       "usb_clear_halt error: devnum %d endp %d ret %d\n",
+                       urb->dev->devnum, target_endp, ret);
+       else
+               dev_info(&urb->dev->dev,
+                        "usb_clear_halt done: devnum %d endp %d\n",
+                        urb->dev->devnum, target_endp);
+
+       return ret;
+}
+
+static int tweak_set_interface_cmd(struct urb *urb)
+{
+       struct usb_ctrlrequest *req;
+       __u16 alternate;
+       __u16 interface;
+       int ret;
+
+       req = (struct usb_ctrlrequest *) urb->setup_packet;
+       alternate = le16_to_cpu(req->wValue);
+       interface = le16_to_cpu(req->wIndex);
+
+       usbip_dbg_stub_rx("set_interface: inf %u alt %u\n",
+                         interface, alternate);
+
+       ret = usb_set_interface(urb->dev, interface, alternate);
+       if (ret < 0)
+               dev_err(&urb->dev->dev,
+                       "usb_set_interface error: inf %u alt %u ret %d\n",
+                       interface, alternate, ret);
+       else
+               dev_info(&urb->dev->dev,
+                       "usb_set_interface done: inf %u alt %u\n",
+                       interface, alternate);
+
+       return ret;
+}
+
+static int tweak_set_configuration_cmd(struct urb *urb)
+{
+       struct stub_priv *priv = (struct stub_priv *) urb->context;
+       struct stub_device *sdev = priv->sdev;
+       struct usb_ctrlrequest *req;
+       __u16 config;
+       int err;
+
+       req = (struct usb_ctrlrequest *) urb->setup_packet;
+       config = le16_to_cpu(req->wValue);
+
+       err = usb_set_configuration(sdev->udev, config);
+       if (err && err != -ENODEV)
+               dev_err(&sdev->udev->dev, "can't set config #%d, error %d\n",
+                       config, err);
+       return 0;
+}
+
+static int tweak_reset_device_cmd(struct urb *urb)
+{
+       struct stub_priv *priv = (struct stub_priv *) urb->context;
+       struct stub_device *sdev = priv->sdev;
+
+       dev_info(&urb->dev->dev, "usb_queue_reset_device\n");
+
+       /*
+        * With the implementation of pre_reset and post_reset the driver no
+        * longer unbinds. This allows the use of synchronous reset.
+        */
+
+       if (usb_lock_device_for_reset(sdev->udev, sdev->interface) < 0) {
+               dev_err(&urb->dev->dev, "could not obtain lock to reset device\n");
+               return 0;
+       }
+       usb_reset_device(sdev->udev);
+       usb_unlock_device(sdev->udev);
+
+       return 0;
+}
+
+/*
+ * clear_halt, set_interface, and set_configuration require special tricks.
+ */
+static void tweak_special_requests(struct urb *urb)
+{
+       if (!urb || !urb->setup_packet)
+               return;
+
+       if (usb_pipetype(urb->pipe) != PIPE_CONTROL)
+               return;
+
+       if (is_clear_halt_cmd(urb))
+               /* tweak clear_halt */
+                tweak_clear_halt_cmd(urb);
+
+       else if (is_set_interface_cmd(urb))
+               /* tweak set_interface */
+               tweak_set_interface_cmd(urb);
+
+       else if (is_set_configuration_cmd(urb))
+               /* tweak set_configuration */
+               tweak_set_configuration_cmd(urb);
+
+       else if (is_reset_device_cmd(urb))
+               tweak_reset_device_cmd(urb);
+       else
+               usbip_dbg_stub_rx("no need to tweak\n");
+}
+
+/*
+ * stub_recv_unlink() unlinks the URB by a call to usb_unlink_urb().
+ * By unlinking the urb asynchronously, stub_rx can continuously
+ * process coming urbs.  Even if the urb is unlinked, its completion
+ * handler will be called and stub_tx will send a return pdu.
+ *
+ * See also comments about unlinking strategy in vhci_hcd.c.
+ */
+static int stub_recv_cmd_unlink(struct stub_device *sdev,
+                               struct usbip_header *pdu)
+{
+       int ret;
+       unsigned long flags;
+       struct stub_priv *priv;
+
+       spin_lock_irqsave(&sdev->priv_lock, flags);
+
+       list_for_each_entry(priv, &sdev->priv_init, list) {
+               if (priv->seqnum != pdu->u.cmd_unlink.seqnum)
+                       continue;
+
+               dev_info(&priv->urb->dev->dev, "unlink urb %p\n",
+                        priv->urb);
+
+               /*
+                * This matched urb is not completed yet (i.e., be in
+                * flight in usb hcd hardware/driver). Now we are
+                * cancelling it. The unlinking flag means that we are
+                * now not going to return the normal result pdu of a
+                * submission request, but going to return a result pdu
+                * of the unlink request.
+                */
+               priv->unlinking = 1;
+
+               /*
+                * In the case that unlinking flag is on, prev->seqnum
+                * is changed from the seqnum of the cancelling urb to
+                * the seqnum of the unlink request. This will be used
+                * to make the result pdu of the unlink request.
+                */
+               priv->seqnum = pdu->base.seqnum;
+
+               spin_unlock_irqrestore(&sdev->priv_lock, flags);
+
+               /*
+                * usb_unlink_urb() is now out of spinlocking to avoid
+                * spinlock recursion since stub_complete() is
+                * sometimes called in this context but not in the
+                * interrupt context.  If stub_complete() is executed
+                * before we call usb_unlink_urb(), usb_unlink_urb()
+                * will return an error value. In this case, stub_tx
+                * will return the result pdu of this unlink request
+                * though submission is completed and actual unlinking
+                * is not executed. OK?
+                */
+               /* In the above case, urb->status is not -ECONNRESET,
+                * so a driver in a client host will know the failure
+                * of the unlink request ?
+                */
+               ret = usb_unlink_urb(priv->urb);
+               if (ret != -EINPROGRESS)
+                       dev_err(&priv->urb->dev->dev,
+                               "failed to unlink a urb %p, ret %d\n",
+                               priv->urb, ret);
+
+               return 0;
+       }
+
+       usbip_dbg_stub_rx("seqnum %d is not pending\n",
+                         pdu->u.cmd_unlink.seqnum);
+
+       /*
+        * The urb of the unlink target is not found in priv_init queue. It was
+        * already completed and its results is/was going to be sent by a
+        * CMD_RET pdu. In this case, usb_unlink_urb() is not needed. We only
+        * return the completeness of this unlink request to vhci_hcd.
+        */
+       stub_enqueue_ret_unlink(sdev, pdu->base.seqnum, 0);
+
+       spin_unlock_irqrestore(&sdev->priv_lock, flags);
+
+       return 0;
+}
+
+static int valid_request(struct stub_device *sdev, struct usbip_header *pdu)
+{
+       struct usbip_device *ud = &sdev->ud;
+       int valid = 0;
+
+       if (pdu->base.devid == sdev->devid) {
+               spin_lock_irq(&ud->lock);
+               if (ud->status == SDEV_ST_USED) {
+                       /* A request is valid. */
+                       valid = 1;
+               }
+               spin_unlock_irq(&ud->lock);
+       }
+
+       return valid;
+}
+
+static struct stub_priv *stub_priv_alloc(struct stub_device *sdev,
+                                        struct usbip_header *pdu)
+{
+       struct stub_priv *priv;
+       struct usbip_device *ud = &sdev->ud;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sdev->priv_lock, flags);
+
+       priv = kmem_cache_zalloc(stub_priv_cache, GFP_ATOMIC);
+       if (!priv) {
+               dev_err(&sdev->interface->dev, "alloc stub_priv\n");
+               spin_unlock_irqrestore(&sdev->priv_lock, flags);
+               usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC);
+               return NULL;
+       }
+
+       priv->seqnum = pdu->base.seqnum;
+       priv->sdev = sdev;
+
+       /*
+        * After a stub_priv is linked to a list_head,
+        * our error handler can free allocated data.
+        */
+       list_add_tail(&priv->list, &sdev->priv_init);
+
+       spin_unlock_irqrestore(&sdev->priv_lock, flags);
+
+       return priv;
+}
+
+static int get_pipe(struct stub_device *sdev, int epnum, int dir)
+{
+       struct usb_device *udev = sdev->udev;
+       struct usb_host_endpoint *ep;
+       struct usb_endpoint_descriptor *epd = NULL;
+
+       if (dir == USBIP_DIR_IN)
+               ep = udev->ep_in[epnum & 0x7f];
+       else
+               ep = udev->ep_out[epnum & 0x7f];
+       if (!ep) {
+               dev_err(&sdev->interface->dev, "no such endpoint?, %d\n",
+                       epnum);
+               BUG();
+       }
+
+       epd = &ep->desc;
+       if (usb_endpoint_xfer_control(epd)) {
+               if (dir == USBIP_DIR_OUT)
+                       return usb_sndctrlpipe(udev, epnum);
+               else
+                       return usb_rcvctrlpipe(udev, epnum);
+       }
+
+       if (usb_endpoint_xfer_bulk(epd)) {
+               if (dir == USBIP_DIR_OUT)
+                       return usb_sndbulkpipe(udev, epnum);
+               else
+                       return usb_rcvbulkpipe(udev, epnum);
+       }
+
+       if (usb_endpoint_xfer_int(epd)) {
+               if (dir == USBIP_DIR_OUT)
+                       return usb_sndintpipe(udev, epnum);
+               else
+                       return usb_rcvintpipe(udev, epnum);
+       }
+
+       if (usb_endpoint_xfer_isoc(epd)) {
+               if (dir == USBIP_DIR_OUT)
+                       return usb_sndisocpipe(udev, epnum);
+               else
+                       return usb_rcvisocpipe(udev, epnum);
+       }
+
+       /* NOT REACHED */
+       dev_err(&sdev->interface->dev, "get pipe, epnum %d\n", epnum);
+       return 0;
+}
+
+static void masking_bogus_flags(struct urb *urb)
+{
+       int                             xfertype;
+       struct usb_device               *dev;
+       struct usb_host_endpoint        *ep;
+       int                             is_out;
+       unsigned int    allowed;
+
+       if (!urb || urb->hcpriv || !urb->complete)
+               return;
+       dev = urb->dev;
+       if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED))
+               return;
+
+       ep = (usb_pipein(urb->pipe) ? dev->ep_in : dev->ep_out)
+               [usb_pipeendpoint(urb->pipe)];
+       if (!ep)
+               return;
+
+       xfertype = usb_endpoint_type(&ep->desc);
+       if (xfertype == USB_ENDPOINT_XFER_CONTROL) {
+               struct usb_ctrlrequest *setup =
+                       (struct usb_ctrlrequest *) urb->setup_packet;
+
+               if (!setup)
+                       return;
+               is_out = !(setup->bRequestType & USB_DIR_IN) ||
+                       !setup->wLength;
+       } else {
+               is_out = usb_endpoint_dir_out(&ep->desc);
+       }
+
+       /* enforce simple/standard policy */
+       allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_INTERRUPT |
+                  URB_DIR_MASK | URB_FREE_BUFFER);
+       switch (xfertype) {
+       case USB_ENDPOINT_XFER_BULK:
+               if (is_out)
+                       allowed |= URB_ZERO_PACKET;
+               /* FALLTHROUGH */
+       case USB_ENDPOINT_XFER_CONTROL:
+               allowed |= URB_NO_FSBR; /* only affects UHCI */
+               /* FALLTHROUGH */
+       default:                        /* all non-iso endpoints */
+               if (!is_out)
+                       allowed |= URB_SHORT_NOT_OK;
+               break;
+       case USB_ENDPOINT_XFER_ISOC:
+               allowed |= URB_ISO_ASAP;
+               break;
+       }
+       urb->transfer_flags &= allowed;
+}
+
+static void stub_recv_cmd_submit(struct stub_device *sdev,
+                                struct usbip_header *pdu)
+{
+       int ret;
+       struct stub_priv *priv;
+       struct usbip_device *ud = &sdev->ud;
+       struct usb_device *udev = sdev->udev;
+       int pipe = get_pipe(sdev, pdu->base.ep, pdu->base.direction);
+
+       priv = stub_priv_alloc(sdev, pdu);
+       if (!priv)
+               return;
+
+       /* setup a urb */
+       if (usb_pipeisoc(pipe))
+               priv->urb = usb_alloc_urb(pdu->u.cmd_submit.number_of_packets,
+                                         GFP_KERNEL);
+       else
+               priv->urb = usb_alloc_urb(0, GFP_KERNEL);
+
+       if (!priv->urb) {
+               dev_err(&sdev->interface->dev, "malloc urb\n");
+               usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC);
+               return;
+       }
+
+       /* allocate urb transfer buffer, if needed */
+       if (pdu->u.cmd_submit.transfer_buffer_length > 0) {
+               priv->urb->transfer_buffer =
+                       kzalloc(pdu->u.cmd_submit.transfer_buffer_length,
+                               GFP_KERNEL);
+               if (!priv->urb->transfer_buffer) {
+                       usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC);
+                       return;
+               }
+       }
+
+       /* copy urb setup packet */
+       priv->urb->setup_packet = kmemdup(&pdu->u.cmd_submit.setup, 8,
+                                         GFP_KERNEL);
+       if (!priv->urb->setup_packet) {
+               dev_err(&sdev->interface->dev, "allocate setup_packet\n");
+               usbip_event_add(ud, SDEV_EVENT_ERROR_MALLOC);
+               return;
+       }
+
+       /* set other members from the base header of pdu */
+       priv->urb->context                = (void *) priv;
+       priv->urb->dev                    = udev;
+       priv->urb->pipe                   = pipe;
+       priv->urb->complete               = stub_complete;
+
+       usbip_pack_pdu(pdu, priv->urb, USBIP_CMD_SUBMIT, 0);
+
+
+       if (usbip_recv_xbuff(ud, priv->urb) < 0)
+               return;
+
+       if (usbip_recv_iso(ud, priv->urb) < 0)
+               return;
+
+       /* no need to submit an intercepted request, but harmless? */
+       tweak_special_requests(priv->urb);
+
+       masking_bogus_flags(priv->urb);
+       /* urb is now ready to submit */
+       ret = usb_submit_urb(priv->urb, GFP_KERNEL);
+
+       if (ret == 0)
+               usbip_dbg_stub_rx("submit urb ok, seqnum %u\n",
+                                 pdu->base.seqnum);
+       else {
+               dev_err(&sdev->interface->dev, "submit_urb error, %d\n", ret);
+               usbip_dump_header(pdu);
+               usbip_dump_urb(priv->urb);
+
+               /*
+                * Pessimistic.
+                * This connection will be discarded.
+                */
+               usbip_event_add(ud, SDEV_EVENT_ERROR_SUBMIT);
+       }
+
+       usbip_dbg_stub_rx("Leave\n");
+}
+
+/* recv a pdu */
+static void stub_rx_pdu(struct usbip_device *ud)
+{
+       int ret;
+       struct usbip_header pdu;
+       struct stub_device *sdev = container_of(ud, struct stub_device, ud);
+       struct device *dev = &sdev->udev->dev;
+
+       usbip_dbg_stub_rx("Enter\n");
+
+       memset(&pdu, 0, sizeof(pdu));
+
+       /* receive a pdu header */
+       ret = usbip_recv(ud->tcp_socket, &pdu, sizeof(pdu));
+       if (ret != sizeof(pdu)) {
+               dev_err(dev, "recv a header, %d\n", ret);
+               usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
+               return;
+       }
+
+       usbip_header_correct_endian(&pdu, 0);
+
+       if (usbip_dbg_flag_stub_rx)
+               usbip_dump_header(&pdu);
+
+       if (!valid_request(sdev, &pdu)) {
+               dev_err(dev, "recv invalid request\n");
+               usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
+               return;
+       }
+
+       switch (pdu.base.command) {
+       case USBIP_CMD_UNLINK:
+               stub_recv_cmd_unlink(sdev, &pdu);
+               break;
+
+       case USBIP_CMD_SUBMIT:
+               stub_recv_cmd_submit(sdev, &pdu);
+               break;
+
+       default:
+               /* NOTREACHED */
+               dev_err(dev, "unknown pdu\n");
+               usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
+               break;
+       }
+}
+
+int stub_rx_loop(void *data)
+{
+       struct usbip_device *ud = data;
+
+       while (!kthread_should_stop()) {
+               if (usbip_event_happened(ud))
+                       break;
+
+               stub_rx_pdu(ud);
+       }
+
+       return 0;
+}
diff --git a/drivers/usb/usbip/stub_tx.c b/drivers/usb/usbip/stub_tx.c
new file mode 100644 (file)
index 0000000..dbcabc9
--- /dev/null
@@ -0,0 +1,398 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <linux/kthread.h>
+#include <linux/socket.h>
+
+#include "usbip_common.h"
+#include "stub.h"
+
+static void stub_free_priv_and_urb(struct stub_priv *priv)
+{
+       struct urb *urb = priv->urb;
+
+       kfree(urb->setup_packet);
+       kfree(urb->transfer_buffer);
+       list_del(&priv->list);
+       kmem_cache_free(stub_priv_cache, priv);
+       usb_free_urb(urb);
+}
+
+/* be in spin_lock_irqsave(&sdev->priv_lock, flags) */
+void stub_enqueue_ret_unlink(struct stub_device *sdev, __u32 seqnum,
+                            __u32 status)
+{
+       struct stub_unlink *unlink;
+
+       unlink = kzalloc(sizeof(struct stub_unlink), GFP_ATOMIC);
+       if (!unlink) {
+               usbip_event_add(&sdev->ud, VDEV_EVENT_ERROR_MALLOC);
+               return;
+       }
+
+       unlink->seqnum = seqnum;
+       unlink->status = status;
+
+       list_add_tail(&unlink->list, &sdev->unlink_tx);
+}
+
+/**
+ * stub_complete - completion handler of a usbip urb
+ * @urb: pointer to the urb completed
+ *
+ * When a urb has completed, the USB core driver calls this function mostly in
+ * the interrupt context. To return the result of a urb, the completed urb is
+ * linked to the pending list of returning.
+ *
+ */
+void stub_complete(struct urb *urb)
+{
+       struct stub_priv *priv = (struct stub_priv *) urb->context;
+       struct stub_device *sdev = priv->sdev;
+       unsigned long flags;
+
+       usbip_dbg_stub_tx("complete! status %d\n", urb->status);
+
+       switch (urb->status) {
+       case 0:
+               /* OK */
+               break;
+       case -ENOENT:
+               dev_info(&urb->dev->dev,
+                        "stopped by a call to usb_kill_urb() because of cleaning up a virtual connection\n");
+               return;
+       case -ECONNRESET:
+               dev_info(&urb->dev->dev,
+                        "unlinked by a call to usb_unlink_urb()\n");
+               break;
+       case -EPIPE:
+               dev_info(&urb->dev->dev, "endpoint %d is stalled\n",
+                        usb_pipeendpoint(urb->pipe));
+               break;
+       case -ESHUTDOWN:
+               dev_info(&urb->dev->dev, "device removed?\n");
+               break;
+       default:
+               dev_info(&urb->dev->dev,
+                        "urb completion with non-zero status %d\n",
+                        urb->status);
+               break;
+       }
+
+       /* link a urb to the queue of tx. */
+       spin_lock_irqsave(&sdev->priv_lock, flags);
+       if (priv->unlinking) {
+               stub_enqueue_ret_unlink(sdev, priv->seqnum, urb->status);
+               stub_free_priv_and_urb(priv);
+       } else {
+               list_move_tail(&priv->list, &sdev->priv_tx);
+       }
+       spin_unlock_irqrestore(&sdev->priv_lock, flags);
+
+       /* wake up tx_thread */
+       wake_up(&sdev->tx_waitq);
+}
+
+static inline void setup_base_pdu(struct usbip_header_basic *base,
+                                 __u32 command, __u32 seqnum)
+{
+       base->command   = command;
+       base->seqnum    = seqnum;
+       base->devid     = 0;
+       base->ep        = 0;
+       base->direction = 0;
+}
+
+static void setup_ret_submit_pdu(struct usbip_header *rpdu, struct urb *urb)
+{
+       struct stub_priv *priv = (struct stub_priv *) urb->context;
+
+       setup_base_pdu(&rpdu->base, USBIP_RET_SUBMIT, priv->seqnum);
+       usbip_pack_pdu(rpdu, urb, USBIP_RET_SUBMIT, 1);
+}
+
+static void setup_ret_unlink_pdu(struct usbip_header *rpdu,
+                                struct stub_unlink *unlink)
+{
+       setup_base_pdu(&rpdu->base, USBIP_RET_UNLINK, unlink->seqnum);
+       rpdu->u.ret_unlink.status = unlink->status;
+}
+
+static struct stub_priv *dequeue_from_priv_tx(struct stub_device *sdev)
+{
+       unsigned long flags;
+       struct stub_priv *priv, *tmp;
+
+       spin_lock_irqsave(&sdev->priv_lock, flags);
+
+       list_for_each_entry_safe(priv, tmp, &sdev->priv_tx, list) {
+               list_move_tail(&priv->list, &sdev->priv_free);
+               spin_unlock_irqrestore(&sdev->priv_lock, flags);
+               return priv;
+       }
+
+       spin_unlock_irqrestore(&sdev->priv_lock, flags);
+
+       return NULL;
+}
+
+static int stub_send_ret_submit(struct stub_device *sdev)
+{
+       unsigned long flags;
+       struct stub_priv *priv, *tmp;
+
+       struct msghdr msg;
+       size_t txsize;
+
+       size_t total_size = 0;
+
+       while ((priv = dequeue_from_priv_tx(sdev)) != NULL) {
+               int ret;
+               struct urb *urb = priv->urb;
+               struct usbip_header pdu_header;
+               struct usbip_iso_packet_descriptor *iso_buffer = NULL;
+               struct kvec *iov = NULL;
+               int iovnum = 0;
+
+               txsize = 0;
+               memset(&pdu_header, 0, sizeof(pdu_header));
+               memset(&msg, 0, sizeof(msg));
+
+               if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
+                       iovnum = 2 + urb->number_of_packets;
+               else
+                       iovnum = 2;
+
+               iov = kcalloc(iovnum, sizeof(struct kvec), GFP_KERNEL);
+
+               if (!iov) {
+                       usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_MALLOC);
+                       return -1;
+               }
+
+               iovnum = 0;
+
+               /* 1. setup usbip_header */
+               setup_ret_submit_pdu(&pdu_header, urb);
+               usbip_dbg_stub_tx("setup txdata seqnum: %d urb: %p\n",
+                                 pdu_header.base.seqnum, urb);
+               usbip_header_correct_endian(&pdu_header, 1);
+
+               iov[iovnum].iov_base = &pdu_header;
+               iov[iovnum].iov_len  = sizeof(pdu_header);
+               iovnum++;
+               txsize += sizeof(pdu_header);
+
+               /* 2. setup transfer buffer */
+               if (usb_pipein(urb->pipe) &&
+                   usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS &&
+                   urb->actual_length > 0) {
+                       iov[iovnum].iov_base = urb->transfer_buffer;
+                       iov[iovnum].iov_len  = urb->actual_length;
+                       iovnum++;
+                       txsize += urb->actual_length;
+               } else if (usb_pipein(urb->pipe) &&
+                          usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+                       /*
+                        * For isochronous packets: actual length is the sum of
+                        * the actual length of the individual, packets, but as
+                        * the packet offsets are not changed there will be
+                        * padding between the packets. To optimally use the
+                        * bandwidth the padding is not transmitted.
+                        */
+
+                       int i;
+
+                       for (i = 0; i < urb->number_of_packets; i++) {
+                               iov[iovnum].iov_base = urb->transfer_buffer +
+                                       urb->iso_frame_desc[i].offset;
+                               iov[iovnum].iov_len =
+                                       urb->iso_frame_desc[i].actual_length;
+                               iovnum++;
+                               txsize += urb->iso_frame_desc[i].actual_length;
+                       }
+
+                       if (txsize != sizeof(pdu_header) + urb->actual_length) {
+                               dev_err(&sdev->interface->dev,
+                                       "actual length of urb %d does not match iso packet sizes %zu\n",
+                                       urb->actual_length,
+                                       txsize-sizeof(pdu_header));
+                               kfree(iov);
+                               usbip_event_add(&sdev->ud,
+                                               SDEV_EVENT_ERROR_TCP);
+                          return -1;
+                       }
+               }
+
+               /* 3. setup iso_packet_descriptor */
+               if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+                       ssize_t len = 0;
+
+                       iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len);
+                       if (!iso_buffer) {
+                               usbip_event_add(&sdev->ud,
+                                               SDEV_EVENT_ERROR_MALLOC);
+                               kfree(iov);
+                               return -1;
+                       }
+
+                       iov[iovnum].iov_base = iso_buffer;
+                       iov[iovnum].iov_len  = len;
+                       txsize += len;
+                       iovnum++;
+               }
+
+               ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg,
+                                               iov,  iovnum, txsize);
+               if (ret != txsize) {
+                       dev_err(&sdev->interface->dev,
+                               "sendmsg failed!, retval %d for %zd\n",
+                               ret, txsize);
+                       kfree(iov);
+                       kfree(iso_buffer);
+                       usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP);
+                       return -1;
+               }
+
+               kfree(iov);
+               kfree(iso_buffer);
+
+               total_size += txsize;
+       }
+
+       spin_lock_irqsave(&sdev->priv_lock, flags);
+       list_for_each_entry_safe(priv, tmp, &sdev->priv_free, list) {
+               stub_free_priv_and_urb(priv);
+       }
+       spin_unlock_irqrestore(&sdev->priv_lock, flags);
+
+       return total_size;
+}
+
+static struct stub_unlink *dequeue_from_unlink_tx(struct stub_device *sdev)
+{
+       unsigned long flags;
+       struct stub_unlink *unlink, *tmp;
+
+       spin_lock_irqsave(&sdev->priv_lock, flags);
+
+       list_for_each_entry_safe(unlink, tmp, &sdev->unlink_tx, list) {
+               list_move_tail(&unlink->list, &sdev->unlink_free);
+               spin_unlock_irqrestore(&sdev->priv_lock, flags);
+               return unlink;
+       }
+
+       spin_unlock_irqrestore(&sdev->priv_lock, flags);
+
+       return NULL;
+}
+
+static int stub_send_ret_unlink(struct stub_device *sdev)
+{
+       unsigned long flags;
+       struct stub_unlink *unlink, *tmp;
+
+       struct msghdr msg;
+       struct kvec iov[1];
+       size_t txsize;
+
+       size_t total_size = 0;
+
+       while ((unlink = dequeue_from_unlink_tx(sdev)) != NULL) {
+               int ret;
+               struct usbip_header pdu_header;
+
+               txsize = 0;
+               memset(&pdu_header, 0, sizeof(pdu_header));
+               memset(&msg, 0, sizeof(msg));
+               memset(&iov, 0, sizeof(iov));
+
+               usbip_dbg_stub_tx("setup ret unlink %lu\n", unlink->seqnum);
+
+               /* 1. setup usbip_header */
+               setup_ret_unlink_pdu(&pdu_header, unlink);
+               usbip_header_correct_endian(&pdu_header, 1);
+
+               iov[0].iov_base = &pdu_header;
+               iov[0].iov_len  = sizeof(pdu_header);
+               txsize += sizeof(pdu_header);
+
+               ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov,
+                                    1, txsize);
+               if (ret != txsize) {
+                       dev_err(&sdev->interface->dev,
+                               "sendmsg failed!, retval %d for %zd\n",
+                               ret, txsize);
+                       usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP);
+                       return -1;
+               }
+
+               usbip_dbg_stub_tx("send txdata\n");
+               total_size += txsize;
+       }
+
+       spin_lock_irqsave(&sdev->priv_lock, flags);
+
+       list_for_each_entry_safe(unlink, tmp, &sdev->unlink_free, list) {
+               list_del(&unlink->list);
+               kfree(unlink);
+       }
+
+       spin_unlock_irqrestore(&sdev->priv_lock, flags);
+
+       return total_size;
+}
+
+int stub_tx_loop(void *data)
+{
+       struct usbip_device *ud = data;
+       struct stub_device *sdev = container_of(ud, struct stub_device, ud);
+
+       while (!kthread_should_stop()) {
+               if (usbip_event_happened(ud))
+                       break;
+
+               /*
+                * send_ret_submit comes earlier than send_ret_unlink.  stub_rx
+                * looks at only priv_init queue. If the completion of a URB is
+                * earlier than the receive of CMD_UNLINK, priv is moved to
+                * priv_tx queue and stub_rx does not find the target priv. In
+                * this case, vhci_rx receives the result of the submit request
+                * and then receives the result of the unlink request. The
+                * result of the submit is given back to the usbcore as the
+                * completion of the unlink request. The request of the
+                * unlink is ignored. This is ok because a driver who calls
+                * usb_unlink_urb() understands the unlink was too late by
+                * getting the status of the given-backed URB which has the
+                * status of usb_submit_urb().
+                */
+               if (stub_send_ret_submit(sdev) < 0)
+                       break;
+
+               if (stub_send_ret_unlink(sdev) < 0)
+                       break;
+
+               wait_event_interruptible(sdev->tx_waitq,
+                                        (!list_empty(&sdev->priv_tx) ||
+                                         !list_empty(&sdev->unlink_tx) ||
+                                         kthread_should_stop()));
+       }
+
+       return 0;
+}
diff --git a/drivers/usb/usbip/usbip_common.c b/drivers/usb/usbip/usbip_common.c
new file mode 100644 (file)
index 0000000..facaaf0
--- /dev/null
@@ -0,0 +1,776 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <asm/byteorder.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <net/sock.h>
+
+#include "usbip_common.h"
+
+#define DRIVER_AUTHOR "Takahiro Hirofuchi <hirofuchi@users.sourceforge.net>"
+#define DRIVER_DESC "USB/IP Core"
+
+#ifdef CONFIG_USBIP_DEBUG
+unsigned long usbip_debug_flag = 0xffffffff;
+#else
+unsigned long usbip_debug_flag;
+#endif
+EXPORT_SYMBOL_GPL(usbip_debug_flag);
+module_param(usbip_debug_flag, ulong, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(usbip_debug_flag, "debug flags (defined in usbip_common.h)");
+
+/* FIXME */
+struct device_attribute dev_attr_usbip_debug;
+EXPORT_SYMBOL_GPL(dev_attr_usbip_debug);
+
+static ssize_t usbip_debug_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%lx\n", usbip_debug_flag);
+}
+
+static ssize_t usbip_debug_store(struct device *dev,
+                                struct device_attribute *attr, const char *buf,
+                                size_t count)
+{
+       if (sscanf(buf, "%lx", &usbip_debug_flag) != 1)
+               return -EINVAL;
+       return count;
+}
+DEVICE_ATTR_RW(usbip_debug);
+
+static void usbip_dump_buffer(char *buff, int bufflen)
+{
+       print_hex_dump(KERN_DEBUG, "usbip-core", DUMP_PREFIX_OFFSET, 16, 4,
+                      buff, bufflen, false);
+}
+
+static void usbip_dump_pipe(unsigned int p)
+{
+       unsigned char type = usb_pipetype(p);
+       unsigned char ep   = usb_pipeendpoint(p);
+       unsigned char dev  = usb_pipedevice(p);
+       unsigned char dir  = usb_pipein(p);
+
+       pr_debug("dev(%d) ep(%d) [%s] ", dev, ep, dir ? "IN" : "OUT");
+
+       switch (type) {
+       case PIPE_ISOCHRONOUS:
+               pr_debug("ISO\n");
+               break;
+       case PIPE_INTERRUPT:
+               pr_debug("INT\n");
+               break;
+       case PIPE_CONTROL:
+               pr_debug("CTRL\n");
+               break;
+       case PIPE_BULK:
+               pr_debug("BULK\n");
+               break;
+       default:
+               pr_debug("ERR\n");
+               break;
+       }
+}
+
+static void usbip_dump_usb_device(struct usb_device *udev)
+{
+       struct device *dev = &udev->dev;
+       int i;
+
+       dev_dbg(dev, "       devnum(%d) devpath(%s) usb speed(%s)",
+               udev->devnum, udev->devpath, usb_speed_string(udev->speed));
+
+       pr_debug("tt %p, ttport %d\n", udev->tt, udev->ttport);
+
+       dev_dbg(dev, "                    ");
+       for (i = 0; i < 16; i++)
+               pr_debug(" %2u", i);
+       pr_debug("\n");
+
+       dev_dbg(dev, "       toggle0(IN) :");
+       for (i = 0; i < 16; i++)
+               pr_debug(" %2u", (udev->toggle[0] & (1 << i)) ? 1 : 0);
+       pr_debug("\n");
+
+       dev_dbg(dev, "       toggle1(OUT):");
+       for (i = 0; i < 16; i++)
+               pr_debug(" %2u", (udev->toggle[1] & (1 << i)) ? 1 : 0);
+       pr_debug("\n");
+
+       dev_dbg(dev, "       epmaxp_in   :");
+       for (i = 0; i < 16; i++) {
+               if (udev->ep_in[i])
+                       pr_debug(" %2u",
+                           le16_to_cpu(udev->ep_in[i]->desc.wMaxPacketSize));
+       }
+       pr_debug("\n");
+
+       dev_dbg(dev, "       epmaxp_out  :");
+       for (i = 0; i < 16; i++) {
+               if (udev->ep_out[i])
+                       pr_debug(" %2u",
+                           le16_to_cpu(udev->ep_out[i]->desc.wMaxPacketSize));
+       }
+       pr_debug("\n");
+
+       dev_dbg(dev, "parent %p, bus %p\n", udev->parent, udev->bus);
+
+       dev_dbg(dev,
+               "descriptor %p, config %p, actconfig %p, rawdescriptors %p\n",
+               &udev->descriptor, udev->config,
+               udev->actconfig, udev->rawdescriptors);
+
+       dev_dbg(dev, "have_langid %d, string_langid %d\n",
+               udev->have_langid, udev->string_langid);
+
+       dev_dbg(dev, "maxchild %d\n", udev->maxchild);
+}
+
+static void usbip_dump_request_type(__u8 rt)
+{
+       switch (rt & USB_RECIP_MASK) {
+       case USB_RECIP_DEVICE:
+               pr_debug("DEVICE");
+               break;
+       case USB_RECIP_INTERFACE:
+               pr_debug("INTERF");
+               break;
+       case USB_RECIP_ENDPOINT:
+               pr_debug("ENDPOI");
+               break;
+       case USB_RECIP_OTHER:
+               pr_debug("OTHER ");
+               break;
+       default:
+               pr_debug("------");
+               break;
+       }
+}
+
+static void usbip_dump_usb_ctrlrequest(struct usb_ctrlrequest *cmd)
+{
+       if (!cmd) {
+               pr_debug("       : null pointer\n");
+               return;
+       }
+
+       pr_debug("       ");
+       pr_debug("bRequestType(%02X) bRequest(%02X) wValue(%04X) wIndex(%04X) wLength(%04X) ",
+                cmd->bRequestType, cmd->bRequest,
+                cmd->wValue, cmd->wIndex, cmd->wLength);
+       pr_debug("\n       ");
+
+       if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
+               pr_debug("STANDARD ");
+               switch (cmd->bRequest) {
+               case USB_REQ_GET_STATUS:
+                       pr_debug("GET_STATUS\n");
+                       break;
+               case USB_REQ_CLEAR_FEATURE:
+                       pr_debug("CLEAR_FEAT\n");
+                       break;
+               case USB_REQ_SET_FEATURE:
+                       pr_debug("SET_FEAT\n");
+                       break;
+               case USB_REQ_SET_ADDRESS:
+                       pr_debug("SET_ADDRRS\n");
+                       break;
+               case USB_REQ_GET_DESCRIPTOR:
+                       pr_debug("GET_DESCRI\n");
+                       break;
+               case USB_REQ_SET_DESCRIPTOR:
+                       pr_debug("SET_DESCRI\n");
+                       break;
+               case USB_REQ_GET_CONFIGURATION:
+                       pr_debug("GET_CONFIG\n");
+                       break;
+               case USB_REQ_SET_CONFIGURATION:
+                       pr_debug("SET_CONFIG\n");
+                       break;
+               case USB_REQ_GET_INTERFACE:
+                       pr_debug("GET_INTERF\n");
+                       break;
+               case USB_REQ_SET_INTERFACE:
+                       pr_debug("SET_INTERF\n");
+                       break;
+               case USB_REQ_SYNCH_FRAME:
+                       pr_debug("SYNC_FRAME\n");
+                       break;
+               default:
+                       pr_debug("REQ(%02X)\n", cmd->bRequest);
+                       break;
+               }
+               usbip_dump_request_type(cmd->bRequestType);
+       } else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_CLASS) {
+               pr_debug("CLASS\n");
+       } else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_VENDOR) {
+               pr_debug("VENDOR\n");
+       } else if ((cmd->bRequestType & USB_TYPE_MASK) == USB_TYPE_RESERVED) {
+               pr_debug("RESERVED\n");
+       }
+}
+
+void usbip_dump_urb(struct urb *urb)
+{
+       struct device *dev;
+
+       if (!urb) {
+               pr_debug("urb: null pointer!!\n");
+               return;
+       }
+
+       if (!urb->dev) {
+               pr_debug("urb->dev: null pointer!!\n");
+               return;
+       }
+
+       dev = &urb->dev->dev;
+
+       dev_dbg(dev, "   urb                   :%p\n", urb);
+       dev_dbg(dev, "   dev                   :%p\n", urb->dev);
+
+       usbip_dump_usb_device(urb->dev);
+
+       dev_dbg(dev, "   pipe                  :%08x ", urb->pipe);
+
+       usbip_dump_pipe(urb->pipe);
+
+       dev_dbg(dev, "   status                :%d\n", urb->status);
+       dev_dbg(dev, "   transfer_flags        :%08X\n", urb->transfer_flags);
+       dev_dbg(dev, "   transfer_buffer       :%p\n", urb->transfer_buffer);
+       dev_dbg(dev, "   transfer_buffer_length:%d\n",
+                                               urb->transfer_buffer_length);
+       dev_dbg(dev, "   actual_length         :%d\n", urb->actual_length);
+       dev_dbg(dev, "   setup_packet          :%p\n", urb->setup_packet);
+
+       if (urb->setup_packet && usb_pipetype(urb->pipe) == PIPE_CONTROL)
+               usbip_dump_usb_ctrlrequest(
+                       (struct usb_ctrlrequest *)urb->setup_packet);
+
+       dev_dbg(dev, "   start_frame           :%d\n", urb->start_frame);
+       dev_dbg(dev, "   number_of_packets     :%d\n", urb->number_of_packets);
+       dev_dbg(dev, "   interval              :%d\n", urb->interval);
+       dev_dbg(dev, "   error_count           :%d\n", urb->error_count);
+       dev_dbg(dev, "   context               :%p\n", urb->context);
+       dev_dbg(dev, "   complete              :%p\n", urb->complete);
+}
+EXPORT_SYMBOL_GPL(usbip_dump_urb);
+
+void usbip_dump_header(struct usbip_header *pdu)
+{
+       pr_debug("BASE: cmd %u seq %u devid %u dir %u ep %u\n",
+                pdu->base.command,
+                pdu->base.seqnum,
+                pdu->base.devid,
+                pdu->base.direction,
+                pdu->base.ep);
+
+       switch (pdu->base.command) {
+       case USBIP_CMD_SUBMIT:
+               pr_debug("USBIP_CMD_SUBMIT: x_flags %u x_len %u sf %u #p %d iv %d\n",
+                        pdu->u.cmd_submit.transfer_flags,
+                        pdu->u.cmd_submit.transfer_buffer_length,
+                        pdu->u.cmd_submit.start_frame,
+                        pdu->u.cmd_submit.number_of_packets,
+                        pdu->u.cmd_submit.interval);
+               break;
+       case USBIP_CMD_UNLINK:
+               pr_debug("USBIP_CMD_UNLINK: seq %u\n",
+                        pdu->u.cmd_unlink.seqnum);
+               break;
+       case USBIP_RET_SUBMIT:
+               pr_debug("USBIP_RET_SUBMIT: st %d al %u sf %d #p %d ec %d\n",
+                        pdu->u.ret_submit.status,
+                        pdu->u.ret_submit.actual_length,
+                        pdu->u.ret_submit.start_frame,
+                        pdu->u.ret_submit.number_of_packets,
+                        pdu->u.ret_submit.error_count);
+               break;
+       case USBIP_RET_UNLINK:
+               pr_debug("USBIP_RET_UNLINK: status %d\n",
+                        pdu->u.ret_unlink.status);
+               break;
+       default:
+               /* NOT REACHED */
+               pr_err("unknown command\n");
+               break;
+       }
+}
+EXPORT_SYMBOL_GPL(usbip_dump_header);
+
+/* Receive data over TCP/IP. */
+int usbip_recv(struct socket *sock, void *buf, int size)
+{
+       int result;
+       struct msghdr msg;
+       struct kvec iov;
+       int total = 0;
+
+       /* for blocks of if (usbip_dbg_flag_xmit) */
+       char *bp = buf;
+       int osize = size;
+
+       usbip_dbg_xmit("enter\n");
+
+       if (!sock || !buf || !size) {
+               pr_err("invalid arg, sock %p buff %p size %d\n", sock, buf,
+                      size);
+               return -EINVAL;
+       }
+
+       do {
+               sock->sk->sk_allocation = GFP_NOIO;
+               iov.iov_base    = buf;
+               iov.iov_len     = size;
+               msg.msg_name    = NULL;
+               msg.msg_namelen = 0;
+               msg.msg_control = NULL;
+               msg.msg_controllen = 0;
+               msg.msg_flags      = MSG_NOSIGNAL;
+
+               result = kernel_recvmsg(sock, &msg, &iov, 1, size, MSG_WAITALL);
+               if (result <= 0) {
+                       pr_debug("receive sock %p buf %p size %u ret %d total %d\n",
+                                sock, buf, size, result, total);
+                       goto err;
+               }
+
+               size -= result;
+               buf += result;
+               total += result;
+       } while (size > 0);
+
+       if (usbip_dbg_flag_xmit) {
+               if (!in_interrupt())
+                       pr_debug("%-10s:", current->comm);
+               else
+                       pr_debug("interrupt  :");
+
+               pr_debug("receiving....\n");
+               usbip_dump_buffer(bp, osize);
+               pr_debug("received, osize %d ret %d size %d total %d\n",
+                        osize, result, size, total);
+       }
+
+       return total;
+
+err:
+       return result;
+}
+EXPORT_SYMBOL_GPL(usbip_recv);
+
+/* there may be more cases to tweak the flags. */
+static unsigned int tweak_transfer_flags(unsigned int flags)
+{
+       flags &= ~URB_NO_TRANSFER_DMA_MAP;
+       return flags;
+}
+
+static void usbip_pack_cmd_submit(struct usbip_header *pdu, struct urb *urb,
+                                 int pack)
+{
+       struct usbip_header_cmd_submit *spdu = &pdu->u.cmd_submit;
+
+       /*
+        * Some members are not still implemented in usbip. I hope this issue
+        * will be discussed when usbip is ported to other operating systems.
+        */
+       if (pack) {
+               spdu->transfer_flags =
+                       tweak_transfer_flags(urb->transfer_flags);
+               spdu->transfer_buffer_length    = urb->transfer_buffer_length;
+               spdu->start_frame               = urb->start_frame;
+               spdu->number_of_packets         = urb->number_of_packets;
+               spdu->interval                  = urb->interval;
+       } else  {
+               urb->transfer_flags         = spdu->transfer_flags;
+               urb->transfer_buffer_length = spdu->transfer_buffer_length;
+               urb->start_frame            = spdu->start_frame;
+               urb->number_of_packets      = spdu->number_of_packets;
+               urb->interval               = spdu->interval;
+       }
+}
+
+static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb,
+                                 int pack)
+{
+       struct usbip_header_ret_submit *rpdu = &pdu->u.ret_submit;
+
+       if (pack) {
+               rpdu->status            = urb->status;
+               rpdu->actual_length     = urb->actual_length;
+               rpdu->start_frame       = urb->start_frame;
+               rpdu->number_of_packets = urb->number_of_packets;
+               rpdu->error_count       = urb->error_count;
+       } else {
+               urb->status             = rpdu->status;
+               urb->actual_length      = rpdu->actual_length;
+               urb->start_frame        = rpdu->start_frame;
+               urb->number_of_packets = rpdu->number_of_packets;
+               urb->error_count        = rpdu->error_count;
+       }
+}
+
+void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd,
+                   int pack)
+{
+       switch (cmd) {
+       case USBIP_CMD_SUBMIT:
+               usbip_pack_cmd_submit(pdu, urb, pack);
+               break;
+       case USBIP_RET_SUBMIT:
+               usbip_pack_ret_submit(pdu, urb, pack);
+               break;
+       default:
+               /* NOT REACHED */
+               pr_err("unknown command\n");
+               break;
+       }
+}
+EXPORT_SYMBOL_GPL(usbip_pack_pdu);
+
+static void correct_endian_basic(struct usbip_header_basic *base, int send)
+{
+       if (send) {
+               base->command   = cpu_to_be32(base->command);
+               base->seqnum    = cpu_to_be32(base->seqnum);
+               base->devid     = cpu_to_be32(base->devid);
+               base->direction = cpu_to_be32(base->direction);
+               base->ep        = cpu_to_be32(base->ep);
+       } else {
+               base->command   = be32_to_cpu(base->command);
+               base->seqnum    = be32_to_cpu(base->seqnum);
+               base->devid     = be32_to_cpu(base->devid);
+               base->direction = be32_to_cpu(base->direction);
+               base->ep        = be32_to_cpu(base->ep);
+       }
+}
+
+static void correct_endian_cmd_submit(struct usbip_header_cmd_submit *pdu,
+                                     int send)
+{
+       if (send) {
+               pdu->transfer_flags = cpu_to_be32(pdu->transfer_flags);
+
+               cpu_to_be32s(&pdu->transfer_buffer_length);
+               cpu_to_be32s(&pdu->start_frame);
+               cpu_to_be32s(&pdu->number_of_packets);
+               cpu_to_be32s(&pdu->interval);
+       } else {
+               pdu->transfer_flags = be32_to_cpu(pdu->transfer_flags);
+
+               be32_to_cpus(&pdu->transfer_buffer_length);
+               be32_to_cpus(&pdu->start_frame);
+               be32_to_cpus(&pdu->number_of_packets);
+               be32_to_cpus(&pdu->interval);
+       }
+}
+
+static void correct_endian_ret_submit(struct usbip_header_ret_submit *pdu,
+                                     int send)
+{
+       if (send) {
+               cpu_to_be32s(&pdu->status);
+               cpu_to_be32s(&pdu->actual_length);
+               cpu_to_be32s(&pdu->start_frame);
+               cpu_to_be32s(&pdu->number_of_packets);
+               cpu_to_be32s(&pdu->error_count);
+       } else {
+               be32_to_cpus(&pdu->status);
+               be32_to_cpus(&pdu->actual_length);
+               be32_to_cpus(&pdu->start_frame);
+               be32_to_cpus(&pdu->number_of_packets);
+               be32_to_cpus(&pdu->error_count);
+       }
+}
+
+static void correct_endian_cmd_unlink(struct usbip_header_cmd_unlink *pdu,
+                                     int send)
+{
+       if (send)
+               pdu->seqnum = cpu_to_be32(pdu->seqnum);
+       else
+               pdu->seqnum = be32_to_cpu(pdu->seqnum);
+}
+
+static void correct_endian_ret_unlink(struct usbip_header_ret_unlink *pdu,
+                                     int send)
+{
+       if (send)
+               cpu_to_be32s(&pdu->status);
+       else
+               be32_to_cpus(&pdu->status);
+}
+
+void usbip_header_correct_endian(struct usbip_header *pdu, int send)
+{
+       __u32 cmd = 0;
+
+       if (send)
+               cmd = pdu->base.command;
+
+       correct_endian_basic(&pdu->base, send);
+
+       if (!send)
+               cmd = pdu->base.command;
+
+       switch (cmd) {
+       case USBIP_CMD_SUBMIT:
+               correct_endian_cmd_submit(&pdu->u.cmd_submit, send);
+               break;
+       case USBIP_RET_SUBMIT:
+               correct_endian_ret_submit(&pdu->u.ret_submit, send);
+               break;
+       case USBIP_CMD_UNLINK:
+               correct_endian_cmd_unlink(&pdu->u.cmd_unlink, send);
+               break;
+       case USBIP_RET_UNLINK:
+               correct_endian_ret_unlink(&pdu->u.ret_unlink, send);
+               break;
+       default:
+               /* NOT REACHED */
+               pr_err("unknown command\n");
+               break;
+       }
+}
+EXPORT_SYMBOL_GPL(usbip_header_correct_endian);
+
+static void usbip_iso_packet_correct_endian(
+               struct usbip_iso_packet_descriptor *iso, int send)
+{
+       /* does not need all members. but copy all simply. */
+       if (send) {
+               iso->offset     = cpu_to_be32(iso->offset);
+               iso->length     = cpu_to_be32(iso->length);
+               iso->status     = cpu_to_be32(iso->status);
+               iso->actual_length = cpu_to_be32(iso->actual_length);
+       } else {
+               iso->offset     = be32_to_cpu(iso->offset);
+               iso->length     = be32_to_cpu(iso->length);
+               iso->status     = be32_to_cpu(iso->status);
+               iso->actual_length = be32_to_cpu(iso->actual_length);
+       }
+}
+
+static void usbip_pack_iso(struct usbip_iso_packet_descriptor *iso,
+                          struct usb_iso_packet_descriptor *uiso, int pack)
+{
+       if (pack) {
+               iso->offset             = uiso->offset;
+               iso->length             = uiso->length;
+               iso->status             = uiso->status;
+               iso->actual_length      = uiso->actual_length;
+       } else {
+               uiso->offset            = iso->offset;
+               uiso->length            = iso->length;
+               uiso->status            = iso->status;
+               uiso->actual_length     = iso->actual_length;
+       }
+}
+
+/* must free buffer */
+struct usbip_iso_packet_descriptor*
+usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen)
+{
+       struct usbip_iso_packet_descriptor *iso;
+       int np = urb->number_of_packets;
+       ssize_t size = np * sizeof(*iso);
+       int i;
+
+       iso = kzalloc(size, GFP_KERNEL);
+       if (!iso)
+               return NULL;
+
+       for (i = 0; i < np; i++) {
+               usbip_pack_iso(&iso[i], &urb->iso_frame_desc[i], 1);
+               usbip_iso_packet_correct_endian(&iso[i], 1);
+       }
+
+       *bufflen = size;
+
+       return iso;
+}
+EXPORT_SYMBOL_GPL(usbip_alloc_iso_desc_pdu);
+
+/* some members of urb must be substituted before. */
+int usbip_recv_iso(struct usbip_device *ud, struct urb *urb)
+{
+       void *buff;
+       struct usbip_iso_packet_descriptor *iso;
+       int np = urb->number_of_packets;
+       int size = np * sizeof(*iso);
+       int i;
+       int ret;
+       int total_length = 0;
+
+       if (!usb_pipeisoc(urb->pipe))
+               return 0;
+
+       /* my Bluetooth dongle gets ISO URBs which are np = 0 */
+       if (np == 0)
+               return 0;
+
+       buff = kzalloc(size, GFP_KERNEL);
+       if (!buff)
+               return -ENOMEM;
+
+       ret = usbip_recv(ud->tcp_socket, buff, size);
+       if (ret != size) {
+               dev_err(&urb->dev->dev, "recv iso_frame_descriptor, %d\n",
+                       ret);
+               kfree(buff);
+
+               if (ud->side == USBIP_STUB)
+                       usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
+               else
+                       usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
+
+               return -EPIPE;
+       }
+
+       iso = (struct usbip_iso_packet_descriptor *) buff;
+       for (i = 0; i < np; i++) {
+               usbip_iso_packet_correct_endian(&iso[i], 0);
+               usbip_pack_iso(&iso[i], &urb->iso_frame_desc[i], 0);
+               total_length += urb->iso_frame_desc[i].actual_length;
+       }
+
+       kfree(buff);
+
+       if (total_length != urb->actual_length) {
+               dev_err(&urb->dev->dev,
+                       "total length of iso packets %d not equal to actual length of buffer %d\n",
+                       total_length, urb->actual_length);
+
+               if (ud->side == USBIP_STUB)
+                       usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
+               else
+                       usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
+
+               return -EPIPE;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(usbip_recv_iso);
+
+/*
+ * This functions restores the padding which was removed for optimizing
+ * the bandwidth during transfer over tcp/ip
+ *
+ * buffer and iso packets need to be stored and be in propeper endian in urb
+ * before calling this function
+ */
+void usbip_pad_iso(struct usbip_device *ud, struct urb *urb)
+{
+       int np = urb->number_of_packets;
+       int i;
+       int actualoffset = urb->actual_length;
+
+       if (!usb_pipeisoc(urb->pipe))
+               return;
+
+       /* if no packets or length of data is 0, then nothing to unpack */
+       if (np == 0 || urb->actual_length == 0)
+               return;
+
+       /*
+        * if actual_length is transfer_buffer_length then no padding is
+        * present.
+        */
+       if (urb->actual_length == urb->transfer_buffer_length)
+               return;
+
+       /*
+        * loop over all packets from last to first (to prevent overwritting
+        * memory when padding) and move them into the proper place
+        */
+       for (i = np-1; i > 0; i--) {
+               actualoffset -= urb->iso_frame_desc[i].actual_length;
+               memmove(urb->transfer_buffer + urb->iso_frame_desc[i].offset,
+                       urb->transfer_buffer + actualoffset,
+                       urb->iso_frame_desc[i].actual_length);
+       }
+}
+EXPORT_SYMBOL_GPL(usbip_pad_iso);
+
+/* some members of urb must be substituted before. */
+int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb)
+{
+       int ret;
+       int size;
+
+       if (ud->side == USBIP_STUB) {
+               /* the direction of urb must be OUT. */
+               if (usb_pipein(urb->pipe))
+                       return 0;
+
+               size = urb->transfer_buffer_length;
+       } else {
+               /* the direction of urb must be IN. */
+               if (usb_pipeout(urb->pipe))
+                       return 0;
+
+               size = urb->actual_length;
+       }
+
+       /* no need to recv xbuff */
+       if (!(size > 0))
+               return 0;
+
+       ret = usbip_recv(ud->tcp_socket, urb->transfer_buffer, size);
+       if (ret != size) {
+               dev_err(&urb->dev->dev, "recv xbuf, %d\n", ret);
+               if (ud->side == USBIP_STUB) {
+                       usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
+               } else {
+                       usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
+                       return -EPIPE;
+               }
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(usbip_recv_xbuff);
+
+static int __init usbip_core_init(void)
+{
+       pr_info(DRIVER_DESC " v" USBIP_VERSION "\n");
+       return 0;
+}
+
+static void __exit usbip_core_exit(void)
+{
+       return;
+}
+
+module_init(usbip_core_init);
+module_exit(usbip_core_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_VERSION(USBIP_VERSION);
diff --git a/drivers/usb/usbip/usbip_common.h b/drivers/usb/usbip/usbip_common.h
new file mode 100644 (file)
index 0000000..86b0847
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef __USBIP_COMMON_H
+#define __USBIP_COMMON_H
+
+#include <linux/compiler.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/net.h>
+#include <linux/printk.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/usb.h>
+#include <linux/wait.h>
+#include <uapi/linux/usbip.h>
+
+#define USBIP_VERSION "1.0.0"
+
+#undef pr_fmt
+
+#ifdef DEBUG
+#define pr_fmt(fmt)     KBUILD_MODNAME ": %s:%d: " fmt, __func__, __LINE__
+#else
+#define pr_fmt(fmt)     KBUILD_MODNAME ": " fmt
+#endif
+
+enum {
+       usbip_debug_xmit        = (1 << 0),
+       usbip_debug_sysfs       = (1 << 1),
+       usbip_debug_urb         = (1 << 2),
+       usbip_debug_eh          = (1 << 3),
+
+       usbip_debug_stub_cmp    = (1 << 8),
+       usbip_debug_stub_dev    = (1 << 9),
+       usbip_debug_stub_rx     = (1 << 10),
+       usbip_debug_stub_tx     = (1 << 11),
+
+       usbip_debug_vhci_rh     = (1 << 8),
+       usbip_debug_vhci_hc     = (1 << 9),
+       usbip_debug_vhci_rx     = (1 << 10),
+       usbip_debug_vhci_tx     = (1 << 11),
+       usbip_debug_vhci_sysfs  = (1 << 12)
+};
+
+#define usbip_dbg_flag_xmit    (usbip_debug_flag & usbip_debug_xmit)
+#define usbip_dbg_flag_vhci_rh (usbip_debug_flag & usbip_debug_vhci_rh)
+#define usbip_dbg_flag_vhci_hc (usbip_debug_flag & usbip_debug_vhci_hc)
+#define usbip_dbg_flag_vhci_rx (usbip_debug_flag & usbip_debug_vhci_rx)
+#define usbip_dbg_flag_vhci_tx (usbip_debug_flag & usbip_debug_vhci_tx)
+#define usbip_dbg_flag_stub_rx (usbip_debug_flag & usbip_debug_stub_rx)
+#define usbip_dbg_flag_stub_tx (usbip_debug_flag & usbip_debug_stub_tx)
+#define usbip_dbg_flag_vhci_sysfs  (usbip_debug_flag & usbip_debug_vhci_sysfs)
+
+extern unsigned long usbip_debug_flag;
+extern struct device_attribute dev_attr_usbip_debug;
+
+#define usbip_dbg_with_flag(flag, fmt, args...)                \
+       do {                                            \
+               if (flag & usbip_debug_flag)            \
+                       pr_debug(fmt, ##args);          \
+       } while (0)
+
+#define usbip_dbg_sysfs(fmt, args...) \
+       usbip_dbg_with_flag(usbip_debug_sysfs, fmt , ##args)
+#define usbip_dbg_xmit(fmt, args...) \
+       usbip_dbg_with_flag(usbip_debug_xmit, fmt , ##args)
+#define usbip_dbg_urb(fmt, args...) \
+       usbip_dbg_with_flag(usbip_debug_urb, fmt , ##args)
+#define usbip_dbg_eh(fmt, args...) \
+       usbip_dbg_with_flag(usbip_debug_eh, fmt , ##args)
+
+#define usbip_dbg_vhci_rh(fmt, args...)        \
+       usbip_dbg_with_flag(usbip_debug_vhci_rh, fmt , ##args)
+#define usbip_dbg_vhci_hc(fmt, args...)        \
+       usbip_dbg_with_flag(usbip_debug_vhci_hc, fmt , ##args)
+#define usbip_dbg_vhci_rx(fmt, args...)        \
+       usbip_dbg_with_flag(usbip_debug_vhci_rx, fmt , ##args)
+#define usbip_dbg_vhci_tx(fmt, args...)        \
+       usbip_dbg_with_flag(usbip_debug_vhci_tx, fmt , ##args)
+#define usbip_dbg_vhci_sysfs(fmt, args...) \
+       usbip_dbg_with_flag(usbip_debug_vhci_sysfs, fmt , ##args)
+
+#define usbip_dbg_stub_cmp(fmt, args...) \
+       usbip_dbg_with_flag(usbip_debug_stub_cmp, fmt , ##args)
+#define usbip_dbg_stub_rx(fmt, args...) \
+       usbip_dbg_with_flag(usbip_debug_stub_rx, fmt , ##args)
+#define usbip_dbg_stub_tx(fmt, args...) \
+       usbip_dbg_with_flag(usbip_debug_stub_tx, fmt , ##args)
+
+/*
+ * USB/IP request headers
+ *
+ * Each request is transferred across the network to its counterpart, which
+ * facilitates the normal USB communication. The values contained in the headers
+ * are basically the same as in a URB. Currently, four request types are
+ * defined:
+ *
+ *  - USBIP_CMD_SUBMIT: a USB request block, corresponds to usb_submit_urb()
+ *    (client to server)
+ *
+ *  - USBIP_RET_SUBMIT: the result of USBIP_CMD_SUBMIT
+ *    (server to client)
+ *
+ *  - USBIP_CMD_UNLINK: an unlink request of a pending USBIP_CMD_SUBMIT,
+ *    corresponds to usb_unlink_urb()
+ *    (client to server)
+ *
+ *  - USBIP_RET_UNLINK: the result of USBIP_CMD_UNLINK
+ *    (server to client)
+ *
+ */
+#define USBIP_CMD_SUBMIT       0x0001
+#define USBIP_CMD_UNLINK       0x0002
+#define USBIP_RET_SUBMIT       0x0003
+#define USBIP_RET_UNLINK       0x0004
+
+#define USBIP_DIR_OUT  0x00
+#define USBIP_DIR_IN   0x01
+
+/**
+ * struct usbip_header_basic - data pertinent to every request
+ * @command: the usbip request type
+ * @seqnum: sequential number that identifies requests; incremented per
+ *         connection
+ * @devid: specifies a remote USB device uniquely instead of busnum and devnum;
+ *        in the stub driver, this value is ((busnum << 16) | devnum)
+ * @direction: direction of the transfer
+ * @ep: endpoint number
+ */
+struct usbip_header_basic {
+       __u32 command;
+       __u32 seqnum;
+       __u32 devid;
+       __u32 direction;
+       __u32 ep;
+} __packed;
+
+/**
+ * struct usbip_header_cmd_submit - USBIP_CMD_SUBMIT packet header
+ * @transfer_flags: URB flags
+ * @transfer_buffer_length: the data size for (in) or (out) transfer
+ * @start_frame: initial frame for isochronous or interrupt transfers
+ * @number_of_packets: number of isochronous packets
+ * @interval: maximum time for the request on the server-side host controller
+ * @setup: setup data for a control request
+ */
+struct usbip_header_cmd_submit {
+       __u32 transfer_flags;
+       __s32 transfer_buffer_length;
+
+       /* it is difficult for usbip to sync frames (reserved only?) */
+       __s32 start_frame;
+       __s32 number_of_packets;
+       __s32 interval;
+
+       unsigned char setup[8];
+} __packed;
+
+/**
+ * struct usbip_header_ret_submit - USBIP_RET_SUBMIT packet header
+ * @status: return status of a non-iso request
+ * @actual_length: number of bytes transferred
+ * @start_frame: initial frame for isochronous or interrupt transfers
+ * @number_of_packets: number of isochronous packets
+ * @error_count: number of errors for isochronous transfers
+ */
+struct usbip_header_ret_submit {
+       __s32 status;
+       __s32 actual_length;
+       __s32 start_frame;
+       __s32 number_of_packets;
+       __s32 error_count;
+} __packed;
+
+/**
+ * struct usbip_header_cmd_unlink - USBIP_CMD_UNLINK packet header
+ * @seqnum: the URB seqnum to unlink
+ */
+struct usbip_header_cmd_unlink {
+       __u32 seqnum;
+} __packed;
+
+/**
+ * struct usbip_header_ret_unlink - USBIP_RET_UNLINK packet header
+ * @status: return status of the request
+ */
+struct usbip_header_ret_unlink {
+       __s32 status;
+} __packed;
+
+/**
+ * struct usbip_header - common header for all usbip packets
+ * @base: the basic header
+ * @u: packet type dependent header
+ */
+struct usbip_header {
+       struct usbip_header_basic base;
+
+       union {
+               struct usbip_header_cmd_submit  cmd_submit;
+               struct usbip_header_ret_submit  ret_submit;
+               struct usbip_header_cmd_unlink  cmd_unlink;
+               struct usbip_header_ret_unlink  ret_unlink;
+       } u;
+} __packed;
+
+/*
+ * This is the same as usb_iso_packet_descriptor but packed for pdu.
+ */
+struct usbip_iso_packet_descriptor {
+       __u32 offset;
+       __u32 length;                   /* expected length */
+       __u32 actual_length;
+       __u32 status;
+} __packed;
+
+enum usbip_side {
+       USBIP_VHCI,
+       USBIP_STUB,
+};
+
+/* event handler */
+#define USBIP_EH_SHUTDOWN      (1 << 0)
+#define USBIP_EH_BYE           (1 << 1)
+#define USBIP_EH_RESET         (1 << 2)
+#define USBIP_EH_UNUSABLE      (1 << 3)
+
+#define SDEV_EVENT_REMOVED   (USBIP_EH_SHUTDOWN | USBIP_EH_RESET | USBIP_EH_BYE)
+#define        SDEV_EVENT_DOWN         (USBIP_EH_SHUTDOWN | USBIP_EH_RESET)
+#define        SDEV_EVENT_ERROR_TCP    (USBIP_EH_SHUTDOWN | USBIP_EH_RESET)
+#define        SDEV_EVENT_ERROR_SUBMIT (USBIP_EH_SHUTDOWN | USBIP_EH_RESET)
+#define        SDEV_EVENT_ERROR_MALLOC (USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE)
+
+#define        VDEV_EVENT_REMOVED      (USBIP_EH_SHUTDOWN | USBIP_EH_BYE)
+#define        VDEV_EVENT_DOWN         (USBIP_EH_SHUTDOWN | USBIP_EH_RESET)
+#define        VDEV_EVENT_ERROR_TCP    (USBIP_EH_SHUTDOWN | USBIP_EH_RESET)
+#define        VDEV_EVENT_ERROR_MALLOC (USBIP_EH_SHUTDOWN | USBIP_EH_UNUSABLE)
+
+/* a common structure for stub_device and vhci_device */
+struct usbip_device {
+       enum usbip_side side;
+       enum usbip_device_status status;
+
+       /* lock for status */
+       spinlock_t lock;
+
+       struct socket *tcp_socket;
+
+       struct task_struct *tcp_rx;
+       struct task_struct *tcp_tx;
+
+       unsigned long event;
+       struct task_struct *eh;
+       wait_queue_head_t eh_waitq;
+
+       struct eh_ops {
+               void (*shutdown)(struct usbip_device *);
+               void (*reset)(struct usbip_device *);
+               void (*unusable)(struct usbip_device *);
+       } eh_ops;
+};
+
+#define kthread_get_run(threadfn, data, namefmt, ...)                     \
+({                                                                        \
+       struct task_struct *__k                                            \
+               = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \
+       if (!IS_ERR(__k)) {                                                \
+               get_task_struct(__k);                                      \
+               wake_up_process(__k);                                      \
+       }                                                                  \
+       __k;                                                               \
+})
+
+#define kthread_stop_put(k)            \
+       do {                            \
+               kthread_stop(k);        \
+               put_task_struct(k);     \
+       } while (0)
+
+/* usbip_common.c */
+void usbip_dump_urb(struct urb *purb);
+void usbip_dump_header(struct usbip_header *pdu);
+
+int usbip_recv(struct socket *sock, void *buf, int size);
+
+void usbip_pack_pdu(struct usbip_header *pdu, struct urb *urb, int cmd,
+                   int pack);
+void usbip_header_correct_endian(struct usbip_header *pdu, int send);
+
+struct usbip_iso_packet_descriptor*
+usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen);
+
+/* some members of urb must be substituted before. */
+int usbip_recv_iso(struct usbip_device *ud, struct urb *urb);
+void usbip_pad_iso(struct usbip_device *ud, struct urb *urb);
+int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb);
+
+/* usbip_event.c */
+int usbip_start_eh(struct usbip_device *ud);
+void usbip_stop_eh(struct usbip_device *ud);
+void usbip_event_add(struct usbip_device *ud, unsigned long event);
+int usbip_event_happened(struct usbip_device *ud);
+
+static inline int interface_to_busnum(struct usb_interface *interface)
+{
+       struct usb_device *udev = interface_to_usbdev(interface);
+
+       return udev->bus->busnum;
+}
+
+static inline int interface_to_devnum(struct usb_interface *interface)
+{
+       struct usb_device *udev = interface_to_usbdev(interface);
+
+       return udev->devnum;
+}
+
+#endif /* __USBIP_COMMON_H */
diff --git a/drivers/usb/usbip/usbip_event.c b/drivers/usb/usbip/usbip_event.c
new file mode 100644 (file)
index 0000000..64933b9
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <linux/kthread.h>
+#include <linux/export.h>
+
+#include "usbip_common.h"
+
+static int event_handler(struct usbip_device *ud)
+{
+       usbip_dbg_eh("enter\n");
+
+       /*
+        * Events are handled by only this thread.
+        */
+       while (usbip_event_happened(ud)) {
+               usbip_dbg_eh("pending event %lx\n", ud->event);
+
+               /*
+                * NOTE: shutdown must come first.
+                * Shutdown the device.
+                */
+               if (ud->event & USBIP_EH_SHUTDOWN) {
+                       ud->eh_ops.shutdown(ud);
+                       ud->event &= ~USBIP_EH_SHUTDOWN;
+               }
+
+               /* Reset the device. */
+               if (ud->event & USBIP_EH_RESET) {
+                       ud->eh_ops.reset(ud);
+                       ud->event &= ~USBIP_EH_RESET;
+               }
+
+               /* Mark the device as unusable. */
+               if (ud->event & USBIP_EH_UNUSABLE) {
+                       ud->eh_ops.unusable(ud);
+                       ud->event &= ~USBIP_EH_UNUSABLE;
+               }
+
+               /* Stop the error handler. */
+               if (ud->event & USBIP_EH_BYE)
+                       return -1;
+       }
+
+       return 0;
+}
+
+static int event_handler_loop(void *data)
+{
+       struct usbip_device *ud = data;
+
+       while (!kthread_should_stop()) {
+               wait_event_interruptible(ud->eh_waitq,
+                                        usbip_event_happened(ud) ||
+                                        kthread_should_stop());
+               usbip_dbg_eh("wakeup\n");
+
+               if (event_handler(ud) < 0)
+                       break;
+       }
+
+       return 0;
+}
+
+int usbip_start_eh(struct usbip_device *ud)
+{
+       init_waitqueue_head(&ud->eh_waitq);
+       ud->event = 0;
+
+       ud->eh = kthread_run(event_handler_loop, ud, "usbip_eh");
+       if (IS_ERR(ud->eh)) {
+               pr_warn("Unable to start control thread\n");
+               return PTR_ERR(ud->eh);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(usbip_start_eh);
+
+void usbip_stop_eh(struct usbip_device *ud)
+{
+       if (ud->eh == current)
+               return; /* do not wait for myself */
+
+       kthread_stop(ud->eh);
+       usbip_dbg_eh("usbip_eh has finished\n");
+}
+EXPORT_SYMBOL_GPL(usbip_stop_eh);
+
+void usbip_event_add(struct usbip_device *ud, unsigned long event)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&ud->lock, flags);
+       ud->event |= event;
+       wake_up(&ud->eh_waitq);
+       spin_unlock_irqrestore(&ud->lock, flags);
+}
+EXPORT_SYMBOL_GPL(usbip_event_add);
+
+int usbip_event_happened(struct usbip_device *ud)
+{
+       int happened = 0;
+
+       spin_lock(&ud->lock);
+       if (ud->event != 0)
+               happened = 1;
+       spin_unlock(&ud->lock);
+
+       return happened;
+}
+EXPORT_SYMBOL_GPL(usbip_event_happened);
diff --git a/drivers/usb/usbip/usbip_protocol.txt b/drivers/usb/usbip/usbip_protocol.txt
new file mode 100644 (file)
index 0000000..16b6fe2
--- /dev/null
@@ -0,0 +1,358 @@
+PRELIMINARY DRAFT, MAY CONTAIN MISTAKES!
+28 Jun 2011
+
+The USB/IP protocol follows a server/client architecture. The server exports the
+USB devices and the clients imports them. The device driver for the exported
+USB device runs on the client machine.
+
+The client may ask for the list of the exported USB devices. To get the list the
+client opens a TCP/IP connection towards the server, and sends an OP_REQ_DEVLIST
+packet on top of the TCP/IP connection (so the actual OP_REQ_DEVLIST may be sent
+in one or more pieces at the low level transport layer). The server sends back
+the OP_REP_DEVLIST packet which lists the exported USB devices. Finally the
+TCP/IP connection is closed.
+
+ virtual host controller                                 usb host
+      "client"                                           "server"
+  (imports USB devices)                             (exports USB devices)
+          |                                                 |
+          |                  OP_REQ_DEVLIST                 |
+          | ----------------------------------------------> |
+          |                                                 |
+          |                  OP_REP_DEVLIST                 |
+          | <---------------------------------------------- |
+          |                                                 |
+
+Once the client knows the list of exported USB devices it may decide to use one
+of them. First the client opens a TCP/IP connection towards the server and
+sends an OP_REQ_IMPORT packet. The server replies with OP_REP_IMPORT. If the
+import was successful the TCP/IP connection remains open and will be used
+to transfer the URB traffic between the client and the server. The client may
+send two types of packets: the USBIP_CMD_SUBMIT to submit an URB, and
+USBIP_CMD_UNLINK to unlink a previously submitted URB. The answers of the
+server may be USBIP_RET_SUBMIT and USBIP_RET_UNLINK respectively.
+
+ virtual host controller                                 usb host
+      "client"                                           "server"
+  (imports USB devices)                             (exports USB devices)
+          |                                                 |
+          |                  OP_REQ_IMPORT                  |
+          | ----------------------------------------------> |
+          |                                                 |
+          |                  OP_REP_IMPORT                  |
+          | <---------------------------------------------- |
+          |                                                 |
+          |                                                 |
+          |            USBIP_CMD_SUBMIT(seqnum = n)         |
+          | ----------------------------------------------> |
+          |                                                 |
+          |            USBIP_RET_SUBMIT(seqnum = n)         |
+          | <---------------------------------------------- |
+          |                        .                        |
+          |                        :                        |
+          |                                                 |
+          |            USBIP_CMD_SUBMIT(seqnum = m)         |
+          | ----------------------------------------------> |
+          |                                                 |
+          |            USBIP_CMD_SUBMIT(seqnum = m+1)       |
+          | ----------------------------------------------> |
+          |                                                 |
+          |            USBIP_CMD_SUBMIT(seqnum = m+2)       |
+          | ----------------------------------------------> |
+          |                                                 |
+          |            USBIP_RET_SUBMIT(seqnum = m)         |
+          | <---------------------------------------------- |
+          |                                                 |
+          |            USBIP_CMD_SUBMIT(seqnum = m+3)       |
+          | ----------------------------------------------> |
+          |                                                 |
+          |            USBIP_RET_SUBMIT(seqnum = m+1)       |
+          | <---------------------------------------------- |
+          |                                                 |
+          |            USBIP_CMD_SUBMIT(seqnum = m+4)       |
+          | ----------------------------------------------> |
+          |                                                 |
+          |            USBIP_RET_SUBMIT(seqnum = m+2)       |
+          | <---------------------------------------------- |
+          |                        .                        |
+          |                        :                        |
+          |                                                 |
+          |               USBIP_CMD_UNLINK                  |
+          | ----------------------------------------------> |
+          |                                                 |
+          |               USBIP_RET_UNLINK                  |
+          | <---------------------------------------------- |
+          |                                                 |
+
+The fields are in network (big endian) byte order meaning that the most significant
+byte (MSB) is stored at the lowest address.
+
+
+OP_REQ_DEVLIST: Retrieve the list of exported USB devices.
+
+ Offset    | Length | Value      | Description
+-----------+--------+------------+---------------------------------------------------
+ 0         | 2      | 0x0100     | Binary-coded decimal USBIP version number: v1.0.0
+-----------+--------+------------+---------------------------------------------------
+ 2         | 2      | 0x8005     | Command code: Retrieve the list of exported USB
+           |        |            |   devices.
+-----------+--------+------------+---------------------------------------------------
+ 4         | 4      | 0x00000000 | Status: unused, shall be set to 0
+
+OP_REP_DEVLIST: Reply with the list of exported USB devices.
+
+ Offset    | Length | Value      | Description
+-----------+--------+------------+---------------------------------------------------
+ 0         | 2      | 0x0100     | Binary-coded decimal USBIP version number: v1.0.0.
+-----------+--------+------------+---------------------------------------------------
+ 2         | 2      | 0x0005     | Reply code: The list of exported USB devices.
+-----------+--------+------------+---------------------------------------------------
+ 4         | 4      | 0x00000000 | Status: 0 for OK
+-----------+--------+------------+---------------------------------------------------
+ 8         | 4      | n          | Number of exported devices: 0 means no exported
+           |        |            |   devices.
+-----------+--------+------------+---------------------------------------------------
+ 0x0C      |        |            | From now on the exported n devices are described,
+           |        |            |   if any. If no devices are exported the message
+           |        |            |   ends with the previous "number of exported
+           |        |            |   devices" field.
+-----------+--------+------------+---------------------------------------------------
+           | 256    |            | path: Path of the device on the host exporting the
+           |        |            |   USB device, string closed with zero byte, e.g.
+           |        |            |   "/sys/devices/pci0000:00/0000:00:1d.1/usb3/3-2"
+           |        |            |   The unused bytes shall be filled with zero
+           |        |            |   bytes.
+-----------+--------+------------+---------------------------------------------------
+ 0x10C     | 32     |            | busid: Bus ID of the exported device, string
+           |        |            |   closed with zero byte, e.g. "3-2". The unused
+           |        |            |   bytes shall be filled with zero bytes.
+-----------+--------+------------+---------------------------------------------------
+ 0x12C     | 4      |            | busnum
+-----------+--------+------------+---------------------------------------------------
+ 0x130     | 4      |            | devnum
+-----------+--------+------------+---------------------------------------------------
+ 0x134     | 4      |            | speed
+-----------+--------+------------+---------------------------------------------------
+ 0x138     | 2      |            | idVendor
+-----------+--------+------------+---------------------------------------------------
+ 0x13A     | 2      |            | idProduct
+-----------+--------+------------+---------------------------------------------------
+ 0x13C     | 2      |            | bcdDevice
+-----------+--------+------------+---------------------------------------------------
+ 0x13E     | 1      |            | bDeviceClass
+-----------+--------+------------+---------------------------------------------------
+ 0x13F     | 1      |            | bDeviceSubClass
+-----------+--------+------------+---------------------------------------------------
+ 0x140     | 1      |            | bDeviceProtocol
+-----------+--------+------------+---------------------------------------------------
+ 0x141     | 1      |            | bConfigurationValue
+-----------+--------+------------+---------------------------------------------------
+ 0x142     | 1      |            | bNumConfigurations
+-----------+--------+------------+---------------------------------------------------
+ 0x143     | 1      |            | bNumInterfaces
+-----------+--------+------------+---------------------------------------------------
+ 0x144     |        | m_0        | From now on each interface is described, all
+           |        |            |   together bNumInterfaces times, with the
+           |        |            |   the following 4 fields:
+-----------+--------+------------+---------------------------------------------------
+           | 1      |            | bInterfaceClass
+-----------+--------+------------+---------------------------------------------------
+ 0x145     | 1      |            | bInterfaceSubClass
+-----------+--------+------------+---------------------------------------------------
+ 0x146     | 1      |            | bInterfaceProtocol
+-----------+--------+------------+---------------------------------------------------
+ 0x147     | 1      |            | padding byte for alignment, shall be set to zero
+-----------+--------+------------+---------------------------------------------------
+ 0xC +     |        |            | The second exported USB device starts at i=1
+ i*0x138 + |        |            | with the busid field.
+ m_(i-1)*4 |        |            |
+
+OP_REQ_IMPORT: Request to import (attach) a remote USB device.
+
+ Offset    | Length | Value      | Description
+-----------+--------+------------+---------------------------------------------------
+ 0         | 2      | 0x0100     | Binary-coded decimal USBIP version number: v1.0.0
+-----------+--------+------------+---------------------------------------------------
+ 2         | 2      | 0x8003     | Command code: import a remote USB device.
+-----------+--------+------------+---------------------------------------------------
+ 4         | 4      | 0x00000000 | Status: unused, shall be set to 0
+-----------+--------+------------+---------------------------------------------------
+ 8         | 32     |            | busid: the busid of the exported device on the
+           |        |            |   remote host. The possible values are taken
+           |        |            |   from the message field OP_REP_DEVLIST.busid.
+           |        |            |   A string closed with zero, the unused bytes
+           |        |            |   shall be filled with zeros.
+-----------+--------+------------+---------------------------------------------------
+
+OP_REP_IMPORT: Reply to import (attach) a remote USB device.
+
+ Offset    | Length | Value      | Description
+-----------+--------+------------+---------------------------------------------------
+ 0         | 2      | 0x0100     | Binary-coded decimal USBIP version number: v1.0.0
+-----------+--------+------------+---------------------------------------------------
+ 2         | 2      | 0x0003     | Reply code: Reply to import.
+-----------+--------+------------+---------------------------------------------------
+ 4         | 4      | 0x00000000 | Status: 0 for OK
+           |        |            |         1 for error
+-----------+--------+------------+---------------------------------------------------
+ 8         |        |            | From now on comes the details of the imported
+           |        |            |   device, if the previous status field was OK (0),
+           |        |            |   otherwise the reply ends with the status field.
+-----------+--------+------------+---------------------------------------------------
+           | 256    |            | path: Path of the device on the host exporting the
+           |        |            |   USB device, string closed with zero byte, e.g.
+           |        |            |   "/sys/devices/pci0000:00/0000:00:1d.1/usb3/3-2"
+           |        |            |   The unused bytes shall be filled with zero
+           |        |            |   bytes.
+-----------+--------+------------+---------------------------------------------------
+ 0x108     | 32     |            | busid: Bus ID of the exported device, string
+           |        |            |   closed with zero byte, e.g. "3-2". The unused
+           |        |            |   bytes shall be filled with zero bytes.
+-----------+--------+------------+---------------------------------------------------
+ 0x128     | 4      |            | busnum
+-----------+--------+------------+---------------------------------------------------
+ 0x12C     | 4      |            | devnum
+-----------+--------+------------+---------------------------------------------------
+ 0x130     | 4      |            | speed
+-----------+--------+------------+---------------------------------------------------
+ 0x134     | 2      |            | idVendor
+-----------+--------+------------+---------------------------------------------------
+ 0x136     | 2      |            | idProduct
+-----------+--------+------------+---------------------------------------------------
+ 0x138     | 2      |            | bcdDevice
+-----------+--------+------------+---------------------------------------------------
+ 0x139     | 1      |            | bDeviceClass
+-----------+--------+------------+---------------------------------------------------
+ 0x13A     | 1      |            | bDeviceSubClass
+-----------+--------+------------+---------------------------------------------------
+ 0x13B     | 1      |            | bDeviceProtocol
+-----------+--------+------------+---------------------------------------------------
+ 0x13C     | 1      |            | bConfigurationValue
+-----------+--------+------------+---------------------------------------------------
+ 0x13D     | 1      |            | bNumConfigurations
+-----------+--------+------------+---------------------------------------------------
+ 0x13E     | 1      |            | bNumInterfaces
+
+USBIP_CMD_SUBMIT: Submit an URB
+
+ Offset    | Length | Value      | Description
+-----------+--------+------------+---------------------------------------------------
+ 0         | 4      | 0x00000001 | command: Submit an URB
+-----------+--------+------------+---------------------------------------------------
+ 4         | 4      |            | seqnum: the sequence number of the URB to submit
+-----------+--------+------------+---------------------------------------------------
+ 8         | 4      |            | devid
+-----------+--------+------------+---------------------------------------------------
+ 0xC       | 4      |            | direction: 0: USBIP_DIR_OUT
+           |        |            |            1: USBIP_DIR_IN
+-----------+--------+------------+---------------------------------------------------
+ 0x10      | 4      |            | ep: endpoint number, possible values are: 0...15
+-----------+--------+------------+---------------------------------------------------
+ 0x14      | 4      |            | transfer_flags: possible values depend on the
+           |        |            |   URB transfer type, see below
+-----------+--------+------------+---------------------------------------------------
+ 0x18      | 4      |            | transfer_buffer_length
+-----------+--------+------------+---------------------------------------------------
+ 0x1C      | 4      |            | start_frame: specify the selected frame to
+           |        |            |   transmit an ISO frame, ignored if URB_ISO_ASAP
+           |        |            |   is specified at transfer_flags
+-----------+--------+------------+---------------------------------------------------
+ 0x20      | 4      |            | number_of_packets: number of ISO packets
+-----------+--------+------------+---------------------------------------------------
+ 0x24      | 4      |            | interval: maximum time for the request on the
+           |        |            |   server-side host controller
+-----------+--------+------------+---------------------------------------------------
+ 0x28      | 8      |            | setup: data bytes for USB setup, filled with
+           |        |            |   zeros if not used
+-----------+--------+------------+---------------------------------------------------
+ 0x30      |        |            | URB data. For ISO transfers the padding between
+           |        |            |   each ISO packets is not transmitted.
+
+
+  Allowed transfer_flags  | value      | control | interrupt | bulk     | isochronous
+ -------------------------+------------+---------+-----------+----------+-------------
+  URB_SHORT_NOT_OK        | 0x00000001 | only in | only in   | only in  | no
+  URB_ISO_ASAP            | 0x00000002 | no      | no        | no       | yes
+  URB_NO_TRANSFER_DMA_MAP | 0x00000004 | yes     | yes       | yes      | yes
+  URB_NO_FSBR             | 0x00000020 | yes     | no        | no       | no
+  URB_ZERO_PACKET         | 0x00000040 | no      | no        | only out | no
+  URB_NO_INTERRUPT        | 0x00000080 | yes     | yes       | yes      | yes
+  URB_FREE_BUFFER         | 0x00000100 | yes     | yes       | yes      | yes
+  URB_DIR_MASK            | 0x00000200 | yes     | yes       | yes      | yes
+
+
+USBIP_RET_SUBMIT: Reply for submitting an URB
+
+ Offset    | Length | Value      | Description
+-----------+--------+------------+---------------------------------------------------
+ 0         | 4      | 0x00000003 | command
+-----------+--------+------------+---------------------------------------------------
+ 4         | 4      |            | seqnum: URB sequence number
+-----------+--------+------------+---------------------------------------------------
+ 8         | 4      |            | devid
+-----------+--------+------------+---------------------------------------------------
+ 0xC       | 4      |            | direction: 0: USBIP_DIR_OUT
+           |        |            |            1: USBIP_DIR_IN
+-----------+--------+------------+---------------------------------------------------
+ 0x10      | 4      |            | ep: endpoint number
+-----------+--------+------------+---------------------------------------------------
+ 0x14      | 4      |            | status: zero for successful URB transaction,
+           |        |            |   otherwise some kind of error happened.
+-----------+--------+------------+---------------------------------------------------
+ 0x18      | 4      | n          | actual_length: number of URB data bytes
+-----------+--------+------------+---------------------------------------------------
+ 0x1C      | 4      |            | start_frame: for an ISO frame the actually
+           |        |            |   selected frame for transmit.
+-----------+--------+------------+---------------------------------------------------
+ 0x20      | 4      |            | number_of_packets
+-----------+--------+------------+---------------------------------------------------
+ 0x24      | 4      |            | error_count
+-----------+--------+------------+---------------------------------------------------
+ 0x28      | 8      |            | setup: data bytes for USB setup, filled with
+           |        |            |   zeros if not used
+-----------+--------+------------+---------------------------------------------------
+ 0x30      | n      |            | URB data bytes. For ISO transfers the padding
+           |        |            |   between each ISO packets is not transmitted.
+
+USBIP_CMD_UNLINK: Unlink an URB
+
+ Offset    | Length | Value      | Description
+-----------+--------+------------+---------------------------------------------------
+ 0         | 4      | 0x00000002 | command: URB unlink command
+-----------+--------+------------+---------------------------------------------------
+ 4         | 4      |            | seqnum: URB sequence number to unlink: FIXME: is this so?
+-----------+--------+------------+---------------------------------------------------
+ 8         | 4      |            | devid
+-----------+--------+------------+---------------------------------------------------
+ 0xC       | 4      |            | direction: 0: USBIP_DIR_OUT
+           |        |            |            1: USBIP_DIR_IN
+-----------+--------+------------+---------------------------------------------------
+ 0x10      | 4      |            | ep: endpoint number: zero
+-----------+--------+------------+---------------------------------------------------
+ 0x14      | 4      |            | seqnum: the URB sequence number given previously
+           |        |            |   at USBIP_CMD_SUBMIT.seqnum field
+-----------+--------+------------+---------------------------------------------------
+ 0x30      | n      |            | URB data bytes. For ISO transfers the padding
+           |        |            |   between each ISO packets is not transmitted.
+
+USBIP_RET_UNLINK: Reply for URB unlink
+
+ Offset    | Length | Value      | Description
+-----------+--------+------------+---------------------------------------------------
+ 0         | 4      | 0x00000004 | command: reply for the URB unlink command
+-----------+--------+------------+---------------------------------------------------
+ 4         | 4      |            | seqnum: the unlinked URB sequence number
+-----------+--------+------------+---------------------------------------------------
+ 8         | 4      |            | devid
+-----------+--------+------------+---------------------------------------------------
+ 0xC       | 4      |            | direction: 0: USBIP_DIR_OUT
+           |        |            |            1: USBIP_DIR_IN
+-----------+--------+------------+---------------------------------------------------
+ 0x10      | 4      |            | ep: endpoint number
+-----------+--------+------------+---------------------------------------------------
+ 0x14      | 4      |            | status: This is the value contained in the
+           |        |            |   urb->status in the URB completition handler.
+           |        |            |   FIXME: a better explanation needed.
+-----------+--------+------------+---------------------------------------------------
+ 0x30      | n      |            | URB data bytes. For ISO transfers the padding
+           |        |            |   between each ISO packets is not transmitted.
diff --git a/drivers/usb/usbip/vhci.h b/drivers/usb/usbip/vhci.h
new file mode 100644 (file)
index 0000000..a863a98
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This 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.
+ *
+ */
+
+#ifndef __USBIP_VHCI_H
+#define __USBIP_VHCI_H
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
+#include <linux/wait.h>
+
+struct vhci_device {
+       struct usb_device *udev;
+
+       /*
+        * devid specifies a remote usb device uniquely instead
+        * of combination of busnum and devnum.
+        */
+       __u32 devid;
+
+       /* speed of a remote device */
+       enum usb_device_speed speed;
+
+       /* vhci root-hub port to which this device is attached */
+       __u32 rhport;
+
+       struct usbip_device ud;
+
+       /* lock for the below link lists */
+       spinlock_t priv_lock;
+
+       /* vhci_priv is linked to one of them. */
+       struct list_head priv_tx;
+       struct list_head priv_rx;
+
+       /* vhci_unlink is linked to one of them */
+       struct list_head unlink_tx;
+       struct list_head unlink_rx;
+
+       /* vhci_tx thread sleeps for this queue */
+       wait_queue_head_t waitq_tx;
+};
+
+/* urb->hcpriv, use container_of() */
+struct vhci_priv {
+       unsigned long seqnum;
+       struct list_head list;
+
+       struct vhci_device *vdev;
+       struct urb *urb;
+};
+
+struct vhci_unlink {
+       /* seqnum of this request */
+       unsigned long seqnum;
+
+       struct list_head list;
+
+       /* seqnum of the unlink target */
+       unsigned long unlink_seqnum;
+};
+
+/* Number of supported ports. Value has an upperbound of USB_MAXCHILDREN */
+#define VHCI_NPORTS 8
+
+/* for usb_bus.hcpriv */
+struct vhci_hcd {
+       spinlock_t lock;
+
+       u32 port_status[VHCI_NPORTS];
+
+       unsigned resuming:1;
+       unsigned long re_timeout;
+
+       atomic_t seqnum;
+
+       /*
+        * NOTE:
+        * wIndex shows the port number and begins from 1.
+        * But, the index of this array begins from 0.
+        */
+       struct vhci_device vdev[VHCI_NPORTS];
+};
+
+extern struct vhci_hcd *the_controller;
+extern const struct attribute_group dev_attr_group;
+
+/* vhci_hcd.c */
+void rh_port_connect(int rhport, enum usb_device_speed speed);
+
+/* vhci_rx.c */
+struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, __u32 seqnum);
+int vhci_rx_loop(void *data);
+
+/* vhci_tx.c */
+int vhci_tx_loop(void *data);
+
+static inline struct vhci_device *port_to_vdev(__u32 port)
+{
+       return &the_controller->vdev[port];
+}
+
+static inline struct vhci_hcd *hcd_to_vhci(struct usb_hcd *hcd)
+{
+       return (struct vhci_hcd *) (hcd->hcd_priv);
+}
+
+static inline struct usb_hcd *vhci_to_hcd(struct vhci_hcd *vhci)
+{
+       return container_of((void *) vhci, struct usb_hcd, hcd_priv);
+}
+
+static inline struct device *vhci_dev(struct vhci_hcd *vhci)
+{
+       return vhci_to_hcd(vhci)->self.controller;
+}
+
+#endif /* __USBIP_VHCI_H */
diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c
new file mode 100644 (file)
index 0000000..c02374b
--- /dev/null
@@ -0,0 +1,1171 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <linux/init.h>
+#include <linux/file.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "usbip_common.h"
+#include "vhci.h"
+
+#define DRIVER_AUTHOR "Takahiro Hirofuchi"
+#define DRIVER_DESC "USB/IP 'Virtual' Host Controller (VHCI) Driver"
+
+/*
+ * TODO
+ *     - update root hub emulation
+ *     - move the emulation code to userland ?
+ *             porting to other operating systems
+ *             minimize kernel code
+ *     - add suspend/resume code
+ *     - clean up everything
+ */
+
+/* See usb gadget dummy hcd */
+
+static int vhci_hub_status(struct usb_hcd *hcd, char *buff);
+static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+                           u16 wIndex, char *buff, u16 wLength);
+static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+                           gfp_t mem_flags);
+static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
+static int vhci_start(struct usb_hcd *vhci_hcd);
+static void vhci_stop(struct usb_hcd *hcd);
+static int vhci_get_frame_number(struct usb_hcd *hcd);
+
+static const char driver_name[] = "vhci_hcd";
+static const char driver_desc[] = "USB/IP Virtual Host Controller";
+
+struct vhci_hcd *the_controller;
+
+static const char * const bit_desc[] = {
+       "CONNECTION",           /*0*/
+       "ENABLE",               /*1*/
+       "SUSPEND",              /*2*/
+       "OVER_CURRENT",         /*3*/
+       "RESET",                /*4*/
+       "R5",                   /*5*/
+       "R6",                   /*6*/
+       "R7",                   /*7*/
+       "POWER",                /*8*/
+       "LOWSPEED",             /*9*/
+       "HIGHSPEED",            /*10*/
+       "PORT_TEST",            /*11*/
+       "INDICATOR",            /*12*/
+       "R13",                  /*13*/
+       "R14",                  /*14*/
+       "R15",                  /*15*/
+       "C_CONNECTION",         /*16*/
+       "C_ENABLE",             /*17*/
+       "C_SUSPEND",            /*18*/
+       "C_OVER_CURRENT",       /*19*/
+       "C_RESET",              /*20*/
+       "R21",                  /*21*/
+       "R22",                  /*22*/
+       "R23",                  /*23*/
+       "R24",                  /*24*/
+       "R25",                  /*25*/
+       "R26",                  /*26*/
+       "R27",                  /*27*/
+       "R28",                  /*28*/
+       "R29",                  /*29*/
+       "R30",                  /*30*/
+       "R31",                  /*31*/
+};
+
+static void dump_port_status_diff(u32 prev_status, u32 new_status)
+{
+       int i = 0;
+       u32 bit = 1;
+
+       pr_debug("status prev -> new: %08x -> %08x\n", prev_status, new_status);
+       while (bit) {
+               u32 prev = prev_status & bit;
+               u32 new = new_status & bit;
+               char change;
+
+               if (!prev && new)
+                       change = '+';
+               else if (prev && !new)
+                       change = '-';
+               else
+                       change = ' ';
+
+               if (prev || new)
+                       pr_debug(" %c%s\n", change, bit_desc[i]);
+               bit <<= 1;
+               i++;
+       }
+       pr_debug("\n");
+}
+
+void rh_port_connect(int rhport, enum usb_device_speed speed)
+{
+       usbip_dbg_vhci_rh("rh_port_connect %d\n", rhport);
+
+       spin_lock(&the_controller->lock);
+
+       the_controller->port_status[rhport] |= USB_PORT_STAT_CONNECTION
+               | (1 << USB_PORT_FEAT_C_CONNECTION);
+
+       switch (speed) {
+       case USB_SPEED_HIGH:
+               the_controller->port_status[rhport] |= USB_PORT_STAT_HIGH_SPEED;
+               break;
+       case USB_SPEED_LOW:
+               the_controller->port_status[rhport] |= USB_PORT_STAT_LOW_SPEED;
+               break;
+       default:
+               break;
+       }
+
+       spin_unlock(&the_controller->lock);
+
+       usb_hcd_poll_rh_status(vhci_to_hcd(the_controller));
+}
+
+static void rh_port_disconnect(int rhport)
+{
+       usbip_dbg_vhci_rh("rh_port_disconnect %d\n", rhport);
+
+       spin_lock(&the_controller->lock);
+
+       the_controller->port_status[rhport] &= ~USB_PORT_STAT_CONNECTION;
+       the_controller->port_status[rhport] |=
+                                       (1 << USB_PORT_FEAT_C_CONNECTION);
+
+       spin_unlock(&the_controller->lock);
+       usb_hcd_poll_rh_status(vhci_to_hcd(the_controller));
+}
+
+#define PORT_C_MASK                            \
+       ((USB_PORT_STAT_C_CONNECTION            \
+         | USB_PORT_STAT_C_ENABLE              \
+         | USB_PORT_STAT_C_SUSPEND             \
+         | USB_PORT_STAT_C_OVERCURRENT         \
+         | USB_PORT_STAT_C_RESET) << 16)
+
+/*
+ * Returns 0 if the status hasn't changed, or the number of bytes in buf.
+ * Ports are 0-indexed from the HCD point of view,
+ * and 1-indexed from the USB core pointer of view.
+ *
+ * @buf: a bitmap to show which port status has been changed.
+ *  bit  0: reserved
+ *  bit  1: the status of port 0 has been changed.
+ *  bit  2: the status of port 1 has been changed.
+ *  ...
+ */
+static int vhci_hub_status(struct usb_hcd *hcd, char *buf)
+{
+       struct vhci_hcd *vhci;
+       int             retval;
+       int             rhport;
+       int             changed = 0;
+
+       retval = DIV_ROUND_UP(VHCI_NPORTS + 1, 8);
+       memset(buf, 0, retval);
+
+       vhci = hcd_to_vhci(hcd);
+
+       spin_lock(&vhci->lock);
+       if (!HCD_HW_ACCESSIBLE(hcd)) {
+               usbip_dbg_vhci_rh("hw accessible flag not on?\n");
+               goto done;
+       }
+
+       /* check pseudo status register for each port */
+       for (rhport = 0; rhport < VHCI_NPORTS; rhport++) {
+               if ((vhci->port_status[rhport] & PORT_C_MASK)) {
+                       /* The status of a port has been changed, */
+                       usbip_dbg_vhci_rh("port %d status changed\n", rhport);
+
+                       buf[(rhport + 1) / 8] |= 1 << (rhport + 1) % 8;
+                       changed = 1;
+               }
+       }
+
+       if ((hcd->state == HC_STATE_SUSPENDED) && (changed == 1))
+               usb_hcd_resume_root_hub(hcd);
+
+done:
+       spin_unlock(&vhci->lock);
+       return changed ? retval : 0;
+}
+
+static inline void hub_descriptor(struct usb_hub_descriptor *desc)
+{
+       memset(desc, 0, sizeof(*desc));
+       desc->bDescriptorType = 0x29;
+       desc->bDescLength = 9;
+       desc->wHubCharacteristics = (__constant_cpu_to_le16(0x0001));
+       desc->bNbrPorts = VHCI_NPORTS;
+       desc->u.hs.DeviceRemovable[0] = 0xff;
+       desc->u.hs.DeviceRemovable[1] = 0xff;
+}
+
+static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
+                           u16 wIndex, char *buf, u16 wLength)
+{
+       struct vhci_hcd *dum;
+       int             retval = 0;
+       int             rhport;
+
+       u32 prev_port_status[VHCI_NPORTS];
+
+       if (!HCD_HW_ACCESSIBLE(hcd))
+               return -ETIMEDOUT;
+
+       /*
+        * NOTE:
+        * wIndex shows the port number and begins from 1.
+        */
+       usbip_dbg_vhci_rh("typeReq %x wValue %x wIndex %x\n", typeReq, wValue,
+                         wIndex);
+       if (wIndex > VHCI_NPORTS)
+               pr_err("invalid port number %d\n", wIndex);
+       rhport = ((__u8)(wIndex & 0x00ff)) - 1;
+
+       dum = hcd_to_vhci(hcd);
+
+       spin_lock(&dum->lock);
+
+       /* store old status and compare now and old later */
+       if (usbip_dbg_flag_vhci_rh) {
+               memcpy(prev_port_status, dum->port_status,
+                       sizeof(prev_port_status));
+       }
+
+       switch (typeReq) {
+       case ClearHubFeature:
+               usbip_dbg_vhci_rh(" ClearHubFeature\n");
+               break;
+       case ClearPortFeature:
+               switch (wValue) {
+               case USB_PORT_FEAT_SUSPEND:
+                       if (dum->port_status[rhport] & USB_PORT_STAT_SUSPEND) {
+                               /* 20msec signaling */
+                               dum->resuming = 1;
+                               dum->re_timeout =
+                                       jiffies + msecs_to_jiffies(20);
+                       }
+                       break;
+               case USB_PORT_FEAT_POWER:
+                       usbip_dbg_vhci_rh(
+                               " ClearPortFeature: USB_PORT_FEAT_POWER\n");
+                       dum->port_status[rhport] = 0;
+                       dum->resuming = 0;
+                       break;
+               case USB_PORT_FEAT_C_RESET:
+                       usbip_dbg_vhci_rh(
+                               " ClearPortFeature: USB_PORT_FEAT_C_RESET\n");
+                       switch (dum->vdev[rhport].speed) {
+                       case USB_SPEED_HIGH:
+                               dum->port_status[rhport] |=
+                                       USB_PORT_STAT_HIGH_SPEED;
+                               break;
+                       case USB_SPEED_LOW:
+                               dum->port_status[rhport] |=
+                                       USB_PORT_STAT_LOW_SPEED;
+                               break;
+                       default:
+                               break;
+                       }
+               default:
+                       usbip_dbg_vhci_rh(" ClearPortFeature: default %x\n",
+                                         wValue);
+                       dum->port_status[rhport] &= ~(1 << wValue);
+                       break;
+               }
+               break;
+       case GetHubDescriptor:
+               usbip_dbg_vhci_rh(" GetHubDescriptor\n");
+               hub_descriptor((struct usb_hub_descriptor *) buf);
+               break;
+       case GetHubStatus:
+               usbip_dbg_vhci_rh(" GetHubStatus\n");
+               *(__le32 *) buf = cpu_to_le32(0);
+               break;
+       case GetPortStatus:
+               usbip_dbg_vhci_rh(" GetPortStatus port %x\n", wIndex);
+               if (wIndex > VHCI_NPORTS || wIndex < 1) {
+                       pr_err("invalid port number %d\n", wIndex);
+                       retval = -EPIPE;
+               }
+
+               /* we do not care about resume. */
+
+               /* whoever resets or resumes must GetPortStatus to
+                * complete it!!
+                */
+               if (dum->resuming && time_after(jiffies, dum->re_timeout)) {
+                       dum->port_status[rhport] |=
+                               (1 << USB_PORT_FEAT_C_SUSPEND);
+                       dum->port_status[rhport] &=
+                               ~(1 << USB_PORT_FEAT_SUSPEND);
+                       dum->resuming = 0;
+                       dum->re_timeout = 0;
+               }
+
+               if ((dum->port_status[rhport] & (1 << USB_PORT_FEAT_RESET)) !=
+                   0 && time_after(jiffies, dum->re_timeout)) {
+                       dum->port_status[rhport] |=
+                               (1 << USB_PORT_FEAT_C_RESET);
+                       dum->port_status[rhport] &=
+                               ~(1 << USB_PORT_FEAT_RESET);
+                       dum->re_timeout = 0;
+
+                       if (dum->vdev[rhport].ud.status ==
+                           VDEV_ST_NOTASSIGNED) {
+                               usbip_dbg_vhci_rh(
+                                       " enable rhport %d (status %u)\n",
+                                       rhport,
+                                       dum->vdev[rhport].ud.status);
+                               dum->port_status[rhport] |=
+                                       USB_PORT_STAT_ENABLE;
+                       }
+               }
+               ((__le16 *) buf)[0] = cpu_to_le16(dum->port_status[rhport]);
+               ((__le16 *) buf)[1] =
+                       cpu_to_le16(dum->port_status[rhport] >> 16);
+
+               usbip_dbg_vhci_rh(" GetPortStatus bye %x %x\n", ((u16 *)buf)[0],
+                                 ((u16 *)buf)[1]);
+               break;
+       case SetHubFeature:
+               usbip_dbg_vhci_rh(" SetHubFeature\n");
+               retval = -EPIPE;
+               break;
+       case SetPortFeature:
+               switch (wValue) {
+               case USB_PORT_FEAT_SUSPEND:
+                       usbip_dbg_vhci_rh(
+                               " SetPortFeature: USB_PORT_FEAT_SUSPEND\n");
+                       break;
+               case USB_PORT_FEAT_RESET:
+                       usbip_dbg_vhci_rh(
+                               " SetPortFeature: USB_PORT_FEAT_RESET\n");
+                       /* if it's already running, disconnect first */
+                       if (dum->port_status[rhport] & USB_PORT_STAT_ENABLE) {
+                               dum->port_status[rhport] &=
+                                       ~(USB_PORT_STAT_ENABLE |
+                                         USB_PORT_STAT_LOW_SPEED |
+                                         USB_PORT_STAT_HIGH_SPEED);
+                               /* FIXME test that code path! */
+                       }
+                       /* 50msec reset signaling */
+                       dum->re_timeout = jiffies + msecs_to_jiffies(50);
+
+                       /* FALLTHROUGH */
+               default:
+                       usbip_dbg_vhci_rh(" SetPortFeature: default %d\n",
+                                         wValue);
+                       dum->port_status[rhport] |= (1 << wValue);
+                       break;
+               }
+               break;
+
+       default:
+               pr_err("default: no such request\n");
+
+               /* "protocol stall" on error */
+               retval = -EPIPE;
+       }
+
+       if (usbip_dbg_flag_vhci_rh) {
+               pr_debug("port %d\n", rhport);
+               /* Only dump valid port status */
+               if (rhport >= 0) {
+                       dump_port_status_diff(prev_port_status[rhport],
+                                             dum->port_status[rhport]);
+               }
+       }
+       usbip_dbg_vhci_rh(" bye\n");
+
+       spin_unlock(&dum->lock);
+
+       return retval;
+}
+
+static struct vhci_device *get_vdev(struct usb_device *udev)
+{
+       int i;
+
+       if (!udev)
+               return NULL;
+
+       for (i = 0; i < VHCI_NPORTS; i++)
+               if (the_controller->vdev[i].udev == udev)
+                       return port_to_vdev(i);
+
+       return NULL;
+}
+
+static void vhci_tx_urb(struct urb *urb)
+{
+       struct vhci_device *vdev = get_vdev(urb->dev);
+       struct vhci_priv *priv;
+
+       if (!vdev) {
+               pr_err("could not get virtual device");
+               return;
+       }
+
+       priv = kzalloc(sizeof(struct vhci_priv), GFP_ATOMIC);
+       if (!priv) {
+               usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC);
+               return;
+       }
+
+       spin_lock(&vdev->priv_lock);
+
+       priv->seqnum = atomic_inc_return(&the_controller->seqnum);
+       if (priv->seqnum == 0xffff)
+               dev_info(&urb->dev->dev, "seqnum max\n");
+
+       priv->vdev = vdev;
+       priv->urb = urb;
+
+       urb->hcpriv = (void *) priv;
+
+       list_add_tail(&priv->list, &vdev->priv_tx);
+
+       wake_up(&vdev->waitq_tx);
+       spin_unlock(&vdev->priv_lock);
+}
+
+static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+                           gfp_t mem_flags)
+{
+       struct device *dev = &urb->dev->dev;
+       int ret = 0;
+       struct vhci_device *vdev;
+
+       usbip_dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n",
+                         hcd, urb, mem_flags);
+
+       /* patch to usb_sg_init() is in 2.5.60 */
+       BUG_ON(!urb->transfer_buffer && urb->transfer_buffer_length);
+
+       spin_lock(&the_controller->lock);
+
+       if (urb->status != -EINPROGRESS) {
+               dev_err(dev, "URB already unlinked!, status %d\n", urb->status);
+               spin_unlock(&the_controller->lock);
+               return urb->status;
+       }
+
+       vdev = port_to_vdev(urb->dev->portnum-1);
+
+       /* refuse enqueue for dead connection */
+       spin_lock(&vdev->ud.lock);
+       if (vdev->ud.status == VDEV_ST_NULL ||
+           vdev->ud.status == VDEV_ST_ERROR) {
+               dev_err(dev, "enqueue for inactive port %d\n", vdev->rhport);
+               spin_unlock(&vdev->ud.lock);
+               spin_unlock(&the_controller->lock);
+               return -ENODEV;
+       }
+       spin_unlock(&vdev->ud.lock);
+
+       ret = usb_hcd_link_urb_to_ep(hcd, urb);
+       if (ret)
+               goto no_need_unlink;
+
+       /*
+        * The enumeration process is as follows;
+        *
+        *  1. Get_Descriptor request to DevAddrs(0) EndPoint(0)
+        *     to get max packet length of default pipe
+        *
+        *  2. Set_Address request to DevAddr(0) EndPoint(0)
+        *
+        */
+       if (usb_pipedevice(urb->pipe) == 0) {
+               __u8 type = usb_pipetype(urb->pipe);
+               struct usb_ctrlrequest *ctrlreq =
+                       (struct usb_ctrlrequest *) urb->setup_packet;
+
+               if (type != PIPE_CONTROL || !ctrlreq) {
+                       dev_err(dev, "invalid request to devnum 0\n");
+                       ret = -EINVAL;
+                       goto no_need_xmit;
+               }
+
+               switch (ctrlreq->bRequest) {
+               case USB_REQ_SET_ADDRESS:
+                       /* set_address may come when a device is reset */
+                       dev_info(dev, "SetAddress Request (%d) to port %d\n",
+                                ctrlreq->wValue, vdev->rhport);
+
+                       if (vdev->udev)
+                               usb_put_dev(vdev->udev);
+                       vdev->udev = usb_get_dev(urb->dev);
+
+                       spin_lock(&vdev->ud.lock);
+                       vdev->ud.status = VDEV_ST_USED;
+                       spin_unlock(&vdev->ud.lock);
+
+                       if (urb->status == -EINPROGRESS) {
+                               /* This request is successfully completed. */
+                               /* If not -EINPROGRESS, possibly unlinked. */
+                               urb->status = 0;
+                       }
+
+                       goto no_need_xmit;
+
+               case USB_REQ_GET_DESCRIPTOR:
+                       if (ctrlreq->wValue == cpu_to_le16(USB_DT_DEVICE << 8))
+                               usbip_dbg_vhci_hc(
+                                       "Not yet?:Get_Descriptor to device 0 (get max pipe size)\n");
+
+                       if (vdev->udev)
+                               usb_put_dev(vdev->udev);
+                       vdev->udev = usb_get_dev(urb->dev);
+                       goto out;
+
+               default:
+                       /* NOT REACHED */
+                       dev_err(dev,
+                               "invalid request to devnum 0 bRequest %u, wValue %u\n",
+                               ctrlreq->bRequest,
+                               ctrlreq->wValue);
+                       ret =  -EINVAL;
+                       goto no_need_xmit;
+               }
+
+       }
+
+out:
+       vhci_tx_urb(urb);
+       spin_unlock(&the_controller->lock);
+
+       return 0;
+
+no_need_xmit:
+       usb_hcd_unlink_urb_from_ep(hcd, urb);
+no_need_unlink:
+       spin_unlock(&the_controller->lock);
+       usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status);
+       return ret;
+}
+
+/*
+ * vhci_rx gives back the urb after receiving the reply of the urb.  If an
+ * unlink pdu is sent or not, vhci_rx receives a normal return pdu and gives
+ * back its urb. For the driver unlinking the urb, the content of the urb is
+ * not important, but the calling to its completion handler is important; the
+ * completion of unlinking is notified by the completion handler.
+ *
+ *
+ * CLIENT SIDE
+ *
+ * - When vhci_hcd receives RET_SUBMIT,
+ *
+ *     - case 1a). the urb of the pdu is not unlinking.
+ *             - normal case
+ *             => just give back the urb
+ *
+ *     - case 1b). the urb of the pdu is unlinking.
+ *             - usbip.ko will return a reply of the unlinking request.
+ *             => give back the urb now and go to case 2b).
+ *
+ * - When vhci_hcd receives RET_UNLINK,
+ *
+ *     - case 2a). a submit request is still pending in vhci_hcd.
+ *             - urb was really pending in usbip.ko and urb_unlink_urb() was
+ *               completed there.
+ *             => free a pending submit request
+ *             => notify unlink completeness by giving back the urb
+ *
+ *     - case 2b). a submit request is *not* pending in vhci_hcd.
+ *             - urb was already given back to the core driver.
+ *             => do not give back the urb
+ *
+ *
+ * SERVER SIDE
+ *
+ * - When usbip receives CMD_UNLINK,
+ *
+ *     - case 3a). the urb of the unlink request is now in submission.
+ *             => do usb_unlink_urb().
+ *             => after the unlink is completed, send RET_UNLINK.
+ *
+ *     - case 3b). the urb of the unlink request is not in submission.
+ *             - may be already completed or never be received
+ *             => send RET_UNLINK
+ *
+ */
+static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
+{
+       struct vhci_priv *priv;
+       struct vhci_device *vdev;
+
+       pr_info("dequeue a urb %p\n", urb);
+
+       spin_lock(&the_controller->lock);
+
+       priv = urb->hcpriv;
+       if (!priv) {
+               /* URB was never linked! or will be soon given back by
+                * vhci_rx. */
+               spin_unlock(&the_controller->lock);
+               return 0;
+       }
+
+       {
+               int ret = 0;
+
+               ret = usb_hcd_check_unlink_urb(hcd, urb, status);
+               if (ret) {
+                       spin_unlock(&the_controller->lock);
+                       return ret;
+               }
+       }
+
+        /* send unlink request here? */
+       vdev = priv->vdev;
+
+       if (!vdev->ud.tcp_socket) {
+               /* tcp connection is closed */
+               spin_lock(&vdev->priv_lock);
+
+               pr_info("device %p seems to be disconnected\n", vdev);
+               list_del(&priv->list);
+               kfree(priv);
+               urb->hcpriv = NULL;
+
+               spin_unlock(&vdev->priv_lock);
+
+               /*
+                * If tcp connection is alive, we have sent CMD_UNLINK.
+                * vhci_rx will receive RET_UNLINK and give back the URB.
+                * Otherwise, we give back it here.
+                */
+               pr_info("gives back urb %p\n", urb);
+
+               usb_hcd_unlink_urb_from_ep(hcd, urb);
+
+               spin_unlock(&the_controller->lock);
+               usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
+                                    urb->status);
+               spin_lock(&the_controller->lock);
+
+       } else {
+               /* tcp connection is alive */
+               struct vhci_unlink *unlink;
+
+               spin_lock(&vdev->priv_lock);
+
+               /* setup CMD_UNLINK pdu */
+               unlink = kzalloc(sizeof(struct vhci_unlink), GFP_ATOMIC);
+               if (!unlink) {
+                       spin_unlock(&vdev->priv_lock);
+                       spin_unlock(&the_controller->lock);
+                       usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_MALLOC);
+                       return -ENOMEM;
+               }
+
+               unlink->seqnum = atomic_inc_return(&the_controller->seqnum);
+               if (unlink->seqnum == 0xffff)
+                       pr_info("seqnum max\n");
+
+               unlink->unlink_seqnum = priv->seqnum;
+
+               pr_info("device %p seems to be still connected\n", vdev);
+
+               /* send cmd_unlink and try to cancel the pending URB in the
+                * peer */
+               list_add_tail(&unlink->list, &vdev->unlink_tx);
+               wake_up(&vdev->waitq_tx);
+
+               spin_unlock(&vdev->priv_lock);
+       }
+
+       spin_unlock(&the_controller->lock);
+
+       usbip_dbg_vhci_hc("leave\n");
+       return 0;
+}
+
+static void vhci_device_unlink_cleanup(struct vhci_device *vdev)
+{
+       struct vhci_unlink *unlink, *tmp;
+
+       spin_lock(&the_controller->lock);
+       spin_lock(&vdev->priv_lock);
+
+       list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) {
+               pr_info("unlink cleanup tx %lu\n", unlink->unlink_seqnum);
+               list_del(&unlink->list);
+               kfree(unlink);
+       }
+
+       while (!list_empty(&vdev->unlink_rx)) {
+               struct urb *urb;
+
+               unlink = list_first_entry(&vdev->unlink_rx, struct vhci_unlink,
+                       list);
+
+               /* give back URB of unanswered unlink request */
+               pr_info("unlink cleanup rx %lu\n", unlink->unlink_seqnum);
+
+               urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum);
+               if (!urb) {
+                       pr_info("the urb (seqnum %lu) was already given back\n",
+                               unlink->unlink_seqnum);
+                       list_del(&unlink->list);
+                       kfree(unlink);
+                       continue;
+               }
+
+               urb->status = -ENODEV;
+
+               usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
+
+               list_del(&unlink->list);
+
+               spin_unlock(&vdev->priv_lock);
+               spin_unlock(&the_controller->lock);
+
+               usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
+                                    urb->status);
+
+               spin_lock(&the_controller->lock);
+               spin_lock(&vdev->priv_lock);
+
+               kfree(unlink);
+       }
+
+       spin_unlock(&vdev->priv_lock);
+       spin_unlock(&the_controller->lock);
+}
+
+/*
+ * The important thing is that only one context begins cleanup.
+ * This is why error handling and cleanup become simple.
+ * We do not want to consider race condition as possible.
+ */
+static void vhci_shutdown_connection(struct usbip_device *ud)
+{
+       struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
+
+       /* need this? see stub_dev.c */
+       if (ud->tcp_socket) {
+               pr_debug("shutdown tcp_socket %p\n", ud->tcp_socket);
+               kernel_sock_shutdown(ud->tcp_socket, SHUT_RDWR);
+       }
+
+       /* kill threads related to this sdev */
+       if (vdev->ud.tcp_rx) {
+               kthread_stop_put(vdev->ud.tcp_rx);
+               vdev->ud.tcp_rx = NULL;
+       }
+       if (vdev->ud.tcp_tx) {
+               kthread_stop_put(vdev->ud.tcp_tx);
+               vdev->ud.tcp_tx = NULL;
+       }
+       pr_info("stop threads\n");
+
+       /* active connection is closed */
+       if (vdev->ud.tcp_socket) {
+               sockfd_put(vdev->ud.tcp_socket);
+               vdev->ud.tcp_socket = NULL;
+       }
+       pr_info("release socket\n");
+
+       vhci_device_unlink_cleanup(vdev);
+
+       /*
+        * rh_port_disconnect() is a trigger of ...
+        *   usb_disable_device():
+        *      disable all the endpoints for a USB device.
+        *   usb_disable_endpoint():
+        *      disable endpoints. pending urbs are unlinked(dequeued).
+        *
+        * NOTE: After calling rh_port_disconnect(), the USB device drivers of a
+        * detached device should release used urbs in a cleanup function (i.e.
+        * xxx_disconnect()). Therefore, vhci_hcd does not need to release
+        * pushed urbs and their private data in this function.
+        *
+        * NOTE: vhci_dequeue() must be considered carefully. When shutting down
+        * a connection, vhci_shutdown_connection() expects vhci_dequeue()
+        * gives back pushed urbs and frees their private data by request of
+        * the cleanup function of a USB driver. When unlinking a urb with an
+        * active connection, vhci_dequeue() does not give back the urb which
+        * is actually given back by vhci_rx after receiving its return pdu.
+        *
+        */
+       rh_port_disconnect(vdev->rhport);
+
+       pr_info("disconnect device\n");
+}
+
+
+static void vhci_device_reset(struct usbip_device *ud)
+{
+       struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
+
+       spin_lock(&ud->lock);
+
+       vdev->speed  = 0;
+       vdev->devid  = 0;
+
+       if (vdev->udev)
+               usb_put_dev(vdev->udev);
+       vdev->udev = NULL;
+
+       if (ud->tcp_socket) {
+               sockfd_put(ud->tcp_socket);
+               ud->tcp_socket = NULL;
+       }
+       ud->status = VDEV_ST_NULL;
+
+       spin_unlock(&ud->lock);
+}
+
+static void vhci_device_unusable(struct usbip_device *ud)
+{
+       spin_lock(&ud->lock);
+       ud->status = VDEV_ST_ERROR;
+       spin_unlock(&ud->lock);
+}
+
+static void vhci_device_init(struct vhci_device *vdev)
+{
+       memset(vdev, 0, sizeof(*vdev));
+
+       vdev->ud.side   = USBIP_VHCI;
+       vdev->ud.status = VDEV_ST_NULL;
+       spin_lock_init(&vdev->ud.lock);
+
+       INIT_LIST_HEAD(&vdev->priv_rx);
+       INIT_LIST_HEAD(&vdev->priv_tx);
+       INIT_LIST_HEAD(&vdev->unlink_tx);
+       INIT_LIST_HEAD(&vdev->unlink_rx);
+       spin_lock_init(&vdev->priv_lock);
+
+       init_waitqueue_head(&vdev->waitq_tx);
+
+       vdev->ud.eh_ops.shutdown = vhci_shutdown_connection;
+       vdev->ud.eh_ops.reset = vhci_device_reset;
+       vdev->ud.eh_ops.unusable = vhci_device_unusable;
+
+       usbip_start_eh(&vdev->ud);
+}
+
+static int vhci_start(struct usb_hcd *hcd)
+{
+       struct vhci_hcd *vhci = hcd_to_vhci(hcd);
+       int rhport;
+       int err = 0;
+
+       usbip_dbg_vhci_hc("enter vhci_start\n");
+
+       /* initialize private data of usb_hcd */
+
+       for (rhport = 0; rhport < VHCI_NPORTS; rhport++) {
+               struct vhci_device *vdev = &vhci->vdev[rhport];
+
+               vhci_device_init(vdev);
+               vdev->rhport = rhport;
+       }
+
+       atomic_set(&vhci->seqnum, 0);
+       spin_lock_init(&vhci->lock);
+
+       hcd->power_budget = 0; /* no limit */
+       hcd->uses_new_polling = 1;
+
+       /* vhci_hcd is now ready to be controlled through sysfs */
+       err = sysfs_create_group(&vhci_dev(vhci)->kobj, &dev_attr_group);
+       if (err) {
+               pr_err("create sysfs files\n");
+               return err;
+       }
+
+       return 0;
+}
+
+static void vhci_stop(struct usb_hcd *hcd)
+{
+       struct vhci_hcd *vhci = hcd_to_vhci(hcd);
+       int rhport = 0;
+
+       usbip_dbg_vhci_hc("stop VHCI controller\n");
+
+       /* 1. remove the userland interface of vhci_hcd */
+       sysfs_remove_group(&vhci_dev(vhci)->kobj, &dev_attr_group);
+
+       /* 2. shutdown all the ports of vhci_hcd */
+       for (rhport = 0; rhport < VHCI_NPORTS; rhport++) {
+               struct vhci_device *vdev = &vhci->vdev[rhport];
+
+               usbip_event_add(&vdev->ud, VDEV_EVENT_REMOVED);
+               usbip_stop_eh(&vdev->ud);
+       }
+}
+
+static int vhci_get_frame_number(struct usb_hcd *hcd)
+{
+       pr_err("Not yet implemented\n");
+       return 0;
+}
+
+#ifdef CONFIG_PM
+
+/* FIXME: suspend/resume */
+static int vhci_bus_suspend(struct usb_hcd *hcd)
+{
+       struct vhci_hcd *vhci = hcd_to_vhci(hcd);
+
+       dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
+
+       spin_lock(&vhci->lock);
+       hcd->state = HC_STATE_SUSPENDED;
+       spin_unlock(&vhci->lock);
+
+       return 0;
+}
+
+static int vhci_bus_resume(struct usb_hcd *hcd)
+{
+       struct vhci_hcd *vhci = hcd_to_vhci(hcd);
+       int rc = 0;
+
+       dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__);
+
+       spin_lock(&vhci->lock);
+       if (!HCD_HW_ACCESSIBLE(hcd))
+               rc = -ESHUTDOWN;
+       else
+               hcd->state = HC_STATE_RUNNING;
+       spin_unlock(&vhci->lock);
+
+       return rc;
+}
+
+#else
+
+#define vhci_bus_suspend      NULL
+#define vhci_bus_resume       NULL
+#endif
+
+static struct hc_driver vhci_hc_driver = {
+       .description    = driver_name,
+       .product_desc   = driver_desc,
+       .hcd_priv_size  = sizeof(struct vhci_hcd),
+
+       .flags          = HCD_USB2,
+
+       .start          = vhci_start,
+       .stop           = vhci_stop,
+
+       .urb_enqueue    = vhci_urb_enqueue,
+       .urb_dequeue    = vhci_urb_dequeue,
+
+       .get_frame_number = vhci_get_frame_number,
+
+       .hub_status_data = vhci_hub_status,
+       .hub_control    = vhci_hub_control,
+       .bus_suspend    = vhci_bus_suspend,
+       .bus_resume     = vhci_bus_resume,
+};
+
+static int vhci_hcd_probe(struct platform_device *pdev)
+{
+       struct usb_hcd          *hcd;
+       int                     ret;
+
+       usbip_dbg_vhci_hc("name %s id %d\n", pdev->name, pdev->id);
+
+       /*
+        * Allocate and initialize hcd.
+        * Our private data is also allocated automatically.
+        */
+       hcd = usb_create_hcd(&vhci_hc_driver, &pdev->dev, dev_name(&pdev->dev));
+       if (!hcd) {
+               pr_err("create hcd failed\n");
+               return -ENOMEM;
+       }
+       hcd->has_tt = 1;
+
+       /* this is private data for vhci_hcd */
+       the_controller = hcd_to_vhci(hcd);
+
+       /*
+        * Finish generic HCD structure initialization and register.
+        * Call the driver's reset() and start() routines.
+        */
+       ret = usb_add_hcd(hcd, 0, 0);
+       if (ret != 0) {
+               pr_err("usb_add_hcd failed %d\n", ret);
+               usb_put_hcd(hcd);
+               the_controller = NULL;
+               return ret;
+       }
+
+       usbip_dbg_vhci_hc("bye\n");
+       return 0;
+}
+
+static int vhci_hcd_remove(struct platform_device *pdev)
+{
+       struct usb_hcd  *hcd;
+
+       hcd = platform_get_drvdata(pdev);
+       if (!hcd)
+               return 0;
+
+       /*
+        * Disconnects the root hub,
+        * then reverses the effects of usb_add_hcd(),
+        * invoking the HCD's stop() methods.
+        */
+       usb_remove_hcd(hcd);
+       usb_put_hcd(hcd);
+       the_controller = NULL;
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+
+/* what should happen for USB/IP under suspend/resume? */
+static int vhci_hcd_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct usb_hcd *hcd;
+       int rhport = 0;
+       int connected = 0;
+       int ret = 0;
+
+       hcd = platform_get_drvdata(pdev);
+
+       spin_lock(&the_controller->lock);
+
+       for (rhport = 0; rhport < VHCI_NPORTS; rhport++)
+               if (the_controller->port_status[rhport] &
+                   USB_PORT_STAT_CONNECTION)
+                       connected += 1;
+
+       spin_unlock(&the_controller->lock);
+
+       if (connected > 0) {
+               dev_info(&pdev->dev,
+                        "We have %d active connection%s. Do not suspend.\n",
+                        connected, (connected == 1 ? "" : "s"));
+               ret =  -EBUSY;
+       } else {
+               dev_info(&pdev->dev, "suspend vhci_hcd");
+               clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+       }
+
+       return ret;
+}
+
+static int vhci_hcd_resume(struct platform_device *pdev)
+{
+       struct usb_hcd *hcd;
+
+       dev_dbg(&pdev->dev, "%s\n", __func__);
+
+       hcd = platform_get_drvdata(pdev);
+       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+       usb_hcd_poll_rh_status(hcd);
+
+       return 0;
+}
+
+#else
+
+#define vhci_hcd_suspend       NULL
+#define vhci_hcd_resume                NULL
+
+#endif
+
+static struct platform_driver vhci_driver = {
+       .probe  = vhci_hcd_probe,
+       .remove = vhci_hcd_remove,
+       .suspend = vhci_hcd_suspend,
+       .resume = vhci_hcd_resume,
+       .driver = {
+               .name = driver_name,
+               .owner = THIS_MODULE,
+       },
+};
+
+/*
+ * The VHCI 'device' is 'virtual'; not a real plug&play hardware.
+ * We need to add this virtual device as a platform device arbitrarily:
+ *     1. platform_device_register()
+ */
+static void the_pdev_release(struct device *dev)
+{
+}
+
+static struct platform_device the_pdev = {
+       /* should be the same name as driver_name */
+       .name = driver_name,
+       .id = -1,
+       .dev = {
+               .release = the_pdev_release,
+       },
+};
+
+static int __init vhci_hcd_init(void)
+{
+       int ret;
+
+       if (usb_disabled())
+               return -ENODEV;
+
+       ret = platform_driver_register(&vhci_driver);
+       if (ret)
+               goto err_driver_register;
+
+       ret = platform_device_register(&the_pdev);
+       if (ret)
+               goto err_platform_device_register;
+
+       pr_info(DRIVER_DESC " v" USBIP_VERSION "\n");
+       return ret;
+
+err_platform_device_register:
+       platform_driver_unregister(&vhci_driver);
+err_driver_register:
+       return ret;
+}
+
+static void __exit vhci_hcd_exit(void)
+{
+       platform_device_unregister(&the_pdev);
+       platform_driver_unregister(&vhci_driver);
+}
+
+module_init(vhci_hcd_init);
+module_exit(vhci_hcd_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_VERSION(USBIP_VERSION);
diff --git a/drivers/usb/usbip/vhci_rx.c b/drivers/usb/usbip/vhci_rx.c
new file mode 100644 (file)
index 0000000..00e4a54
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <linux/kthread.h>
+#include <linux/slab.h>
+
+#include "usbip_common.h"
+#include "vhci.h"
+
+/* get URB from transmitted urb queue. caller must hold vdev->priv_lock */
+struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, __u32 seqnum)
+{
+       struct vhci_priv *priv, *tmp;
+       struct urb *urb = NULL;
+       int status;
+
+       list_for_each_entry_safe(priv, tmp, &vdev->priv_rx, list) {
+               if (priv->seqnum != seqnum)
+                       continue;
+
+               urb = priv->urb;
+               status = urb->status;
+
+               usbip_dbg_vhci_rx("find urb %p vurb %p seqnum %u\n",
+                               urb, priv, seqnum);
+
+               switch (status) {
+               case -ENOENT:
+                       /* fall through */
+               case -ECONNRESET:
+                       dev_info(&urb->dev->dev,
+                                "urb %p was unlinked %ssynchronuously.\n", urb,
+                                status == -ENOENT ? "" : "a");
+                       break;
+               case -EINPROGRESS:
+                       /* no info output */
+                       break;
+               default:
+                       dev_info(&urb->dev->dev,
+                                "urb %p may be in a error, status %d\n", urb,
+                                status);
+               }
+
+               list_del(&priv->list);
+               kfree(priv);
+               urb->hcpriv = NULL;
+
+               break;
+       }
+
+       return urb;
+}
+
+static void vhci_recv_ret_submit(struct vhci_device *vdev,
+                                struct usbip_header *pdu)
+{
+       struct usbip_device *ud = &vdev->ud;
+       struct urb *urb;
+
+       spin_lock(&vdev->priv_lock);
+       urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum);
+       spin_unlock(&vdev->priv_lock);
+
+       if (!urb) {
+               pr_err("cannot find a urb of seqnum %u\n", pdu->base.seqnum);
+               pr_info("max seqnum %d\n",
+                       atomic_read(&the_controller->seqnum));
+               usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
+               return;
+       }
+
+       /* unpack the pdu to a urb */
+       usbip_pack_pdu(pdu, urb, USBIP_RET_SUBMIT, 0);
+
+       /* recv transfer buffer */
+       if (usbip_recv_xbuff(ud, urb) < 0)
+               return;
+
+       /* recv iso_packet_descriptor */
+       if (usbip_recv_iso(ud, urb) < 0)
+               return;
+
+       /* restore the padding in iso packets */
+       usbip_pad_iso(ud, urb);
+
+       if (usbip_dbg_flag_vhci_rx)
+               usbip_dump_urb(urb);
+
+       usbip_dbg_vhci_rx("now giveback urb %p\n", urb);
+
+       spin_lock(&the_controller->lock);
+       usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
+       spin_unlock(&the_controller->lock);
+
+       usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status);
+
+       usbip_dbg_vhci_rx("Leave\n");
+}
+
+static struct vhci_unlink *dequeue_pending_unlink(struct vhci_device *vdev,
+                                                 struct usbip_header *pdu)
+{
+       struct vhci_unlink *unlink, *tmp;
+
+       spin_lock(&vdev->priv_lock);
+
+       list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) {
+               pr_info("unlink->seqnum %lu\n", unlink->seqnum);
+               if (unlink->seqnum == pdu->base.seqnum) {
+                       usbip_dbg_vhci_rx("found pending unlink, %lu\n",
+                                         unlink->seqnum);
+                       list_del(&unlink->list);
+
+                       spin_unlock(&vdev->priv_lock);
+                       return unlink;
+               }
+       }
+
+       spin_unlock(&vdev->priv_lock);
+
+       return NULL;
+}
+
+static void vhci_recv_ret_unlink(struct vhci_device *vdev,
+                                struct usbip_header *pdu)
+{
+       struct vhci_unlink *unlink;
+       struct urb *urb;
+
+       usbip_dump_header(pdu);
+
+       unlink = dequeue_pending_unlink(vdev, pdu);
+       if (!unlink) {
+               pr_info("cannot find the pending unlink %u\n",
+                       pdu->base.seqnum);
+               return;
+       }
+
+       spin_lock(&vdev->priv_lock);
+       urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum);
+       spin_unlock(&vdev->priv_lock);
+
+       if (!urb) {
+               /*
+                * I get the result of a unlink request. But, it seems that I
+                * already received the result of its submit result and gave
+                * back the URB.
+                */
+               pr_info("the urb (seqnum %d) was already given back\n",
+                       pdu->base.seqnum);
+       } else {
+               usbip_dbg_vhci_rx("now giveback urb %p\n", urb);
+
+               /* If unlink is successful, status is -ECONNRESET */
+               urb->status = pdu->u.ret_unlink.status;
+               pr_info("urb->status %d\n", urb->status);
+
+               spin_lock(&the_controller->lock);
+               usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
+               spin_unlock(&the_controller->lock);
+
+               usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
+                                    urb->status);
+       }
+
+       kfree(unlink);
+}
+
+static int vhci_priv_tx_empty(struct vhci_device *vdev)
+{
+       int empty = 0;
+
+       spin_lock(&vdev->priv_lock);
+       empty = list_empty(&vdev->priv_rx);
+       spin_unlock(&vdev->priv_lock);
+
+       return empty;
+}
+
+/* recv a pdu */
+static void vhci_rx_pdu(struct usbip_device *ud)
+{
+       int ret;
+       struct usbip_header pdu;
+       struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
+
+       usbip_dbg_vhci_rx("Enter\n");
+
+       memset(&pdu, 0, sizeof(pdu));
+
+       /* receive a pdu header */
+       ret = usbip_recv(ud->tcp_socket, &pdu, sizeof(pdu));
+       if (ret < 0) {
+               if (ret == -ECONNRESET)
+                       pr_info("connection reset by peer\n");
+               else if (ret == -EAGAIN) {
+                       /* ignore if connection was idle */
+                       if (vhci_priv_tx_empty(vdev))
+                               return;
+                       pr_info("connection timed out with pending urbs\n");
+               } else if (ret != -ERESTARTSYS)
+                       pr_info("xmit failed %d\n", ret);
+
+               usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
+               return;
+       }
+       if (ret == 0) {
+               pr_info("connection closed");
+               usbip_event_add(ud, VDEV_EVENT_DOWN);
+               return;
+       }
+       if (ret != sizeof(pdu)) {
+               pr_err("received pdu size is %d, should be %d\n", ret,
+                      (unsigned int)sizeof(pdu));
+               usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
+               return;
+       }
+
+       usbip_header_correct_endian(&pdu, 0);
+
+       if (usbip_dbg_flag_vhci_rx)
+               usbip_dump_header(&pdu);
+
+       switch (pdu.base.command) {
+       case USBIP_RET_SUBMIT:
+               vhci_recv_ret_submit(vdev, &pdu);
+               break;
+       case USBIP_RET_UNLINK:
+               vhci_recv_ret_unlink(vdev, &pdu);
+               break;
+       default:
+               /* NOT REACHED */
+               pr_err("unknown pdu %u\n", pdu.base.command);
+               usbip_dump_header(&pdu);
+               usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
+               break;
+       }
+}
+
+int vhci_rx_loop(void *data)
+{
+       struct usbip_device *ud = data;
+
+       while (!kthread_should_stop()) {
+               if (usbip_event_happened(ud))
+                       break;
+
+               vhci_rx_pdu(ud);
+       }
+
+       return 0;
+}
diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c
new file mode 100644 (file)
index 0000000..211f43f
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <linux/kthread.h>
+#include <linux/file.h>
+#include <linux/net.h>
+
+#include "usbip_common.h"
+#include "vhci.h"
+
+/* TODO: refine locking ?*/
+
+/* Sysfs entry to show port status */
+static ssize_t status_show(struct device *dev, struct device_attribute *attr,
+                          char *out)
+{
+       char *s = out;
+       int i = 0;
+
+       BUG_ON(!the_controller || !out);
+
+       spin_lock(&the_controller->lock);
+
+       /*
+        * output example:
+        * prt sta spd dev socket           local_busid
+        * 000 004 000 000         c5a7bb80 1-2.3
+        * 001 004 000 000         d8cee980 2-3.4
+        *
+        * IP address can be retrieved from a socket pointer address by looking
+        * up /proc/net/{tcp,tcp6}. Also, a userland program may remember a
+        * port number and its peer IP address.
+        */
+       out += sprintf(out,
+                      "prt sta spd bus dev socket           local_busid\n");
+
+       for (i = 0; i < VHCI_NPORTS; i++) {
+               struct vhci_device *vdev = port_to_vdev(i);
+
+               spin_lock(&vdev->ud.lock);
+               out += sprintf(out, "%03u %03u ", i, vdev->ud.status);
+
+               if (vdev->ud.status == VDEV_ST_USED) {
+                       out += sprintf(out, "%03u %08x ",
+                                      vdev->speed, vdev->devid);
+                       out += sprintf(out, "%16p ", vdev->ud.tcp_socket);
+                       out += sprintf(out, "%s", dev_name(&vdev->udev->dev));
+
+               } else {
+                       out += sprintf(out, "000 000 000 0000000000000000 0-0");
+               }
+
+               out += sprintf(out, "\n");
+               spin_unlock(&vdev->ud.lock);
+       }
+
+       spin_unlock(&the_controller->lock);
+
+       return out - s;
+}
+static DEVICE_ATTR_RO(status);
+
+/* Sysfs entry to shutdown a virtual connection */
+static int vhci_port_disconnect(__u32 rhport)
+{
+       struct vhci_device *vdev;
+
+       usbip_dbg_vhci_sysfs("enter\n");
+
+       /* lock */
+       spin_lock(&the_controller->lock);
+
+       vdev = port_to_vdev(rhport);
+
+       spin_lock(&vdev->ud.lock);
+       if (vdev->ud.status == VDEV_ST_NULL) {
+               pr_err("not connected %d\n", vdev->ud.status);
+
+               /* unlock */
+               spin_unlock(&vdev->ud.lock);
+               spin_unlock(&the_controller->lock);
+
+               return -EINVAL;
+       }
+
+       /* unlock */
+       spin_unlock(&vdev->ud.lock);
+       spin_unlock(&the_controller->lock);
+
+       usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN);
+
+       return 0;
+}
+
+static ssize_t store_detach(struct device *dev, struct device_attribute *attr,
+                           const char *buf, size_t count)
+{
+       int err;
+       __u32 rhport = 0;
+
+       if (sscanf(buf, "%u", &rhport) != 1)
+               return -EINVAL;
+
+       /* check rhport */
+       if (rhport >= VHCI_NPORTS) {
+               dev_err(dev, "invalid port %u\n", rhport);
+               return -EINVAL;
+       }
+
+       err = vhci_port_disconnect(rhport);
+       if (err < 0)
+               return -EINVAL;
+
+       usbip_dbg_vhci_sysfs("Leave\n");
+
+       return count;
+}
+static DEVICE_ATTR(detach, S_IWUSR, NULL, store_detach);
+
+/* Sysfs entry to establish a virtual connection */
+static int valid_args(__u32 rhport, enum usb_device_speed speed)
+{
+       /* check rhport */
+       if (rhport >= VHCI_NPORTS) {
+               pr_err("port %u\n", rhport);
+               return -EINVAL;
+       }
+
+       /* check speed */
+       switch (speed) {
+       case USB_SPEED_LOW:
+       case USB_SPEED_FULL:
+       case USB_SPEED_HIGH:
+       case USB_SPEED_WIRELESS:
+               break;
+       default:
+               pr_err("Failed attach request for unsupported USB speed: %s\n",
+                       usb_speed_string(speed));
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/*
+ * To start a new USB/IP attachment, a userland program needs to setup a TCP
+ * connection and then write its socket descriptor with remote device
+ * information into this sysfs file.
+ *
+ * A remote device is virtually attached to the root-hub port of @rhport with
+ * @speed. @devid is embedded into a request to specify the remote device in a
+ * server host.
+ *
+ * write() returns 0 on success, else negative errno.
+ */
+static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
+                           const char *buf, size_t count)
+{
+       struct vhci_device *vdev;
+       struct socket *socket;
+       int sockfd = 0;
+       __u32 rhport = 0, devid = 0, speed = 0;
+       int err;
+
+       /*
+        * @rhport: port number of vhci_hcd
+        * @sockfd: socket descriptor of an established TCP connection
+        * @devid: unique device identifier in a remote host
+        * @speed: usb device speed in a remote host
+        */
+       if (sscanf(buf, "%u %u %u %u", &rhport, &sockfd, &devid, &speed) != 4)
+               return -EINVAL;
+
+       usbip_dbg_vhci_sysfs("rhport(%u) sockfd(%u) devid(%u) speed(%u)\n",
+                            rhport, sockfd, devid, speed);
+
+       /* check received parameters */
+       if (valid_args(rhport, speed) < 0)
+               return -EINVAL;
+
+       /* Extract socket from fd. */
+       socket = sockfd_lookup(sockfd, &err);
+       if (!socket)
+               return -EINVAL;
+
+       /* now need lock until setting vdev status as used */
+
+       /* begin a lock */
+       spin_lock(&the_controller->lock);
+       vdev = port_to_vdev(rhport);
+       spin_lock(&vdev->ud.lock);
+
+       if (vdev->ud.status != VDEV_ST_NULL) {
+               /* end of the lock */
+               spin_unlock(&vdev->ud.lock);
+               spin_unlock(&the_controller->lock);
+
+               sockfd_put(socket);
+
+               dev_err(dev, "port %d already used\n", rhport);
+               return -EINVAL;
+       }
+
+       dev_info(dev,
+                "rhport(%u) sockfd(%d) devid(%u) speed(%u) speed_str(%s)\n",
+                rhport, sockfd, devid, speed, usb_speed_string(speed));
+
+       vdev->devid         = devid;
+       vdev->speed         = speed;
+       vdev->ud.tcp_socket = socket;
+       vdev->ud.status     = VDEV_ST_NOTASSIGNED;
+
+       spin_unlock(&vdev->ud.lock);
+       spin_unlock(&the_controller->lock);
+       /* end the lock */
+
+       vdev->ud.tcp_rx = kthread_get_run(vhci_rx_loop, &vdev->ud, "vhci_rx");
+       vdev->ud.tcp_tx = kthread_get_run(vhci_tx_loop, &vdev->ud, "vhci_tx");
+
+       rh_port_connect(rhport, speed);
+
+       return count;
+}
+static DEVICE_ATTR(attach, S_IWUSR, NULL, store_attach);
+
+static struct attribute *dev_attrs[] = {
+       &dev_attr_status.attr,
+       &dev_attr_detach.attr,
+       &dev_attr_attach.attr,
+       &dev_attr_usbip_debug.attr,
+       NULL,
+};
+
+const struct attribute_group dev_attr_group = {
+       .attrs = dev_attrs,
+};
diff --git a/drivers/usb/usbip/vhci_tx.c b/drivers/usb/usbip/vhci_tx.c
new file mode 100644 (file)
index 0000000..409fd99
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2003-2008 Takahiro Hirofuchi
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <linux/kthread.h>
+#include <linux/slab.h>
+
+#include "usbip_common.h"
+#include "vhci.h"
+
+static void setup_cmd_submit_pdu(struct usbip_header *pdup,  struct urb *urb)
+{
+       struct vhci_priv *priv = ((struct vhci_priv *)urb->hcpriv);
+       struct vhci_device *vdev = priv->vdev;
+
+       usbip_dbg_vhci_tx("URB, local devnum %u, remote devid %u\n",
+                         usb_pipedevice(urb->pipe), vdev->devid);
+
+       pdup->base.command   = USBIP_CMD_SUBMIT;
+       pdup->base.seqnum    = priv->seqnum;
+       pdup->base.devid     = vdev->devid;
+       pdup->base.direction = usb_pipein(urb->pipe) ?
+               USBIP_DIR_IN : USBIP_DIR_OUT;
+       pdup->base.ep        = usb_pipeendpoint(urb->pipe);
+
+       usbip_pack_pdu(pdup, urb, USBIP_CMD_SUBMIT, 1);
+
+       if (urb->setup_packet)
+               memcpy(pdup->u.cmd_submit.setup, urb->setup_packet, 8);
+}
+
+static struct vhci_priv *dequeue_from_priv_tx(struct vhci_device *vdev)
+{
+       struct vhci_priv *priv, *tmp;
+
+       spin_lock(&vdev->priv_lock);
+
+       list_for_each_entry_safe(priv, tmp, &vdev->priv_tx, list) {
+               list_move_tail(&priv->list, &vdev->priv_rx);
+               spin_unlock(&vdev->priv_lock);
+               return priv;
+       }
+
+       spin_unlock(&vdev->priv_lock);
+
+       return NULL;
+}
+
+static int vhci_send_cmd_submit(struct vhci_device *vdev)
+{
+       struct vhci_priv *priv = NULL;
+
+       struct msghdr msg;
+       struct kvec iov[3];
+       size_t txsize;
+
+       size_t total_size = 0;
+
+       while ((priv = dequeue_from_priv_tx(vdev)) != NULL) {
+               int ret;
+               struct urb *urb = priv->urb;
+               struct usbip_header pdu_header;
+               struct usbip_iso_packet_descriptor *iso_buffer = NULL;
+
+               txsize = 0;
+               memset(&pdu_header, 0, sizeof(pdu_header));
+               memset(&msg, 0, sizeof(msg));
+               memset(&iov, 0, sizeof(iov));
+
+               usbip_dbg_vhci_tx("setup txdata urb %p\n", urb);
+
+               /* 1. setup usbip_header */
+               setup_cmd_submit_pdu(&pdu_header, urb);
+               usbip_header_correct_endian(&pdu_header, 1);
+
+               iov[0].iov_base = &pdu_header;
+               iov[0].iov_len  = sizeof(pdu_header);
+               txsize += sizeof(pdu_header);
+
+               /* 2. setup transfer buffer */
+               if (!usb_pipein(urb->pipe) && urb->transfer_buffer_length > 0) {
+                       iov[1].iov_base = urb->transfer_buffer;
+                       iov[1].iov_len  = urb->transfer_buffer_length;
+                       txsize += urb->transfer_buffer_length;
+               }
+
+               /* 3. setup iso_packet_descriptor */
+               if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+                       ssize_t len = 0;
+
+                       iso_buffer = usbip_alloc_iso_desc_pdu(urb, &len);
+                       if (!iso_buffer) {
+                               usbip_event_add(&vdev->ud,
+                                               SDEV_EVENT_ERROR_MALLOC);
+                               return -1;
+                       }
+
+                       iov[2].iov_base = iso_buffer;
+                       iov[2].iov_len  = len;
+                       txsize += len;
+               }
+
+               ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, iov, 3, txsize);
+               if (ret != txsize) {
+                       pr_err("sendmsg failed!, ret=%d for %zd\n", ret,
+                              txsize);
+                       kfree(iso_buffer);
+                       usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP);
+                       return -1;
+               }
+
+               kfree(iso_buffer);
+               usbip_dbg_vhci_tx("send txdata\n");
+
+               total_size += txsize;
+       }
+
+       return total_size;
+}
+
+static struct vhci_unlink *dequeue_from_unlink_tx(struct vhci_device *vdev)
+{
+       struct vhci_unlink *unlink, *tmp;
+
+       spin_lock(&vdev->priv_lock);
+
+       list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) {
+               list_move_tail(&unlink->list, &vdev->unlink_rx);
+               spin_unlock(&vdev->priv_lock);
+               return unlink;
+       }
+
+       spin_unlock(&vdev->priv_lock);
+
+       return NULL;
+}
+
+static int vhci_send_cmd_unlink(struct vhci_device *vdev)
+{
+       struct vhci_unlink *unlink = NULL;
+
+       struct msghdr msg;
+       struct kvec iov[3];
+       size_t txsize;
+
+       size_t total_size = 0;
+
+       while ((unlink = dequeue_from_unlink_tx(vdev)) != NULL) {
+               int ret;
+               struct usbip_header pdu_header;
+
+               txsize = 0;
+               memset(&pdu_header, 0, sizeof(pdu_header));
+               memset(&msg, 0, sizeof(msg));
+               memset(&iov, 0, sizeof(iov));
+
+               usbip_dbg_vhci_tx("setup cmd unlink, %lu\n", unlink->seqnum);
+
+               /* 1. setup usbip_header */
+               pdu_header.base.command = USBIP_CMD_UNLINK;
+               pdu_header.base.seqnum  = unlink->seqnum;
+               pdu_header.base.devid   = vdev->devid;
+               pdu_header.base.ep      = 0;
+               pdu_header.u.cmd_unlink.seqnum = unlink->unlink_seqnum;
+
+               usbip_header_correct_endian(&pdu_header, 1);
+
+               iov[0].iov_base = &pdu_header;
+               iov[0].iov_len  = sizeof(pdu_header);
+               txsize += sizeof(pdu_header);
+
+               ret = kernel_sendmsg(vdev->ud.tcp_socket, &msg, iov, 1, txsize);
+               if (ret != txsize) {
+                       pr_err("sendmsg failed!, ret=%d for %zd\n", ret,
+                              txsize);
+                       usbip_event_add(&vdev->ud, VDEV_EVENT_ERROR_TCP);
+                       return -1;
+               }
+
+               usbip_dbg_vhci_tx("send txdata\n");
+
+               total_size += txsize;
+       }
+
+       return total_size;
+}
+
+int vhci_tx_loop(void *data)
+{
+       struct usbip_device *ud = data;
+       struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
+
+       while (!kthread_should_stop()) {
+               if (vhci_send_cmd_submit(vdev) < 0)
+                       break;
+
+               if (vhci_send_cmd_unlink(vdev) < 0)
+                       break;
+
+               wait_event_interruptible(vdev->waitq_tx,
+                                        (!list_empty(&vdev->priv_tx) ||
+                                         !list_empty(&vdev->unlink_tx) ||
+                                         kthread_should_stop()));
+
+               usbip_dbg_vhci_tx("pending urbs ?, now wake up\n");
+       }
+
+       return 0;
+}
index 3e2e4ed2015739bf9acd3cea2a7fd22fa8c3a1d8..e279015be466166742367f7bcb958639f856b447 100644 (file)
@@ -2602,6 +2602,7 @@ static void wa_buf_in_cb(struct urb *urb)
        dev = &wa->usb_iface->dev;
        --(wa->active_buf_in_urbs);
        active_buf_in_urbs = wa->active_buf_in_urbs;
+       rpipe = xfer->ep->hcpriv;
 
        if (usb_pipeisoc(xfer->urb->pipe)) {
                struct usb_iso_packet_descriptor *iso_frame_desc =
@@ -2659,7 +2660,6 @@ static void wa_buf_in_cb(struct urb *urb)
                          resubmit_dti = (isoc_data_frame_count ==
                                                        urb_frame_count);
                } else if (active_buf_in_urbs == 0) {
-                       rpipe = xfer->ep->hcpriv;
                        dev_dbg(dev,
                                "xfer %p 0x%08X#%u: data in done (%zu bytes)\n",
                                xfer, wa_xfer_id(xfer), seg->index,
@@ -2685,7 +2685,6 @@ static void wa_buf_in_cb(struct urb *urb)
                 */
                resubmit_dti = wa->dti_state != WA_DTI_TRANSFER_RESULT_PENDING;
                spin_lock_irqsave(&xfer->lock, flags);
-               rpipe = xfer->ep->hcpriv;
                if (printk_ratelimit())
                        dev_err(dev, "xfer %p 0x%08X#%u: data in error %d\n",
                                xfer, wa_xfer_id(xfer), seg->index,
index 80079b8fed155c39f109bd65d12e4e5e155a1b3c..d0303f0dbe15348d7eee118c74a94e0fbfbd6f45 100644 (file)
@@ -431,16 +431,19 @@ void uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e *bce)
        uwb_dev->mac_addr = *bce->mac_addr;
        uwb_dev->dev_addr = bce->dev_addr;
        dev_set_name(&uwb_dev->dev, "%s", macbuf);
+
+       /* plug the beacon cache */
+       bce->uwb_dev = uwb_dev;
+       uwb_dev->bce = bce;
+       uwb_bce_get(bce);               /* released in uwb_dev_sys_release() */
+
        result = uwb_dev_add(uwb_dev, &rc->uwb_dev.dev, rc);
        if (result < 0) {
                dev_err(dev, "new device %s: cannot instantiate device\n",
                        macbuf);
                goto error_dev_add;
        }
-       /* plug the beacon cache */
-       bce->uwb_dev = uwb_dev;
-       uwb_dev->bce = bce;
-       uwb_bce_get(bce);               /* released in uwb_dev_sys_release() */
+
        dev_info(dev, "uwb device (mac %s dev %s) connected to %s %s\n",
                 macbuf, devbuf, rc->uwb_dev.dev.parent->bus->name,
                 dev_name(rc->uwb_dev.dev.parent));
@@ -448,6 +451,8 @@ void uwbd_dev_onair(struct uwb_rc *rc, struct uwb_beca_e *bce)
        return;
 
 error_dev_add:
+       bce->uwb_dev = NULL;
+       uwb_bce_put(bce);
        kfree(uwb_dev);
        return;
 }
index d7a3d13e72ec3900232c34ab35d121eadfff2683..b85983e97f0afbc70665d1aa134d5b182e25976e 100644 (file)
@@ -173,6 +173,7 @@ static int pwm_backlight_parse_dt(struct device *dev,
                data->max_brightness--;
        }
 
+       data->enable_gpio = -EINVAL;
        return 0;
 }
 
index beadd3edaa176625aaeb47440a44b830e5c78fd4..6ad23bd3523a991b8fc9096adc272708e83c85dc 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/list.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
+#include <linux/bitops.h>
 #include <linux/clk.h>
 #include <linux/hardirq.h>
 #include <linux/dma-mapping.h>
@@ -638,9 +639,7 @@ static int clcdfb_of_init_tft_panel(struct clcd_fb *fb, u32 r0, u32 g0, u32 b0)
                if (g0 != panels[i].g0)
                        continue;
                if (r0 == panels[i].r0 && b0 == panels[i].b0)
-                       fb->panel->caps = panels[i].caps & CLCD_CAP_RGB;
-               if (r0 == panels[i].b0 && b0 == panels[i].r0)
-                       fb->panel->caps = panels[i].caps & CLCD_CAP_BGR;
+                       fb->panel->caps = panels[i].caps;
        }
 
        return fb->panel->caps ? 0 : -EINVAL;
@@ -650,6 +649,7 @@ static int clcdfb_of_init_display(struct clcd_fb *fb)
 {
        struct device_node *endpoint;
        int err;
+       unsigned int bpp;
        u32 max_bandwidth;
        u32 tft_r0b0g0[3];
 
@@ -667,11 +667,22 @@ static int clcdfb_of_init_display(struct clcd_fb *fb)
 
        err = of_property_read_u32(fb->dev->dev.of_node, "max-memory-bandwidth",
                        &max_bandwidth);
-       if (!err)
-               fb->panel->bpp = 8 * max_bandwidth / (fb->panel->mode.xres *
-                               fb->panel->mode.yres * fb->panel->mode.refresh);
-       else
-               fb->panel->bpp = 32;
+       if (!err) {
+               /*
+                * max_bandwidth is in bytes per second and pixclock in
+                * pico-seconds, so the maximum allowed bits per pixel is
+                *   8 * max_bandwidth / (PICOS2KHZ(pixclock) * 1000)
+                * Rearrange this calculation to avoid overflow and then ensure
+                * result is a valid format.
+                */
+               bpp = max_bandwidth / (1000 / 8)
+                       / PICOS2KHZ(fb->panel->mode.pixclock);
+               bpp = rounddown_pow_of_two(bpp);
+               if (bpp > 32)
+                       bpp = 32;
+       } else
+               bpp = 32;
+       fb->panel->bpp = bpp;
 
 #ifdef CONFIG_CPU_BIG_ENDIAN
        fb->panel->cntl |= CNTL_BEBO;
index 92640d46770a19f5b249f63ad4b020fa6fa84b1a..1d8bdb92939b2c034dbd6b7e15f3b076146a6c6a 100644 (file)
@@ -1102,12 +1102,14 @@ static int atmel_lcdfb_of_init(struct atmel_lcdfb_info *sinfo)
        timings = of_get_display_timings(display_np);
        if (!timings) {
                dev_err(dev, "failed to get display timings\n");
+               ret = -EINVAL;
                goto put_display_node;
        }
 
        timings_np = of_find_node_by_name(display_np, "display-timings");
        if (!timings_np) {
                dev_err(dev, "failed to find display-timings node\n");
+               ret = -ENODEV;
                goto put_display_node;
        }
 
index 206a66b61072f5d1bd97c6d21453b0a9e6f99f18..59abdc6a97f668ed1b67e6bd9e958b74479bd99e 100644 (file)
@@ -273,7 +273,7 @@ static struct chips_init_reg chips_init_xr[] = {
        { 0xa8, 0x00 }
 };
 
-static void __init chips_hw_init(void)
+static void chips_hw_init(void)
 {
        int i;
 
index 788f6b37fce703aec7ef08b91abd9c77d3fdd4e7..10c876c95772350cdb890e001b7ea4b3cd838358 100644 (file)
@@ -419,7 +419,7 @@ static void lcd_cfg_horizontal_sync(int back_porch, int pulse_width,
 {
        u32 reg;
 
-       reg = lcdc_read(LCD_RASTER_TIMING_0_REG) & 0xf;
+       reg = lcdc_read(LCD_RASTER_TIMING_0_REG) & 0x3ff;
        reg |= (((back_porch-1) & 0xff) << 24)
            | (((front_porch-1) & 0xff) << 16)
            | (((pulse_width-1) & 0x3f) << 10);
index 987edf1100380b9d075067c659980931cfbda31b..5c098d5b40432ef2cec004ce420ef9660ef81599 100644 (file)
@@ -236,6 +236,7 @@ timingfail:
        if (native_mode)
                of_node_put(native_mode);
        display_timings_release(disp);
+       disp = NULL;
 entryfail:
        kfree(disp);
 dispfail:
index 5c660c77f03b58a32c24749b7053df6608a23230..1e0a317d3dcdda5b6041ae8481006f1d1479934b 100644 (file)
@@ -230,8 +230,8 @@ static enum bp_state reserve_additional_memory(long credit)
        rc = add_memory(nid, hotplug_start_paddr, balloon_hotplug << PAGE_SHIFT);
 
        if (rc) {
-               pr_info("%s: add_memory() failed: %i\n", __func__, rc);
-               return BP_EAGAIN;
+               pr_warn("Cannot add additional memory (%i)\n", rc);
+               return BP_ECANCELED;
        }
 
        balloon_hotplug -= credit;
index 787d17945418b19c53d408d710e2558a6bb85ad8..e53fe191738cfe8ce7c7cfe6202c2651258ff952 100644 (file)
@@ -124,7 +124,7 @@ static int add_grefs(struct ioctl_gntalloc_alloc_gref *op,
        int i, rc, readonly;
        LIST_HEAD(queue_gref);
        LIST_HEAD(queue_file);
-       struct gntalloc_gref *gref;
+       struct gntalloc_gref *gref, *next;
 
        readonly = !(op->flags & GNTALLOC_FLAG_WRITABLE);
        rc = -ENOMEM;
@@ -141,13 +141,11 @@ static int add_grefs(struct ioctl_gntalloc_alloc_gref *op,
                        goto undo;
 
                /* Grant foreign access to the page. */
-               gref->gref_id = gnttab_grant_foreign_access(op->domid,
+               rc = gnttab_grant_foreign_access(op->domid,
                        pfn_to_mfn(page_to_pfn(gref->page)), readonly);
-               if ((int)gref->gref_id < 0) {
-                       rc = gref->gref_id;
+               if (rc < 0)
                        goto undo;
-               }
-               gref_ids[i] = gref->gref_id;
+               gref_ids[i] = gref->gref_id = rc;
        }
 
        /* Add to gref lists. */
@@ -162,8 +160,8 @@ undo:
        mutex_lock(&gref_mutex);
        gref_size -= (op->count - i);
 
-       list_for_each_entry(gref, &queue_file, next_file) {
-               /* __del_gref does not remove from queue_file */
+       list_for_each_entry_safe(gref, next, &queue_file, next_file) {
+               list_del(&gref->next_file);
                __del_gref(gref);
        }
 
@@ -193,7 +191,7 @@ static void __del_gref(struct gntalloc_gref *gref)
 
        gref->notify.flags = 0;
 
-       if (gref->gref_id > 0) {
+       if (gref->gref_id) {
                if (gnttab_query_foreign_access(gref->gref_id))
                        return;
 
index 5f1e1f3cd18619ed2899dcc5e967ca274f690189..f8bb36f9d9cef862c6c502b5ba25b7d38476cd85 100644 (file)
@@ -103,16 +103,11 @@ static void do_suspend(void)
 
        shutting_down = SHUTDOWN_SUSPEND;
 
-#ifdef CONFIG_PREEMPT
-       /* If the kernel is preemptible, we need to freeze all the processes
-          to prevent them from being in the middle of a pagetable update
-          during suspend. */
        err = freeze_processes();
        if (err) {
                pr_err("%s: freeze failed %d\n", __func__, err);
                goto out;
        }
-#endif
 
        err = dpm_suspend_start(PMSG_FREEZE);
        if (err) {
@@ -157,10 +152,8 @@ out_resume:
        dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
 
 out_thaw:
-#ifdef CONFIG_PREEMPT
        thaw_processes();
 out:
-#endif
        shutting_down = SHUTDOWN_INVALID;
 }
 #endif /* CONFIG_HIBERNATE_CALLBACKS */
index 97bc62cbe2dab816cd33b20b86e6baa73d2ae19f..733750096b71b38d23783926b4f85da9ac2d35ea 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -793,6 +793,8 @@ void exit_aio(struct mm_struct *mm)
 
        for (i = 0; i < table->nr; ++i) {
                struct kioctx *ctx = table->table[i];
+               struct completion requests_done =
+                       COMPLETION_INITIALIZER_ONSTACK(requests_done);
 
                if (!ctx)
                        continue;
@@ -804,7 +806,10 @@ void exit_aio(struct mm_struct *mm)
                 * that it needs to unmap the area, just set it to 0.
                 */
                ctx->mmap_size = 0;
-               kill_ioctx(mm, ctx, NULL);
+               kill_ioctx(mm, ctx, &requests_done);
+
+               /* Wait until all IO for the context are done. */
+               wait_for_completion(&requests_done);
        }
 
        RCU_INIT_POINTER(mm->ioctx_table, NULL);
@@ -1111,6 +1116,12 @@ static long aio_read_events_ring(struct kioctx *ctx,
        tail = ring->tail;
        kunmap_atomic(ring);
 
+       /*
+        * Ensure that once we've read the current tail pointer, that
+        * we also see the events that were stored up to the tail.
+        */
+       smp_rmb();
+
        pr_debug("h%u t%u m%u\n", head, tail, ctx->nr_events);
 
        if (head == tail)
index 5a201d81049c09fcb280f26539d0ad5c6c5c5b51..fbd76ded9a34b3260a5e794115fff0312b3c6e08 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/freezer.h>
-#include <linux/workqueue.h>
 #include "async-thread.h"
 #include "ctree.h"
 
@@ -55,8 +54,39 @@ struct btrfs_workqueue {
        struct __btrfs_workqueue *high;
 };
 
-static inline struct __btrfs_workqueue
-*__btrfs_alloc_workqueue(const char *name, int flags, int max_active,
+static void normal_work_helper(struct btrfs_work *work);
+
+#define BTRFS_WORK_HELPER(name)                                        \
+void btrfs_##name(struct work_struct *arg)                             \
+{                                                                      \
+       struct btrfs_work *work = container_of(arg, struct btrfs_work,  \
+                                              normal_work);            \
+       normal_work_helper(work);                                       \
+}
+
+BTRFS_WORK_HELPER(worker_helper);
+BTRFS_WORK_HELPER(delalloc_helper);
+BTRFS_WORK_HELPER(flush_delalloc_helper);
+BTRFS_WORK_HELPER(cache_helper);
+BTRFS_WORK_HELPER(submit_helper);
+BTRFS_WORK_HELPER(fixup_helper);
+BTRFS_WORK_HELPER(endio_helper);
+BTRFS_WORK_HELPER(endio_meta_helper);
+BTRFS_WORK_HELPER(endio_meta_write_helper);
+BTRFS_WORK_HELPER(endio_raid56_helper);
+BTRFS_WORK_HELPER(rmw_helper);
+BTRFS_WORK_HELPER(endio_write_helper);
+BTRFS_WORK_HELPER(freespace_write_helper);
+BTRFS_WORK_HELPER(delayed_meta_helper);
+BTRFS_WORK_HELPER(readahead_helper);
+BTRFS_WORK_HELPER(qgroup_rescan_helper);
+BTRFS_WORK_HELPER(extent_refs_helper);
+BTRFS_WORK_HELPER(scrub_helper);
+BTRFS_WORK_HELPER(scrubwrc_helper);
+BTRFS_WORK_HELPER(scrubnc_helper);
+
+static struct __btrfs_workqueue *
+__btrfs_alloc_workqueue(const char *name, int flags, int max_active,
                         int thresh)
 {
        struct __btrfs_workqueue *ret = kzalloc(sizeof(*ret), GFP_NOFS);
@@ -232,13 +262,11 @@ static void run_ordered_work(struct __btrfs_workqueue *wq)
        spin_unlock_irqrestore(lock, flags);
 }
 
-static void normal_work_helper(struct work_struct *arg)
+static void normal_work_helper(struct btrfs_work *work)
 {
-       struct btrfs_work *work;
        struct __btrfs_workqueue *wq;
        int need_order = 0;
 
-       work = container_of(arg, struct btrfs_work, normal_work);
        /*
         * We should not touch things inside work in the following cases:
         * 1) after work->func() if it has no ordered_free
@@ -262,7 +290,7 @@ static void normal_work_helper(struct work_struct *arg)
                trace_btrfs_all_work_done(work);
 }
 
-void btrfs_init_work(struct btrfs_work *work,
+void btrfs_init_work(struct btrfs_work *work, btrfs_work_func_t uniq_func,
                     btrfs_func_t func,
                     btrfs_func_t ordered_func,
                     btrfs_func_t ordered_free)
@@ -270,7 +298,7 @@ void btrfs_init_work(struct btrfs_work *work,
        work->func = func;
        work->ordered_func = ordered_func;
        work->ordered_free = ordered_free;
-       INIT_WORK(&work->normal_work, normal_work_helper);
+       INIT_WORK(&work->normal_work, uniq_func);
        INIT_LIST_HEAD(&work->ordered_list);
        work->flags = 0;
 }
index 9c6b66d15fb0a07cd0a6a4656d6865848aa5c8ea..e9e31c94758fd6ddea5cbd458d5aca04a27e9a73 100644 (file)
 
 #ifndef __BTRFS_ASYNC_THREAD_
 #define __BTRFS_ASYNC_THREAD_
+#include <linux/workqueue.h>
 
 struct btrfs_workqueue;
 /* Internal use only */
 struct __btrfs_workqueue;
 struct btrfs_work;
 typedef void (*btrfs_func_t)(struct btrfs_work *arg);
+typedef void (*btrfs_work_func_t)(struct work_struct *arg);
 
 struct btrfs_work {
        btrfs_func_t func;
@@ -38,11 +40,35 @@ struct btrfs_work {
        unsigned long flags;
 };
 
+#define BTRFS_WORK_HELPER_PROTO(name)                                  \
+void btrfs_##name(struct work_struct *arg)
+
+BTRFS_WORK_HELPER_PROTO(worker_helper);
+BTRFS_WORK_HELPER_PROTO(delalloc_helper);
+BTRFS_WORK_HELPER_PROTO(flush_delalloc_helper);
+BTRFS_WORK_HELPER_PROTO(cache_helper);
+BTRFS_WORK_HELPER_PROTO(submit_helper);
+BTRFS_WORK_HELPER_PROTO(fixup_helper);
+BTRFS_WORK_HELPER_PROTO(endio_helper);
+BTRFS_WORK_HELPER_PROTO(endio_meta_helper);
+BTRFS_WORK_HELPER_PROTO(endio_meta_write_helper);
+BTRFS_WORK_HELPER_PROTO(endio_raid56_helper);
+BTRFS_WORK_HELPER_PROTO(rmw_helper);
+BTRFS_WORK_HELPER_PROTO(endio_write_helper);
+BTRFS_WORK_HELPER_PROTO(freespace_write_helper);
+BTRFS_WORK_HELPER_PROTO(delayed_meta_helper);
+BTRFS_WORK_HELPER_PROTO(readahead_helper);
+BTRFS_WORK_HELPER_PROTO(qgroup_rescan_helper);
+BTRFS_WORK_HELPER_PROTO(extent_refs_helper);
+BTRFS_WORK_HELPER_PROTO(scrub_helper);
+BTRFS_WORK_HELPER_PROTO(scrubwrc_helper);
+BTRFS_WORK_HELPER_PROTO(scrubnc_helper);
+
 struct btrfs_workqueue *btrfs_alloc_workqueue(const char *name,
                                              int flags,
                                              int max_active,
                                              int thresh);
-void btrfs_init_work(struct btrfs_work *work,
+void btrfs_init_work(struct btrfs_work *work, btrfs_work_func_t helper,
                     btrfs_func_t func,
                     btrfs_func_t ordered_func,
                     btrfs_func_t ordered_free);
index da775bfdebc989d905c931cde0f12bd00027abc9..a2e90f855d7d1e3cad650fc1d9691fd2de01cf65 100644 (file)
@@ -1395,8 +1395,8 @@ static int btrfs_wq_run_delayed_node(struct btrfs_delayed_root *delayed_root,
                return -ENOMEM;
 
        async_work->delayed_root = delayed_root;
-       btrfs_init_work(&async_work->work, btrfs_async_run_delayed_root,
-                       NULL, NULL);
+       btrfs_init_work(&async_work->work, btrfs_delayed_meta_helper,
+                       btrfs_async_run_delayed_root, NULL, NULL);
        async_work->nr = nr;
 
        btrfs_queue_work(root->fs_info->delayed_workers, &async_work->work);
index d0ed9e664f7d4d26c69a12498f80b3ad59809a43..a1d36e62179c528041f292675e7452102863de45 100644 (file)
@@ -39,7 +39,6 @@
 #include "btrfs_inode.h"
 #include "volumes.h"
 #include "print-tree.h"
-#include "async-thread.h"
 #include "locking.h"
 #include "tree-log.h"
 #include "free-space-cache.h"
@@ -693,35 +692,41 @@ static void end_workqueue_bio(struct bio *bio, int err)
 {
        struct end_io_wq *end_io_wq = bio->bi_private;
        struct btrfs_fs_info *fs_info;
+       struct btrfs_workqueue *wq;
+       btrfs_work_func_t func;
 
        fs_info = end_io_wq->info;
        end_io_wq->error = err;
-       btrfs_init_work(&end_io_wq->work, end_workqueue_fn, NULL, NULL);
 
        if (bio->bi_rw & REQ_WRITE) {
-               if (end_io_wq->metadata == BTRFS_WQ_ENDIO_METADATA)
-                       btrfs_queue_work(fs_info->endio_meta_write_workers,
-                                        &end_io_wq->work);
-               else if (end_io_wq->metadata == BTRFS_WQ_ENDIO_FREE_SPACE)
-                       btrfs_queue_work(fs_info->endio_freespace_worker,
-                                        &end_io_wq->work);
-               else if (end_io_wq->metadata == BTRFS_WQ_ENDIO_RAID56)
-                       btrfs_queue_work(fs_info->endio_raid56_workers,
-                                        &end_io_wq->work);
-               else
-                       btrfs_queue_work(fs_info->endio_write_workers,
-                                        &end_io_wq->work);
+               if (end_io_wq->metadata == BTRFS_WQ_ENDIO_METADATA) {
+                       wq = fs_info->endio_meta_write_workers;
+                       func = btrfs_endio_meta_write_helper;
+               } else if (end_io_wq->metadata == BTRFS_WQ_ENDIO_FREE_SPACE) {
+                       wq = fs_info->endio_freespace_worker;
+                       func = btrfs_freespace_write_helper;
+               } else if (end_io_wq->metadata == BTRFS_WQ_ENDIO_RAID56) {
+                       wq = fs_info->endio_raid56_workers;
+                       func = btrfs_endio_raid56_helper;
+               } else {
+                       wq = fs_info->endio_write_workers;
+                       func = btrfs_endio_write_helper;
+               }
        } else {
-               if (end_io_wq->metadata == BTRFS_WQ_ENDIO_RAID56)
-                       btrfs_queue_work(fs_info->endio_raid56_workers,
-                                        &end_io_wq->work);
-               else if (end_io_wq->metadata)
-                       btrfs_queue_work(fs_info->endio_meta_workers,
-                                        &end_io_wq->work);
-               else
-                       btrfs_queue_work(fs_info->endio_workers,
-                                        &end_io_wq->work);
+               if (end_io_wq->metadata == BTRFS_WQ_ENDIO_RAID56) {
+                       wq = fs_info->endio_raid56_workers;
+                       func = btrfs_endio_raid56_helper;
+               } else if (end_io_wq->metadata) {
+                       wq = fs_info->endio_meta_workers;
+                       func = btrfs_endio_meta_helper;
+               } else {
+                       wq = fs_info->endio_workers;
+                       func = btrfs_endio_helper;
+               }
        }
+
+       btrfs_init_work(&end_io_wq->work, func, end_workqueue_fn, NULL, NULL);
+       btrfs_queue_work(wq, &end_io_wq->work);
 }
 
 /*
@@ -828,7 +833,7 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode,
        async->submit_bio_start = submit_bio_start;
        async->submit_bio_done = submit_bio_done;
 
-       btrfs_init_work(&async->work, run_one_async_start,
+       btrfs_init_work(&async->work, btrfs_worker_helper, run_one_async_start,
                        run_one_async_done, run_one_async_free);
 
        async->bio_flags = bio_flags;
@@ -3450,7 +3455,8 @@ static int write_all_supers(struct btrfs_root *root, int max_mirrors)
                btrfs_set_stack_device_generation(dev_item, 0);
                btrfs_set_stack_device_type(dev_item, dev->type);
                btrfs_set_stack_device_id(dev_item, dev->devid);
-               btrfs_set_stack_device_total_bytes(dev_item, dev->total_bytes);
+               btrfs_set_stack_device_total_bytes(dev_item,
+                                                  dev->disk_total_bytes);
                btrfs_set_stack_device_bytes_used(dev_item, dev->bytes_used);
                btrfs_set_stack_device_io_align(dev_item, dev->io_align);
                btrfs_set_stack_device_io_width(dev_item, dev->io_width);
index 102ed3143976fa9cfe98e21f237f45ed7fbed3c2..3efe1c3877bf34c4643ce99fb90d52fedda74d06 100644 (file)
@@ -552,7 +552,8 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
        caching_ctl->block_group = cache;
        caching_ctl->progress = cache->key.objectid;
        atomic_set(&caching_ctl->count, 1);
-       btrfs_init_work(&caching_ctl->work, caching_thread, NULL, NULL);
+       btrfs_init_work(&caching_ctl->work, btrfs_cache_helper,
+                       caching_thread, NULL, NULL);
 
        spin_lock(&cache->lock);
        /*
@@ -2749,8 +2750,8 @@ int btrfs_async_run_delayed_refs(struct btrfs_root *root,
                async->sync = 0;
        init_completion(&async->wait);
 
-       btrfs_init_work(&async->work, delayed_ref_async_start,
-                       NULL, NULL);
+       btrfs_init_work(&async->work, btrfs_extent_refs_helper,
+                       delayed_ref_async_start, NULL, NULL);
 
        btrfs_queue_work(root->fs_info->extent_workers, &async->work);
 
@@ -3586,13 +3587,7 @@ static u64 get_restripe_target(struct btrfs_fs_info *fs_info, u64 flags)
  */
 static u64 btrfs_reduce_alloc_profile(struct btrfs_root *root, u64 flags)
 {
-       /*
-        * we add in the count of missing devices because we want
-        * to make sure that any RAID levels on a degraded FS
-        * continue to be honored.
-        */
-       u64 num_devices = root->fs_info->fs_devices->rw_devices +
-               root->fs_info->fs_devices->missing_devices;
+       u64 num_devices = root->fs_info->fs_devices->rw_devices;
        u64 target;
        u64 tmp;
 
@@ -8440,13 +8435,7 @@ static u64 update_block_group_flags(struct btrfs_root *root, u64 flags)
        if (stripped)
                return extended_to_chunk(stripped);
 
-       /*
-        * we add in the count of missing devices because we want
-        * to make sure that any RAID levels on a degraded FS
-        * continue to be honored.
-        */
-       num_devices = root->fs_info->fs_devices->rw_devices +
-               root->fs_info->fs_devices->missing_devices;
+       num_devices = root->fs_info->fs_devices->rw_devices;
 
        stripped = BTRFS_BLOCK_GROUP_RAID0 |
                BTRFS_BLOCK_GROUP_RAID5 | BTRFS_BLOCK_GROUP_RAID6 |
index 3e11aab9f391d9bce24c329694d62d3a48ced811..af0359dcf337dbfec421b49fedbb8b5d0ecbf8b8 100644 (file)
@@ -2532,6 +2532,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                                        test_bit(BIO_UPTODATE, &bio->bi_flags);
                                if (err)
                                        uptodate = 0;
+                               offset += len;
                                continue;
                        }
                }
@@ -4207,8 +4208,8 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                return -ENOMEM;
        path->leave_spinning = 1;
 
-       start = ALIGN(start, BTRFS_I(inode)->root->sectorsize);
-       len = ALIGN(len, BTRFS_I(inode)->root->sectorsize);
+       start = round_down(start, BTRFS_I(inode)->root->sectorsize);
+       len = round_up(max, BTRFS_I(inode)->root->sectorsize) - start;
 
        /*
         * lookup the last file extent.  We're not using i_size here
index d3afac292d677e0ed492255ca7cb3890cde717b1..ff1cc0399b9a206c127b4707b6dcd69d455d8231 100644 (file)
@@ -1840,7 +1840,15 @@ int btrfs_release_file(struct inode *inode, struct file *filp)
 {
        if (filp->private_data)
                btrfs_ioctl_trans_end(filp);
-       filemap_flush(inode->i_mapping);
+       /*
+        * ordered_data_close is set by settattr when we are about to truncate
+        * a file from a non-zero size to a zero size.  This tries to
+        * flush down new bytes that may have been written if the
+        * application were using truncate to replace a file in place.
+        */
+       if (test_and_clear_bit(BTRFS_INODE_ORDERED_DATA_CLOSE,
+                              &BTRFS_I(inode)->runtime_flags))
+                       filemap_flush(inode->i_mapping);
        return 0;
 }
 
@@ -1958,7 +1966,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 
        btrfs_init_log_ctx(&ctx);
 
-       ret = btrfs_log_dentry_safe(trans, root, dentry, &ctx);
+       ret = btrfs_log_dentry_safe(trans, root, dentry, start, end, &ctx);
        if (ret < 0) {
                /* Fallthrough and commit/free transaction. */
                ret = 1;
@@ -2088,10 +2096,9 @@ static int fill_holes(struct btrfs_trans_handle *trans, struct inode *inode,
                goto out;
        }
 
-       if (hole_mergeable(inode, leaf, path->slots[0]+1, offset, end)) {
+       if (hole_mergeable(inode, leaf, path->slots[0], offset, end)) {
                u64 num_bytes;
 
-               path->slots[0]++;
                key.offset = offset;
                btrfs_set_item_key_safe(root, path, &key);
                fi = btrfs_item_ptr(leaf, path->slots[0],
@@ -2216,7 +2223,7 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
                goto out_only_mutex;
        }
 
-       lockstart = round_up(offset , BTRFS_I(inode)->root->sectorsize);
+       lockstart = round_up(offset, BTRFS_I(inode)->root->sectorsize);
        lockend = round_down(offset + len,
                             BTRFS_I(inode)->root->sectorsize) - 1;
        same_page = ((offset >> PAGE_CACHE_SHIFT) ==
@@ -2277,7 +2284,7 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
                                                tail_start + tail_len, 0, 1);
                                if (ret)
                                        goto out_only_mutex;
-                               }
+                       }
                }
        }
 
index 03708ef3deefb11edd7998ee831bf370e6ad8a66..016c403bfe7e4241b33c6b6c3e4101ba5ea993b2 100644 (file)
@@ -778,8 +778,12 @@ retry:
                                                ins.offset,
                                                BTRFS_ORDERED_COMPRESSED,
                                                async_extent->compress_type);
-               if (ret)
+               if (ret) {
+                       btrfs_drop_extent_cache(inode, async_extent->start,
+                                               async_extent->start +
+                                               async_extent->ram_size - 1, 0);
                        goto out_free_reserve;
+               }
 
                /*
                 * clear dirty, set writeback and unlock the pages.
@@ -971,14 +975,14 @@ static noinline int cow_file_range(struct inode *inode,
                ret = btrfs_add_ordered_extent(inode, start, ins.objectid,
                                               ram_size, cur_alloc_size, 0);
                if (ret)
-                       goto out_reserve;
+                       goto out_drop_extent_cache;
 
                if (root->root_key.objectid ==
                    BTRFS_DATA_RELOC_TREE_OBJECTID) {
                        ret = btrfs_reloc_clone_csums(inode, start,
                                                      cur_alloc_size);
                        if (ret)
-                               goto out_reserve;
+                               goto out_drop_extent_cache;
                }
 
                if (disk_num_bytes < cur_alloc_size)
@@ -1006,6 +1010,8 @@ static noinline int cow_file_range(struct inode *inode,
 out:
        return ret;
 
+out_drop_extent_cache:
+       btrfs_drop_extent_cache(inode, start, start + ram_size - 1, 0);
 out_reserve:
        btrfs_free_reserved_extent(root, ins.objectid, ins.offset, 1);
 out_unlock:
@@ -1096,8 +1102,10 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page,
                async_cow->end = cur_end;
                INIT_LIST_HEAD(&async_cow->extents);
 
-               btrfs_init_work(&async_cow->work, async_cow_start,
-                               async_cow_submit, async_cow_free);
+               btrfs_init_work(&async_cow->work,
+                               btrfs_delalloc_helper,
+                               async_cow_start, async_cow_submit,
+                               async_cow_free);
 
                nr_pages = (cur_end - start + PAGE_CACHE_SIZE) >>
                        PAGE_CACHE_SHIFT;
@@ -1881,7 +1889,8 @@ static int btrfs_writepage_start_hook(struct page *page, u64 start, u64 end)
 
        SetPageChecked(page);
        page_cache_get(page);
-       btrfs_init_work(&fixup->work, btrfs_writepage_fixup_worker, NULL, NULL);
+       btrfs_init_work(&fixup->work, btrfs_fixup_helper,
+                       btrfs_writepage_fixup_worker, NULL, NULL);
        fixup->page = page;
        btrfs_queue_work(root->fs_info->fixup_workers, &fixup->work);
        return -EBUSY;
@@ -2822,7 +2831,8 @@ static int btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end,
        struct inode *inode = page->mapping->host;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_ordered_extent *ordered_extent = NULL;
-       struct btrfs_workqueue *workers;
+       struct btrfs_workqueue *wq;
+       btrfs_work_func_t func;
 
        trace_btrfs_writepage_end_io_hook(page, start, end, uptodate);
 
@@ -2831,13 +2841,17 @@ static int btrfs_writepage_end_io_hook(struct page *page, u64 start, u64 end,
                                            end - start + 1, uptodate))
                return 0;
 
-       btrfs_init_work(&ordered_extent->work, finish_ordered_fn, NULL, NULL);
+       if (btrfs_is_free_space_inode(inode)) {
+               wq = root->fs_info->endio_freespace_worker;
+               func = btrfs_freespace_write_helper;
+       } else {
+               wq = root->fs_info->endio_write_workers;
+               func = btrfs_endio_write_helper;
+       }
 
-       if (btrfs_is_free_space_inode(inode))
-               workers = root->fs_info->endio_freespace_worker;
-       else
-               workers = root->fs_info->endio_write_workers;
-       btrfs_queue_work(workers, &ordered_extent->work);
+       btrfs_init_work(&ordered_extent->work, func, finish_ordered_fn, NULL,
+                       NULL);
+       btrfs_queue_work(wq, &ordered_extent->work);
 
        return 0;
 }
@@ -4234,7 +4248,8 @@ out:
                        btrfs_abort_transaction(trans, root, ret);
        }
 error:
-       if (last_size != (u64)-1)
+       if (last_size != (u64)-1 &&
+           root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID)
                btrfs_ordered_update_i_size(inode, last_size, NULL);
        btrfs_free_path(path);
        return err;
@@ -4674,6 +4689,11 @@ static void evict_inode_truncate_pages(struct inode *inode)
                clear_bit(EXTENT_FLAG_LOGGING, &em->flags);
                remove_extent_mapping(map_tree, em);
                free_extent_map(em);
+               if (need_resched()) {
+                       write_unlock(&map_tree->lock);
+                       cond_resched();
+                       write_lock(&map_tree->lock);
+               }
        }
        write_unlock(&map_tree->lock);
 
@@ -4696,6 +4716,7 @@ static void evict_inode_truncate_pages(struct inode *inode)
                                 &cached_state, GFP_NOFS);
                free_extent_state(state);
 
+               cond_resched();
                spin_lock(&io_tree->lock);
        }
        spin_unlock(&io_tree->lock);
@@ -5181,6 +5202,42 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
                        iput(inode);
                        inode = ERR_PTR(ret);
                }
+               /*
+                * If orphan cleanup did remove any orphans, it means the tree
+                * was modified and therefore the commit root is not the same as
+                * the current root anymore. This is a problem, because send
+                * uses the commit root and therefore can see inode items that
+                * don't exist in the current root anymore, and for example make
+                * calls to btrfs_iget, which will do tree lookups based on the
+                * current root and not on the commit root. Those lookups will
+                * fail, returning a -ESTALE error, and making send fail with
+                * that error. So make sure a send does not see any orphans we
+                * have just removed, and that it will see the same inodes
+                * regardless of whether a transaction commit happened before
+                * it started (meaning that the commit root will be the same as
+                * the current root) or not.
+                */
+               if (sub_root->node != sub_root->commit_root) {
+                       u64 sub_flags = btrfs_root_flags(&sub_root->root_item);
+
+                       if (sub_flags & BTRFS_ROOT_SUBVOL_RDONLY) {
+                               struct extent_buffer *eb;
+
+                               /*
+                                * Assert we can't have races between dentry
+                                * lookup called through the snapshot creation
+                                * ioctl and the VFS.
+                                */
+                               ASSERT(mutex_is_locked(&dir->i_mutex));
+
+                               down_write(&root->fs_info->commit_root_sem);
+                               eb = sub_root->commit_root;
+                               sub_root->commit_root =
+                                       btrfs_root_node(sub_root);
+                               up_write(&root->fs_info->commit_root_sem);
+                               free_extent_buffer(eb);
+                       }
+               }
        }
 
        return inode;
@@ -5577,6 +5634,17 @@ int btrfs_set_inode_index(struct inode *dir, u64 *index)
        return ret;
 }
 
+static int btrfs_insert_inode_locked(struct inode *inode)
+{
+       struct btrfs_iget_args args;
+       args.location = &BTRFS_I(inode)->location;
+       args.root = BTRFS_I(inode)->root;
+
+       return insert_inode_locked4(inode,
+                  btrfs_inode_hash(inode->i_ino, BTRFS_I(inode)->root),
+                  btrfs_find_actor, &args);
+}
+
 static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
                                     struct btrfs_root *root,
                                     struct inode *dir,
@@ -5605,6 +5673,13 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
                return ERR_PTR(-ENOMEM);
        }
 
+       /*
+        * O_TMPFILE, set link count to 0, so that after this point,
+        * we fill in an inode item with the correct link count.
+        */
+       if (!name)
+               set_nlink(inode, 0);
+
        /*
         * we have to initialize this early, so we can reclaim the inode
         * number if we fail afterwards in this function.
@@ -5662,10 +5737,19 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
                sizes[1] = name_len + sizeof(*ref);
        }
 
+       location = &BTRFS_I(inode)->location;
+       location->objectid = objectid;
+       location->offset = 0;
+       btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY);
+
+       ret = btrfs_insert_inode_locked(inode);
+       if (ret < 0)
+               goto fail;
+
        path->leave_spinning = 1;
        ret = btrfs_insert_empty_items(trans, root, path, key, sizes, nitems);
        if (ret != 0)
-               goto fail;
+               goto fail_unlock;
 
        inode_init_owner(inode, dir, mode);
        inode_set_bytes(inode, 0);
@@ -5688,11 +5772,6 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
        btrfs_mark_buffer_dirty(path->nodes[0]);
        btrfs_free_path(path);
 
-       location = &BTRFS_I(inode)->location;
-       location->objectid = objectid;
-       location->offset = 0;
-       btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY);
-
        btrfs_inherit_iflags(inode, dir);
 
        if (S_ISREG(mode)) {
@@ -5703,7 +5782,6 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
                                BTRFS_INODE_NODATASUM;
        }
 
-       btrfs_insert_inode_hash(inode);
        inode_tree_add(inode);
 
        trace_btrfs_inode_new(inode);
@@ -5718,6 +5796,9 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
                          btrfs_ino(inode), root->root_key.objectid, ret);
 
        return inode;
+
+fail_unlock:
+       unlock_new_inode(inode);
 fail:
        if (dir && name)
                BTRFS_I(dir)->index_cnt--;
@@ -5852,28 +5933,28 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
                goto out_unlock;
        }
 
-       err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
-       if (err) {
-               drop_inode = 1;
-               goto out_unlock;
-       }
-
        /*
        * If the active LSM wants to access the inode during
        * d_instantiate it needs these. Smack checks to see
        * if the filesystem supports xattrs by looking at the
        * ops vector.
        */
-
        inode->i_op = &btrfs_special_inode_operations;
-       err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
+       init_special_inode(inode, inode->i_mode, rdev);
+
+       err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
        if (err)
-               drop_inode = 1;
-       else {
-               init_special_inode(inode, inode->i_mode, rdev);
+               goto out_unlock_inode;
+
+       err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
+       if (err) {
+               goto out_unlock_inode;
+       } else {
                btrfs_update_inode(trans, root, inode);
+               unlock_new_inode(inode);
                d_instantiate(dentry, inode);
        }
+
 out_unlock:
        btrfs_end_transaction(trans, root);
        btrfs_balance_delayed_items(root);
@@ -5883,6 +5964,12 @@ out_unlock:
                iput(inode);
        }
        return err;
+
+out_unlock_inode:
+       drop_inode = 1;
+       unlock_new_inode(inode);
+       goto out_unlock;
+
 }
 
 static int btrfs_create(struct inode *dir, struct dentry *dentry,
@@ -5917,15 +6004,6 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
                goto out_unlock;
        }
        drop_inode_on_err = 1;
-
-       err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
-       if (err)
-               goto out_unlock;
-
-       err = btrfs_update_inode(trans, root, inode);
-       if (err)
-               goto out_unlock;
-
        /*
        * If the active LSM wants to access the inode during
        * d_instantiate it needs these. Smack checks to see
@@ -5934,14 +6012,23 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
        */
        inode->i_fop = &btrfs_file_operations;
        inode->i_op = &btrfs_file_inode_operations;
+       inode->i_mapping->a_ops = &btrfs_aops;
+       inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
+
+       err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
+       if (err)
+               goto out_unlock_inode;
+
+       err = btrfs_update_inode(trans, root, inode);
+       if (err)
+               goto out_unlock_inode;
 
        err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
        if (err)
-               goto out_unlock;
+               goto out_unlock_inode;
 
-       inode->i_mapping->a_ops = &btrfs_aops;
-       inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
        BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
+       unlock_new_inode(inode);
        d_instantiate(dentry, inode);
 
 out_unlock:
@@ -5953,6 +6040,11 @@ out_unlock:
        btrfs_balance_delayed_items(root);
        btrfs_btree_balance_dirty(root);
        return err;
+
+out_unlock_inode:
+       unlock_new_inode(inode);
+       goto out_unlock;
+
 }
 
 static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
@@ -6060,25 +6152,30 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        }
 
        drop_on_err = 1;
+       /* these must be set before we unlock the inode */
+       inode->i_op = &btrfs_dir_inode_operations;
+       inode->i_fop = &btrfs_dir_file_operations;
 
        err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
        if (err)
-               goto out_fail;
-
-       inode->i_op = &btrfs_dir_inode_operations;
-       inode->i_fop = &btrfs_dir_file_operations;
+               goto out_fail_inode;
 
        btrfs_i_size_write(inode, 0);
        err = btrfs_update_inode(trans, root, inode);
        if (err)
-               goto out_fail;
+               goto out_fail_inode;
 
        err = btrfs_add_link(trans, dir, inode, dentry->d_name.name,
                             dentry->d_name.len, 0, index);
        if (err)
-               goto out_fail;
+               goto out_fail_inode;
 
        d_instantiate(dentry, inode);
+       /*
+        * mkdir is special.  We're unlocking after we call d_instantiate
+        * to avoid a race with nfsd calling d_instantiate.
+        */
+       unlock_new_inode(inode);
        drop_on_err = 0;
 
 out_fail:
@@ -6088,6 +6185,10 @@ out_fail:
        btrfs_balance_delayed_items(root);
        btrfs_btree_balance_dirty(root);
        return err;
+
+out_fail_inode:
+       unlock_new_inode(inode);
+       goto out_fail;
 }
 
 /* helper for btfs_get_extent.  Given an existing extent in the tree,
@@ -6097,14 +6198,14 @@ out_fail:
 static int merge_extent_mapping(struct extent_map_tree *em_tree,
                                struct extent_map *existing,
                                struct extent_map *em,
-                               u64 map_start, u64 map_len)
+                               u64 map_start)
 {
        u64 start_diff;
 
        BUG_ON(map_start < em->start || map_start >= extent_map_end(em));
        start_diff = map_start - em->start;
        em->start = map_start;
-       em->len = map_len;
+       em->len = existing->start - em->start;
        if (em->block_start < EXTENT_MAP_LAST_BYTE &&
            !test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) {
                em->block_start += start_diff;
@@ -6275,6 +6376,8 @@ next:
                        goto not_found;
                if (start + len <= found_key.offset)
                        goto not_found;
+               if (start > found_key.offset)
+                       goto next;
                em->start = start;
                em->orig_start = start;
                em->len = found_key.offset - start;
@@ -6390,8 +6493,7 @@ insert:
                                                         em->len);
                        if (existing) {
                                err = merge_extent_mapping(em_tree, existing,
-                                                          em, start,
-                                                          root->sectorsize);
+                                                          em, start);
                                free_extent_map(existing);
                                if (err) {
                                        free_extent_map(em);
@@ -7158,7 +7260,8 @@ again:
        if (!ret)
                goto out_test;
 
-       btrfs_init_work(&ordered->work, finish_ordered_fn, NULL, NULL);
+       btrfs_init_work(&ordered->work, btrfs_endio_write_helper,
+                       finish_ordered_fn, NULL, NULL);
        btrfs_queue_work(root->fs_info->endio_write_workers,
                         &ordered->work);
 out_test:
@@ -7306,10 +7409,8 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
        map_length = orig_bio->bi_iter.bi_size;
        ret = btrfs_map_block(root->fs_info, rw, start_sector << 9,
                              &map_length, NULL, 0);
-       if (ret) {
-               bio_put(orig_bio);
+       if (ret)
                return -EIO;
-       }
 
        if (map_length >= orig_bio->bi_iter.bi_size) {
                bio = orig_bio;
@@ -7326,6 +7427,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
        bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev, start_sector, GFP_NOFS);
        if (!bio)
                return -ENOMEM;
+
        bio->bi_private = dip;
        bio->bi_end_io = btrfs_end_dio_bio;
        atomic_inc(&dip->pending_bios);
@@ -7534,7 +7636,8 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
        count = iov_iter_count(iter);
        if (test_bit(BTRFS_INODE_HAS_ASYNC_EXTENT,
                     &BTRFS_I(inode)->runtime_flags))
-               filemap_fdatawrite_range(inode->i_mapping, offset, count);
+               filemap_fdatawrite_range(inode->i_mapping, offset,
+                                        offset + count - 1);
 
        if (rw & WRITE) {
                /*
@@ -8041,6 +8144,7 @@ int btrfs_create_subvol_root(struct btrfs_trans_handle *trans,
 
        set_nlink(inode, 1);
        btrfs_i_size_write(inode, 0);
+       unlock_new_inode(inode);
 
        err = btrfs_subvol_inherit_props(trans, new_root, parent_root);
        if (err)
@@ -8495,7 +8599,9 @@ struct btrfs_delalloc_work *btrfs_alloc_delalloc_work(struct inode *inode,
        work->inode = inode;
        work->wait = wait;
        work->delay_iput = delay_iput;
-       btrfs_init_work(&work->work, btrfs_run_delalloc_work, NULL, NULL);
+       WARN_ON_ONCE(!inode);
+       btrfs_init_work(&work->work, btrfs_flush_delalloc_helper,
+                       btrfs_run_delalloc_work, NULL, NULL);
 
        return work;
 }
@@ -8699,12 +8805,6 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
                goto out_unlock;
        }
 
-       err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
-       if (err) {
-               drop_inode = 1;
-               goto out_unlock;
-       }
-
        /*
        * If the active LSM wants to access the inode during
        * d_instantiate it needs these. Smack checks to see
@@ -8713,23 +8813,22 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
        */
        inode->i_fop = &btrfs_file_operations;
        inode->i_op = &btrfs_file_inode_operations;
+       inode->i_mapping->a_ops = &btrfs_aops;
+       inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
+       BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
+
+       err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
+       if (err)
+               goto out_unlock_inode;
 
        err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index);
        if (err)
-               drop_inode = 1;
-       else {
-               inode->i_mapping->a_ops = &btrfs_aops;
-               inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
-               BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
-       }
-       if (drop_inode)
-               goto out_unlock;
+               goto out_unlock_inode;
 
        path = btrfs_alloc_path();
        if (!path) {
                err = -ENOMEM;
-               drop_inode = 1;
-               goto out_unlock;
+               goto out_unlock_inode;
        }
        key.objectid = btrfs_ino(inode);
        key.offset = 0;
@@ -8738,9 +8837,8 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
        err = btrfs_insert_empty_item(trans, root, path, &key,
                                      datasize);
        if (err) {
-               drop_inode = 1;
                btrfs_free_path(path);
-               goto out_unlock;
+               goto out_unlock_inode;
        }
        leaf = path->nodes[0];
        ei = btrfs_item_ptr(leaf, path->slots[0],
@@ -8764,12 +8862,15 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
        inode_set_bytes(inode, name_len);
        btrfs_i_size_write(inode, name_len);
        err = btrfs_update_inode(trans, root, inode);
-       if (err)
+       if (err) {
                drop_inode = 1;
+               goto out_unlock_inode;
+       }
+
+       unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
 
 out_unlock:
-       if (!err)
-               d_instantiate(dentry, inode);
        btrfs_end_transaction(trans, root);
        if (drop_inode) {
                inode_dec_link_count(inode);
@@ -8777,6 +8878,11 @@ out_unlock:
        }
        btrfs_btree_balance_dirty(root);
        return err;
+
+out_unlock_inode:
+       drop_inode = 1;
+       unlock_new_inode(inode);
+       goto out_unlock;
 }
 
 static int __btrfs_prealloc_file_range(struct inode *inode, int mode,
@@ -8960,14 +9066,6 @@ static int btrfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
                goto out;
        }
 
-       ret = btrfs_init_inode_security(trans, inode, dir, NULL);
-       if (ret)
-               goto out;
-
-       ret = btrfs_update_inode(trans, root, inode);
-       if (ret)
-               goto out;
-
        inode->i_fop = &btrfs_file_operations;
        inode->i_op = &btrfs_file_inode_operations;
 
@@ -8975,10 +9073,26 @@ static int btrfs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
        inode->i_mapping->backing_dev_info = &root->fs_info->bdi;
        BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
 
+       ret = btrfs_init_inode_security(trans, inode, dir, NULL);
+       if (ret)
+               goto out_inode;
+
+       ret = btrfs_update_inode(trans, root, inode);
+       if (ret)
+               goto out_inode;
        ret = btrfs_orphan_add(trans, inode);
        if (ret)
-               goto out;
+               goto out_inode;
 
+       /*
+        * We set number of links to 0 in btrfs_new_inode(), and here we set
+        * it to 1 because d_tmpfile() will issue a warning if the count is 0,
+        * through:
+        *
+        *    d_tmpfile() -> inode_dec_link_count() -> drop_nlink()
+        */
+       set_nlink(inode, 1);
+       unlock_new_inode(inode);
        d_tmpfile(dentry, inode);
        mark_inode_dirty(inode);
 
@@ -8988,8 +9102,12 @@ out:
                iput(inode);
        btrfs_balance_delayed_items(root);
        btrfs_btree_balance_dirty(root);
-
        return ret;
+
+out_inode:
+       unlock_new_inode(inode);
+       goto out;
+
 }
 
 static const struct inode_operations btrfs_dir_inode_operations = {
index 47aceb494d1d456da8940c5e7a1d3eed3fa4adc5..8a8e29878c34283812f8d990c2432cff94bbab2a 100644 (file)
@@ -711,39 +711,6 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
        if (ret)
                goto fail;
 
-       ret = btrfs_orphan_cleanup(pending_snapshot->snap);
-       if (ret)
-               goto fail;
-
-       /*
-        * If orphan cleanup did remove any orphans, it means the tree was
-        * modified and therefore the commit root is not the same as the
-        * current root anymore. This is a problem, because send uses the
-        * commit root and therefore can see inode items that don't exist
-        * in the current root anymore, and for example make calls to
-        * btrfs_iget, which will do tree lookups based on the current root
-        * and not on the commit root. Those lookups will fail, returning a
-        * -ESTALE error, and making send fail with that error. So make sure
-        * a send does not see any orphans we have just removed, and that it
-        * will see the same inodes regardless of whether a transaction
-        * commit happened before it started (meaning that the commit root
-        * will be the same as the current root) or not.
-        */
-       if (readonly && pending_snapshot->snap->node !=
-           pending_snapshot->snap->commit_root) {
-               trans = btrfs_join_transaction(pending_snapshot->snap);
-               if (IS_ERR(trans) && PTR_ERR(trans) != -ENOENT) {
-                       ret = PTR_ERR(trans);
-                       goto fail;
-               }
-               if (!IS_ERR(trans)) {
-                       ret = btrfs_commit_transaction(trans,
-                                                      pending_snapshot->snap);
-                       if (ret)
-                               goto fail;
-               }
-       }
-
        inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry);
        if (IS_ERR(inode)) {
                ret = PTR_ERR(inode);
@@ -1052,8 +1019,10 @@ static bool defrag_check_next_extent(struct inode *inode, struct extent_map *em)
                return false;
 
        next = defrag_lookup_extent(inode, em->start + em->len);
-       if (!next || next->block_start >= EXTENT_MAP_LAST_BYTE ||
-           (em->block_start + em->block_len == next->block_start))
+       if (!next || next->block_start >= EXTENT_MAP_LAST_BYTE)
+               ret = false;
+       else if ((em->block_start + em->block_len == next->block_start) &&
+                (em->block_len > 128 * 1024 && next->block_len > 128 * 1024))
                ret = false;
 
        free_extent_map(next);
@@ -1088,7 +1057,6 @@ static int should_defrag_range(struct inode *inode, u64 start, int thresh,
        }
 
        next_mergeable = defrag_check_next_extent(inode, em);
-
        /*
         * we hit a real extent, if it is big or the next extent is not a
         * real extent, don't bother defragging it
@@ -1735,7 +1703,7 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file,
            ~(BTRFS_SUBVOL_CREATE_ASYNC | BTRFS_SUBVOL_RDONLY |
              BTRFS_SUBVOL_QGROUP_INHERIT)) {
                ret = -EOPNOTSUPP;
-               goto out;
+               goto free_args;
        }
 
        if (vol_args->flags & BTRFS_SUBVOL_CREATE_ASYNC)
@@ -1745,27 +1713,31 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file,
        if (vol_args->flags & BTRFS_SUBVOL_QGROUP_INHERIT) {
                if (vol_args->size > PAGE_CACHE_SIZE) {
                        ret = -EINVAL;
-                       goto out;
+                       goto free_args;
                }
                inherit = memdup_user(vol_args->qgroup_inherit, vol_args->size);
                if (IS_ERR(inherit)) {
                        ret = PTR_ERR(inherit);
-                       goto out;
+                       goto free_args;
                }
        }
 
        ret = btrfs_ioctl_snap_create_transid(file, vol_args->name,
                                              vol_args->fd, subvol, ptr,
                                              readonly, inherit);
+       if (ret)
+               goto free_inherit;
 
-       if (ret == 0 && ptr &&
-           copy_to_user(arg +
-                        offsetof(struct btrfs_ioctl_vol_args_v2,
-                                 transid), ptr, sizeof(*ptr)))
+       if (ptr && copy_to_user(arg +
+                               offsetof(struct btrfs_ioctl_vol_args_v2,
+                                       transid),
+                               ptr, sizeof(*ptr)))
                ret = -EFAULT;
-out:
-       kfree(vol_args);
+
+free_inherit:
        kfree(inherit);
+free_args:
+       kfree(vol_args);
        return ret;
 }
 
@@ -2685,7 +2657,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
        vol_args = memdup_user(arg, sizeof(*vol_args));
        if (IS_ERR(vol_args)) {
                ret = PTR_ERR(vol_args);
-               goto out;
+               goto err_drop;
        }
 
        vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
@@ -2703,6 +2675,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
 
 out:
        kfree(vol_args);
+err_drop:
        mnt_drop_write_file(file);
        return ret;
 }
@@ -3527,7 +3500,8 @@ process_slot:
                        btrfs_mark_buffer_dirty(leaf);
                        btrfs_release_path(path);
 
-                       last_dest_end = new_key.offset + datal;
+                       last_dest_end = ALIGN(new_key.offset + datal,
+                                             root->sectorsize);
                        ret = clone_finish_inode_update(trans, inode,
                                                        last_dest_end,
                                                        destoff, olen);
index 963895c1f801dcbbde3ce9c5e621c91308793f7a..ac734ec4cc20ecbc47bc1b495b75021b4c699edf 100644 (file)
@@ -615,6 +615,7 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr)
                spin_unlock(&root->ordered_extent_lock);
 
                btrfs_init_work(&ordered->flush_work,
+                               btrfs_flush_delalloc_helper,
                                btrfs_run_ordered_extent_work, NULL, NULL);
                list_add_tail(&ordered->work_list, &works);
                btrfs_queue_work(root->fs_info->flush_workers,
index b497498484bebaf5774aa3c4d016a5e4f0b05ff1..ded5c601d9162a7699a3fa4802a8c9df9bd37722 100644 (file)
@@ -1973,7 +1973,7 @@ static int qgroup_subtree_accounting(struct btrfs_trans_handle *trans,
                                   elem.seq, &roots);
        btrfs_put_tree_mod_seq(fs_info, &elem);
        if (ret < 0)
-               return ret;
+               goto out;
 
        if (roots->nnodes != 1)
                goto out;
@@ -2720,6 +2720,7 @@ qgroup_rescan_init(struct btrfs_fs_info *fs_info, u64 progress_objectid,
        memset(&fs_info->qgroup_rescan_work, 0,
               sizeof(fs_info->qgroup_rescan_work));
        btrfs_init_work(&fs_info->qgroup_rescan_work,
+                       btrfs_qgroup_rescan_helper,
                        btrfs_qgroup_rescan_worker, NULL, NULL);
 
        if (ret) {
index 4a88f073fdd79bf5440f2d54fb4771fc4361212c..0a6b6e4bcbb97a8af56ad6a58aef9f514c3b1132 100644 (file)
@@ -1416,7 +1416,8 @@ cleanup:
 
 static void async_rmw_stripe(struct btrfs_raid_bio *rbio)
 {
-       btrfs_init_work(&rbio->work, rmw_work, NULL, NULL);
+       btrfs_init_work(&rbio->work, btrfs_rmw_helper,
+                       rmw_work, NULL, NULL);
 
        btrfs_queue_work(rbio->fs_info->rmw_workers,
                         &rbio->work);
@@ -1424,7 +1425,8 @@ static void async_rmw_stripe(struct btrfs_raid_bio *rbio)
 
 static void async_read_rebuild(struct btrfs_raid_bio *rbio)
 {
-       btrfs_init_work(&rbio->work, read_rebuild_work, NULL, NULL);
+       btrfs_init_work(&rbio->work, btrfs_rmw_helper,
+                       read_rebuild_work, NULL, NULL);
 
        btrfs_queue_work(rbio->fs_info->rmw_workers,
                         &rbio->work);
@@ -1665,7 +1667,8 @@ static void btrfs_raid_unplug(struct blk_plug_cb *cb, bool from_schedule)
        plug = container_of(cb, struct btrfs_plug_cb, cb);
 
        if (from_schedule) {
-               btrfs_init_work(&plug->work, unplug_work, NULL, NULL);
+               btrfs_init_work(&plug->work, btrfs_rmw_helper,
+                               unplug_work, NULL, NULL);
                btrfs_queue_work(plug->info->rmw_workers,
                                 &plug->work);
                return;
index 09230cf3a2447b3541826f21b2f3fe1dcce202ce..20408c6b665ae94e03a152c94bb822bb87fdc63e 100644 (file)
@@ -798,7 +798,8 @@ static void reada_start_machine(struct btrfs_fs_info *fs_info)
                /* FIXME we cannot handle this properly right now */
                BUG();
        }
-       btrfs_init_work(&rmw->work, reada_start_machine_worker, NULL, NULL);
+       btrfs_init_work(&rmw->work, btrfs_readahead_helper,
+                       reada_start_machine_worker, NULL, NULL);
        rmw->fs_info = fs_info;
 
        btrfs_queue_work(fs_info->readahead_workers, &rmw->work);
index b6d198f5181ed6d07f8f9c29782bd5a99e46f9ce..f4a41f37be229b555fb2e26993aff7055ee7fff1 100644 (file)
@@ -428,8 +428,8 @@ struct scrub_ctx *scrub_setup_ctx(struct btrfs_device *dev, int is_dev_replace)
                sbio->index = i;
                sbio->sctx = sctx;
                sbio->page_count = 0;
-               btrfs_init_work(&sbio->work, scrub_bio_end_io_worker,
-                               NULL, NULL);
+               btrfs_init_work(&sbio->work, btrfs_scrub_helper,
+                               scrub_bio_end_io_worker, NULL, NULL);
 
                if (i != SCRUB_BIOS_PER_SCTX - 1)
                        sctx->bios[i]->next_free = i + 1;
@@ -999,8 +999,8 @@ nodatasum_case:
                fixup_nodatasum->root = fs_info->extent_root;
                fixup_nodatasum->mirror_num = failed_mirror_index + 1;
                scrub_pending_trans_workers_inc(sctx);
-               btrfs_init_work(&fixup_nodatasum->work, scrub_fixup_nodatasum,
-                               NULL, NULL);
+               btrfs_init_work(&fixup_nodatasum->work, btrfs_scrub_helper,
+                               scrub_fixup_nodatasum, NULL, NULL);
                btrfs_queue_work(fs_info->scrub_workers,
                                 &fixup_nodatasum->work);
                goto out;
@@ -1616,7 +1616,8 @@ static void scrub_wr_bio_end_io(struct bio *bio, int err)
        sbio->err = err;
        sbio->bio = bio;
 
-       btrfs_init_work(&sbio->work, scrub_wr_bio_end_io_worker, NULL, NULL);
+       btrfs_init_work(&sbio->work, btrfs_scrubwrc_helper,
+                        scrub_wr_bio_end_io_worker, NULL, NULL);
        btrfs_queue_work(fs_info->scrub_wr_completion_workers, &sbio->work);
 }
 
@@ -2904,6 +2905,7 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
        struct scrub_ctx *sctx;
        int ret;
        struct btrfs_device *dev;
+       struct rcu_string *name;
 
        if (btrfs_fs_closing(fs_info))
                return -EINVAL;
@@ -2965,6 +2967,16 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
                return -ENODEV;
        }
 
+       if (!is_dev_replace && !readonly && !dev->writeable) {
+               mutex_unlock(&fs_info->fs_devices->device_list_mutex);
+               rcu_read_lock();
+               name = rcu_dereference(dev->name);
+               btrfs_err(fs_info, "scrub: device %s is not writable",
+                         name->str);
+               rcu_read_unlock();
+               return -EROFS;
+       }
+
        mutex_lock(&fs_info->scrub_lock);
        if (!dev->in_fs_metadata || dev->is_tgtdev_for_dev_replace) {
                mutex_unlock(&fs_info->scrub_lock);
@@ -3203,7 +3215,8 @@ static int copy_nocow_pages(struct scrub_ctx *sctx, u64 logical, u64 len,
        nocow_ctx->len = len;
        nocow_ctx->mirror_num = mirror_num;
        nocow_ctx->physical_for_dev_replace = physical_for_dev_replace;
-       btrfs_init_work(&nocow_ctx->work, copy_nocow_pages_worker, NULL, NULL);
+       btrfs_init_work(&nocow_ctx->work, btrfs_scrubnc_helper,
+                       copy_nocow_pages_worker, NULL, NULL);
        INIT_LIST_HEAD(&nocow_ctx->inodes);
        btrfs_queue_work(fs_info->scrub_nocow_workers,
                         &nocow_ctx->work);
index 78699364f537c423b9fa25cb0e3c124ded8c6ce7..12e53556e214c2c26f0a67aadf63b53637178822 100644 (file)
@@ -614,7 +614,7 @@ int btrfs_kobj_rm_device(struct btrfs_fs_info *fs_info,
        if (!fs_info->device_dir_kobj)
                return -EINVAL;
 
-       if (one_device) {
+       if (one_device && one_device->bdev) {
                disk = one_device->bdev->bd_part;
                disk_kobj = &part_to_dev(disk)->kobj;
 
index 9e1f2cd5e67ab0fff18ec12df76c965e109e662c..d296efe2d3e76ce4f690687a9647cf7f8c71a27f 100644 (file)
 #define LOG_WALK_REPLAY_ALL 3
 
 static int btrfs_log_inode(struct btrfs_trans_handle *trans,
-                            struct btrfs_root *root, struct inode *inode,
-                            int inode_only);
+                          struct btrfs_root *root, struct inode *inode,
+                          int inode_only,
+                          const loff_t start,
+                          const loff_t end);
 static int link_to_fixup_dir(struct btrfs_trans_handle *trans,
                             struct btrfs_root *root,
                             struct btrfs_path *path, u64 objectid);
@@ -3298,7 +3300,7 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
        struct list_head ordered_sums;
        int skip_csum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM;
        bool has_extents = false;
-       bool need_find_last_extent = (*last_extent == 0);
+       bool need_find_last_extent = true;
        bool done = false;
 
        INIT_LIST_HEAD(&ordered_sums);
@@ -3352,8 +3354,7 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
                 */
                if (ins_keys[i].type == BTRFS_EXTENT_DATA_KEY) {
                        has_extents = true;
-                       if (need_find_last_extent &&
-                           first_key.objectid == (u64)-1)
+                       if (first_key.objectid == (u64)-1)
                                first_key = ins_keys[i];
                } else {
                        need_find_last_extent = false;
@@ -3427,6 +3428,16 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
        if (!has_extents)
                return ret;
 
+       if (need_find_last_extent && *last_extent == first_key.offset) {
+               /*
+                * We don't have any leafs between our current one and the one
+                * we processed before that can have file extent items for our
+                * inode (and have a generation number smaller than our current
+                * transaction id).
+                */
+               need_find_last_extent = false;
+       }
+
        /*
         * Because we use btrfs_search_forward we could skip leaves that were
         * not modified and then assume *last_extent is valid when it really
@@ -3537,7 +3548,7 @@ fill_holes:
                                               0, 0);
                if (ret)
                        break;
-               *last_extent = offset + len;
+               *last_extent = extent_end;
        }
        /*
         * Need to let the callers know we dropped the path so they should
@@ -3849,8 +3860,10 @@ process:
  * This handles both files and directories.
  */
 static int btrfs_log_inode(struct btrfs_trans_handle *trans,
-                            struct btrfs_root *root, struct inode *inode,
-                            int inode_only)
+                          struct btrfs_root *root, struct inode *inode,
+                          int inode_only,
+                          const loff_t start,
+                          const loff_t end)
 {
        struct btrfs_path *path;
        struct btrfs_path *dst_path;
@@ -3867,6 +3880,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
        int ins_nr;
        bool fast_search = false;
        u64 ino = btrfs_ino(inode);
+       struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
 
        path = btrfs_alloc_path();
        if (!path)
@@ -4040,13 +4054,35 @@ log_extents:
                        goto out_unlock;
                }
        } else if (inode_only == LOG_INODE_ALL) {
-               struct extent_map_tree *tree = &BTRFS_I(inode)->extent_tree;
                struct extent_map *em, *n;
 
-               write_lock(&tree->lock);
-               list_for_each_entry_safe(em, n, &tree->modified_extents, list)
-                       list_del_init(&em->list);
-               write_unlock(&tree->lock);
+               write_lock(&em_tree->lock);
+               /*
+                * We can't just remove every em if we're called for a ranged
+                * fsync - that is, one that doesn't cover the whole possible
+                * file range (0 to LLONG_MAX). This is because we can have
+                * em's that fall outside the range we're logging and therefore
+                * their ordered operations haven't completed yet
+                * (btrfs_finish_ordered_io() not invoked yet). This means we
+                * didn't get their respective file extent item in the fs/subvol
+                * tree yet, and need to let the next fast fsync (one which
+                * consults the list of modified extent maps) find the em so
+                * that it logs a matching file extent item and waits for the
+                * respective ordered operation to complete (if it's still
+                * running).
+                *
+                * Removing every em outside the range we're logging would make
+                * the next fast fsync not log their matching file extent items,
+                * therefore making us lose data after a log replay.
+                */
+               list_for_each_entry_safe(em, n, &em_tree->modified_extents,
+                                        list) {
+                       const u64 mod_end = em->mod_start + em->mod_len - 1;
+
+                       if (em->mod_start >= start && mod_end <= end)
+                               list_del_init(&em->list);
+               }
+               write_unlock(&em_tree->lock);
        }
 
        if (inode_only == LOG_INODE_ALL && S_ISDIR(inode->i_mode)) {
@@ -4056,8 +4092,19 @@ log_extents:
                        goto out_unlock;
                }
        }
-       BTRFS_I(inode)->logged_trans = trans->transid;
-       BTRFS_I(inode)->last_log_commit = BTRFS_I(inode)->last_sub_trans;
+
+       write_lock(&em_tree->lock);
+       /*
+        * If we're doing a ranged fsync and there are still modified extents
+        * in the list, we must run on the next fsync call as it might cover
+        * those extents (a full fsync or an fsync for other range).
+        */
+       if (list_empty(&em_tree->modified_extents)) {
+               BTRFS_I(inode)->logged_trans = trans->transid;
+               BTRFS_I(inode)->last_log_commit =
+                       BTRFS_I(inode)->last_sub_trans;
+       }
+       write_unlock(&em_tree->lock);
 out_unlock:
        if (unlikely(err))
                btrfs_put_logged_extents(&logged_list);
@@ -4152,7 +4199,10 @@ out:
  */
 static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
                                  struct btrfs_root *root, struct inode *inode,
-                                 struct dentry *parent, int exists_only,
+                                 struct dentry *parent,
+                                 const loff_t start,
+                                 const loff_t end,
+                                 int exists_only,
                                  struct btrfs_log_ctx *ctx)
 {
        int inode_only = exists_only ? LOG_INODE_EXISTS : LOG_INODE_ALL;
@@ -4198,7 +4248,7 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
        if (ret)
                goto end_no_trans;
 
-       ret = btrfs_log_inode(trans, root, inode, inode_only);
+       ret = btrfs_log_inode(trans, root, inode, inode_only, start, end);
        if (ret)
                goto end_trans;
 
@@ -4226,7 +4276,8 @@ static int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
 
                if (BTRFS_I(inode)->generation >
                    root->fs_info->last_trans_committed) {
-                       ret = btrfs_log_inode(trans, root, inode, inode_only);
+                       ret = btrfs_log_inode(trans, root, inode, inode_only,
+                                             0, LLONG_MAX);
                        if (ret)
                                goto end_trans;
                }
@@ -4260,13 +4311,15 @@ end_no_trans:
  */
 int btrfs_log_dentry_safe(struct btrfs_trans_handle *trans,
                          struct btrfs_root *root, struct dentry *dentry,
+                         const loff_t start,
+                         const loff_t end,
                          struct btrfs_log_ctx *ctx)
 {
        struct dentry *parent = dget_parent(dentry);
        int ret;
 
        ret = btrfs_log_inode_parent(trans, root, dentry->d_inode, parent,
-                                    0, ctx);
+                                    start, end, 0, ctx);
        dput(parent);
 
        return ret;
@@ -4503,6 +4556,7 @@ int btrfs_log_new_name(struct btrfs_trans_handle *trans,
                    root->fs_info->last_trans_committed))
                return 0;
 
-       return btrfs_log_inode_parent(trans, root, inode, parent, 1, NULL);
+       return btrfs_log_inode_parent(trans, root, inode, parent, 0,
+                                     LLONG_MAX, 1, NULL);
 }
 
index 7f5b41bd5373810a04159d8c28facbd289c5c03c..e2e798ae7cd7c6c989a6633fe7dae682ab4a5148 100644 (file)
@@ -59,6 +59,8 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans,
 int btrfs_recover_log_trees(struct btrfs_root *tree_root);
 int btrfs_log_dentry_safe(struct btrfs_trans_handle *trans,
                          struct btrfs_root *root, struct dentry *dentry,
+                         const loff_t start,
+                         const loff_t end,
                          struct btrfs_log_ctx *ctx);
 int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
                                 struct btrfs_root *root,
index 6cb82f62cb7c22c4b3038e248e52b9694171a5bd..340a92d08e84d9e5268a18fe5f3112465fa47888 100644 (file)
@@ -508,6 +508,44 @@ static noinline int device_list_add(const char *path,
                ret = 1;
                device->fs_devices = fs_devices;
        } else if (!device->name || strcmp(device->name->str, path)) {
+               /*
+                * When FS is already mounted.
+                * 1. If you are here and if the device->name is NULL that
+                *    means this device was missing at time of FS mount.
+                * 2. If you are here and if the device->name is different
+                *    from 'path' that means either
+                *      a. The same device disappeared and reappeared with
+                *         different name. or
+                *      b. The missing-disk-which-was-replaced, has
+                *         reappeared now.
+                *
+                * We must allow 1 and 2a above. But 2b would be a spurious
+                * and unintentional.
+                *
+                * Further in case of 1 and 2a above, the disk at 'path'
+                * would have missed some transaction when it was away and
+                * in case of 2a the stale bdev has to be updated as well.
+                * 2b must not be allowed at all time.
+                */
+
+               /*
+                * As of now don't allow update to btrfs_fs_device through
+                * the btrfs dev scan cli, after FS has been mounted.
+                */
+               if (fs_devices->opened) {
+                       return -EBUSY;
+               } else {
+                       /*
+                        * That is if the FS is _not_ mounted and if you
+                        * are here, that means there is more than one
+                        * disk with same uuid and devid.We keep the one
+                        * with larger generation number or the last-in if
+                        * generation are equal.
+                        */
+                       if (found_transid < device->generation)
+                               return -EEXIST;
+               }
+
                name = rcu_string_strdup(path, GFP_NOFS);
                if (!name)
                        return -ENOMEM;
@@ -519,6 +557,15 @@ static noinline int device_list_add(const char *path,
                }
        }
 
+       /*
+        * Unmount does not free the btrfs_device struct but would zero
+        * generation along with most of the other members. So just update
+        * it back. We need it to pick the disk with largest generation
+        * (as above).
+        */
+       if (!fs_devices->opened)
+               device->generation = found_transid;
+
        if (found_transid > fs_devices->latest_trans) {
                fs_devices->latest_devid = devid;
                fs_devices->latest_trans = found_transid;
@@ -1436,7 +1483,7 @@ static int btrfs_add_device(struct btrfs_trans_handle *trans,
        btrfs_set_device_io_align(leaf, dev_item, device->io_align);
        btrfs_set_device_io_width(leaf, dev_item, device->io_width);
        btrfs_set_device_sector_size(leaf, dev_item, device->sector_size);
-       btrfs_set_device_total_bytes(leaf, dev_item, device->total_bytes);
+       btrfs_set_device_total_bytes(leaf, dev_item, device->disk_total_bytes);
        btrfs_set_device_bytes_used(leaf, dev_item, device->bytes_used);
        btrfs_set_device_group(leaf, dev_item, 0);
        btrfs_set_device_seek_speed(leaf, dev_item, 0);
@@ -1671,7 +1718,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
        device->fs_devices->total_devices--;
 
        if (device->missing)
-               root->fs_info->fs_devices->missing_devices--;
+               device->fs_devices->missing_devices--;
 
        next_device = list_entry(root->fs_info->fs_devices->devices.next,
                                 struct btrfs_device, dev_list);
@@ -1801,8 +1848,12 @@ void btrfs_rm_dev_replace_srcdev(struct btrfs_fs_info *fs_info,
        if (srcdev->bdev) {
                fs_info->fs_devices->open_devices--;
 
-               /* zero out the old super */
-               btrfs_scratch_superblock(srcdev);
+               /*
+                * zero out the old super if it is not writable
+                * (e.g. seed device)
+                */
+               if (srcdev->writeable)
+                       btrfs_scratch_superblock(srcdev);
        }
 
        call_rcu(&srcdev->rcu, free_device);
@@ -1941,6 +1992,9 @@ static int btrfs_prepare_sprout(struct btrfs_root *root)
        fs_devices->seeding = 0;
        fs_devices->num_devices = 0;
        fs_devices->open_devices = 0;
+       fs_devices->missing_devices = 0;
+       fs_devices->num_can_discard = 0;
+       fs_devices->rotating = 0;
        fs_devices->seed = seed_devices;
 
        generate_random_uuid(fs_devices->fsid);
@@ -5800,7 +5854,8 @@ struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info,
        else
                generate_random_uuid(dev->uuid);
 
-       btrfs_init_work(&dev->work, pending_bios_fn, NULL, NULL);
+       btrfs_init_work(&dev->work, btrfs_submit_helper,
+                       pending_bios_fn, NULL, NULL);
 
        return dev;
 }
index 603f18a65c121e5586f903baff101a8637bdb852..a2172f3f69e318915f092885da0b4d49755d33f1 100644 (file)
@@ -22,6 +22,11 @@ config CIFS
          support for OS/2 and Windows ME and similar servers is provided as
          well.
 
+         The module also provides optional support for the followon
+         protocols for CIFS including SMB3, which enables
+         useful performance and security features (see the description
+         of CONFIG_CIFS_SMB2).
+
          The cifs module provides an advanced network file system
          client for mounting to CIFS compliant servers.  It includes
          support for DFS (hierarchical name space), secure per-user
@@ -121,7 +126,8 @@ config CIFS_ACL
          depends on CIFS_XATTR && KEYS
          help
            Allows fetching CIFS/NTFS ACL from the server.  The DACL blob
-           is handed over to the application/caller.
+           is handed over to the application/caller.  See the man
+           page for getcifsacl for more information.
 
 config CIFS_DEBUG
        bool "Enable CIFS debugging routines"
@@ -162,7 +168,7 @@ config CIFS_NFSD_EXPORT
           Allows NFS server to export a CIFS mounted share (nfsd over cifs)
 
 config CIFS_SMB2
-       bool "SMB2 network file system support"
+       bool "SMB2 and SMB3 network file system support"
        depends on CIFS && INET
        select NLS
        select KEYS
@@ -170,16 +176,21 @@ config CIFS_SMB2
        select DNS_RESOLVER
 
        help
-         This enables experimental support for the SMB2 (Server Message Block
-         version 2) protocol. The SMB2 protocol is the successor to the
-         popular CIFS and SMB network file sharing protocols. SMB2 is the
-         native file sharing mechanism for recent versions of Windows
-         operating systems (since Vista).  SMB2 enablement will eventually
-         allow users better performance, security and features, than would be
-         possible with cifs. Note that smb2 mount options also are simpler
-         (compared to cifs) due to protocol improvements.
-
-         Unless you are a developer or tester, say N.
+         This enables support for the Server Message Block version 2
+         family of protocols, including SMB3.  SMB3 support is
+         enabled on mount by specifying "vers=3.0" in the mount
+         options. These protocols are the successors to the popular
+         CIFS and SMB network file sharing protocols. SMB3 is the
+         native file sharing mechanism for the more recent
+         versions of Windows (Windows 8 and Windows 2012 and
+         later) and Samba server and many others support SMB3 well.
+         In general SMB3 enables better performance, security
+         and features, than would be possible with CIFS (Note that
+         when mounting to Samba, due to the CIFS POSIX extensions,
+         CIFS mounts can provide slightly better POSIX compatibility
+         than SMB3 mounts do though). Note that SMB2/SMB3 mount
+         options are also slightly simpler (compared to CIFS) due
+         to protocol improvements.
 
 config CIFS_FSCACHE
          bool "Provide CIFS client caching support"
index dfc731b02aa9b3daca3a15d95346bcd82cc2b3d5..25b8392bfdd2a7fd9864af5008e809dc41e3a7df 100644 (file)
 #define SERVER_NAME_LENGTH 40
 #define SERVER_NAME_LEN_WITH_NULL     (SERVER_NAME_LENGTH + 1)
 
-/* used to define string lengths for reversing unicode strings */
-/*         (256+1)*2 = 514                                     */
-/*           (max path length + 1 for null) * 2 for unicode    */
-#define MAX_NAME 514
-
 /* SMB echo "timeout" -- FIXME: tunable? */
 #define SMB_ECHO_INTERVAL (60 * HZ)
 
index 03ed8a09581ca0104468d1207ff0cadefd0f9390..8a9fded7c135f6deb936873ad06fa86fc11c9f85 100644 (file)
@@ -837,7 +837,6 @@ cifs_demultiplex_thread(void *p)
        struct TCP_Server_Info *server = p;
        unsigned int pdu_length;
        char *buf = NULL;
-       struct task_struct *task_to_wake = NULL;
        struct mid_q_entry *mid_entry;
 
        current->flags |= PF_MEMALLOC;
@@ -928,19 +927,7 @@ cifs_demultiplex_thread(void *p)
        if (server->smallbuf) /* no sense logging a debug message if NULL */
                cifs_small_buf_release(server->smallbuf);
 
-       task_to_wake = xchg(&server->tsk, NULL);
        clean_demultiplex_info(server);
-
-       /* if server->tsk was NULL then wait for a signal before exiting */
-       if (!task_to_wake) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               while (!signal_pending(current)) {
-                       schedule();
-                       set_current_state(TASK_INTERRUPTIBLE);
-               }
-               set_current_state(TASK_RUNNING);
-       }
-
        module_put_and_exit(0);
 }
 
@@ -1600,6 +1587,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                        tmp_end++;
                        if (!(tmp_end < end && tmp_end[1] == delim)) {
                                /* No it is not. Set the password to NULL */
+                               kfree(vol->password);
                                vol->password = NULL;
                                break;
                        }
@@ -1637,6 +1625,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
                                        options = end;
                        }
 
+                       kfree(vol->password);
                        /* Now build new password string */
                        temp_len = strlen(value);
                        vol->password = kzalloc(temp_len+1, GFP_KERNEL);
@@ -2061,8 +2050,6 @@ cifs_find_tcp_session(struct smb_vol *vol)
 static void
 cifs_put_tcp_session(struct TCP_Server_Info *server)
 {
-       struct task_struct *task;
-
        spin_lock(&cifs_tcp_ses_lock);
        if (--server->srv_count > 0) {
                spin_unlock(&cifs_tcp_ses_lock);
@@ -2086,10 +2073,6 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
        kfree(server->session_key.response);
        server->session_key.response = NULL;
        server->session_key.len = 0;
-
-       task = xchg(&server->tsk, NULL);
-       if (task)
-               force_sig(SIGKILL, task);
 }
 
 static struct TCP_Server_Info *
index 3db0c5fd9a1109629764cf5f2b759dd9ddd8cd8a..6cbd9c688cfe818a773a2a7f42c64ce59d693de1 100644 (file)
@@ -497,6 +497,14 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
                goto out;
        }
 
+       if (file->f_flags & O_DIRECT &&
+           CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
+               if (CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+                       file->f_op = &cifs_file_direct_nobrl_ops;
+               else
+                       file->f_op = &cifs_file_direct_ops;
+               }
+
        file_info = cifs_new_fileinfo(&fid, file, tlink, oplock);
        if (file_info == NULL) {
                if (server->ops->close)
index d5fec92e036068b98bf2e3426e3f8d159b70e048..7c018a1c52f7d474ce3b6d5ffb63c62485db831b 100644 (file)
@@ -467,6 +467,14 @@ int cifs_open(struct inode *inode, struct file *file)
        cifs_dbg(FYI, "inode = 0x%p file flags are 0x%x for %s\n",
                 inode, file->f_flags, full_path);
 
+       if (file->f_flags & O_DIRECT &&
+           cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
+               if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+                       file->f_op = &cifs_file_direct_nobrl_ops;
+               else
+                       file->f_op = &cifs_file_direct_ops;
+       }
+
        if (server->oplocks)
                oplock = REQ_OPLOCK;
        else
index 949ec909ec9ab94747ed332cc96cdcdbc29fd47b..7899a40465b303db85e1903e9fec1fe57124a261 100644 (file)
@@ -1720,7 +1720,10 @@ cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
 unlink_target:
        /* Try unlinking the target dentry if it's not negative */
        if (target_dentry->d_inode && (rc == -EACCES || rc == -EEXIST)) {
-               tmprc = cifs_unlink(target_dir, target_dentry);
+               if (d_is_dir(target_dentry))
+                       tmprc = cifs_rmdir(target_dir, target_dentry);
+               else
+                       tmprc = cifs_unlink(target_dir, target_dentry);
                if (tmprc)
                        goto cifs_rename_exit;
                rc = cifs_do_rename(xid, source_dentry, from_name,
index 798c80a41c886b3fba7e66f8264066902d35b8cb..b334a89d6a66eb2151973d6405083db3c254710b 100644 (file)
@@ -596,8 +596,8 @@ find_cifs_entry(const unsigned int xid, struct cifs_tcon *tcon, loff_t pos,
                if (server->ops->dir_needs_close(cfile)) {
                        cfile->invalidHandle = true;
                        spin_unlock(&cifs_file_list_lock);
-                       if (server->ops->close)
-                               server->ops->close(xid, tcon, &cfile->fid);
+                       if (server->ops->close_dir)
+                               server->ops->close_dir(xid, tcon, &cfile->fid);
                } else
                        spin_unlock(&cifs_file_list_lock);
                if (cfile->srch_inf.ntwrk_buf_start) {
index 39ee32688eac93abb107eb07e5f5566237602ba8..3a5e83317683d1c16156c4511ab7657940b48d97 100644 (file)
@@ -243,10 +243,11 @@ static void decode_ascii_ssetup(char **pbcc_area, __u16 bleft,
        kfree(ses->serverOS);
 
        ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
-       if (ses->serverOS)
+       if (ses->serverOS) {
                strncpy(ses->serverOS, bcc_ptr, len);
-       if (strncmp(ses->serverOS, "OS/2", 4) == 0)
-               cifs_dbg(FYI, "OS/2 server\n");
+               if (strncmp(ses->serverOS, "OS/2", 4) == 0)
+                       cifs_dbg(FYI, "OS/2 server\n");
+       }
 
        bcc_ptr += len + 1;
        bleft -= len + 1;
index 3f17b455083141c572fac5d88e95e56fbe54f89a..45992944e23859b1706fed3d0430ea0cee445a10 100644 (file)
@@ -50,7 +50,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
                goto out;
        }
 
-       smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
+       smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
                            GFP_KERNEL);
        if (smb2_data == NULL) {
                rc = -ENOMEM;
index 0150182a44946dcebdb9aae71130f7c8a479eab9..899bbc86f73e1416aafcd00708052c22bd87f52e 100644 (file)
@@ -131,7 +131,7 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
        *adjust_tz = false;
        *symlink = false;
 
-       smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
+       smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
                            GFP_KERNEL);
        if (smb2_data == NULL)
                return -ENOMEM;
index 5a48aa290dfe83fdab6f9af322aadcdd0ebe3b3b..f522193b7184facd4926cfa3447b7fcbf5268cce 100644 (file)
@@ -389,7 +389,7 @@ smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon,
        int rc;
        struct smb2_file_all_info *smb2_data;
 
-       smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
+       smb2_data = kzalloc(sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
                            GFP_KERNEL);
        if (smb2_data == NULL)
                return -ENOMEM;
@@ -1035,7 +1035,7 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
                if (keep_size == false)
                        return -EOPNOTSUPP;
 
-       /* 
+       /*
         * Must check if file sparse since fallocate -z (zero range) assumes
         * non-sparse allocation
         */
index fa0dd044213b9dc7dab5ec26d37c469627e9ca49..74b3a6684383c9bfd08f481c8575932cefa06766 100644 (file)
@@ -530,7 +530,7 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
        struct smb2_sess_setup_rsp *rsp = NULL;
        struct kvec iov[2];
        int rc = 0;
-       int resp_buftype;
+       int resp_buftype = CIFS_NO_BUFFER;
        __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
        struct TCP_Server_Info *server = ses->server;
        u16 blob_length = 0;
@@ -1403,8 +1403,7 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
        rsp = (struct smb2_close_rsp *)iov[0].iov_base;
 
        if (rc != 0) {
-               if (tcon)
-                       cifs_stats_fail_inc(tcon, SMB2_CLOSE_HE);
+               cifs_stats_fail_inc(tcon, SMB2_CLOSE_HE);
                goto close_exit;
        }
 
@@ -1533,7 +1532,7 @@ SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
 {
        return query_info(xid, tcon, persistent_fid, volatile_fid,
                          FILE_ALL_INFORMATION,
-                         sizeof(struct smb2_file_all_info) + MAX_NAME * 2,
+                         sizeof(struct smb2_file_all_info) + PATH_MAX * 2,
                          sizeof(struct smb2_file_all_info), data);
 }
 
index b10b48c2a7afaf859f2b508d5bca784abfe870ac..7bcfff900f058cd9d98278c1fa13ed2b0202eccc 100644 (file)
@@ -1852,7 +1852,8 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
                goto error_tgt_fput;
 
        /* Check if EPOLLWAKEUP is allowed */
-       ep_take_care_of_epollwakeup(&epds);
+       if (ep_op_has_event(op))
+               ep_take_care_of_epollwakeup(&epds);
 
        /*
         * We have to check that the file structure underneath the file descriptor
index 5b19760b1de59ddc6340f8845832c031a272a4db..b0c225cdb52cd20ba5927149c338d9749e951f57 100644 (file)
@@ -1825,7 +1825,7 @@ ext4_group_first_block_no(struct super_block *sb, ext4_group_t group_no)
 /*
  * Special error return code only used by dx_probe() and its callers.
  */
-#define ERR_BAD_DX_DIR -75000
+#define ERR_BAD_DX_DIR (-(MAX_ERRNO - 1))
 
 /*
  * Timeout and state flag for lazy initialization inode thread.
@@ -2454,6 +2454,22 @@ static inline void ext4_update_i_disksize(struct inode *inode, loff_t newsize)
        up_write(&EXT4_I(inode)->i_data_sem);
 }
 
+/* Update i_size, i_disksize. Requires i_mutex to avoid races with truncate */
+static inline int ext4_update_inode_size(struct inode *inode, loff_t newsize)
+{
+       int changed = 0;
+
+       if (newsize > inode->i_size) {
+               i_size_write(inode, newsize);
+               changed = 1;
+       }
+       if (newsize > EXT4_I(inode)->i_disksize) {
+               ext4_update_i_disksize(inode, newsize);
+               changed |= 2;
+       }
+       return changed;
+}
+
 struct ext4_group_info {
        unsigned long   bb_state;
        struct rb_root  bb_free_root;
index 76c2df382b7d05619bbe4093d2115ca6dafa617e..74292a71b384e2fd480357a8115c5e4936fa6f20 100644 (file)
@@ -4665,7 +4665,8 @@ retry:
 }
 
 static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
-                                 ext4_lblk_t len, int flags, int mode)
+                                 ext4_lblk_t len, loff_t new_size,
+                                 int flags, int mode)
 {
        struct inode *inode = file_inode(file);
        handle_t *handle;
@@ -4674,8 +4675,10 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
        int retries = 0;
        struct ext4_map_blocks map;
        unsigned int credits;
+       loff_t epos;
 
        map.m_lblk = offset;
+       map.m_len = len;
        /*
         * Don't normalize the request if it can fit in one extent so
         * that it doesn't get unnecessarily split into multiple
@@ -4690,9 +4693,7 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
        credits = ext4_chunk_trans_blocks(inode, len);
 
 retry:
-       while (ret >= 0 && ret < len) {
-               map.m_lblk = map.m_lblk + ret;
-               map.m_len = len = len - ret;
+       while (ret >= 0 && len) {
                handle = ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS,
                                            credits);
                if (IS_ERR(handle)) {
@@ -4709,6 +4710,21 @@ retry:
                        ret2 = ext4_journal_stop(handle);
                        break;
                }
+               map.m_lblk += ret;
+               map.m_len = len = len - ret;
+               epos = (loff_t)map.m_lblk << inode->i_blkbits;
+               inode->i_ctime = ext4_current_time(inode);
+               if (new_size) {
+                       if (epos > new_size)
+                               epos = new_size;
+                       if (ext4_update_inode_size(inode, epos) & 0x1)
+                               inode->i_mtime = inode->i_ctime;
+               } else {
+                       if (epos > inode->i_size)
+                               ext4_set_inode_flag(inode,
+                                                   EXT4_INODE_EOFBLOCKS);
+               }
+               ext4_mark_inode_dirty(handle, inode);
                ret2 = ext4_journal_stop(handle);
                if (ret2)
                        break;
@@ -4731,7 +4747,8 @@ static long ext4_zero_range(struct file *file, loff_t offset,
        loff_t new_size = 0;
        int ret = 0;
        int flags;
-       int partial;
+       int credits;
+       int partial_begin, partial_end;
        loff_t start, end;
        ext4_lblk_t lblk;
        struct address_space *mapping = inode->i_mapping;
@@ -4771,7 +4788,8 @@ static long ext4_zero_range(struct file *file, loff_t offset,
 
        if (start < offset || end > offset + len)
                return -EINVAL;
-       partial = (offset + len) & ((1 << blkbits) - 1);
+       partial_begin = offset & ((1 << blkbits) - 1);
+       partial_end = (offset + len) & ((1 << blkbits) - 1);
 
        lblk = start >> blkbits;
        max_blocks = (end >> blkbits);
@@ -4805,7 +4823,7 @@ static long ext4_zero_range(struct file *file, loff_t offset,
                 * If we have a partial block after EOF we have to allocate
                 * the entire block.
                 */
-               if (partial)
+               if (partial_end)
                        max_blocks += 1;
        }
 
@@ -4813,6 +4831,7 @@ static long ext4_zero_range(struct file *file, loff_t offset,
 
                /* Now release the pages and zero block aligned part of pages*/
                truncate_pagecache_range(inode, start, end - 1);
+               inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
 
                /* Wait all existing dio workers, newcomers will block on i_mutex */
                ext4_inode_block_unlocked_dio(inode);
@@ -4825,13 +4844,22 @@ static long ext4_zero_range(struct file *file, loff_t offset,
                if (ret)
                        goto out_dio;
 
-               ret = ext4_alloc_file_blocks(file, lblk, max_blocks, flags,
-                                            mode);
+               ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
+                                            flags, mode);
                if (ret)
                        goto out_dio;
        }
+       if (!partial_begin && !partial_end)
+               goto out_dio;
 
-       handle = ext4_journal_start(inode, EXT4_HT_MISC, 4);
+       /*
+        * In worst case we have to writeout two nonadjacent unwritten
+        * blocks and update the inode
+        */
+       credits = (2 * ext4_ext_index_trans_blocks(inode, 2)) + 1;
+       if (ext4_should_journal_data(inode))
+               credits += 2;
+       handle = ext4_journal_start(inode, EXT4_HT_MISC, credits);
        if (IS_ERR(handle)) {
                ret = PTR_ERR(handle);
                ext4_std_error(inode->i_sb, ret);
@@ -4839,12 +4867,8 @@ static long ext4_zero_range(struct file *file, loff_t offset,
        }
 
        inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
-
        if (new_size) {
-               if (new_size > i_size_read(inode))
-                       i_size_write(inode, new_size);
-               if (new_size > EXT4_I(inode)->i_disksize)
-                       ext4_update_i_disksize(inode, new_size);
+               ext4_update_inode_size(inode, new_size);
        } else {
                /*
                * Mark that we allocate beyond EOF so the subsequent truncate
@@ -4853,7 +4877,6 @@ static long ext4_zero_range(struct file *file, loff_t offset,
                if ((offset + len) > i_size_read(inode))
                        ext4_set_inode_flag(inode, EXT4_INODE_EOFBLOCKS);
        }
-
        ext4_mark_inode_dirty(handle, inode);
 
        /* Zero out partial block at the edges of the range */
@@ -4880,13 +4903,11 @@ out_mutex:
 long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
 {
        struct inode *inode = file_inode(file);
-       handle_t *handle;
        loff_t new_size = 0;
        unsigned int max_blocks;
        int ret = 0;
        int flags;
        ext4_lblk_t lblk;
-       struct timespec tv;
        unsigned int blkbits = inode->i_blkbits;
 
        /* Return error if mode is not supported */
@@ -4937,36 +4958,15 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
                        goto out;
        }
 
-       ret = ext4_alloc_file_blocks(file, lblk, max_blocks, flags, mode);
+       ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
+                                    flags, mode);
        if (ret)
                goto out;
 
-       handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
-       if (IS_ERR(handle))
-               goto out;
-
-       tv = inode->i_ctime = ext4_current_time(inode);
-
-       if (new_size) {
-               if (new_size > i_size_read(inode)) {
-                       i_size_write(inode, new_size);
-                       inode->i_mtime = tv;
-               }
-               if (new_size > EXT4_I(inode)->i_disksize)
-                       ext4_update_i_disksize(inode, new_size);
-       } else {
-               /*
-               * Mark that we allocate beyond EOF so the subsequent truncate
-               * can proceed even if the new size is the same as i_size.
-               */
-               if ((offset + len) > i_size_read(inode))
-                       ext4_set_inode_flag(inode, EXT4_INODE_EOFBLOCKS);
+       if (file->f_flags & O_SYNC && EXT4_SB(inode->i_sb)->s_journal) {
+               ret = jbd2_complete_transaction(EXT4_SB(inode->i_sb)->s_journal,
+                                               EXT4_I(inode)->i_sync_tid);
        }
-       ext4_mark_inode_dirty(handle, inode);
-       if (file->f_flags & O_SYNC)
-               ext4_handle_sync(handle);
-
-       ext4_journal_stop(handle);
 out:
        mutex_unlock(&inode->i_mutex);
        trace_ext4_fallocate_exit(inode, offset, max_blocks, ret);
index 367a60c07cf034e6983d8a51cf0eb321394b6209..3aa26e9117c440b7145cd4196433cd1568a9b20b 100644 (file)
@@ -1055,27 +1055,11 @@ static int ext4_write_end(struct file *file,
        } else
                copied = block_write_end(file, mapping, pos,
                                         len, copied, page, fsdata);
-
        /*
-        * No need to use i_size_read() here, the i_size
-        * cannot change under us because we hole i_mutex.
-        *
-        * But it's important to update i_size while still holding page lock:
+        * it's important to update i_size while still holding page lock:
         * page writeout could otherwise come in and zero beyond i_size.
         */
-       if (pos + copied > inode->i_size) {
-               i_size_write(inode, pos + copied);
-               i_size_changed = 1;
-       }
-
-       if (pos + copied > EXT4_I(inode)->i_disksize) {
-               /* We need to mark inode dirty even if
-                * new_i_size is less that inode->i_size
-                * but greater than i_disksize. (hint delalloc)
-                */
-               ext4_update_i_disksize(inode, (pos + copied));
-               i_size_changed = 1;
-       }
+       i_size_changed = ext4_update_inode_size(inode, pos + copied);
        unlock_page(page);
        page_cache_release(page);
 
@@ -1123,7 +1107,7 @@ static int ext4_journalled_write_end(struct file *file,
        int ret = 0, ret2;
        int partial = 0;
        unsigned from, to;
-       loff_t new_i_size;
+       int size_changed = 0;
 
        trace_ext4_journalled_write_end(inode, pos, len, copied);
        from = pos & (PAGE_CACHE_SIZE - 1);
@@ -1146,20 +1130,18 @@ static int ext4_journalled_write_end(struct file *file,
                if (!partial)
                        SetPageUptodate(page);
        }
-       new_i_size = pos + copied;
-       if (new_i_size > inode->i_size)
-               i_size_write(inode, pos+copied);
+       size_changed = ext4_update_inode_size(inode, pos + copied);
        ext4_set_inode_state(inode, EXT4_STATE_JDATA);
        EXT4_I(inode)->i_datasync_tid = handle->h_transaction->t_tid;
-       if (new_i_size > EXT4_I(inode)->i_disksize) {
-               ext4_update_i_disksize(inode, new_i_size);
+       unlock_page(page);
+       page_cache_release(page);
+
+       if (size_changed) {
                ret2 = ext4_mark_inode_dirty(handle, inode);
                if (!ret)
                        ret = ret2;
        }
 
-       unlock_page(page);
-       page_cache_release(page);
        if (pos + len > inode->i_size && ext4_can_truncate(inode))
                /* if we have allocated more blocks and copied
                 * less. We will have blocks allocated outside
@@ -2095,6 +2077,7 @@ static int mpage_map_and_submit_extent(handle_t *handle,
        struct ext4_map_blocks *map = &mpd->map;
        int err;
        loff_t disksize;
+       int progress = 0;
 
        mpd->io_submit.io_end->offset =
                                ((loff_t)map->m_lblk) << inode->i_blkbits;
@@ -2111,8 +2094,11 @@ static int mpage_map_and_submit_extent(handle_t *handle,
                         * is non-zero, a commit should free up blocks.
                         */
                        if ((err == -ENOMEM) ||
-                           (err == -ENOSPC && ext4_count_free_clusters(sb)))
+                           (err == -ENOSPC && ext4_count_free_clusters(sb))) {
+                               if (progress)
+                                       goto update_disksize;
                                return err;
+                       }
                        ext4_msg(sb, KERN_CRIT,
                                 "Delayed block allocation failed for "
                                 "inode %lu at logical offset %llu with"
@@ -2129,15 +2115,17 @@ static int mpage_map_and_submit_extent(handle_t *handle,
                        *give_up_on_write = true;
                        return err;
                }
+               progress = 1;
                /*
                 * Update buffer state, submit mapped pages, and get us new
                 * extent to map
                 */
                err = mpage_map_and_submit_buffers(mpd);
                if (err < 0)
-                       return err;
+                       goto update_disksize;
        } while (map->m_len);
 
+update_disksize:
        /*
         * Update on-disk size after IO is submitted.  Races with
         * truncate are avoided by checking i_size under i_data_sem.
index 956027711faf29aa52669d27061794840e332e08..8b0f9ef517d690ea0ede0958c8aa726aebb86b35 100644 (file)
@@ -1412,6 +1412,8 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
        int last = first + count - 1;
        struct super_block *sb = e4b->bd_sb;
 
+       if (WARN_ON(count == 0))
+               return;
        BUG_ON(last >= (sb->s_blocksize << 3));
        assert_spin_locked(ext4_group_lock_ptr(sb, e4b->bd_group));
        /* Don't bother if the block group is corrupt. */
@@ -3221,6 +3223,8 @@ static void ext4_discard_allocated_blocks(struct ext4_allocation_context *ac)
        int err;
 
        if (pa == NULL) {
+               if (ac->ac_f_ex.fe_len == 0)
+                       return;
                err = ext4_mb_load_buddy(ac->ac_sb, ac->ac_f_ex.fe_group, &e4b);
                if (err) {
                        /*
@@ -3235,6 +3239,7 @@ static void ext4_discard_allocated_blocks(struct ext4_allocation_context *ac)
                mb_free_blocks(ac->ac_inode, &e4b, ac->ac_f_ex.fe_start,
                               ac->ac_f_ex.fe_len);
                ext4_unlock_group(ac->ac_sb, ac->ac_f_ex.fe_group);
+               ext4_mb_unload_buddy(&e4b);
                return;
        }
        if (pa->pa_type == MB_INODE_PA)
index b147a67baa0d976d026857308350d85b8de72e01..603e4ebbd0ac1a8eb33f27f0e06cf302d3ce3352 100644 (file)
@@ -1227,7 +1227,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
                                   buffer */
        int num = 0;
        ext4_lblk_t  nblocks;
-       int i, err;
+       int i, err = 0;
        int namelen;
 
        *res_dir = NULL;
@@ -1264,7 +1264,11 @@ static struct buffer_head * ext4_find_entry (struct inode *dir,
                 * return.  Otherwise, fall back to doing a search the
                 * old fashioned way.
                 */
-               if (bh || (err != ERR_BAD_DX_DIR))
+               if (err == -ENOENT)
+                       return NULL;
+               if (err && err != ERR_BAD_DX_DIR)
+                       return ERR_PTR(err);
+               if (bh)
                        return bh;
                dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, "
                               "falling back\n"));
@@ -1295,6 +1299,11 @@ restart:
                                }
                                num++;
                                bh = ext4_getblk(NULL, dir, b++, 0, &err);
+                               if (unlikely(err)) {
+                                       if (ra_max == 0)
+                                               return ERR_PTR(err);
+                                       break;
+                               }
                                bh_use[ra_max] = bh;
                                if (bh)
                                        ll_rw_block(READ | REQ_META | REQ_PRIO,
@@ -1417,6 +1426,8 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
                return ERR_PTR(-ENAMETOOLONG);
 
        bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
+       if (IS_ERR(bh))
+               return (struct dentry *) bh;
        inode = NULL;
        if (bh) {
                __u32 ino = le32_to_cpu(de->inode);
@@ -1450,6 +1461,8 @@ struct dentry *ext4_get_parent(struct dentry *child)
        struct buffer_head *bh;
 
        bh = ext4_find_entry(child->d_inode, &dotdot, &de, NULL);
+       if (IS_ERR(bh))
+               return (struct dentry *) bh;
        if (!bh)
                return ERR_PTR(-ENOENT);
        ino = le32_to_cpu(de->inode);
@@ -2727,6 +2740,8 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
 
        retval = -ENOENT;
        bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
+       if (IS_ERR(bh))
+               return PTR_ERR(bh);
        if (!bh)
                goto end_rmdir;
 
@@ -2794,6 +2809,8 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
 
        retval = -ENOENT;
        bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);
+       if (IS_ERR(bh))
+               return PTR_ERR(bh);
        if (!bh)
                goto end_unlink;
 
@@ -3121,6 +3138,8 @@ static int ext4_find_delete_entry(handle_t *handle, struct inode *dir,
        struct ext4_dir_entry_2 *de;
 
        bh = ext4_find_entry(dir, d_name, &de, NULL);
+       if (IS_ERR(bh))
+               return PTR_ERR(bh);
        if (bh) {
                retval = ext4_delete_entry(handle, dir, de, bh);
                brelse(bh);
@@ -3128,7 +3147,8 @@ static int ext4_find_delete_entry(handle_t *handle, struct inode *dir,
        return retval;
 }
 
-static void ext4_rename_delete(handle_t *handle, struct ext4_renament *ent)
+static void ext4_rename_delete(handle_t *handle, struct ext4_renament *ent,
+                              int force_reread)
 {
        int retval;
        /*
@@ -3140,7 +3160,8 @@ static void ext4_rename_delete(handle_t *handle, struct ext4_renament *ent)
        if (le32_to_cpu(ent->de->inode) != ent->inode->i_ino ||
            ent->de->name_len != ent->dentry->d_name.len ||
            strncmp(ent->de->name, ent->dentry->d_name.name,
-                   ent->de->name_len)) {
+                   ent->de->name_len) ||
+           force_reread) {
                retval = ext4_find_delete_entry(handle, ent->dir,
                                                &ent->dentry->d_name);
        } else {
@@ -3191,6 +3212,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
                .dentry = new_dentry,
                .inode = new_dentry->d_inode,
        };
+       int force_reread;
        int retval;
 
        dquot_initialize(old.dir);
@@ -3202,6 +3224,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
                dquot_initialize(new.inode);
 
        old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL);
+       if (IS_ERR(old.bh))
+               return PTR_ERR(old.bh);
        /*
         *  Check for inode number is _not_ due to possible IO errors.
         *  We might rmdir the source, keep it as pwd of some process
@@ -3214,6 +3238,11 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
 
        new.bh = ext4_find_entry(new.dir, &new.dentry->d_name,
                                 &new.de, &new.inlined);
+       if (IS_ERR(new.bh)) {
+               retval = PTR_ERR(new.bh);
+               new.bh = NULL;
+               goto end_rename;
+       }
        if (new.bh) {
                if (!new.inode) {
                        brelse(new.bh);
@@ -3246,6 +3275,15 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
                if (retval)
                        goto end_rename;
        }
+       /*
+        * If we're renaming a file within an inline_data dir and adding or
+        * setting the new dirent causes a conversion from inline_data to
+        * extents/blockmap, we need to force the dirent delete code to
+        * re-read the directory, or else we end up trying to delete a dirent
+        * from what is now the extent tree root (or a block map).
+        */
+       force_reread = (new.dir->i_ino == old.dir->i_ino &&
+                       ext4_test_inode_flag(new.dir, EXT4_INODE_INLINE_DATA));
        if (!new.bh) {
                retval = ext4_add_entry(handle, new.dentry, old.inode);
                if (retval)
@@ -3256,6 +3294,9 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
                if (retval)
                        goto end_rename;
        }
+       if (force_reread)
+               force_reread = !ext4_test_inode_flag(new.dir,
+                                                    EXT4_INODE_INLINE_DATA);
 
        /*
         * Like most other Unix systems, set the ctime for inodes on a
@@ -3267,7 +3308,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
        /*
         * ok, that's it
         */
-       ext4_rename_delete(handle, &old);
+       ext4_rename_delete(handle, &old, force_reread);
 
        if (new.inode) {
                ext4_dec_count(handle, new.inode);
@@ -3330,6 +3371,8 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
 
        old.bh = ext4_find_entry(old.dir, &old.dentry->d_name,
                                 &old.de, &old.inlined);
+       if (IS_ERR(old.bh))
+               return PTR_ERR(old.bh);
        /*
         *  Check for inode number is _not_ due to possible IO errors.
         *  We might rmdir the source, keep it as pwd of some process
@@ -3342,6 +3385,11 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
 
        new.bh = ext4_find_entry(new.dir, &new.dentry->d_name,
                                 &new.de, &new.inlined);
+       if (IS_ERR(new.bh)) {
+               retval = PTR_ERR(new.bh);
+               new.bh = NULL;
+               goto end_rename;
+       }
 
        /* RENAME_EXCHANGE case: old *and* new must both exist */
        if (!new.bh || le32_to_cpu(new.de->inode) != new.inode->i_ino)
index bb0e80f03e2eb7291c91b9808f96d5469edfd903..1e43b905ff9854d7a6f45eab3da091b5867a0188 100644 (file)
@@ -575,6 +575,7 @@ handle_bb:
                bh = bclean(handle, sb, block);
                if (IS_ERR(bh)) {
                        err = PTR_ERR(bh);
+                       bh = NULL;
                        goto out;
                }
                overhead = ext4_group_overhead_blocks(sb, group);
@@ -603,6 +604,7 @@ handle_ib:
                bh = bclean(handle, sb, block);
                if (IS_ERR(bh)) {
                        err = PTR_ERR(bh);
+                       bh = NULL;
                        goto out;
                }
 
index 32b43ad154b99742a6476b218a62fd568466381c..0b28b36e7915ccf2e440c8782c618473f31d9576 100644 (file)
@@ -3181,9 +3181,9 @@ static int set_journal_csum_feature_set(struct super_block *sb)
 
        if (EXT4_HAS_RO_COMPAT_FEATURE(sb,
                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) {
-               /* journal checksum v2 */
+               /* journal checksum v3 */
                compat = 0;
-               incompat = JBD2_FEATURE_INCOMPAT_CSUM_V2;
+               incompat = JBD2_FEATURE_INCOMPAT_CSUM_V3;
        } else {
                /* journal checksum v1 */
                compat = JBD2_FEATURE_COMPAT_CHECKSUM;
@@ -3205,6 +3205,7 @@ static int set_journal_csum_feature_set(struct super_block *sb)
                jbd2_journal_clear_features(sbi->s_journal,
                                JBD2_FEATURE_COMPAT_CHECKSUM, 0,
                                JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT |
+                               JBD2_FEATURE_INCOMPAT_CSUM_V3 |
                                JBD2_FEATURE_INCOMPAT_CSUM_V2);
        }
 
index 214fe1054fceef32e74589e06a8d89203d9cc601..736a348509f7d6cfc6041d4e7f8838972c3413e3 100644 (file)
@@ -23,7 +23,7 @@ config F2FS_STAT_FS
          mounted as f2fs. Each file shows the whole f2fs information.
 
          /sys/kernel/debug/f2fs/status includes:
-           - major file system information managed by f2fs currently
+           - major filesystem information managed by f2fs currently
            - average SIT information about whole segments
            - current memory footprint consumed by f2fs.
 
@@ -68,6 +68,6 @@ config F2FS_CHECK_FS
        bool "F2FS consistency checking feature"
        depends on F2FS_FS
        help
-         Enables BUG_ONs which check the file system consistency in runtime.
+         Enables BUG_ONs which check the filesystem consistency in runtime.
 
          If you want to improve the performance, say N.
index 6aeed5bada52b1e6bdf9d1bc8228c9e69fb35b13..ec3b7a5381fa3fca2165aa9bcdb7402c0eace5bc 100644 (file)
@@ -160,14 +160,11 @@ static int f2fs_write_meta_page(struct page *page,
                goto redirty_out;
        if (wbc->for_reclaim)
                goto redirty_out;
-
-       /* Should not write any meta pages, if any IO error was occurred */
-       if (unlikely(is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG)))
-               goto no_write;
+       if (unlikely(f2fs_cp_error(sbi)))
+               goto redirty_out;
 
        f2fs_wait_on_page_writeback(page, META);
        write_meta_page(sbi, page);
-no_write:
        dec_page_count(sbi, F2FS_DIRTY_META);
        unlock_page(page);
        return 0;
@@ -348,7 +345,7 @@ bool exist_written_data(struct f2fs_sb_info *sbi, nid_t ino, int mode)
        return e ? true : false;
 }
 
-static void release_dirty_inode(struct f2fs_sb_info *sbi)
+void release_dirty_inode(struct f2fs_sb_info *sbi)
 {
        struct ino_entry *e, *tmp;
        int i;
@@ -446,8 +443,8 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
        struct f2fs_orphan_block *orphan_blk = NULL;
        unsigned int nentries = 0;
        unsigned short index;
-       unsigned short orphan_blocks = (unsigned short)((sbi->n_orphans +
-               (F2FS_ORPHANS_PER_BLOCK - 1)) / F2FS_ORPHANS_PER_BLOCK);
+       unsigned short orphan_blocks =
+                       (unsigned short)GET_ORPHAN_BLOCKS(sbi->n_orphans);
        struct page *page = NULL;
        struct ino_entry *orphan = NULL;
 
@@ -737,7 +734,7 @@ retry:
 /*
  * Freeze all the FS-operations for checkpoint.
  */
-static void block_operations(struct f2fs_sb_info *sbi)
+static int block_operations(struct f2fs_sb_info *sbi)
 {
        struct writeback_control wbc = {
                .sync_mode = WB_SYNC_ALL,
@@ -745,6 +742,7 @@ static void block_operations(struct f2fs_sb_info *sbi)
                .for_reclaim = 0,
        };
        struct blk_plug plug;
+       int err = 0;
 
        blk_start_plug(&plug);
 
@@ -754,11 +752,15 @@ retry_flush_dents:
        if (get_pages(sbi, F2FS_DIRTY_DENTS)) {
                f2fs_unlock_all(sbi);
                sync_dirty_dir_inodes(sbi);
+               if (unlikely(f2fs_cp_error(sbi))) {
+                       err = -EIO;
+                       goto out;
+               }
                goto retry_flush_dents;
        }
 
        /*
-        * POR: we should ensure that there is no dirty node pages
+        * POR: we should ensure that there are no dirty node pages
         * until finishing nat/sit flush.
         */
 retry_flush_nodes:
@@ -767,9 +769,16 @@ retry_flush_nodes:
        if (get_pages(sbi, F2FS_DIRTY_NODES)) {
                up_write(&sbi->node_write);
                sync_node_pages(sbi, 0, &wbc);
+               if (unlikely(f2fs_cp_error(sbi))) {
+                       f2fs_unlock_all(sbi);
+                       err = -EIO;
+                       goto out;
+               }
                goto retry_flush_nodes;
        }
+out:
        blk_finish_plug(&plug);
+       return err;
 }
 
 static void unblock_operations(struct f2fs_sb_info *sbi)
@@ -813,8 +822,11 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
        discard_next_dnode(sbi, NEXT_FREE_BLKADDR(sbi, curseg));
 
        /* Flush all the NAT/SIT pages */
-       while (get_pages(sbi, F2FS_DIRTY_META))
+       while (get_pages(sbi, F2FS_DIRTY_META)) {
                sync_meta_pages(sbi, META, LONG_MAX);
+               if (unlikely(f2fs_cp_error(sbi)))
+                       return;
+       }
 
        next_free_nid(sbi, &last_nid);
 
@@ -825,7 +837,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
        ckpt->elapsed_time = cpu_to_le64(get_mtime(sbi));
        ckpt->valid_block_count = cpu_to_le64(valid_user_blocks(sbi));
        ckpt->free_segment_count = cpu_to_le32(free_segments(sbi));
-       for (i = 0; i < 3; i++) {
+       for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) {
                ckpt->cur_node_segno[i] =
                        cpu_to_le32(curseg_segno(sbi, i + CURSEG_HOT_NODE));
                ckpt->cur_node_blkoff[i] =
@@ -833,7 +845,7 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
                ckpt->alloc_type[i + CURSEG_HOT_NODE] =
                                curseg_alloc_type(sbi, i + CURSEG_HOT_NODE);
        }
-       for (i = 0; i < 3; i++) {
+       for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
                ckpt->cur_data_segno[i] =
                        cpu_to_le32(curseg_segno(sbi, i + CURSEG_HOT_DATA));
                ckpt->cur_data_blkoff[i] =
@@ -848,24 +860,23 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
 
        /* 2 cp  + n data seg summary + orphan inode blocks */
        data_sum_blocks = npages_for_summary_flush(sbi);
-       if (data_sum_blocks < 3)
+       if (data_sum_blocks < NR_CURSEG_DATA_TYPE)
                set_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG);
        else
                clear_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG);
 
-       orphan_blocks = (sbi->n_orphans + F2FS_ORPHANS_PER_BLOCK - 1)
-                                       / F2FS_ORPHANS_PER_BLOCK;
+       orphan_blocks = GET_ORPHAN_BLOCKS(sbi->n_orphans);
        ckpt->cp_pack_start_sum = cpu_to_le32(1 + cp_payload_blks +
                        orphan_blocks);
 
        if (is_umount) {
                set_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
-               ckpt->cp_pack_total_block_count = cpu_to_le32(+
+               ckpt->cp_pack_total_block_count = cpu_to_le32(F2FS_CP_PACKS+
                                cp_payload_blks + data_sum_blocks +
                                orphan_blocks + NR_CURSEG_NODE_TYPE);
        } else {
                clear_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
-               ckpt->cp_pack_total_block_count = cpu_to_le32(2 +
+               ckpt->cp_pack_total_block_count = cpu_to_le32(F2FS_CP_PACKS +
                                cp_payload_blks + data_sum_blocks +
                                orphan_blocks);
        }
@@ -924,6 +935,9 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
        /* wait for previous submitted node/meta pages writeback */
        wait_on_all_pages_writeback(sbi);
 
+       if (unlikely(f2fs_cp_error(sbi)))
+               return;
+
        filemap_fdatawait_range(NODE_MAPPING(sbi), 0, LONG_MAX);
        filemap_fdatawait_range(META_MAPPING(sbi), 0, LONG_MAX);
 
@@ -934,15 +948,17 @@ static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
        /* Here, we only have one bio having CP pack */
        sync_meta_pages(sbi, META_FLUSH, LONG_MAX);
 
-       if (!is_set_ckpt_flags(ckpt, CP_ERROR_FLAG)) {
-               clear_prefree_segments(sbi);
-               release_dirty_inode(sbi);
-               F2FS_RESET_SB_DIRT(sbi);
-       }
+       release_dirty_inode(sbi);
+
+       if (unlikely(f2fs_cp_error(sbi)))
+               return;
+
+       clear_prefree_segments(sbi);
+       F2FS_RESET_SB_DIRT(sbi);
 }
 
 /*
- * We guarantee that this checkpoint procedure should not fail.
+ * We guarantee that this checkpoint procedure will not fail.
  */
 void write_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
 {
@@ -952,7 +968,13 @@ void write_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
        trace_f2fs_write_checkpoint(sbi->sb, is_umount, "start block_ops");
 
        mutex_lock(&sbi->cp_mutex);
-       block_operations(sbi);
+
+       if (!sbi->s_dirty)
+               goto out;
+       if (unlikely(f2fs_cp_error(sbi)))
+               goto out;
+       if (block_operations(sbi))
+               goto out;
 
        trace_f2fs_write_checkpoint(sbi->sb, is_umount, "finish block_ops");
 
@@ -976,9 +998,9 @@ void write_checkpoint(struct f2fs_sb_info *sbi, bool is_umount)
        do_checkpoint(sbi, is_umount);
 
        unblock_operations(sbi);
-       mutex_unlock(&sbi->cp_mutex);
-
        stat_inc_cp_count(sbi->stat_info);
+out:
+       mutex_unlock(&sbi->cp_mutex);
        trace_f2fs_write_checkpoint(sbi->sb, is_umount, "finish checkpoint");
 }
 
@@ -999,8 +1021,8 @@ void init_ino_entry_info(struct f2fs_sb_info *sbi)
         * for cp pack we can have max 1020*504 orphan entries
         */
        sbi->n_orphans = 0;
-       sbi->max_orphans = (sbi->blocks_per_seg - 2 - NR_CURSEG_TYPE)
-                               * F2FS_ORPHANS_PER_BLOCK;
+       sbi->max_orphans = (sbi->blocks_per_seg - F2FS_CP_PACKS -
+                       NR_CURSEG_TYPE) * F2FS_ORPHANS_PER_BLOCK;
 }
 
 int __init create_checkpoint_caches(void)
index 03313099c51c44b957f84fb6ec4a6ab698eee970..76de83e25a891d8cf85c4b84d2641dbf414a77e6 100644 (file)
@@ -53,7 +53,7 @@ static void f2fs_write_end_io(struct bio *bio, int err)
                struct page *page = bvec->bv_page;
 
                if (unlikely(err)) {
-                       SetPageError(page);
+                       set_page_dirty(page);
                        set_bit(AS_EIO, &page->mapping->flags);
                        f2fs_stop_checkpoint(sbi);
                }
@@ -691,7 +691,7 @@ get_next:
                        allocated = true;
                        blkaddr = dn.data_blkaddr;
                }
-               /* Give more consecutive addresses for the read ahead */
+               /* Give more consecutive addresses for the readahead */
                if (blkaddr == (bh_result->b_blocknr + ofs)) {
                        ofs++;
                        dn.ofs_in_node++;
@@ -739,7 +739,7 @@ static int f2fs_read_data_page(struct file *file, struct page *page)
 
        trace_f2fs_readpage(page, DATA);
 
-       /* If the file has inline data, try to read it directlly */
+       /* If the file has inline data, try to read it directly */
        if (f2fs_has_inline_data(inode))
                ret = f2fs_read_inline_data(inode, page);
        else
@@ -836,10 +836,19 @@ write:
 
        /* Dentry blocks are controlled by checkpoint */
        if (S_ISDIR(inode->i_mode)) {
+               if (unlikely(f2fs_cp_error(sbi)))
+                       goto redirty_out;
                err = do_write_data_page(page, &fio);
                goto done;
        }
 
+       /* we should bypass data pages to proceed the kworkder jobs */
+       if (unlikely(f2fs_cp_error(sbi))) {
+               SetPageError(page);
+               unlock_page(page);
+               return 0;
+       }
+
        if (!wbc->for_reclaim)
                need_balance_fs = true;
        else if (has_not_enough_free_secs(sbi, 0))
@@ -927,7 +936,7 @@ static void f2fs_write_failed(struct address_space *mapping, loff_t to)
 
        if (to > inode->i_size) {
                truncate_pagecache(inode, inode->i_size);
-               truncate_blocks(inode, inode->i_size);
+               truncate_blocks(inode, inode->i_size, true);
        }
 }
 
@@ -946,7 +955,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
 
        f2fs_balance_fs(sbi);
 repeat:
-       err = f2fs_convert_inline_data(inode, pos + len);
+       err = f2fs_convert_inline_data(inode, pos + len, NULL);
        if (err)
                goto fail;
 
index a441ba33be11bd2f12b1a948cad200ad22be33d6..fecebdbfd7810fbccf61c984c9e029c345b7fdef 100644 (file)
@@ -32,7 +32,7 @@ static void update_general_status(struct f2fs_sb_info *sbi)
        struct f2fs_stat_info *si = F2FS_STAT(sbi);
        int i;
 
-       /* valid check of the segment numbers */
+       /* validation check of the segment numbers */
        si->hit_ext = sbi->read_hit_ext;
        si->total_ext = sbi->total_hit_ext;
        si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES);
@@ -152,7 +152,7 @@ static void update_mem_info(struct f2fs_sb_info *sbi)
        si->base_mem += NR_DIRTY_TYPE * f2fs_bitmap_size(TOTAL_SEGS(sbi));
        si->base_mem += f2fs_bitmap_size(TOTAL_SECS(sbi));
 
-       /* buld nm */
+       /* build nm */
        si->base_mem += sizeof(struct f2fs_nm_info);
        si->base_mem += __bitmap_size(sbi, NAT_BITMAP);
 
index bcf893c3d9036d0eb743ff8c34bae2eda23e9582..155fb056b7f1ab0424beb480b328bd12d0c18aff 100644 (file)
@@ -124,7 +124,7 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,
 
                /*
                 * For the most part, it should be a bug when name_len is zero.
-                * We stop here for figuring out where the bugs are occurred.
+                * We stop here for figuring out where the bugs has occurred.
                 */
                f2fs_bug_on(!de->name_len);
 
@@ -391,7 +391,7 @@ put_error:
 error:
        /* once the failed inode becomes a bad inode, i_mode is S_IFREG */
        truncate_inode_pages(&inode->i_data, 0);
-       truncate_blocks(inode, 0);
+       truncate_blocks(inode, 0, false);
        remove_dirty_dir_inode(inode);
        remove_inode_page(inode);
        return ERR_PTR(err);
@@ -563,7 +563,7 @@ fail:
 }
 
 /*
- * It only removes the dentry from the dentry page,corresponding name
+ * It only removes the dentry from the dentry page, corresponding name
  * entry in name page does not need to be touched during deletion.
  */
 void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
index 4dab5338a97af496ad6f5ee5867a6e6457a03ec5..e921242186f6a1e8af2a128460db45b064027b67 100644 (file)
@@ -24,7 +24,7 @@
 #define f2fs_bug_on(condition) BUG_ON(condition)
 #define f2fs_down_write(x, y)  down_write_nest_lock(x, y)
 #else
-#define f2fs_bug_on(condition)
+#define f2fs_bug_on(condition) WARN_ON(condition)
 #define f2fs_down_write(x, y)  down_write(x)
 #endif
 
@@ -395,7 +395,7 @@ enum count_type {
 };
 
 /*
- * The below are the page types of bios used in submti_bio().
+ * The below are the page types of bios used in submit_bio().
  * The available types are:
  * DATA                        User data pages. It operates as async mode.
  * NODE                        Node pages. It operates as async mode.
@@ -470,7 +470,7 @@ struct f2fs_sb_info {
        struct list_head dir_inode_list;        /* dir inode list */
        spinlock_t dir_inode_lock;              /* for dir inode list lock */
 
-       /* basic file system units */
+       /* basic filesystem units */
        unsigned int log_sectors_per_block;     /* log2 sectors per block */
        unsigned int log_blocksize;             /* log2 block size */
        unsigned int blocksize;                 /* block size */
@@ -799,7 +799,7 @@ static inline block_t __start_cp_addr(struct f2fs_sb_info *sbi)
 
        /*
         * odd numbered checkpoint should at cp segment 0
-        * and even segent must be at cp segment 1
+        * and even segment must be at cp segment 1
         */
        if (!(ckpt_version & 1))
                start_addr += sbi->blocks_per_seg;
@@ -1096,6 +1096,11 @@ static inline int f2fs_readonly(struct super_block *sb)
        return sb->s_flags & MS_RDONLY;
 }
 
+static inline bool f2fs_cp_error(struct f2fs_sb_info *sbi)
+{
+       return is_set_ckpt_flags(sbi->ckpt, CP_ERROR_FLAG);
+}
+
 static inline void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi)
 {
        set_ckpt_flags(sbi->ckpt, CP_ERROR_FLAG);
@@ -1117,7 +1122,7 @@ static inline void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi)
  */
 int f2fs_sync_file(struct file *, loff_t, loff_t, int);
 void truncate_data_blocks(struct dnode_of_data *);
-int truncate_blocks(struct inode *, u64);
+int truncate_blocks(struct inode *, u64, bool);
 void f2fs_truncate(struct inode *);
 int f2fs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 int f2fs_setattr(struct dentry *, struct iattr *);
@@ -1202,10 +1207,8 @@ int sync_node_pages(struct f2fs_sb_info *, nid_t, struct writeback_control *);
 bool alloc_nid(struct f2fs_sb_info *, nid_t *);
 void alloc_nid_done(struct f2fs_sb_info *, nid_t);
 void alloc_nid_failed(struct f2fs_sb_info *, nid_t);
-void recover_node_page(struct f2fs_sb_info *, struct page *,
-               struct f2fs_summary *, struct node_info *, block_t);
 void recover_inline_xattr(struct inode *, struct page *);
-bool recover_xattr_data(struct inode *, struct page *, block_t);
+void recover_xattr_data(struct inode *, struct page *, block_t);
 int recover_inode_page(struct f2fs_sb_info *, struct page *);
 int restore_node_summary(struct f2fs_sb_info *, unsigned int,
                                struct f2fs_summary_block *);
@@ -1238,8 +1241,6 @@ void write_data_page(struct page *, struct dnode_of_data *, block_t *,
 void rewrite_data_page(struct page *, block_t, struct f2fs_io_info *);
 void recover_data_page(struct f2fs_sb_info *, struct page *,
                                struct f2fs_summary *, block_t, block_t);
-void rewrite_node_page(struct f2fs_sb_info *, struct page *,
-                               struct f2fs_summary *, block_t, block_t);
 void allocate_data_block(struct f2fs_sb_info *, struct page *,
                block_t, block_t *, struct f2fs_summary *, int);
 void f2fs_wait_on_page_writeback(struct page *, enum page_type);
@@ -1262,6 +1263,7 @@ int ra_meta_pages(struct f2fs_sb_info *, int, int, int);
 long sync_meta_pages(struct f2fs_sb_info *, enum page_type, long);
 void add_dirty_inode(struct f2fs_sb_info *, nid_t, int type);
 void remove_dirty_inode(struct f2fs_sb_info *, nid_t, int type);
+void release_dirty_inode(struct f2fs_sb_info *);
 bool exist_written_data(struct f2fs_sb_info *, nid_t, int);
 int acquire_orphan_inode(struct f2fs_sb_info *);
 void release_orphan_inode(struct f2fs_sb_info *);
@@ -1439,8 +1441,8 @@ extern const struct inode_operations f2fs_special_inode_operations;
  */
 bool f2fs_may_inline(struct inode *);
 int f2fs_read_inline_data(struct inode *, struct page *);
-int f2fs_convert_inline_data(struct inode *, pgoff_t);
+int f2fs_convert_inline_data(struct inode *, pgoff_t, struct page *);
 int f2fs_write_inline_data(struct inode *, struct page *, unsigned int);
 void truncate_inline_data(struct inode *, u64);
-int recover_inline_data(struct inode *, struct page *);
+bool recover_inline_data(struct inode *, struct page *);
 #endif
index 208f1a9bd569b6d2c7afafa20c5a5dff9f9b39d1..060aee65aee801d61f7ab5f6b2666a60c0c3363a 100644 (file)
@@ -41,6 +41,11 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma,
 
        sb_start_pagefault(inode->i_sb);
 
+       /* force to convert with normal data indices */
+       err = f2fs_convert_inline_data(inode, MAX_INLINE_DATA + 1, page);
+       if (err)
+               goto out;
+
        /* block allocation */
        f2fs_lock_op(sbi);
        set_new_dnode(&dn, inode, NULL, NULL, 0);
@@ -110,6 +115,25 @@ static int get_parent_ino(struct inode *inode, nid_t *pino)
        return 1;
 }
 
+static inline bool need_do_checkpoint(struct inode *inode)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       bool need_cp = false;
+
+       if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1)
+               need_cp = true;
+       else if (file_wrong_pino(inode))
+               need_cp = true;
+       else if (!space_for_roll_forward(sbi))
+               need_cp = true;
+       else if (!is_checkpointed_node(sbi, F2FS_I(inode)->i_pino))
+               need_cp = true;
+       else if (F2FS_I(inode)->xattr_ver == cur_cp_version(F2FS_CKPT(sbi)))
+               need_cp = true;
+
+       return need_cp;
+}
+
 int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 {
        struct inode *inode = file->f_mapping->host;
@@ -154,23 +178,12 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
        /* guarantee free sections for fsync */
        f2fs_balance_fs(sbi);
 
-       down_read(&fi->i_sem);
-
        /*
         * Both of fdatasync() and fsync() are able to be recovered from
         * sudden-power-off.
         */
-       if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1)
-               need_cp = true;
-       else if (file_wrong_pino(inode))
-               need_cp = true;
-       else if (!space_for_roll_forward(sbi))
-               need_cp = true;
-       else if (!is_checkpointed_node(sbi, F2FS_I(inode)->i_pino))
-               need_cp = true;
-       else if (F2FS_I(inode)->xattr_ver == cur_cp_version(F2FS_CKPT(sbi)))
-               need_cp = true;
-
+       down_read(&fi->i_sem);
+       need_cp = need_do_checkpoint(inode);
        up_read(&fi->i_sem);
 
        if (need_cp) {
@@ -288,7 +301,7 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence)
                if (err && err != -ENOENT) {
                        goto fail;
                } else if (err == -ENOENT) {
-                       /* direct node is not exist */
+                       /* direct node does not exists */
                        if (whence == SEEK_DATA) {
                                pgofs = PGOFS_OF_NEXT_DNODE(pgofs,
                                                        F2FS_I(inode));
@@ -417,7 +430,7 @@ out:
        f2fs_put_page(page, 1);
 }
 
-int truncate_blocks(struct inode *inode, u64 from)
+int truncate_blocks(struct inode *inode, u64 from, bool lock)
 {
        struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
        unsigned int blocksize = inode->i_sb->s_blocksize;
@@ -433,14 +446,16 @@ int truncate_blocks(struct inode *inode, u64 from)
        free_from = (pgoff_t)
                        ((from + blocksize - 1) >> (sbi->log_blocksize));
 
-       f2fs_lock_op(sbi);
+       if (lock)
+               f2fs_lock_op(sbi);
 
        set_new_dnode(&dn, inode, NULL, NULL, 0);
        err = get_dnode_of_data(&dn, free_from, LOOKUP_NODE);
        if (err) {
                if (err == -ENOENT)
                        goto free_next;
-               f2fs_unlock_op(sbi);
+               if (lock)
+                       f2fs_unlock_op(sbi);
                trace_f2fs_truncate_blocks_exit(inode, err);
                return err;
        }
@@ -458,7 +473,8 @@ int truncate_blocks(struct inode *inode, u64 from)
        f2fs_put_dnode(&dn);
 free_next:
        err = truncate_inode_blocks(inode, free_from);
-       f2fs_unlock_op(sbi);
+       if (lock)
+               f2fs_unlock_op(sbi);
 done:
        /* lastly zero out the first data page */
        truncate_partial_data_page(inode, from);
@@ -475,7 +491,7 @@ void f2fs_truncate(struct inode *inode)
 
        trace_f2fs_truncate(inode);
 
-       if (!truncate_blocks(inode, i_size_read(inode))) {
+       if (!truncate_blocks(inode, i_size_read(inode), true)) {
                inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                mark_inode_dirty(inode);
        }
@@ -533,7 +549,7 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
 
        if ((attr->ia_valid & ATTR_SIZE) &&
                        attr->ia_size != i_size_read(inode)) {
-               err = f2fs_convert_inline_data(inode, attr->ia_size);
+               err = f2fs_convert_inline_data(inode, attr->ia_size, NULL);
                if (err)
                        return err;
 
@@ -622,7 +638,7 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len)
        loff_t off_start, off_end;
        int ret = 0;
 
-       ret = f2fs_convert_inline_data(inode, MAX_INLINE_DATA + 1);
+       ret = f2fs_convert_inline_data(inode, MAX_INLINE_DATA + 1, NULL);
        if (ret)
                return ret;
 
@@ -678,7 +694,7 @@ static int expand_inode_data(struct inode *inode, loff_t offset,
        if (ret)
                return ret;
 
-       ret = f2fs_convert_inline_data(inode, offset + len);
+       ret = f2fs_convert_inline_data(inode, offset + len, NULL);
        if (ret)
                return ret;
 
index d7947d90ccc3df487919723578bf5f81dde2d8a6..943a31db7cc3679c117716b220a58cce1b50a12d 100644 (file)
@@ -58,7 +58,7 @@ static int gc_thread_func(void *data)
                 * 3. IO subsystem is idle by checking the # of requests in
                 *    bdev's request list.
                 *
-                * Note) We have to avoid triggering GCs too much frequently.
+                * Note) We have to avoid triggering GCs frequently.
                 * Because it is possible that some segments can be
                 * invalidated soon after by user update or deletion.
                 * So, I'd like to wait some time to collect dirty segments.
@@ -222,7 +222,7 @@ static unsigned int get_cb_cost(struct f2fs_sb_info *sbi, unsigned int segno)
 
        u = (vblocks * 100) >> sbi->log_blocks_per_seg;
 
-       /* Handle if the system time is changed by user */
+       /* Handle if the system time has changed by the user */
        if (mtime < sit_i->min_mtime)
                sit_i->min_mtime = mtime;
        if (mtime > sit_i->max_mtime)
@@ -593,7 +593,7 @@ next_step:
 
                if (phase == 2) {
                        inode = f2fs_iget(sb, dni.ino);
-                       if (IS_ERR(inode))
+                       if (IS_ERR(inode) || is_bad_inode(inode))
                                continue;
 
                        start_bidx = start_bidx_of_node(nofs, F2FS_I(inode));
@@ -693,7 +693,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi)
 gc_more:
        if (unlikely(!(sbi->sb->s_flags & MS_ACTIVE)))
                goto stop;
-       if (unlikely(is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG)))
+       if (unlikely(f2fs_cp_error(sbi)))
                goto stop;
 
        if (gc_type == BG_GC && has_not_enough_free_secs(sbi, nfree)) {
index 5d5eb6047bf467a4c27fba131acdf7ffbff4ab20..16f0b2b22999ffbc3c8ed46afe0e042d4748ea14 100644 (file)
@@ -91,7 +91,7 @@ static inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi)
        block_t invalid_user_blocks = sbi->user_block_count -
                                        written_block_count(sbi);
        /*
-        * Background GC is triggered with the following condition.
+        * Background GC is triggered with the following conditions.
         * 1. There are a number of invalid blocks.
         * 2. There is not enough free space.
         */
index 948d17bf7281f6c9c32cf1e889dc844e57fbe893..a844fcfb9a8dcc70859e44c8933c465d9be36fb9 100644 (file)
@@ -42,7 +42,8 @@ static void TEA_transform(unsigned int buf[4], unsigned int const in[])
        buf[1] += b1;
 }
 
-static void str2hashbuf(const char *msg, size_t len, unsigned int *buf, int num)
+static void str2hashbuf(const unsigned char *msg, size_t len,
+                               unsigned int *buf, int num)
 {
        unsigned pad, val;
        int i;
@@ -73,9 +74,9 @@ f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info)
 {
        __u32 hash;
        f2fs_hash_t f2fs_hash;
-       const char *p;
+       const unsigned char *p;
        __u32 in[8], buf[4];
-       const char *name = name_info->name;
+       const unsigned char *name = name_info->name;
        size_t len = name_info->len;
 
        if ((len <= 2) && (name[0] == '.') &&
index 5beeccef9ae1bf968c29f688e4b70664e6f8ce82..3e8ecdf3742b18d72eba2e9c780f2c6e8d215c5e 100644 (file)
@@ -68,7 +68,7 @@ out:
 
 static int __f2fs_convert_inline_data(struct inode *inode, struct page *page)
 {
-       int err;
+       int err = 0;
        struct page *ipage;
        struct dnode_of_data dn;
        void *src_addr, *dst_addr;
@@ -86,6 +86,10 @@ static int __f2fs_convert_inline_data(struct inode *inode, struct page *page)
                goto out;
        }
 
+       /* someone else converted inline_data already */
+       if (!f2fs_has_inline_data(inode))
+               goto out;
+
        /*
         * i_addr[0] is not used for inline data,
         * so reserving new block will not destroy inline data
@@ -124,9 +128,10 @@ out:
        return err;
 }
 
-int f2fs_convert_inline_data(struct inode *inode, pgoff_t to_size)
+int f2fs_convert_inline_data(struct inode *inode, pgoff_t to_size,
+                                               struct page *page)
 {
-       struct page *page;
+       struct page *new_page = page;
        int err;
 
        if (!f2fs_has_inline_data(inode))
@@ -134,17 +139,20 @@ int f2fs_convert_inline_data(struct inode *inode, pgoff_t to_size)
        else if (to_size <= MAX_INLINE_DATA)
                return 0;
 
-       page = grab_cache_page(inode->i_mapping, 0);
-       if (!page)
-               return -ENOMEM;
+       if (!page || page->index != 0) {
+               new_page = grab_cache_page(inode->i_mapping, 0);
+               if (!new_page)
+                       return -ENOMEM;
+       }
 
-       err = __f2fs_convert_inline_data(inode, page);
-       f2fs_put_page(page, 1);
+       err = __f2fs_convert_inline_data(inode, new_page);
+       if (!page || page->index != 0)
+               f2fs_put_page(new_page, 1);
        return err;
 }
 
 int f2fs_write_inline_data(struct inode *inode,
-                          struct page *page, unsigned size)
+                               struct page *page, unsigned size)
 {
        void *src_addr, *dst_addr;
        struct page *ipage;
@@ -199,7 +207,7 @@ void truncate_inline_data(struct inode *inode, u64 from)
        f2fs_put_page(ipage, 1);
 }
 
-int recover_inline_data(struct inode *inode, struct page *npage)
+bool recover_inline_data(struct inode *inode, struct page *npage)
 {
        struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
        struct f2fs_inode *ri = NULL;
@@ -218,7 +226,7 @@ int recover_inline_data(struct inode *inode, struct page *npage)
                ri = F2FS_INODE(npage);
 
        if (f2fs_has_inline_data(inode) &&
-                       ri && ri->i_inline & F2FS_INLINE_DATA) {
+                       ri && (ri->i_inline & F2FS_INLINE_DATA)) {
 process_inline:
                ipage = get_node_page(sbi, inode->i_ino);
                f2fs_bug_on(IS_ERR(ipage));
@@ -230,7 +238,7 @@ process_inline:
                memcpy(dst_addr, src_addr, MAX_INLINE_DATA);
                update_inode(inode, ipage);
                f2fs_put_page(ipage, 1);
-               return -1;
+               return true;
        }
 
        if (f2fs_has_inline_data(inode)) {
@@ -242,10 +250,10 @@ process_inline:
                clear_inode_flag(F2FS_I(inode), FI_INLINE_DATA);
                update_inode(inode, ipage);
                f2fs_put_page(ipage, 1);
-       } else if (ri && ri->i_inline & F2FS_INLINE_DATA) {
-               truncate_blocks(inode, 0);
+       } else if (ri && (ri->i_inline & F2FS_INLINE_DATA)) {
+               truncate_blocks(inode, 0, false);
                set_inode_flag(F2FS_I(inode), FI_INLINE_DATA);
                goto process_inline;
        }
-       return 0;
+       return false;
 }
index 27b03776ffd21b8377dd645ba15591c1e783c19e..ee103fd7283c4e26acb39abf80fdaacdafea116f 100644 (file)
@@ -134,9 +134,7 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
        return 0;
 out:
        clear_nlink(inode);
-       unlock_new_inode(inode);
-       make_bad_inode(inode);
-       iput(inode);
+       iget_failed(inode);
        alloc_nid_failed(sbi, ino);
        return err;
 }
@@ -229,7 +227,7 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
        f2fs_delete_entry(de, page, inode);
        f2fs_unlock_op(sbi);
 
-       /* In order to evict this inode,  we set it dirty */
+       /* In order to evict this inode, we set it dirty */
        mark_inode_dirty(inode);
 fail:
        trace_f2fs_unlink_exit(inode, err);
@@ -267,9 +265,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
        return err;
 out:
        clear_nlink(inode);
-       unlock_new_inode(inode);
-       make_bad_inode(inode);
-       iput(inode);
+       iget_failed(inode);
        alloc_nid_failed(sbi, inode->i_ino);
        return err;
 }
@@ -308,9 +304,7 @@ static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 out_fail:
        clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
        clear_nlink(inode);
-       unlock_new_inode(inode);
-       make_bad_inode(inode);
-       iput(inode);
+       iget_failed(inode);
        alloc_nid_failed(sbi, inode->i_ino);
        return err;
 }
@@ -354,9 +348,7 @@ static int f2fs_mknod(struct inode *dir, struct dentry *dentry,
        return 0;
 out:
        clear_nlink(inode);
-       unlock_new_inode(inode);
-       make_bad_inode(inode);
-       iput(inode);
+       iget_failed(inode);
        alloc_nid_failed(sbi, inode->i_ino);
        return err;
 }
@@ -688,9 +680,7 @@ release_out:
 out:
        f2fs_unlock_op(sbi);
        clear_nlink(inode);
-       unlock_new_inode(inode);
-       make_bad_inode(inode);
-       iput(inode);
+       iget_failed(inode);
        alloc_nid_failed(sbi, inode->i_ino);
        return err;
 }
@@ -704,7 +694,6 @@ const struct inode_operations f2fs_dir_inode_operations = {
        .mkdir          = f2fs_mkdir,
        .rmdir          = f2fs_rmdir,
        .mknod          = f2fs_mknod,
-       .rename         = f2fs_rename,
        .rename2        = f2fs_rename2,
        .tmpfile        = f2fs_tmpfile,
        .getattr        = f2fs_getattr,
index d3d90d2846313d546c1328145d48a2013645f3dd..45378196e19acbab2b2d3150a5158681eaa4a045 100644 (file)
@@ -237,7 +237,7 @@ retry:
                        nat_get_blkaddr(e) != NULL_ADDR &&
                        new_blkaddr == NEW_ADDR);
 
-       /* increament version no as node is removed */
+       /* increment version no as node is removed */
        if (nat_get_blkaddr(e) != NEW_ADDR && new_blkaddr == NULL_ADDR) {
                unsigned char version = nat_get_version(e);
                nat_set_version(e, inc_node_version(version));
@@ -274,7 +274,7 @@ int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
 }
 
 /*
- * This function returns always success
+ * This function always returns success
  */
 void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni)
 {
@@ -650,7 +650,7 @@ static int truncate_partial_nodes(struct dnode_of_data *dn,
 
        /* get indirect nodes in the path */
        for (i = 0; i < idx + 1; i++) {
-               /* refernece count'll be increased */
+               /* reference count'll be increased */
                pages[i] = get_node_page(sbi, nid[i]);
                if (IS_ERR(pages[i])) {
                        err = PTR_ERR(pages[i]);
@@ -823,22 +823,26 @@ int truncate_xattr_node(struct inode *inode, struct page *page)
  */
 void remove_inode_page(struct inode *inode)
 {
-       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
-       struct page *page;
-       nid_t ino = inode->i_ino;
        struct dnode_of_data dn;
 
-       page = get_node_page(sbi, ino);
-       if (IS_ERR(page))
+       set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino);
+       if (get_dnode_of_data(&dn, 0, LOOKUP_NODE))
                return;
 
-       if (truncate_xattr_node(inode, page)) {
-               f2fs_put_page(page, 1);
+       if (truncate_xattr_node(inode, dn.inode_page)) {
+               f2fs_put_dnode(&dn);
                return;
        }
-       /* 0 is possible, after f2fs_new_inode() is failed */
+
+       /* remove potential inline_data blocks */
+       if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
+                               S_ISLNK(inode->i_mode))
+               truncate_data_blocks_range(&dn, 1);
+
+       /* 0 is possible, after f2fs_new_inode() has failed */
        f2fs_bug_on(inode->i_blocks != 0 && inode->i_blocks != 1);
-       set_new_dnode(&dn, inode, page, page, ino);
+
+       /* will put inode & node pages */
        truncate_node(&dn);
 }
 
@@ -1129,8 +1133,11 @@ continue_unlock:
                                set_fsync_mark(page, 0);
                                set_dentry_mark(page, 0);
                        }
-                       NODE_MAPPING(sbi)->a_ops->writepage(page, wbc);
-                       wrote++;
+
+                       if (NODE_MAPPING(sbi)->a_ops->writepage(page, wbc))
+                               unlock_page(page);
+                       else
+                               wrote++;
 
                        if (--wbc->nr_to_write == 0)
                                break;
@@ -1212,6 +1219,8 @@ static int f2fs_write_node_page(struct page *page,
 
        if (unlikely(sbi->por_doing))
                goto redirty_out;
+       if (unlikely(f2fs_cp_error(sbi)))
+               goto redirty_out;
 
        f2fs_wait_on_page_writeback(page, NODE);
 
@@ -1540,15 +1549,6 @@ void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid)
                kmem_cache_free(free_nid_slab, i);
 }
 
-void recover_node_page(struct f2fs_sb_info *sbi, struct page *page,
-               struct f2fs_summary *sum, struct node_info *ni,
-               block_t new_blkaddr)
-{
-       rewrite_node_page(sbi, page, sum, ni->blk_addr, new_blkaddr);
-       set_node_addr(sbi, ni, new_blkaddr, false);
-       clear_node_page_dirty(page);
-}
-
 void recover_inline_xattr(struct inode *inode, struct page *page)
 {
        struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
@@ -1557,40 +1557,33 @@ void recover_inline_xattr(struct inode *inode, struct page *page)
        struct page *ipage;
        struct f2fs_inode *ri;
 
-       if (!f2fs_has_inline_xattr(inode))
-               return;
-
-       if (!IS_INODE(page))
-               return;
-
-       ri = F2FS_INODE(page);
-       if (!(ri->i_inline & F2FS_INLINE_XATTR))
-               return;
-
        ipage = get_node_page(sbi, inode->i_ino);
        f2fs_bug_on(IS_ERR(ipage));
 
+       ri = F2FS_INODE(page);
+       if (!(ri->i_inline & F2FS_INLINE_XATTR)) {
+               clear_inode_flag(F2FS_I(inode), FI_INLINE_XATTR);
+               goto update_inode;
+       }
+
        dst_addr = inline_xattr_addr(ipage);
        src_addr = inline_xattr_addr(page);
        inline_size = inline_xattr_size(inode);
 
        f2fs_wait_on_page_writeback(ipage, NODE);
        memcpy(dst_addr, src_addr, inline_size);
-
+update_inode:
        update_inode(inode, ipage);
        f2fs_put_page(ipage, 1);
 }
 
-bool recover_xattr_data(struct inode *inode, struct page *page, block_t blkaddr)
+void recover_xattr_data(struct inode *inode, struct page *page, block_t blkaddr)
 {
        struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
        nid_t prev_xnid = F2FS_I(inode)->i_xattr_nid;
        nid_t new_xnid = nid_of_node(page);
        struct node_info ni;
 
-       if (!f2fs_has_xattr_block(ofs_of_node(page)))
-               return false;
-
        /* 1: invalidate the previous xattr nid */
        if (!prev_xnid)
                goto recover_xnid;
@@ -1618,7 +1611,6 @@ recover_xnid:
        set_node_addr(sbi, &ni, blkaddr, false);
 
        update_inode_page(inode);
-       return true;
 }
 
 int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
@@ -1637,7 +1629,7 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
        if (!ipage)
                return -ENOMEM;
 
-       /* Should not use this inode  from free nid list */
+       /* Should not use this inode from free nid list */
        remove_free_nid(NM_I(sbi), ino);
 
        SetPageUptodate(ipage);
@@ -1651,6 +1643,7 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
        dst->i_blocks = cpu_to_le64(1);
        dst->i_links = cpu_to_le32(1);
        dst->i_xattr_nid = 0;
+       dst->i_inline = src->i_inline & F2FS_INLINE_XATTR;
 
        new_ni = old_ni;
        new_ni.ino = ino;
@@ -1659,13 +1652,14 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
                WARN_ON(1);
        set_node_addr(sbi, &new_ni, NEW_ADDR, false);
        inc_valid_inode_count(sbi);
+       set_page_dirty(ipage);
        f2fs_put_page(ipage, 1);
        return 0;
 }
 
 /*
  * ra_sum_pages() merge contiguous pages into one bio and submit.
- * these pre-readed pages are alloced in bd_inode's mapping tree.
+ * these pre-read pages are allocated in bd_inode's mapping tree.
  */
 static int ra_sum_pages(struct f2fs_sb_info *sbi, struct page **pages,
                                int start, int nrpages)
@@ -1709,7 +1703,7 @@ int restore_node_summary(struct f2fs_sb_info *sbi,
        for (i = 0; !err && i < last_offset; i += nrpages, addr += nrpages) {
                nrpages = min(last_offset - i, bio_blocks);
 
-               /* read ahead node pages */
+               /* readahead node pages */
                nrpages = ra_sum_pages(sbi, pages, addr, nrpages);
                if (!nrpages)
                        return -ENOMEM;
@@ -1967,7 +1961,7 @@ static int init_node_manager(struct f2fs_sb_info *sbi)
        nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nat_blocks;
 
        /* not used nids: 0, node, meta, (and root counted as valid node) */
-       nm_i->available_nids = nm_i->max_nid - 3;
+       nm_i->available_nids = nm_i->max_nid - F2FS_RESERVED_NODE_NUM;
        nm_i->fcnt = 0;
        nm_i->nat_cnt = 0;
        nm_i->ram_thresh = DEF_RAM_THRESHOLD;
index fe1c6d921ba2fb535464d031d5822877e6eeccbd..756c41cd25829f789931df79f14a95bebcba5431 100644 (file)
@@ -62,8 +62,10 @@ static int recover_dentry(struct page *ipage, struct inode *inode)
        }
 retry:
        de = f2fs_find_entry(dir, &name, &page);
-       if (de && inode->i_ino == le32_to_cpu(de->ino))
+       if (de && inode->i_ino == le32_to_cpu(de->ino)) {
+               clear_inode_flag(F2FS_I(inode), FI_INC_LINK);
                goto out_unmap_put;
+       }
        if (de) {
                einode = f2fs_iget(inode->i_sb, le32_to_cpu(de->ino));
                if (IS_ERR(einode)) {
@@ -300,14 +302,19 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
        struct node_info ni;
        int err = 0, recovered = 0;
 
-       recover_inline_xattr(inode, page);
-
-       if (recover_inline_data(inode, page))
+       /* step 1: recover xattr */
+       if (IS_INODE(page)) {
+               recover_inline_xattr(inode, page);
+       } else if (f2fs_has_xattr_block(ofs_of_node(page))) {
+               recover_xattr_data(inode, page, blkaddr);
                goto out;
+       }
 
-       if (recover_xattr_data(inode, page, blkaddr))
+       /* step 2: recover inline data */
+       if (recover_inline_data(inode, page))
                goto out;
 
+       /* step 3: recover data indices */
        start = start_bidx_of_node(ofs_of_node(page), fi);
        end = start + ADDRS_PER_PAGE(page, fi);
 
@@ -364,8 +371,6 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
        fill_node_footer(dn.node_page, dn.nid, ni.ino,
                                        ofs_of_node(page), false);
        set_page_dirty(dn.node_page);
-
-       recover_node_page(sbi, dn.node_page, &sum, &ni, blkaddr);
 err:
        f2fs_put_dnode(&dn);
        f2fs_unlock_op(sbi);
@@ -452,6 +457,9 @@ int recover_fsync_data(struct f2fs_sb_info *sbi)
        /* step #1: find fsynced inode numbers */
        sbi->por_doing = true;
 
+       /* prevent checkpoint */
+       mutex_lock(&sbi->cp_mutex);
+
        blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
 
        err = find_fsync_dnodes(sbi, &inode_list);
@@ -465,7 +473,8 @@ int recover_fsync_data(struct f2fs_sb_info *sbi)
 
        /* step #2: recover data */
        err = recover_data(sbi, &inode_list, CURSEG_WARM_NODE);
-       f2fs_bug_on(!list_empty(&inode_list));
+       if (!err)
+               f2fs_bug_on(!list_empty(&inode_list));
 out:
        destroy_fsync_dnodes(&inode_list);
        kmem_cache_destroy(fsync_entry_slab);
@@ -482,8 +491,13 @@ out:
                /* Flush all the NAT/SIT pages */
                while (get_pages(sbi, F2FS_DIRTY_META))
                        sync_meta_pages(sbi, META, LONG_MAX);
+               set_ckpt_flags(sbi->ckpt, CP_ERROR_FLAG);
+               mutex_unlock(&sbi->cp_mutex);
        } else if (need_writecp) {
+               mutex_unlock(&sbi->cp_mutex);
                write_checkpoint(sbi, false);
+       } else {
+               mutex_unlock(&sbi->cp_mutex);
        }
        return err;
 }
index 0dfeebae2a50f1d8ff4b7a33e19a25fb32c2e834..0aa337cd5bba85703bdcecde7fe0a35de76bf121 100644 (file)
@@ -62,7 +62,7 @@ static inline unsigned long __reverse_ffs(unsigned long word)
 }
 
 /*
- * __find_rev_next(_zero)_bit is copied from lib/find_next_bit.c becasue
+ * __find_rev_next(_zero)_bit is copied from lib/find_next_bit.c because
  * f2fs_set_bit makes MSB and LSB reversed in a byte.
  * Example:
  *                             LSB <--> MSB
@@ -808,7 +808,7 @@ static void __refresh_next_blkoff(struct f2fs_sb_info *sbi,
 }
 
 /*
- * This function always allocates a used segment (from dirty seglist) by SSR
+ * This function always allocates a used segment(from dirty seglist) by SSR
  * manner, so it should recover the existing segment information of valid blocks
  */
 static void change_curseg(struct f2fs_sb_info *sbi, int type, bool reuse)
@@ -1103,55 +1103,6 @@ void recover_data_page(struct f2fs_sb_info *sbi,
        mutex_unlock(&curseg->curseg_mutex);
 }
 
-void rewrite_node_page(struct f2fs_sb_info *sbi,
-                       struct page *page, struct f2fs_summary *sum,
-                       block_t old_blkaddr, block_t new_blkaddr)
-{
-       struct sit_info *sit_i = SIT_I(sbi);
-       int type = CURSEG_WARM_NODE;
-       struct curseg_info *curseg;
-       unsigned int segno, old_cursegno;
-       block_t next_blkaddr = next_blkaddr_of_node(page);
-       unsigned int next_segno = GET_SEGNO(sbi, next_blkaddr);
-       struct f2fs_io_info fio = {
-               .type = NODE,
-               .rw = WRITE_SYNC,
-       };
-
-       curseg = CURSEG_I(sbi, type);
-
-       mutex_lock(&curseg->curseg_mutex);
-       mutex_lock(&sit_i->sentry_lock);
-
-       segno = GET_SEGNO(sbi, new_blkaddr);
-       old_cursegno = curseg->segno;
-
-       /* change the current segment */
-       if (segno != curseg->segno) {
-               curseg->next_segno = segno;
-               change_curseg(sbi, type, true);
-       }
-       curseg->next_blkoff = GET_BLKOFF_FROM_SEG0(sbi, new_blkaddr);
-       __add_sum_entry(sbi, type, sum);
-
-       /* change the current log to the next block addr in advance */
-       if (next_segno != segno) {
-               curseg->next_segno = next_segno;
-               change_curseg(sbi, type, true);
-       }
-       curseg->next_blkoff = GET_BLKOFF_FROM_SEG0(sbi, next_blkaddr);
-
-       /* rewrite node page */
-       set_page_writeback(page);
-       f2fs_submit_page_mbio(sbi, page, new_blkaddr, &fio);
-       f2fs_submit_merged_bio(sbi, NODE, WRITE);
-       refresh_sit_entry(sbi, old_blkaddr, new_blkaddr);
-       locate_dirty_segment(sbi, old_cursegno);
-
-       mutex_unlock(&sit_i->sentry_lock);
-       mutex_unlock(&curseg->curseg_mutex);
-}
-
 static inline bool is_merged_page(struct f2fs_sb_info *sbi,
                                        struct page *page, enum page_type type)
 {
index 55973f7b0330be844e17c0f02b7c02d661ca8c3e..ff483257283b8789968473b4beda6c2ddbaff43b 100644 (file)
@@ -549,7 +549,7 @@ static inline void verify_block_addr(struct f2fs_sb_info *sbi, block_t blk_addr)
 }
 
 /*
- * Summary block is always treated as invalid block
+ * Summary block is always treated as an invalid block
  */
 static inline void check_block_count(struct f2fs_sb_info *sbi,
                int segno, struct f2fs_sit_entry *raw_sit)
index 657582fc7601ad27f81ef034a6f5e55cf46abc1e..41bdf511003deb6978cf852203906840167f90b6 100644 (file)
@@ -432,9 +432,15 @@ static void f2fs_put_super(struct super_block *sb)
        stop_gc_thread(sbi);
 
        /* We don't need to do checkpoint when it's clean */
-       if (sbi->s_dirty && get_pages(sbi, F2FS_DIRTY_NODES))
+       if (sbi->s_dirty)
                write_checkpoint(sbi, true);
 
+       /*
+        * normally superblock is clean, so we need to release this.
+        * In addition, EIO will skip do checkpoint, we need this as well.
+        */
+       release_dirty_inode(sbi);
+
        iput(sbi->node_inode);
        iput(sbi->meta_inode);
 
@@ -457,9 +463,6 @@ int f2fs_sync_fs(struct super_block *sb, int sync)
 
        trace_f2fs_sync_fs(sb, sync);
 
-       if (!sbi->s_dirty && !get_pages(sbi, F2FS_DIRTY_NODES))
-               return 0;
-
        if (sync) {
                mutex_lock(&sbi->gc_mutex);
                write_checkpoint(sbi, false);
@@ -505,8 +508,8 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_bfree = buf->f_blocks - valid_user_blocks(sbi) - ovp_count;
        buf->f_bavail = user_block_count - valid_user_blocks(sbi);
 
-       buf->f_files = sbi->total_node_count;
-       buf->f_ffree = sbi->total_node_count - valid_inode_count(sbi);
+       buf->f_files = sbi->total_node_count - F2FS_RESERVED_NODE_NUM;
+       buf->f_ffree = buf->f_files - valid_inode_count(sbi);
 
        buf->f_namelen = F2FS_NAME_LEN;
        buf->f_fsid.val[0] = (u32)id;
@@ -663,7 +666,7 @@ restore_gc:
        if (need_restart_gc) {
                if (start_gc_thread(sbi))
                        f2fs_msg(sbi->sb, KERN_WARNING,
-                               "background gc thread is stop");
+                               "background gc thread has stopped");
        } else if (need_stop_gc) {
                stop_gc_thread(sbi);
        }
@@ -812,7 +815,7 @@ static int sanity_check_ckpt(struct f2fs_sb_info *sbi)
        if (unlikely(fsmeta >= total))
                return 1;
 
-       if (unlikely(is_set_ckpt_flags(ckpt, CP_ERROR_FLAG))) {
+       if (unlikely(f2fs_cp_error(sbi))) {
                f2fs_msg(sbi->sb, KERN_ERR, "A bug case: need to run fsck");
                return 1;
        }
@@ -899,8 +902,10 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
        struct buffer_head *raw_super_buf;
        struct inode *root;
        long err = -EINVAL;
+       bool retry = true;
        int i;
 
+try_onemore:
        /* allocate memory for f2fs-specific super block info */
        sbi = kzalloc(sizeof(struct f2fs_sb_info), GFP_KERNEL);
        if (!sbi)
@@ -1080,9 +1085,11 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
        /* recover fsynced data */
        if (!test_opt(sbi, DISABLE_ROLL_FORWARD)) {
                err = recover_fsync_data(sbi);
-               if (err)
+               if (err) {
                        f2fs_msg(sb, KERN_ERR,
                                "Cannot recover all fsync data errno=%ld", err);
+                       goto free_kobj;
+               }
        }
 
        /*
@@ -1123,6 +1130,13 @@ free_sb_buf:
        brelse(raw_super_buf);
 free_sbi:
        kfree(sbi);
+
+       /* give only one another chance */
+       if (retry) {
+               retry = 0;
+               shrink_dcache_sb(sb);
+               goto try_onemore;
+       }
        return err;
 }
 
index 8bea941ee309607647cbc7a8c1282e0419dcef12..728a5dc3dc1654190e9709ce1f19fbc87a39d843 100644 (file)
@@ -528,7 +528,7 @@ static int __f2fs_setxattr(struct inode *inode, int index,
                int free;
                /*
                 * If value is NULL, it is remove operation.
-                * In case of update operation, we caculate free.
+                * In case of update operation, we calculate free.
                 */
                free = MIN_OFFSET(inode) - ((char *)last - (char *)base_addr);
                if (found)
index 6fac743498565746bfb6dd5f29e0abacb48a0865..b73e0215baa7ceeb0dbfd3a77c79d5d498231e60 100644 (file)
@@ -97,7 +97,7 @@ static void jbd2_commit_block_csum_set(journal_t *j, struct buffer_head *bh)
        struct commit_header *h;
        __u32 csum;
 
-       if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return;
 
        h = (struct commit_header *)(bh->b_data);
@@ -313,11 +313,11 @@ static __u32 jbd2_checksum_data(__u32 crc32_sum, struct buffer_head *bh)
        return checksum;
 }
 
-static void write_tag_block(int tag_bytes, journal_block_tag_t *tag,
+static void write_tag_block(journal_t *j, journal_block_tag_t *tag,
                                   unsigned long long block)
 {
        tag->t_blocknr = cpu_to_be32(block & (u32)~0);
-       if (tag_bytes > JBD2_TAG_SIZE32)
+       if (JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_64BIT))
                tag->t_blocknr_high = cpu_to_be32((block >> 31) >> 1);
 }
 
@@ -327,7 +327,7 @@ static void jbd2_descr_block_csum_set(journal_t *j,
        struct jbd2_journal_block_tail *tail;
        __u32 csum;
 
-       if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return;
 
        tail = (struct jbd2_journal_block_tail *)(bh->b_data + j->j_blocksize -
@@ -340,12 +340,13 @@ static void jbd2_descr_block_csum_set(journal_t *j,
 static void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag,
                                    struct buffer_head *bh, __u32 sequence)
 {
+       journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag;
        struct page *page = bh->b_page;
        __u8 *addr;
        __u32 csum32;
        __be32 seq;
 
-       if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return;
 
        seq = cpu_to_be32(sequence);
@@ -355,8 +356,10 @@ static void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag,
                             bh->b_size);
        kunmap_atomic(addr);
 
-       /* We only have space to store the lower 16 bits of the crc32c. */
-       tag->t_checksum = cpu_to_be16(csum32);
+       if (JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V3))
+               tag3->t_checksum = cpu_to_be32(csum32);
+       else
+               tag->t_checksum = cpu_to_be16(csum32);
 }
 /*
  * jbd2_journal_commit_transaction
@@ -396,7 +399,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
        LIST_HEAD(io_bufs);
        LIST_HEAD(log_bufs);
 
-       if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2))
+       if (jbd2_journal_has_csum_v2or3(journal))
                csum_size = sizeof(struct jbd2_journal_block_tail);
 
        /*
@@ -690,7 +693,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
                        tag_flag |= JBD2_FLAG_SAME_UUID;
 
                tag = (journal_block_tag_t *) tagp;
-               write_tag_block(tag_bytes, tag, jh2bh(jh)->b_blocknr);
+               write_tag_block(journal, tag, jh2bh(jh)->b_blocknr);
                tag->t_flags = cpu_to_be16(tag_flag);
                jbd2_block_tag_csum_set(journal, tag, wbuf[bufs],
                                        commit_transaction->t_tid);
index 67b8e303946ceaa79a0fd0d39ecd8ca428b67f1f..19d74d86d99cc630aec2c0ca8f7bf4ef619e3aa3 100644 (file)
@@ -124,7 +124,7 @@ EXPORT_SYMBOL(__jbd2_debug);
 /* Checksumming functions */
 static int jbd2_verify_csum_type(journal_t *j, journal_superblock_t *sb)
 {
-       if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return 1;
 
        return sb->s_checksum_type == JBD2_CRC32C_CHKSUM;
@@ -145,7 +145,7 @@ static __be32 jbd2_superblock_csum(journal_t *j, journal_superblock_t *sb)
 
 static int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb)
 {
-       if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return 1;
 
        return sb->s_checksum == jbd2_superblock_csum(j, sb);
@@ -153,7 +153,7 @@ static int jbd2_superblock_csum_verify(journal_t *j, journal_superblock_t *sb)
 
 static void jbd2_superblock_csum_set(journal_t *j, journal_superblock_t *sb)
 {
-       if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return;
 
        sb->s_checksum = jbd2_superblock_csum(j, sb);
@@ -1522,21 +1522,29 @@ static int journal_get_superblock(journal_t *journal)
                goto out;
        }
 
-       if (JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM) &&
-           JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
+       if (jbd2_journal_has_csum_v2or3(journal) &&
+           JBD2_HAS_COMPAT_FEATURE(journal, JBD2_FEATURE_COMPAT_CHECKSUM)) {
                /* Can't have checksum v1 and v2 on at the same time! */
                printk(KERN_ERR "JBD2: Can't enable checksumming v1 and v2 "
                       "at the same time!\n");
                goto out;
        }
 
+       if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2) &&
+           JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V3)) {
+               /* Can't have checksum v2 and v3 at the same time! */
+               printk(KERN_ERR "JBD2: Can't enable checksumming v2 and v3 "
+                      "at the same time!\n");
+               goto out;
+       }
+
        if (!jbd2_verify_csum_type(journal, sb)) {
                printk(KERN_ERR "JBD2: Unknown checksum type\n");
                goto out;
        }
 
        /* Load the checksum driver */
-       if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
+       if (jbd2_journal_has_csum_v2or3(journal)) {
                journal->j_chksum_driver = crypto_alloc_shash("crc32c", 0, 0);
                if (IS_ERR(journal->j_chksum_driver)) {
                        printk(KERN_ERR "JBD2: Cannot load crc32c driver.\n");
@@ -1553,7 +1561,7 @@ static int journal_get_superblock(journal_t *journal)
        }
 
        /* Precompute checksum seed for all metadata */
-       if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2))
+       if (jbd2_journal_has_csum_v2or3(journal))
                journal->j_csum_seed = jbd2_chksum(journal, ~0, sb->s_uuid,
                                                   sizeof(sb->s_uuid));
 
@@ -1813,8 +1821,14 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
        if (!jbd2_journal_check_available_features(journal, compat, ro, incompat))
                return 0;
 
-       /* Asking for checksumming v2 and v1?  Only give them v2. */
-       if (incompat & JBD2_FEATURE_INCOMPAT_CSUM_V2 &&
+       /* If enabling v2 checksums, turn on v3 instead */
+       if (incompat & JBD2_FEATURE_INCOMPAT_CSUM_V2) {
+               incompat &= ~JBD2_FEATURE_INCOMPAT_CSUM_V2;
+               incompat |= JBD2_FEATURE_INCOMPAT_CSUM_V3;
+       }
+
+       /* Asking for checksumming v3 and v1?  Only give them v3. */
+       if (incompat & JBD2_FEATURE_INCOMPAT_CSUM_V3 &&
            compat & JBD2_FEATURE_COMPAT_CHECKSUM)
                compat &= ~JBD2_FEATURE_COMPAT_CHECKSUM;
 
@@ -1823,8 +1837,8 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
 
        sb = journal->j_superblock;
 
-       /* If enabling v2 checksums, update superblock */
-       if (INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V2)) {
+       /* If enabling v3 checksums, update superblock */
+       if (INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V3)) {
                sb->s_checksum_type = JBD2_CRC32C_CHKSUM;
                sb->s_feature_compat &=
                        ~cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM);
@@ -1842,8 +1856,7 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
                }
 
                /* Precompute checksum seed for all metadata */
-               if (JBD2_HAS_INCOMPAT_FEATURE(journal,
-                                             JBD2_FEATURE_INCOMPAT_CSUM_V2))
+               if (jbd2_journal_has_csum_v2or3(journal))
                        journal->j_csum_seed = jbd2_chksum(journal, ~0,
                                                           sb->s_uuid,
                                                           sizeof(sb->s_uuid));
@@ -1852,7 +1865,8 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat,
        /* If enabling v1 checksums, downgrade superblock */
        if (COMPAT_FEATURE_ON(JBD2_FEATURE_COMPAT_CHECKSUM))
                sb->s_feature_incompat &=
-                       ~cpu_to_be32(JBD2_FEATURE_INCOMPAT_CSUM_V2);
+                       ~cpu_to_be32(JBD2_FEATURE_INCOMPAT_CSUM_V2 |
+                                    JBD2_FEATURE_INCOMPAT_CSUM_V3);
 
        sb->s_feature_compat    |= cpu_to_be32(compat);
        sb->s_feature_ro_compat |= cpu_to_be32(ro);
@@ -2165,16 +2179,20 @@ int jbd2_journal_blocks_per_page(struct inode *inode)
  */
 size_t journal_tag_bytes(journal_t *journal)
 {
-       journal_block_tag_t tag;
-       size_t x = 0;
+       size_t sz;
+
+       if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V3))
+               return sizeof(journal_block_tag3_t);
+
+       sz = sizeof(journal_block_tag_t);
 
        if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2))
-               x += sizeof(tag.t_checksum);
+               sz += sizeof(__u16);
 
        if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT))
-               return x + JBD2_TAG_SIZE64;
+               return sz;
        else
-               return x + JBD2_TAG_SIZE32;
+               return sz - sizeof(__u32);
 }
 
 /*
index 3b6bb19d60b17abceadec4c38df5d3570c0fcba9..9b329b55ffe3726a611ccf8282190e420d173080 100644 (file)
@@ -181,7 +181,7 @@ static int jbd2_descr_block_csum_verify(journal_t *j,
        __be32 provided;
        __u32 calculated;
 
-       if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return 1;
 
        tail = (struct jbd2_journal_block_tail *)(buf + j->j_blocksize -
@@ -205,7 +205,7 @@ static int count_tags(journal_t *journal, struct buffer_head *bh)
        int                     nr = 0, size = journal->j_blocksize;
        int                     tag_bytes = journal_tag_bytes(journal);
 
-       if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2))
+       if (jbd2_journal_has_csum_v2or3(journal))
                size -= sizeof(struct jbd2_journal_block_tail);
 
        tagp = &bh->b_data[sizeof(journal_header_t)];
@@ -338,10 +338,11 @@ int jbd2_journal_skip_recovery(journal_t *journal)
        return err;
 }
 
-static inline unsigned long long read_tag_block(int tag_bytes, journal_block_tag_t *tag)
+static inline unsigned long long read_tag_block(journal_t *journal,
+                                               journal_block_tag_t *tag)
 {
        unsigned long long block = be32_to_cpu(tag->t_blocknr);
-       if (tag_bytes > JBD2_TAG_SIZE32)
+       if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT))
                block |= (u64)be32_to_cpu(tag->t_blocknr_high) << 32;
        return block;
 }
@@ -384,7 +385,7 @@ static int jbd2_commit_block_csum_verify(journal_t *j, void *buf)
        __be32 provided;
        __u32 calculated;
 
-       if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return 1;
 
        h = buf;
@@ -399,17 +400,21 @@ static int jbd2_commit_block_csum_verify(journal_t *j, void *buf)
 static int jbd2_block_tag_csum_verify(journal_t *j, journal_block_tag_t *tag,
                                      void *buf, __u32 sequence)
 {
+       journal_block_tag3_t *tag3 = (journal_block_tag3_t *)tag;
        __u32 csum32;
        __be32 seq;
 
-       if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return 1;
 
        seq = cpu_to_be32(sequence);
        csum32 = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&seq, sizeof(seq));
        csum32 = jbd2_chksum(j, csum32, buf, j->j_blocksize);
 
-       return tag->t_checksum == cpu_to_be16(csum32);
+       if (JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V3))
+               return tag3->t_checksum == cpu_to_be32(csum32);
+       else
+               return tag->t_checksum == cpu_to_be16(csum32);
 }
 
 static int do_one_pass(journal_t *journal,
@@ -426,6 +431,7 @@ static int do_one_pass(journal_t *journal,
        int                     tag_bytes = journal_tag_bytes(journal);
        __u32                   crc32_sum = ~0; /* Transactional Checksums */
        int                     descr_csum_size = 0;
+       int                     block_error = 0;
 
        /*
         * First thing is to establish what we expect to find in the log
@@ -512,8 +518,7 @@ static int do_one_pass(journal_t *journal,
                switch(blocktype) {
                case JBD2_DESCRIPTOR_BLOCK:
                        /* Verify checksum first */
-                       if (JBD2_HAS_INCOMPAT_FEATURE(journal,
-                                       JBD2_FEATURE_INCOMPAT_CSUM_V2))
+                       if (jbd2_journal_has_csum_v2or3(journal))
                                descr_csum_size =
                                        sizeof(struct jbd2_journal_block_tail);
                        if (descr_csum_size > 0 &&
@@ -574,7 +579,7 @@ static int do_one_pass(journal_t *journal,
                                        unsigned long long blocknr;
 
                                        J_ASSERT(obh != NULL);
-                                       blocknr = read_tag_block(tag_bytes,
+                                       blocknr = read_tag_block(journal,
                                                                 tag);
 
                                        /* If the block has been
@@ -598,7 +603,8 @@ static int do_one_pass(journal_t *journal,
                                                       "checksum recovering "
                                                       "block %llu in log\n",
                                                       blocknr);
-                                               continue;
+                                               block_error = 1;
+                                               goto skip_write;
                                        }
 
                                        /* Find a buffer for the new
@@ -797,7 +803,8 @@ static int do_one_pass(journal_t *journal,
                                success = -EIO;
                }
        }
-
+       if (block_error && success == 0)
+               success = -EIO;
        return success;
 
  failed:
@@ -811,7 +818,7 @@ static int jbd2_revoke_block_csum_verify(journal_t *j,
        __be32 provided;
        __u32 calculated;
 
-       if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return 1;
 
        tail = (struct jbd2_journal_revoke_tail *)(buf + j->j_blocksize -
index 198c9c10276dadf45983f3615f0804f27ee085e7..d5e95a175c9244a24f26b52b4b9755ceee6f1400 100644 (file)
@@ -91,8 +91,8 @@
 #include <linux/list.h>
 #include <linux/init.h>
 #include <linux/bio.h>
-#endif
 #include <linux/log2.h>
+#endif
 
 static struct kmem_cache *jbd2_revoke_record_cache;
 static struct kmem_cache *jbd2_revoke_table_cache;
@@ -597,7 +597,7 @@ static void write_one_revoke_record(journal_t *journal,
        offset = *offsetp;
 
        /* Do we need to leave space at the end for a checksum? */
-       if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2))
+       if (jbd2_journal_has_csum_v2or3(journal))
                csum_size = sizeof(struct jbd2_journal_revoke_tail);
 
        /* Make sure we have a descriptor with space left for the record */
@@ -644,7 +644,7 @@ static void jbd2_revoke_csum_set(journal_t *j, struct buffer_head *bh)
        struct jbd2_journal_revoke_tail *tail;
        __u32 csum;
 
-       if (!JBD2_HAS_INCOMPAT_FEATURE(j, JBD2_FEATURE_INCOMPAT_CSUM_V2))
+       if (!jbd2_journal_has_csum_v2or3(j))
                return;
 
        tail = (struct jbd2_journal_revoke_tail *)(bh->b_data + j->j_blocksize -
index 8f27c93f8d2ed88edd55e623baac11b6f94ccfd5..ec9e082f9ecd905af16f2dd09de37822376cfe66 100644 (file)
@@ -253,13 +253,11 @@ static int lockd_up_net(struct svc_serv *serv, struct net *net)
 
        error = make_socks(serv, net);
        if (error < 0)
-               goto err_socks;
+               goto err_bind;
        set_grace_period(net);
        dprintk("lockd_up_net: per-net data created; net=%p\n", net);
        return 0;
 
-err_socks:
-       svc_rpcb_cleanup(serv, net);
 err_bind:
        ln->nlmsvc_users--;
        return error;
index cb66fb05ad4a97e6ed9e975dc631c09b42d7fc03..bb08857f90b56cb2b51a77b3f69acfef33a8fd9c 100644 (file)
@@ -1619,7 +1619,7 @@ static int generic_add_lease(struct file *filp, long arg, struct file_lock **flp
        smp_mb();
        error = check_conflicting_open(dentry, arg);
        if (error)
-               locks_unlink_lock(flp);
+               locks_unlink_lock(before);
 out:
        if (is_deleg)
                mutex_unlock(&inode->i_mutex);
index a01c7730e9af3ad07f3e993d2f7f27f04f615604..ef42d9bee2121f8e6a68937a5ecaa7670721ded9 100644 (file)
@@ -1217,6 +1217,11 @@ static void namespace_unlock(void)
        head.first->pprev = &head.first;
        INIT_HLIST_HEAD(&unmounted);
 
+       /* undo decrements we'd done in umount_tree() */
+       hlist_for_each_entry(mnt, &head, mnt_hash)
+               if (mnt->mnt_ex_mountpoint.mnt)
+                       mntget(mnt->mnt_ex_mountpoint.mnt);
+
        up_write(&namespace_sem);
 
        synchronize_rcu();
@@ -1253,6 +1258,9 @@ void umount_tree(struct mount *mnt, int how)
                hlist_add_head(&p->mnt_hash, &tmp_list);
        }
 
+       hlist_for_each_entry(p, &tmp_list, mnt_hash)
+               list_del_init(&p->mnt_child);
+
        if (how)
                propagate_umount(&tmp_list);
 
@@ -1263,9 +1271,9 @@ void umount_tree(struct mount *mnt, int how)
                p->mnt_ns = NULL;
                if (how < 2)
                        p->mnt.mnt_flags |= MNT_SYNC_UMOUNT;
-               list_del_init(&p->mnt_child);
                if (mnt_has_parent(p)) {
                        put_mountpoint(p->mnt_mp);
+                       mnt_add_count(p->mnt_parent, -1);
                        /* move the reference to mountpoint into ->mnt_ex_mountpoint */
                        p->mnt_ex_mountpoint.dentry = p->mnt_mountpoint;
                        p->mnt_ex_mountpoint.mnt = &p->mnt_parent->mnt;
index 1c5ff6d5838585c4b6b0806aa64b579e58a64bc0..6a4f3666e273e33cab30fb4de866ebf79f791dac 100644 (file)
@@ -1412,24 +1412,18 @@ int nfs_fs_proc_net_init(struct net *net)
        p = proc_create("volumes", S_IFREG|S_IRUGO,
                        nn->proc_nfsfs, &nfs_volume_list_fops);
        if (!p)
-               goto error_2;
+               goto error_1;
        return 0;
 
-error_2:
-       remove_proc_entry("servers", nn->proc_nfsfs);
 error_1:
-       remove_proc_entry("fs/nfsfs", NULL);
+       remove_proc_subtree("nfsfs", net->proc_net);
 error_0:
        return -ENOMEM;
 }
 
 void nfs_fs_proc_net_exit(struct net *net)
 {
-       struct nfs_net *nn = net_generic(net, nfs_net_id);
-
-       remove_proc_entry("volumes", nn->proc_nfsfs);
-       remove_proc_entry("servers", nn->proc_nfsfs);
-       remove_proc_entry("fs/nfsfs", NULL);
+       remove_proc_subtree("nfsfs", net->proc_net);
 }
 
 /*
index 1359c4a27393a6723fc3b22c244dd6422da4a9f3..90978075f7302a791813b6dd29c0ec9f9e5850eb 100644 (file)
@@ -1269,11 +1269,12 @@ filelayout_search_commit_reqs(struct nfs_commit_info *cinfo, struct page *page)
 static void filelayout_retry_commit(struct nfs_commit_info *cinfo, int idx)
 {
        struct pnfs_ds_commit_info *fl_cinfo = cinfo->ds;
-       struct pnfs_commit_bucket *bucket = fl_cinfo->buckets;
+       struct pnfs_commit_bucket *bucket;
        struct pnfs_layout_segment *freeme;
        int i;
 
-       for (i = idx; i < fl_cinfo->nbuckets; i++, bucket++) {
+       for (i = idx; i < fl_cinfo->nbuckets; i++) {
+               bucket = &fl_cinfo->buckets[i];
                if (list_empty(&bucket->committing))
                        continue;
                nfs_retry_commit(&bucket->committing, bucket->clseg, cinfo);
index d0fec260132add4ce0d8917cd1bb47c15408be90..24c6898159cc1ea5e2622574968ff1bbf62268b5 100644 (file)
@@ -129,7 +129,10 @@ static int __nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
                .rpc_argp       = &args,
                .rpc_resp       = &fattr,
        };
-       int status;
+       int status = 0;
+
+       if (acl == NULL && (!S_ISDIR(inode->i_mode) || dfacl == NULL))
+               goto out;
 
        status = -EOPNOTSUPP;
        if (!nfs_server_capable(inode, NFS_CAP_ACLS))
index 92193eddb41dc315868af5f437f083a3a4c0302a..a8b855ab4e227b7d9b2c90d911f27ef4d49f9fb7 100644 (file)
@@ -130,16 +130,15 @@ enum {
  */
 
 struct nfs4_lock_state {
-       struct list_head                ls_locks;   /* Other lock stateids */
-       struct nfs4_state *             ls_state;   /* Pointer to open state */
+       struct list_head        ls_locks;       /* Other lock stateids */
+       struct nfs4_state *     ls_state;       /* Pointer to open state */
 #define NFS_LOCK_INITIALIZED 0
 #define NFS_LOCK_LOST        1
-       unsigned long                   ls_flags;
+       unsigned long           ls_flags;
        struct nfs_seqid_counter        ls_seqid;
-       nfs4_stateid                    ls_stateid;
-       atomic_t                        ls_count;
-       fl_owner_t                      ls_owner;
-       struct work_struct              ls_release;
+       nfs4_stateid            ls_stateid;
+       atomic_t                ls_count;
+       fl_owner_t              ls_owner;
 };
 
 /* bits for nfs4_state->flags */
index 75ae8d22f067d55b7edfe77bbb44d2b0067880f8..7dd8aca31c29b9c0079dce94136e70d716072f78 100644 (file)
@@ -2560,6 +2560,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
        struct nfs4_closedata *calldata = data;
        struct nfs4_state *state = calldata->state;
        struct nfs_server *server = NFS_SERVER(calldata->inode);
+       nfs4_stateid *res_stateid = NULL;
 
        dprintk("%s: begin!\n", __func__);
        if (!nfs4_sequence_done(task, &calldata->res.seq_res))
@@ -2570,12 +2571,12 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
         */
        switch (task->tk_status) {
                case 0:
-                       if (calldata->roc)
+                       res_stateid = &calldata->res.stateid;
+                       if (calldata->arg.fmode == 0 && calldata->roc)
                                pnfs_roc_set_barrier(state->inode,
                                                     calldata->roc_barrier);
-                       nfs_clear_open_stateid(state, &calldata->res.stateid, 0);
                        renew_lease(server, calldata->timestamp);
-                       goto out_release;
+                       break;
                case -NFS4ERR_ADMIN_REVOKED:
                case -NFS4ERR_STALE_STATEID:
                case -NFS4ERR_OLD_STATEID:
@@ -2589,7 +2590,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
                                goto out_release;
                        }
        }
-       nfs_clear_open_stateid(state, NULL, calldata->arg.fmode);
+       nfs_clear_open_stateid(state, res_stateid, calldata->arg.fmode);
 out_release:
        nfs_release_seqid(calldata->arg.seqid);
        nfs_refresh_inode(calldata->inode, calldata->res.fattr);
@@ -2601,6 +2602,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
        struct nfs4_closedata *calldata = data;
        struct nfs4_state *state = calldata->state;
        struct inode *inode = calldata->inode;
+       bool is_rdonly, is_wronly, is_rdwr;
        int call_close = 0;
 
        dprintk("%s: begin!\n", __func__);
@@ -2608,18 +2610,24 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
                goto out_wait;
 
        task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
-       calldata->arg.fmode = FMODE_READ|FMODE_WRITE;
        spin_lock(&state->owner->so_lock);
+       is_rdwr = test_bit(NFS_O_RDWR_STATE, &state->flags);
+       is_rdonly = test_bit(NFS_O_RDONLY_STATE, &state->flags);
+       is_wronly = test_bit(NFS_O_WRONLY_STATE, &state->flags);
+       /* Calculate the current open share mode */
+       calldata->arg.fmode = 0;
+       if (is_rdonly || is_rdwr)
+               calldata->arg.fmode |= FMODE_READ;
+       if (is_wronly || is_rdwr)
+               calldata->arg.fmode |= FMODE_WRITE;
        /* Calculate the change in open mode */
        if (state->n_rdwr == 0) {
                if (state->n_rdonly == 0) {
-                       call_close |= test_bit(NFS_O_RDONLY_STATE, &state->flags);
-                       call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags);
+                       call_close |= is_rdonly || is_rdwr;
                        calldata->arg.fmode &= ~FMODE_READ;
                }
                if (state->n_wronly == 0) {
-                       call_close |= test_bit(NFS_O_WRONLY_STATE, &state->flags);
-                       call_close |= test_bit(NFS_O_RDWR_STATE, &state->flags);
+                       call_close |= is_wronly || is_rdwr;
                        calldata->arg.fmode &= ~FMODE_WRITE;
                }
        }
index a043f618cd5a30ef35a8ec63d54ff12034a2387f..22fe35104c0c1cb30b1d1a27c9996380710a00c6 100644 (file)
@@ -799,18 +799,6 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
        return NULL;
 }
 
-static void
-free_lock_state_work(struct work_struct *work)
-{
-       struct nfs4_lock_state *lsp = container_of(work,
-                                       struct nfs4_lock_state, ls_release);
-       struct nfs4_state *state = lsp->ls_state;
-       struct nfs_server *server = state->owner->so_server;
-       struct nfs_client *clp = server->nfs_client;
-
-       clp->cl_mvops->free_lock_state(server, lsp);
-}
-
 /*
  * Return a compatible lock_state. If no initialized lock_state structure
  * exists, return an uninitialized one.
@@ -832,7 +820,6 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f
        if (lsp->ls_seqid.owner_id < 0)
                goto out_free;
        INIT_LIST_HEAD(&lsp->ls_locks);
-       INIT_WORK(&lsp->ls_release, free_lock_state_work);
        return lsp;
 out_free:
        kfree(lsp);
@@ -896,12 +883,13 @@ void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
        if (list_empty(&state->lock_states))
                clear_bit(LK_STATE_IN_USE, &state->flags);
        spin_unlock(&state->state_lock);
-       if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags))
-               queue_work(nfsiod_workqueue, &lsp->ls_release);
-       else {
-               server = state->owner->so_server;
+       server = state->owner->so_server;
+       if (test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags)) {
+               struct nfs_client *clp = server->nfs_client;
+
+               clp->cl_mvops->free_lock_state(server, lsp);
+       } else
                nfs4_free_lock_state(server, lsp);
-       }
 }
 
 static void nfs4_fl_copy_lock(struct file_lock *dst, struct file_lock *src)
index f9821ce6658a4b09006e7d51d575319658753501..e94457c33ad630a3c290bf1c31486b55bd4884eb 100644 (file)
@@ -2657,6 +2657,7 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
        struct xdr_stream *xdr = cd->xdr;
        int start_offset = xdr->buf->len;
        int cookie_offset;
+       u32 name_and_cookie;
        int entry_bytes;
        __be32 nfserr = nfserr_toosmall;
        __be64 wire_offset;
@@ -2718,7 +2719,14 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
        cd->rd_maxcount -= entry_bytes;
        if (!cd->rd_dircount)
                goto fail;
-       cd->rd_dircount--;
+       /*
+        * RFC 3530 14.2.24 describes rd_dircount as only a "hint", so
+        * let's always let through the first entry, at least:
+        */
+       name_and_cookie = 4 * XDR_QUADLEN(namlen) + 8;
+       if (name_and_cookie > cd->rd_dircount && cd->cookie_offset)
+               goto fail;
+       cd->rd_dircount -= min(cd->rd_dircount, name_and_cookie);
        cd->cookie_offset = cookie_offset;
 skip_entry:
        cd->common.err = nfs_ok;
@@ -3321,6 +3329,10 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
        }
        maxcount = min_t(int, maxcount-16, bytes_left);
 
+       /* RFC 3530 14.2.24 allows us to ignore dircount when it's 0: */
+       if (!readdir->rd_dircount)
+               readdir->rd_dircount = INT_MAX;
+
        readdir->xdr = xdr;
        readdir->rd_maxcount = maxcount;
        readdir->common.err = 0;
index 238a5930cb3c7d16e1c76952e66c6bf24f5299ae..9d7e2b9659cbdf2687e26bbbf0dc784ba7cced6d 100644 (file)
@@ -42,7 +42,7 @@ static int show_mark_fhandle(struct seq_file *m, struct inode *inode)
 {
        struct {
                struct file_handle handle;
-               u8 pad[64];
+               u8 pad[MAX_HANDLE_SZ];
        } f;
        int size, ret, i;
 
@@ -50,7 +50,7 @@ static int show_mark_fhandle(struct seq_file *m, struct inode *inode)
        size = f.handle.handle_bytes >> 2;
 
        ret = exportfs_encode_inode_fh(inode, (struct fid *)f.handle.f_handle, &size, 0);
-       if ((ret == 255) || (ret == -ENOSPC)) {
+       if ((ret == FILEID_INVALID) || (ret < 0)) {
                WARN_ONCE(1, "Can't encode file handler for inotify: %d\n", ret);
                return 0;
        }
index 1ec141e758d73497288f35a13f4e7a965f381a30..62e8ec619b4ce54f6509fcfa2f33cfc381f4fd5e 100644 (file)
@@ -160,9 +160,18 @@ static void o2quo_make_decision(struct work_struct *work)
        }
 
 out:
-       spin_unlock(&qs->qs_lock);
-       if (fence)
+       if (fence) {
+               spin_unlock(&qs->qs_lock);
                o2quo_fence_self();
+       } else {
+               mlog(ML_NOTICE, "not fencing this node, heartbeating: %d, "
+                       "connected: %d, lowest: %d (%sreachable)\n",
+                       qs->qs_heartbeating, qs->qs_connected, lowest_hb,
+                       lowest_reachable ? "" : "un");
+               spin_unlock(&qs->qs_lock);
+
+       }
+
 }
 
 static void o2quo_set_hold(struct o2quo_state *qs, u8 node)
index 681691bc233a1d8991ba4ec5ad1512524afd1b8d..ea34952f9496a6bfaa698165d6b818bd601ebf17 100644 (file)
@@ -1480,6 +1480,14 @@ static int o2net_set_nodelay(struct socket *sock)
        return ret;
 }
 
+static int o2net_set_usertimeout(struct socket *sock)
+{
+       int user_timeout = O2NET_TCP_USER_TIMEOUT;
+
+       return kernel_setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT,
+                               (char *)&user_timeout, sizeof(user_timeout));
+}
+
 static void o2net_initialize_handshake(void)
 {
        o2net_hand->o2hb_heartbeat_timeout_ms = cpu_to_be32(
@@ -1536,16 +1544,20 @@ static void o2net_idle_timer(unsigned long data)
 #endif
 
        printk(KERN_NOTICE "o2net: Connection to " SC_NODEF_FMT " has been "
-              "idle for %lu.%lu secs, shutting it down.\n", SC_NODEF_ARGS(sc),
-              msecs / 1000, msecs % 1000);
+              "idle for %lu.%lu secs.\n",
+              SC_NODEF_ARGS(sc), msecs / 1000, msecs % 1000);
 
-       /*
-        * Initialize the nn_timeout so that the next connection attempt
-        * will continue in o2net_start_connect.
+       /* idle timerout happen, don't shutdown the connection, but
+        * make fence decision. Maybe the connection can recover before
+        * the decision is made.
         */
        atomic_set(&nn->nn_timeout, 1);
+       o2quo_conn_err(o2net_num_from_nn(nn));
+       queue_delayed_work(o2net_wq, &nn->nn_still_up,
+                       msecs_to_jiffies(O2NET_QUORUM_DELAY_MS));
+
+       o2net_sc_reset_idle_timer(sc);
 
-       o2net_sc_queue_work(sc, &sc->sc_shutdown_work);
 }
 
 static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc)
@@ -1560,6 +1572,15 @@ static void o2net_sc_reset_idle_timer(struct o2net_sock_container *sc)
 
 static void o2net_sc_postpone_idle(struct o2net_sock_container *sc)
 {
+       struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num);
+
+       /* clear fence decision since the connection recover from timeout*/
+       if (atomic_read(&nn->nn_timeout)) {
+               o2quo_conn_up(o2net_num_from_nn(nn));
+               cancel_delayed_work(&nn->nn_still_up);
+               atomic_set(&nn->nn_timeout, 0);
+       }
+
        /* Only push out an existing timer */
        if (timer_pending(&sc->sc_idle_timeout))
                o2net_sc_reset_idle_timer(sc);
@@ -1650,6 +1671,12 @@ static void o2net_start_connect(struct work_struct *work)
                goto out;
        }
 
+       ret = o2net_set_usertimeout(sock);
+       if (ret) {
+               mlog(ML_ERROR, "set TCP_USER_TIMEOUT failed with %d\n", ret);
+               goto out;
+       }
+
        o2net_register_callbacks(sc->sc_sock->sk, sc);
 
        spin_lock(&nn->nn_lock);
@@ -1831,6 +1858,12 @@ static int o2net_accept_one(struct socket *sock, int *more)
                goto out;
        }
 
+       ret = o2net_set_usertimeout(new_sock);
+       if (ret) {
+               mlog(ML_ERROR, "set TCP_USER_TIMEOUT failed with %d\n", ret);
+               goto out;
+       }
+
        slen = sizeof(sin);
        ret = new_sock->ops->getname(new_sock, (struct sockaddr *) &sin,
                                       &slen, 1);
index 5bada2a69b503cd365d626a25e4ae6d08ad50b7a..c571e849fda482b17bc89c93f3cebcf4d1229be3 100644 (file)
@@ -63,6 +63,7 @@ typedef void (o2net_post_msg_handler_func)(int status, void *data,
 #define O2NET_KEEPALIVE_DELAY_MS_DEFAULT       2000
 #define O2NET_IDLE_TIMEOUT_MS_DEFAULT          30000
 
+#define O2NET_TCP_USER_TIMEOUT                 0x7fffffff
 
 /* TODO: figure this out.... */
 static inline int o2net_link_down(int err, struct socket *sock)
index 6f66b3751ace1c032dcbbfbb49bf87444702479a..53e6c40ed4c6a451bc38d0727176c0827e564930 100644 (file)
@@ -35,9 +35,8 @@
                copy_to_user((typeof(a) __user *)b, &(a), sizeof(a))
 
 /*
- * This call is void because we are already reporting an error that may
- * be -EFAULT.  The error will be returned from the ioctl(2) call.  It's
- * just a best-effort to tell userspace that this request caused the error.
+ * This is just a best-effort to tell userspace that this request
+ * caused the error.
  */
 static inline void o2info_set_request_error(struct ocfs2_info_request *kreq,
                                        struct ocfs2_info_request __user *req)
@@ -146,136 +145,105 @@ bail:
 static int ocfs2_info_handle_blocksize(struct inode *inode,
                                       struct ocfs2_info_request __user *req)
 {
-       int status = -EFAULT;
        struct ocfs2_info_blocksize oib;
 
        if (o2info_from_user(oib, req))
-               goto bail;
+               return -EFAULT;
 
        oib.ib_blocksize = inode->i_sb->s_blocksize;
 
        o2info_set_request_filled(&oib.ib_req);
 
        if (o2info_to_user(oib, req))
-               goto bail;
-
-       status = 0;
-bail:
-       if (status)
-               o2info_set_request_error(&oib.ib_req, req);
+               return -EFAULT;
 
-       return status;
+       return 0;
 }
 
 static int ocfs2_info_handle_clustersize(struct inode *inode,
                                         struct ocfs2_info_request __user *req)
 {
-       int status = -EFAULT;
        struct ocfs2_info_clustersize oic;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
        if (o2info_from_user(oic, req))
-               goto bail;
+               return -EFAULT;
 
        oic.ic_clustersize = osb->s_clustersize;
 
        o2info_set_request_filled(&oic.ic_req);
 
        if (o2info_to_user(oic, req))
-               goto bail;
-
-       status = 0;
-bail:
-       if (status)
-               o2info_set_request_error(&oic.ic_req, req);
+               return -EFAULT;
 
-       return status;
+       return 0;
 }
 
 static int ocfs2_info_handle_maxslots(struct inode *inode,
                                      struct ocfs2_info_request __user *req)
 {
-       int status = -EFAULT;
        struct ocfs2_info_maxslots oim;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
        if (o2info_from_user(oim, req))
-               goto bail;
+               return -EFAULT;
 
        oim.im_max_slots = osb->max_slots;
 
        o2info_set_request_filled(&oim.im_req);
 
        if (o2info_to_user(oim, req))
-               goto bail;
+               return -EFAULT;
 
-       status = 0;
-bail:
-       if (status)
-               o2info_set_request_error(&oim.im_req, req);
-
-       return status;
+       return 0;
 }
 
 static int ocfs2_info_handle_label(struct inode *inode,
                                   struct ocfs2_info_request __user *req)
 {
-       int status = -EFAULT;
        struct ocfs2_info_label oil;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
        if (o2info_from_user(oil, req))
-               goto bail;
+               return -EFAULT;
 
        memcpy(oil.il_label, osb->vol_label, OCFS2_MAX_VOL_LABEL_LEN);
 
        o2info_set_request_filled(&oil.il_req);
 
        if (o2info_to_user(oil, req))
-               goto bail;
+               return -EFAULT;
 
-       status = 0;
-bail:
-       if (status)
-               o2info_set_request_error(&oil.il_req, req);
-
-       return status;
+       return 0;
 }
 
 static int ocfs2_info_handle_uuid(struct inode *inode,
                                  struct ocfs2_info_request __user *req)
 {
-       int status = -EFAULT;
        struct ocfs2_info_uuid oiu;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
        if (o2info_from_user(oiu, req))
-               goto bail;
+               return -EFAULT;
 
        memcpy(oiu.iu_uuid_str, osb->uuid_str, OCFS2_TEXT_UUID_LEN + 1);
 
        o2info_set_request_filled(&oiu.iu_req);
 
        if (o2info_to_user(oiu, req))
-               goto bail;
-
-       status = 0;
-bail:
-       if (status)
-               o2info_set_request_error(&oiu.iu_req, req);
+               return -EFAULT;
 
-       return status;
+       return 0;
 }
 
 static int ocfs2_info_handle_fs_features(struct inode *inode,
                                         struct ocfs2_info_request __user *req)
 {
-       int status = -EFAULT;
        struct ocfs2_info_fs_features oif;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
        if (o2info_from_user(oif, req))
-               goto bail;
+               return -EFAULT;
 
        oif.if_compat_features = osb->s_feature_compat;
        oif.if_incompat_features = osb->s_feature_incompat;
@@ -284,39 +252,28 @@ static int ocfs2_info_handle_fs_features(struct inode *inode,
        o2info_set_request_filled(&oif.if_req);
 
        if (o2info_to_user(oif, req))
-               goto bail;
+               return -EFAULT;
 
-       status = 0;
-bail:
-       if (status)
-               o2info_set_request_error(&oif.if_req, req);
-
-       return status;
+       return 0;
 }
 
 static int ocfs2_info_handle_journal_size(struct inode *inode,
                                          struct ocfs2_info_request __user *req)
 {
-       int status = -EFAULT;
        struct ocfs2_info_journal_size oij;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
 
        if (o2info_from_user(oij, req))
-               goto bail;
+               return -EFAULT;
 
        oij.ij_journal_size = i_size_read(osb->journal->j_inode);
 
        o2info_set_request_filled(&oij.ij_req);
 
        if (o2info_to_user(oij, req))
-               goto bail;
+               return -EFAULT;
 
-       status = 0;
-bail:
-       if (status)
-               o2info_set_request_error(&oij.ij_req, req);
-
-       return status;
+       return 0;
 }
 
 static int ocfs2_info_scan_inode_alloc(struct ocfs2_super *osb,
@@ -373,7 +330,7 @@ static int ocfs2_info_handle_freeinode(struct inode *inode,
        u32 i;
        u64 blkno = -1;
        char namebuf[40];
-       int status = -EFAULT, type = INODE_ALLOC_SYSTEM_INODE;
+       int status, type = INODE_ALLOC_SYSTEM_INODE;
        struct ocfs2_info_freeinode *oifi = NULL;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct inode *inode_alloc = NULL;
@@ -385,8 +342,10 @@ static int ocfs2_info_handle_freeinode(struct inode *inode,
                goto out_err;
        }
 
-       if (o2info_from_user(*oifi, req))
-               goto bail;
+       if (o2info_from_user(*oifi, req)) {
+               status = -EFAULT;
+               goto out_free;
+       }
 
        oifi->ifi_slotnum = osb->max_slots;
 
@@ -424,14 +383,16 @@ static int ocfs2_info_handle_freeinode(struct inode *inode,
 
        o2info_set_request_filled(&oifi->ifi_req);
 
-       if (o2info_to_user(*oifi, req))
-               goto bail;
+       if (o2info_to_user(*oifi, req)) {
+               status = -EFAULT;
+               goto out_free;
+       }
 
        status = 0;
 bail:
        if (status)
                o2info_set_request_error(&oifi->ifi_req, req);
-
+out_free:
        kfree(oifi);
 out_err:
        return status;
@@ -658,7 +619,7 @@ static int ocfs2_info_handle_freefrag(struct inode *inode,
 {
        u64 blkno = -1;
        char namebuf[40];
-       int status = -EFAULT, type = GLOBAL_BITMAP_SYSTEM_INODE;
+       int status, type = GLOBAL_BITMAP_SYSTEM_INODE;
 
        struct ocfs2_info_freefrag *oiff;
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
@@ -671,8 +632,10 @@ static int ocfs2_info_handle_freefrag(struct inode *inode,
                goto out_err;
        }
 
-       if (o2info_from_user(*oiff, req))
-               goto bail;
+       if (o2info_from_user(*oiff, req)) {
+               status = -EFAULT;
+               goto out_free;
+       }
        /*
         * chunksize from userspace should be power of 2.
         */
@@ -711,14 +674,14 @@ static int ocfs2_info_handle_freefrag(struct inode *inode,
 
        if (o2info_to_user(*oiff, req)) {
                status = -EFAULT;
-               goto bail;
+               goto out_free;
        }
 
        status = 0;
 bail:
        if (status)
                o2info_set_request_error(&oiff->iff_req, req);
-
+out_free:
        kfree(oiff);
 out_err:
        return status;
@@ -727,23 +690,17 @@ out_err:
 static int ocfs2_info_handle_unknown(struct inode *inode,
                                     struct ocfs2_info_request __user *req)
 {
-       int status = -EFAULT;
        struct ocfs2_info_request oir;
 
        if (o2info_from_user(oir, req))
-               goto bail;
+               return -EFAULT;
 
        o2info_clear_request_filled(&oir);
 
        if (o2info_to_user(oir, req))
-               goto bail;
+               return -EFAULT;
 
-       status = 0;
-bail:
-       if (status)
-               o2info_set_request_error(&oir, req);
-
-       return status;
+       return 0;
 }
 
 /*
index 302bf22c4a30762013dbbfd64d0353250101eb62..aae331a5d03b2591e670c9a08451bd00ad8e66f9 100644 (file)
@@ -381,6 +381,7 @@ static void __propagate_umount(struct mount *mnt)
                 * other children
                 */
                if (child && list_empty(&child->mnt_mounts)) {
+                       list_del_init(&child->mnt_child);
                        hlist_del_init_rcu(&child->mnt_hash);
                        hlist_add_before_rcu(&child->mnt_hash, &mnt->mnt_hash);
                }
index b28d1dd10e8b70194a604a1fca654237edd817be..bdc729d80e5e4eb863ad4fcf849aa6ea886a7519 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -65,7 +65,7 @@ int sync_filesystem(struct super_block *sb)
                return ret;
        return __sync_filesystem(sb, 1);
 }
-EXPORT_SYMBOL_GPL(sync_filesystem);
+EXPORT_SYMBOL(sync_filesystem);
 
 static void sync_inodes_one_sb(struct super_block *sb, void *arg)
 {
index 6eaf5edf1ea1577e88cafc60184963e1b18df5a5..e77db621ec8985ad21878c45e970ebc3f23258cb 100644 (file)
@@ -45,7 +45,7 @@ void udf_free_inode(struct inode *inode)
        udf_free_blocks(sb, NULL, &UDF_I(inode)->i_location, 0, 1);
 }
 
-struct inode *udf_new_inode(struct inode *dir, umode_t mode, int *err)
+struct inode *udf_new_inode(struct inode *dir, umode_t mode)
 {
        struct super_block *sb = dir->i_sb;
        struct udf_sb_info *sbi = UDF_SB(sb);
@@ -55,14 +55,12 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode, int *err)
        struct udf_inode_info *iinfo;
        struct udf_inode_info *dinfo = UDF_I(dir);
        struct logicalVolIntegrityDescImpUse *lvidiu;
+       int err;
 
        inode = new_inode(sb);
 
-       if (!inode) {
-               *err = -ENOMEM;
-               return NULL;
-       }
-       *err = -ENOSPC;
+       if (!inode)
+               return ERR_PTR(-ENOMEM);
 
        iinfo = UDF_I(inode);
        if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE)) {
@@ -80,21 +78,22 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode, int *err)
        }
        if (!iinfo->i_ext.i_data) {
                iput(inode);
-               *err = -ENOMEM;
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        }
 
+       err = -ENOSPC;
        block = udf_new_block(dir->i_sb, NULL,
                              dinfo->i_location.partitionReferenceNum,
-                             start, err);
-       if (*err) {
+                             start, &err);
+       if (err) {
                iput(inode);
-               return NULL;
+               return ERR_PTR(err);
        }
 
        lvidiu = udf_sb_lvidiu(sb);
        if (lvidiu) {
                iinfo->i_unique = lvid_get_unique_id(sb);
+               inode->i_generation = iinfo->i_unique;
                mutex_lock(&sbi->s_alloc_mutex);
                if (S_ISDIR(mode))
                        le32_add_cpu(&lvidiu->numDirs, 1);
@@ -123,9 +122,12 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode, int *err)
                iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
        inode->i_mtime = inode->i_atime = inode->i_ctime =
                iinfo->i_crtime = current_fs_time(inode->i_sb);
-       insert_inode_hash(inode);
+       if (unlikely(insert_inode_locked(inode) < 0)) {
+               make_bad_inode(inode);
+               iput(inode);
+               return ERR_PTR(-EIO);
+       }
        mark_inode_dirty(inode);
 
-       *err = 0;
        return inode;
 }
index 236cd48184c2df20e75bc9fee098ded782f2560f..08598843288fe0c2dd206940d6437c606ef41c1f 100644 (file)
@@ -51,7 +51,6 @@ MODULE_LICENSE("GPL");
 
 static umode_t udf_convert_permissions(struct fileEntry *);
 static int udf_update_inode(struct inode *, int);
-static void udf_fill_inode(struct inode *, struct buffer_head *);
 static int udf_sync_inode(struct inode *inode);
 static int udf_alloc_i_data(struct inode *inode, size_t size);
 static sector_t inode_getblk(struct inode *, sector_t, int *, int *);
@@ -1271,12 +1270,33 @@ update_time:
        return 0;
 }
 
-static void __udf_read_inode(struct inode *inode)
+/*
+ * Maximum length of linked list formed by ICB hierarchy. The chosen number is
+ * arbitrary - just that we hopefully don't limit any real use of rewritten
+ * inode on write-once media but avoid looping for too long on corrupted media.
+ */
+#define UDF_MAX_ICB_NESTING 1024
+
+static int udf_read_inode(struct inode *inode)
 {
        struct buffer_head *bh = NULL;
        struct fileEntry *fe;
+       struct extendedFileEntry *efe;
        uint16_t ident;
        struct udf_inode_info *iinfo = UDF_I(inode);
+       struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
+       struct kernel_lb_addr *iloc = &iinfo->i_location;
+       unsigned int link_count;
+       unsigned int indirections = 0;
+       int ret = -EIO;
+
+reread:
+       if (iloc->logicalBlockNum >=
+           sbi->s_partmaps[iloc->partitionReferenceNum].s_partition_len) {
+               udf_debug("block=%d, partition=%d out of range\n",
+                         iloc->logicalBlockNum, iloc->partitionReferenceNum);
+               return -EIO;
+       }
 
        /*
         * Set defaults, but the inode is still incomplete!
@@ -1290,78 +1310,54 @@ static void __udf_read_inode(struct inode *inode)
         *      i_nlink = 1
         *      i_op = NULL;
         */
-       bh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 0, &ident);
+       bh = udf_read_ptagged(inode->i_sb, iloc, 0, &ident);
        if (!bh) {
                udf_err(inode->i_sb, "(ino %ld) failed !bh\n", inode->i_ino);
-               make_bad_inode(inode);
-               return;
+               return -EIO;
        }
 
        if (ident != TAG_IDENT_FE && ident != TAG_IDENT_EFE &&
            ident != TAG_IDENT_USE) {
                udf_err(inode->i_sb, "(ino %ld) failed ident=%d\n",
                        inode->i_ino, ident);
-               brelse(bh);
-               make_bad_inode(inode);
-               return;
+               goto out;
        }
 
        fe = (struct fileEntry *)bh->b_data;
+       efe = (struct extendedFileEntry *)bh->b_data;
 
        if (fe->icbTag.strategyType == cpu_to_le16(4096)) {
                struct buffer_head *ibh;
 
-               ibh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 1,
-                                       &ident);
+               ibh = udf_read_ptagged(inode->i_sb, iloc, 1, &ident);
                if (ident == TAG_IDENT_IE && ibh) {
-                       struct buffer_head *nbh = NULL;
                        struct kernel_lb_addr loc;
                        struct indirectEntry *ie;
 
                        ie = (struct indirectEntry *)ibh->b_data;
                        loc = lelb_to_cpu(ie->indirectICB.extLocation);
 
-                       if (ie->indirectICB.extLength &&
-                               (nbh = udf_read_ptagged(inode->i_sb, &loc, 0,
-                                                       &ident))) {
-                               if (ident == TAG_IDENT_FE ||
-                                       ident == TAG_IDENT_EFE) {
-                                       memcpy(&iinfo->i_location,
-                                               &loc,
-                                               sizeof(struct kernel_lb_addr));
-                                       brelse(bh);
-                                       brelse(ibh);
-                                       brelse(nbh);
-                                       __udf_read_inode(inode);
-                                       return;
+                       if (ie->indirectICB.extLength) {
+                               brelse(ibh);
+                               memcpy(&iinfo->i_location, &loc,
+                                      sizeof(struct kernel_lb_addr));
+                               if (++indirections > UDF_MAX_ICB_NESTING) {
+                                       udf_err(inode->i_sb,
+                                               "too many ICBs in ICB hierarchy"
+                                               " (max %d supported)\n",
+                                               UDF_MAX_ICB_NESTING);
+                                       goto out;
                                }
-                               brelse(nbh);
+                               brelse(bh);
+                               goto reread;
                        }
                }
                brelse(ibh);
        } else if (fe->icbTag.strategyType != cpu_to_le16(4)) {
                udf_err(inode->i_sb, "unsupported strategy type: %d\n",
                        le16_to_cpu(fe->icbTag.strategyType));
-               brelse(bh);
-               make_bad_inode(inode);
-               return;
+               goto out;
        }
-       udf_fill_inode(inode, bh);
-
-       brelse(bh);
-}
-
-static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
-{
-       struct fileEntry *fe;
-       struct extendedFileEntry *efe;
-       struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
-       struct udf_inode_info *iinfo = UDF_I(inode);
-       unsigned int link_count;
-
-       fe = (struct fileEntry *)bh->b_data;
-       efe = (struct extendedFileEntry *)bh->b_data;
-
        if (fe->icbTag.strategyType == cpu_to_le16(4))
                iinfo->i_strat4096 = 0;
        else /* if (fe->icbTag.strategyType == cpu_to_le16(4096)) */
@@ -1378,11 +1374,10 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
        if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_EFE)) {
                iinfo->i_efe = 1;
                iinfo->i_use = 0;
-               if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize -
-                                       sizeof(struct extendedFileEntry))) {
-                       make_bad_inode(inode);
-                       return;
-               }
+               ret = udf_alloc_i_data(inode, inode->i_sb->s_blocksize -
+                                       sizeof(struct extendedFileEntry));
+               if (ret)
+                       goto out;
                memcpy(iinfo->i_ext.i_data,
                       bh->b_data + sizeof(struct extendedFileEntry),
                       inode->i_sb->s_blocksize -
@@ -1390,11 +1385,10 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
        } else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_FE)) {
                iinfo->i_efe = 0;
                iinfo->i_use = 0;
-               if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize -
-                                               sizeof(struct fileEntry))) {
-                       make_bad_inode(inode);
-                       return;
-               }
+               ret = udf_alloc_i_data(inode, inode->i_sb->s_blocksize -
+                                               sizeof(struct fileEntry));
+               if (ret)
+                       goto out;
                memcpy(iinfo->i_ext.i_data,
                       bh->b_data + sizeof(struct fileEntry),
                       inode->i_sb->s_blocksize - sizeof(struct fileEntry));
@@ -1404,18 +1398,18 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
                iinfo->i_lenAlloc = le32_to_cpu(
                                ((struct unallocSpaceEntry *)bh->b_data)->
                                 lengthAllocDescs);
-               if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize -
-                                       sizeof(struct unallocSpaceEntry))) {
-                       make_bad_inode(inode);
-                       return;
-               }
+               ret = udf_alloc_i_data(inode, inode->i_sb->s_blocksize -
+                                       sizeof(struct unallocSpaceEntry));
+               if (ret)
+                       goto out;
                memcpy(iinfo->i_ext.i_data,
                       bh->b_data + sizeof(struct unallocSpaceEntry),
                       inode->i_sb->s_blocksize -
                                        sizeof(struct unallocSpaceEntry));
-               return;
+               return 0;
        }
 
+       ret = -EIO;
        read_lock(&sbi->s_cred_lock);
        i_uid_write(inode, le32_to_cpu(fe->uid));
        if (!uid_valid(inode->i_uid) ||
@@ -1441,8 +1435,10 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
        read_unlock(&sbi->s_cred_lock);
 
        link_count = le16_to_cpu(fe->fileLinkCount);
-       if (!link_count)
-               link_count = 1;
+       if (!link_count) {
+               ret = -ESTALE;
+               goto out;
+       }
        set_nlink(inode, link_count);
 
        inode->i_size = le64_to_cpu(fe->informationLength);
@@ -1488,6 +1484,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
                iinfo->i_lenAlloc = le32_to_cpu(efe->lengthAllocDescs);
                iinfo->i_checkpoint = le32_to_cpu(efe->checkpoint);
        }
+       inode->i_generation = iinfo->i_unique;
 
        switch (fe->icbTag.fileType) {
        case ICBTAG_FILE_TYPE_DIRECTORY:
@@ -1537,8 +1534,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
        default:
                udf_err(inode->i_sb, "(ino %ld) failed unknown file type=%d\n",
                        inode->i_ino, fe->icbTag.fileType);
-               make_bad_inode(inode);
-               return;
+               goto out;
        }
        if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) {
                struct deviceSpec *dsea =
@@ -1549,8 +1545,12 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
                                      le32_to_cpu(dsea->minorDeviceIdent)));
                        /* Developer ID ??? */
                } else
-                       make_bad_inode(inode);
+                       goto out;
        }
+       ret = 0;
+out:
+       brelse(bh);
+       return ret;
 }
 
 static int udf_alloc_i_data(struct inode *inode, size_t size)
@@ -1664,7 +1664,7 @@ static int udf_update_inode(struct inode *inode, int do_sync)
                     FE_PERM_U_DELETE | FE_PERM_U_CHATTR));
        fe->permissions = cpu_to_le32(udfperms);
 
-       if (S_ISDIR(inode->i_mode))
+       if (S_ISDIR(inode->i_mode) && inode->i_nlink > 0)
                fe->fileLinkCount = cpu_to_le16(inode->i_nlink - 1);
        else
                fe->fileLinkCount = cpu_to_le16(inode->i_nlink);
@@ -1830,32 +1830,23 @@ struct inode *udf_iget(struct super_block *sb, struct kernel_lb_addr *ino)
 {
        unsigned long block = udf_get_lb_pblock(sb, ino, 0);
        struct inode *inode = iget_locked(sb, block);
+       int err;
 
        if (!inode)
-               return NULL;
-
-       if (inode->i_state & I_NEW) {
-               memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr));
-               __udf_read_inode(inode);
-               unlock_new_inode(inode);
-       }
+               return ERR_PTR(-ENOMEM);
 
-       if (is_bad_inode(inode))
-               goto out_iput;
+       if (!(inode->i_state & I_NEW))
+               return inode;
 
-       if (ino->logicalBlockNum >= UDF_SB(sb)->
-                       s_partmaps[ino->partitionReferenceNum].s_partition_len) {
-               udf_debug("block=%d, partition=%d out of range\n",
-                         ino->logicalBlockNum, ino->partitionReferenceNum);
-               make_bad_inode(inode);
-               goto out_iput;
+       memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr));
+       err = udf_read_inode(inode);
+       if (err < 0) {
+               iget_failed(inode);
+               return ERR_PTR(err);
        }
+       unlock_new_inode(inode);
 
        return inode;
-
- out_iput:
-       iput(inode);
-       return NULL;
 }
 
 int udf_add_aext(struct inode *inode, struct extent_position *epos,
index 83a06001742bfaab6781bc26509517196fc3af16..c12e260fd6c417eb9c690782b8860f0e5eeff8d9 100644 (file)
@@ -270,9 +270,8 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
                                                NULL, 0),
                };
                inode = udf_iget(dir->i_sb, lb);
-               if (!inode) {
-                       return ERR_PTR(-EACCES);
-               }
+               if (IS_ERR(inode))
+                       return inode;
        } else
 #endif /* UDF_RECOVERY */
 
@@ -285,9 +284,8 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
 
                loc = lelb_to_cpu(cfi.icb.extLocation);
                inode = udf_iget(dir->i_sb, &loc);
-               if (!inode) {
-                       return ERR_PTR(-EACCES);
-               }
+               if (IS_ERR(inode))
+                       return ERR_CAST(inode);
        }
 
        return d_splice_alias(inode, dentry);
@@ -550,32 +548,18 @@ static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
        return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL);
 }
 
-static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                     bool excl)
+static int udf_add_nondir(struct dentry *dentry, struct inode *inode)
 {
+       struct udf_inode_info *iinfo = UDF_I(inode);
+       struct inode *dir = dentry->d_parent->d_inode;
        struct udf_fileident_bh fibh;
-       struct inode *inode;
        struct fileIdentDesc cfi, *fi;
        int err;
-       struct udf_inode_info *iinfo;
-
-       inode = udf_new_inode(dir, mode, &err);
-       if (!inode) {
-               return err;
-       }
-
-       iinfo = UDF_I(inode);
-       if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
-               inode->i_data.a_ops = &udf_adinicb_aops;
-       else
-               inode->i_data.a_ops = &udf_aops;
-       inode->i_op = &udf_file_inode_operations;
-       inode->i_fop = &udf_file_operations;
-       mark_inode_dirty(inode);
 
        fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
-       if (!fi) {
+       if (unlikely(!fi)) {
                inode_dec_link_count(inode);
+               unlock_new_inode(inode);
                iput(inode);
                return err;
        }
@@ -589,23 +573,21 @@ static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode,
        if (fibh.sbh != fibh.ebh)
                brelse(fibh.ebh);
        brelse(fibh.sbh);
+       unlock_new_inode(inode);
        d_instantiate(dentry, inode);
 
        return 0;
 }
 
-static int udf_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
+static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+                     bool excl)
 {
-       struct inode *inode;
-       struct udf_inode_info *iinfo;
-       int err;
+       struct inode *inode = udf_new_inode(dir, mode);
 
-       inode = udf_new_inode(dir, mode, &err);
-       if (!inode)
-               return err;
+       if (IS_ERR(inode))
+               return PTR_ERR(inode);
 
-       iinfo = UDF_I(inode);
-       if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
+       if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
                inode->i_data.a_ops = &udf_adinicb_aops;
        else
                inode->i_data.a_ops = &udf_aops;
@@ -613,7 +595,25 @@ static int udf_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
        inode->i_fop = &udf_file_operations;
        mark_inode_dirty(inode);
 
+       return udf_add_nondir(dentry, inode);
+}
+
+static int udf_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode)
+{
+       struct inode *inode = udf_new_inode(dir, mode);
+
+       if (IS_ERR(inode))
+               return PTR_ERR(inode);
+
+       if (UDF_I(inode)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
+               inode->i_data.a_ops = &udf_adinicb_aops;
+       else
+               inode->i_data.a_ops = &udf_aops;
+       inode->i_op = &udf_file_inode_operations;
+       inode->i_fop = &udf_file_operations;
+       mark_inode_dirty(inode);
        d_tmpfile(dentry, inode);
+       unlock_new_inode(inode);
        return 0;
 }
 
@@ -621,44 +621,16 @@ static int udf_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
                     dev_t rdev)
 {
        struct inode *inode;
-       struct udf_fileident_bh fibh;
-       struct fileIdentDesc cfi, *fi;
-       int err;
-       struct udf_inode_info *iinfo;
 
        if (!old_valid_dev(rdev))
                return -EINVAL;
 
-       err = -EIO;
-       inode = udf_new_inode(dir, mode, &err);
-       if (!inode)
-               goto out;
+       inode = udf_new_inode(dir, mode);
+       if (IS_ERR(inode))
+               return PTR_ERR(inode);
 
-       iinfo = UDF_I(inode);
        init_special_inode(inode, mode, rdev);
-       fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
-       if (!fi) {
-               inode_dec_link_count(inode);
-               iput(inode);
-               return err;
-       }
-       cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
-       cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
-       *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
-               cpu_to_le32(iinfo->i_unique & 0x00000000FFFFFFFFUL);
-       udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
-       if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
-               mark_inode_dirty(dir);
-       mark_inode_dirty(inode);
-
-       if (fibh.sbh != fibh.ebh)
-               brelse(fibh.ebh);
-       brelse(fibh.sbh);
-       d_instantiate(dentry, inode);
-       err = 0;
-
-out:
-       return err;
+       return udf_add_nondir(dentry, inode);
 }
 
 static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
@@ -670,10 +642,9 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        struct udf_inode_info *dinfo = UDF_I(dir);
        struct udf_inode_info *iinfo;
 
-       err = -EIO;
-       inode = udf_new_inode(dir, S_IFDIR | mode, &err);
-       if (!inode)
-               goto out;
+       inode = udf_new_inode(dir, S_IFDIR | mode);
+       if (IS_ERR(inode))
+               return PTR_ERR(inode);
 
        iinfo = UDF_I(inode);
        inode->i_op = &udf_dir_inode_operations;
@@ -681,6 +652,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err);
        if (!fi) {
                inode_dec_link_count(inode);
+               unlock_new_inode(inode);
                iput(inode);
                goto out;
        }
@@ -699,6 +671,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        if (!fi) {
                clear_nlink(inode);
                mark_inode_dirty(inode);
+               unlock_new_inode(inode);
                iput(inode);
                goto out;
        }
@@ -710,6 +683,7 @@ static int udf_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
        udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
        inc_nlink(dir);
        mark_inode_dirty(dir);
+       unlock_new_inode(inode);
        d_instantiate(dentry, inode);
        if (fibh.sbh != fibh.ebh)
                brelse(fibh.ebh);
@@ -876,14 +850,11 @@ out:
 static int udf_symlink(struct inode *dir, struct dentry *dentry,
                       const char *symname)
 {
-       struct inode *inode;
+       struct inode *inode = udf_new_inode(dir, S_IFLNK | S_IRWXUGO);
        struct pathComponent *pc;
        const char *compstart;
-       struct udf_fileident_bh fibh;
        struct extent_position epos = {};
        int eoffset, elen = 0;
-       struct fileIdentDesc *fi;
-       struct fileIdentDesc cfi;
        uint8_t *ea;
        int err;
        int block;
@@ -892,9 +863,8 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
        struct udf_inode_info *iinfo;
        struct super_block *sb = dir->i_sb;
 
-       inode = udf_new_inode(dir, S_IFLNK | S_IRWXUGO, &err);
-       if (!inode)
-               goto out;
+       if (IS_ERR(inode))
+               return PTR_ERR(inode);
 
        iinfo = UDF_I(inode);
        down_write(&iinfo->i_data_sem);
@@ -1012,32 +982,15 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
        mark_inode_dirty(inode);
        up_write(&iinfo->i_data_sem);
 
-       fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err);
-       if (!fi)
-               goto out_fail;
-       cfi.icb.extLength = cpu_to_le32(sb->s_blocksize);
-       cfi.icb.extLocation = cpu_to_lelb(iinfo->i_location);
-       if (UDF_SB(inode->i_sb)->s_lvid_bh) {
-               *(__le32 *)((struct allocDescImpUse *)cfi.icb.impUse)->impUse =
-                       cpu_to_le32(lvid_get_unique_id(sb));
-       }
-       udf_write_fi(dir, &cfi, fi, &fibh, NULL, NULL);
-       if (UDF_I(dir)->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
-               mark_inode_dirty(dir);
-       if (fibh.sbh != fibh.ebh)
-               brelse(fibh.ebh);
-       brelse(fibh.sbh);
-       d_instantiate(dentry, inode);
-       err = 0;
-
+       err = udf_add_nondir(dentry, inode);
 out:
        kfree(name);
        return err;
 
 out_no_entry:
        up_write(&iinfo->i_data_sem);
-out_fail:
        inode_dec_link_count(inode);
+       unlock_new_inode(inode);
        iput(inode);
        goto out;
 }
@@ -1222,7 +1175,7 @@ static struct dentry *udf_get_parent(struct dentry *child)
        struct udf_fileident_bh fibh;
 
        if (!udf_find_entry(child->d_inode, &dotdot, &fibh, &cfi))
-               goto out_unlock;
+               return ERR_PTR(-EACCES);
 
        if (fibh.sbh != fibh.ebh)
                brelse(fibh.ebh);
@@ -1230,12 +1183,10 @@ static struct dentry *udf_get_parent(struct dentry *child)
 
        tloc = lelb_to_cpu(cfi.icb.extLocation);
        inode = udf_iget(child->d_inode->i_sb, &tloc);
-       if (!inode)
-               goto out_unlock;
+       if (IS_ERR(inode))
+               return ERR_CAST(inode);
 
        return d_obtain_alias(inode);
-out_unlock:
-       return ERR_PTR(-EACCES);
 }
 
 
@@ -1252,8 +1203,8 @@ static struct dentry *udf_nfs_get_inode(struct super_block *sb, u32 block,
        loc.partitionReferenceNum = partref;
        inode = udf_iget(sb, &loc);
 
-       if (inode == NULL)
-               return ERR_PTR(-ENOMEM);
+       if (IS_ERR(inode))
+               return ERR_CAST(inode);
 
        if (generation && inode->i_generation != generation) {
                iput(inode);
index 813da94d447b3b44418d2ce84bc70121cb62c92e..5401fc33f5cc906b76b846e62f74751cabd50a68 100644 (file)
@@ -961,12 +961,14 @@ struct inode *udf_find_metadata_inode_efe(struct super_block *sb,
 
        metadata_fe = udf_iget(sb, &addr);
 
-       if (metadata_fe == NULL)
+       if (IS_ERR(metadata_fe)) {
                udf_warn(sb, "metadata inode efe not found\n");
-       else if (UDF_I(metadata_fe)->i_alloc_type != ICBTAG_FLAG_AD_SHORT) {
+               return metadata_fe;
+       }
+       if (UDF_I(metadata_fe)->i_alloc_type != ICBTAG_FLAG_AD_SHORT) {
                udf_warn(sb, "metadata inode efe does not have short allocation descriptors!\n");
                iput(metadata_fe);
-               metadata_fe = NULL;
+               return ERR_PTR(-EIO);
        }
 
        return metadata_fe;
@@ -978,6 +980,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition)
        struct udf_part_map *map;
        struct udf_meta_data *mdata;
        struct kernel_lb_addr addr;
+       struct inode *fe;
 
        map = &sbi->s_partmaps[partition];
        mdata = &map->s_type_specific.s_metadata;
@@ -986,22 +989,24 @@ static int udf_load_metadata_files(struct super_block *sb, int partition)
        udf_debug("Metadata file location: block = %d part = %d\n",
                  mdata->s_meta_file_loc, map->s_partition_num);
 
-       mdata->s_metadata_fe = udf_find_metadata_inode_efe(sb,
-               mdata->s_meta_file_loc, map->s_partition_num);
-
-       if (mdata->s_metadata_fe == NULL) {
+       fe = udf_find_metadata_inode_efe(sb, mdata->s_meta_file_loc,
+                                        map->s_partition_num);
+       if (IS_ERR(fe)) {
                /* mirror file entry */
                udf_debug("Mirror metadata file location: block = %d part = %d\n",
                          mdata->s_mirror_file_loc, map->s_partition_num);
 
-               mdata->s_mirror_fe = udf_find_metadata_inode_efe(sb,
-                       mdata->s_mirror_file_loc, map->s_partition_num);
+               fe = udf_find_metadata_inode_efe(sb, mdata->s_mirror_file_loc,
+                                                map->s_partition_num);
 
-               if (mdata->s_mirror_fe == NULL) {
+               if (IS_ERR(fe)) {
                        udf_err(sb, "Both metadata and mirror metadata inode efe can not found\n");
-                       return -EIO;
+                       return PTR_ERR(fe);
                }
-       }
+               mdata->s_mirror_fe = fe;
+       } else
+               mdata->s_metadata_fe = fe;
+
 
        /*
         * bitmap file entry
@@ -1015,15 +1020,16 @@ static int udf_load_metadata_files(struct super_block *sb, int partition)
                udf_debug("Bitmap file location: block = %d part = %d\n",
                          addr.logicalBlockNum, addr.partitionReferenceNum);
 
-               mdata->s_bitmap_fe = udf_iget(sb, &addr);
-               if (mdata->s_bitmap_fe == NULL) {
+               fe = udf_iget(sb, &addr);
+               if (IS_ERR(fe)) {
                        if (sb->s_flags & MS_RDONLY)
                                udf_warn(sb, "bitmap inode efe not found but it's ok since the disc is mounted read-only\n");
                        else {
                                udf_err(sb, "bitmap inode efe not found and attempted read-write mount\n");
-                               return -EIO;
+                               return PTR_ERR(fe);
                        }
-               }
+               } else
+                       mdata->s_bitmap_fe = fe;
        }
 
        udf_debug("udf_load_metadata_files Ok\n");
@@ -1111,13 +1117,15 @@ static int udf_fill_partdesc_info(struct super_block *sb,
                                phd->unallocSpaceTable.extPosition),
                        .partitionReferenceNum = p_index,
                };
+               struct inode *inode;
 
-               map->s_uspace.s_table = udf_iget(sb, &loc);
-               if (!map->s_uspace.s_table) {
+               inode = udf_iget(sb, &loc);
+               if (IS_ERR(inode)) {
                        udf_debug("cannot load unallocSpaceTable (part %d)\n",
                                  p_index);
-                       return -EIO;
+                       return PTR_ERR(inode);
                }
+               map->s_uspace.s_table = inode;
                map->s_partition_flags |= UDF_PART_FLAG_UNALLOC_TABLE;
                udf_debug("unallocSpaceTable (part %d) @ %ld\n",
                          p_index, map->s_uspace.s_table->i_ino);
@@ -1144,14 +1152,15 @@ static int udf_fill_partdesc_info(struct super_block *sb,
                                phd->freedSpaceTable.extPosition),
                        .partitionReferenceNum = p_index,
                };
+               struct inode *inode;
 
-               map->s_fspace.s_table = udf_iget(sb, &loc);
-               if (!map->s_fspace.s_table) {
+               inode = udf_iget(sb, &loc);
+               if (IS_ERR(inode)) {
                        udf_debug("cannot load freedSpaceTable (part %d)\n",
                                  p_index);
-                       return -EIO;
+                       return PTR_ERR(inode);
                }
-
+               map->s_fspace.s_table = inode;
                map->s_partition_flags |= UDF_PART_FLAG_FREED_TABLE;
                udf_debug("freedSpaceTable (part %d) @ %ld\n",
                          p_index, map->s_fspace.s_table->i_ino);
@@ -1178,6 +1187,7 @@ static void udf_find_vat_block(struct super_block *sb, int p_index,
        struct udf_part_map *map = &sbi->s_partmaps[p_index];
        sector_t vat_block;
        struct kernel_lb_addr ino;
+       struct inode *inode;
 
        /*
         * VAT file entry is in the last recorded block. Some broken disks have
@@ -1186,10 +1196,13 @@ static void udf_find_vat_block(struct super_block *sb, int p_index,
        ino.partitionReferenceNum = type1_index;
        for (vat_block = start_block;
             vat_block >= map->s_partition_root &&
-            vat_block >= start_block - 3 &&
-            !sbi->s_vat_inode; vat_block--) {
+            vat_block >= start_block - 3; vat_block--) {
                ino.logicalBlockNum = vat_block - map->s_partition_root;
-               sbi->s_vat_inode = udf_iget(sb, &ino);
+               inode = udf_iget(sb, &ino);
+               if (!IS_ERR(inode)) {
+                       sbi->s_vat_inode = inode;
+                       break;
+               }
        }
 }
 
@@ -2205,10 +2218,10 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
        /* assign inodes by physical block number */
        /* perhaps it's not extensible enough, but for now ... */
        inode = udf_iget(sb, &rootdir);
-       if (!inode) {
+       if (IS_ERR(inode)) {
                udf_err(sb, "Error in udf_iget, block=%d, partition=%d\n",
                       rootdir.logicalBlockNum, rootdir.partitionReferenceNum);
-               ret = -EIO;
+               ret = PTR_ERR(inode);
                goto error_out;
        }
 
index be7dabbbcb49ef171b33e0ec2bc4a672c073282d..742557be9936399fba764f645c04b969d2a3cfd5 100644 (file)
@@ -143,7 +143,6 @@ extern int udf_expand_file_adinicb(struct inode *);
 extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *);
 extern struct buffer_head *udf_bread(struct inode *, int, int, int *);
 extern int udf_setsize(struct inode *, loff_t);
-extern void udf_read_inode(struct inode *);
 extern void udf_evict_inode(struct inode *);
 extern int udf_write_inode(struct inode *, struct writeback_control *wbc);
 extern long udf_block_map(struct inode *, sector_t);
@@ -209,7 +208,7 @@ extern int udf_CS0toUTF8(struct ustr *, const struct ustr *);
 
 /* ialloc.c */
 extern void udf_free_inode(struct inode *);
-extern struct inode *udf_new_inode(struct inode *, umode_t, int *);
+extern struct inode *udf_new_inode(struct inode *, umode_t);
 
 /* truncate.c */
 extern void udf_truncate_tail_extent(struct inode *);
index 7c580c97990ee05dee7e5ad42a9c5754bfe4384d..be7d42c7d9382bf8072a7e6e9eff7e03b24bab25 100644 (file)
@@ -902,9 +902,6 @@ void ufs_evict_inode(struct inode * inode)
        invalidate_inode_buffers(inode);
        clear_inode(inode);
 
-       if (want_delete) {
-               lock_ufs(inode->i_sb);
-               ufs_free_inode (inode);
-               unlock_ufs(inode->i_sb);
-       }
+       if (want_delete)
+               ufs_free_inode(inode);
 }
index 90d74b8f8eba8dacd536c74ac161cceddc241196..2df62a73f20ce2071c17d81c343ada85ae287d2a 100644 (file)
@@ -126,12 +126,12 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry,
        if (l > sb->s_blocksize)
                goto out_notlocked;
 
-       lock_ufs(dir->i_sb);
        inode = ufs_new_inode(dir, S_IFLNK | S_IRWXUGO);
        err = PTR_ERR(inode);
        if (IS_ERR(inode))
-               goto out;
+               goto out_notlocked;
 
+       lock_ufs(dir->i_sb);
        if (l > UFS_SB(sb)->s_uspi->s_maxsymlinklen) {
                /* slow symlink */
                inode->i_op = &ufs_symlink_inode_operations;
@@ -181,13 +181,9 @@ static int ufs_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
        struct inode * inode;
        int err;
 
-       lock_ufs(dir->i_sb);
-       inode_inc_link_count(dir);
-
        inode = ufs_new_inode(dir, S_IFDIR|mode);
-       err = PTR_ERR(inode);
        if (IS_ERR(inode))
-               goto out_dir;
+               return PTR_ERR(inode);
 
        inode->i_op = &ufs_dir_inode_operations;
        inode->i_fop = &ufs_dir_operations;
@@ -195,6 +191,9 @@ static int ufs_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
 
        inode_inc_link_count(inode);
 
+       lock_ufs(dir->i_sb);
+       inode_inc_link_count(dir);
+
        err = ufs_make_empty(inode, dir);
        if (err)
                goto out_fail;
@@ -212,7 +211,6 @@ out_fail:
        inode_dec_link_count(inode);
        inode_dec_link_count(inode);
        iput (inode);
-out_dir:
        inode_dec_link_count(dir);
        unlock_ufs(dir->i_sb);
        goto out;
index de2d26d328446e65698dca0ff9f4fe2317c3f04e..86df952d3e24e7054477338f479d325fa212ce0c 100644 (file)
@@ -5424,7 +5424,7 @@ xfs_bmap_shift_extents(
        struct xfs_bmap_free    *flist,
        int                     num_exts)
 {
-       struct xfs_btree_cur            *cur;
+       struct xfs_btree_cur            *cur = NULL;
        struct xfs_bmbt_rec_host        *gotp;
        struct xfs_bmbt_irec            got;
        struct xfs_bmbt_irec            left;
@@ -5435,7 +5435,7 @@ xfs_bmap_shift_extents(
        int                             error = 0;
        int                             i;
        int                             whichfork = XFS_DATA_FORK;
-       int                             logflags;
+       int                             logflags = 0;
        xfs_filblks_t                   blockcount = 0;
        int                             total_extents;
 
@@ -5478,16 +5478,11 @@ xfs_bmap_shift_extents(
                }
        }
 
-       /* We are going to change core inode */
-       logflags = XFS_ILOG_CORE;
        if (ifp->if_flags & XFS_IFBROOT) {
                cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
                cur->bc_private.b.firstblock = *firstblock;
                cur->bc_private.b.flist = flist;
                cur->bc_private.b.flags = 0;
-       } else {
-               cur = NULL;
-               logflags |= XFS_ILOG_DEXT;
        }
 
        /*
@@ -5545,11 +5540,14 @@ xfs_bmap_shift_extents(
                        blockcount = left.br_blockcount +
                                got.br_blockcount;
                        xfs_iext_remove(ip, *current_ext, 1, 0);
+                       logflags |= XFS_ILOG_CORE;
                        if (cur) {
                                error = xfs_btree_delete(cur, &i);
                                if (error)
                                        goto del_cursor;
                                XFS_WANT_CORRUPTED_GOTO(i == 1, del_cursor);
+                       } else {
+                               logflags |= XFS_ILOG_DEXT;
                        }
                        XFS_IFORK_NEXT_SET(ip, whichfork,
                                XFS_IFORK_NEXTENTS(ip, whichfork) - 1);
@@ -5575,6 +5573,7 @@ xfs_bmap_shift_extents(
                        got.br_startoff = startoff;
                }
 
+               logflags |= XFS_ILOG_CORE;
                if (cur) {
                        error = xfs_bmbt_update(cur, got.br_startoff,
                                                got.br_startblock,
@@ -5582,6 +5581,8 @@ xfs_bmap_shift_extents(
                                                got.br_state);
                        if (error)
                                goto del_cursor;
+               } else {
+                       logflags |= XFS_ILOG_DEXT;
                }
 
                (*current_ext)++;
@@ -5597,6 +5598,7 @@ del_cursor:
                xfs_btree_del_cursor(cur,
                        error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR);
 
-       xfs_trans_log_inode(tp, ip, logflags);
+       if (logflags)
+               xfs_trans_log_inode(tp, ip, logflags);
        return error;
 }
index 11e9b4caa54f168f7e429f5d7e5a01302d026e1c..b984647c24db02e98b4e030fd03c7bac75740923 100644 (file)
@@ -1753,11 +1753,72 @@ xfs_vm_readpages(
        return mpage_readpages(mapping, pages, nr_pages, xfs_get_blocks);
 }
 
+/*
+ * This is basically a copy of __set_page_dirty_buffers() with one
+ * small tweak: buffers beyond EOF do not get marked dirty. If we mark them
+ * dirty, we'll never be able to clean them because we don't write buffers
+ * beyond EOF, and that means we can't invalidate pages that span EOF
+ * that have been marked dirty. Further, the dirty state can leak into
+ * the file interior if the file is extended, resulting in all sorts of
+ * bad things happening as the state does not match the underlying data.
+ *
+ * XXX: this really indicates that bufferheads in XFS need to die. Warts like
+ * this only exist because of bufferheads and how the generic code manages them.
+ */
+STATIC int
+xfs_vm_set_page_dirty(
+       struct page             *page)
+{
+       struct address_space    *mapping = page->mapping;
+       struct inode            *inode = mapping->host;
+       loff_t                  end_offset;
+       loff_t                  offset;
+       int                     newly_dirty;
+
+       if (unlikely(!mapping))
+               return !TestSetPageDirty(page);
+
+       end_offset = i_size_read(inode);
+       offset = page_offset(page);
+
+       spin_lock(&mapping->private_lock);
+       if (page_has_buffers(page)) {
+               struct buffer_head *head = page_buffers(page);
+               struct buffer_head *bh = head;
+
+               do {
+                       if (offset < end_offset)
+                               set_buffer_dirty(bh);
+                       bh = bh->b_this_page;
+                       offset += 1 << inode->i_blkbits;
+               } while (bh != head);
+       }
+       newly_dirty = !TestSetPageDirty(page);
+       spin_unlock(&mapping->private_lock);
+
+       if (newly_dirty) {
+               /* sigh - __set_page_dirty() is static, so copy it here, too */
+               unsigned long flags;
+
+               spin_lock_irqsave(&mapping->tree_lock, flags);
+               if (page->mapping) {    /* Race with truncate? */
+                       WARN_ON_ONCE(!PageUptodate(page));
+                       account_page_dirtied(page, mapping);
+                       radix_tree_tag_set(&mapping->page_tree,
+                                       page_index(page), PAGECACHE_TAG_DIRTY);
+               }
+               spin_unlock_irqrestore(&mapping->tree_lock, flags);
+               __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
+       }
+       return newly_dirty;
+}
+
 const struct address_space_operations xfs_address_space_operations = {
        .readpage               = xfs_vm_readpage,
        .readpages              = xfs_vm_readpages,
        .writepage              = xfs_vm_writepage,
        .writepages             = xfs_vm_writepages,
+       .set_page_dirty         = xfs_vm_set_page_dirty,
        .releasepage            = xfs_vm_releasepage,
        .invalidatepage         = xfs_vm_invalidatepage,
        .write_begin            = xfs_vm_write_begin,
index 2f1e30d39a3540f9d545e8ab9c5afd52af0047a9..1707980f9a4b564842cd435d9efc70571a5a9b18 100644 (file)
@@ -1470,6 +1470,26 @@ xfs_collapse_file_space(
        start_fsb = XFS_B_TO_FSB(mp, offset + len);
        shift_fsb = XFS_B_TO_FSB(mp, len);
 
+       /*
+        * Writeback the entire file and force remove any post-eof blocks. The
+        * writeback prevents changes to the extent list via concurrent
+        * writeback and the eofblocks trim prevents the extent shift algorithm
+        * from running into a post-eof delalloc extent.
+        *
+        * XXX: This is a temporary fix until the extent shift loop below is
+        * converted to use offsets and lookups within the ILOCK rather than
+        * carrying around the index into the extent list for the next
+        * iteration.
+        */
+       error = filemap_write_and_wait(VFS_I(ip)->i_mapping);
+       if (error)
+               return error;
+       if (xfs_can_free_eofblocks(ip, true)) {
+               error = xfs_free_eofblocks(mp, ip, false);
+               if (error)
+                       return error;
+       }
+
        error = xfs_free_file_space(ip, offset, len);
        if (error)
                return error;
index 076b1708d1345474ec2fd4e3a4c2e3bc605cb75a..de5368c803f9db192416e21032ade4535a0efcdd 100644 (file)
@@ -291,12 +291,22 @@ xfs_file_read_iter(
                if (inode->i_mapping->nrpages) {
                        ret = filemap_write_and_wait_range(
                                                        VFS_I(ip)->i_mapping,
-                                                       pos, -1);
+                                                       pos, pos + size - 1);
                        if (ret) {
                                xfs_rw_iunlock(ip, XFS_IOLOCK_EXCL);
                                return ret;
                        }
-                       truncate_pagecache_range(VFS_I(ip), pos, -1);
+
+                       /*
+                        * Invalidate whole pages. This can return an error if
+                        * we fail to invalidate a page, but this should never
+                        * happen on XFS. Warn if it does fail.
+                        */
+                       ret = invalidate_inode_pages2_range(VFS_I(ip)->i_mapping,
+                                       pos >> PAGE_CACHE_SHIFT,
+                                       (pos + size - 1) >> PAGE_CACHE_SHIFT);
+                       WARN_ON_ONCE(ret);
+                       ret = 0;
                }
                xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL);
        }
@@ -632,10 +642,19 @@ xfs_file_dio_aio_write(
 
        if (mapping->nrpages) {
                ret = filemap_write_and_wait_range(VFS_I(ip)->i_mapping,
-                                                   pos, -1);
+                                                   pos, pos + count - 1);
                if (ret)
                        goto out;
-               truncate_pagecache_range(VFS_I(ip), pos, -1);
+               /*
+                * Invalidate whole pages. This can return an error if
+                * we fail to invalidate a page, but this should never
+                * happen on XFS. Warn if it does fail.
+                */
+               ret = invalidate_inode_pages2_range(VFS_I(ip)->i_mapping,
+                                       pos >> PAGE_CACHE_SHIFT,
+                                       (pos + count - 1) >> PAGE_CACHE_SHIFT);
+               WARN_ON_ONCE(ret);
+               ret = 0;
        }
 
        /*
index bcfd808b1098e81e410310e33582d814274188b8..c1c9de19edbe8abc62f2508bf9a7723bd9027d08 100644 (file)
@@ -246,7 +246,6 @@ struct acpi_device_pnp {
        acpi_device_name device_name;   /* Driver-determined */
        acpi_device_class device_class; /*        "          */
        union acpi_object *str_obj;     /* unicode string for _STR method */
-       unsigned long sun;              /* _SUN */
 };
 
 #define acpi_device_bid(d)     ((d)->pnp.bus_id)
index eb726b9c57627f2e978751a9fe61fa910a2740f7..a1e31f274fcd55f7cfff245c8516d8e263206fb0 100644 (file)
@@ -127,10 +127,9 @@ enum {
        BLK_MQ_RQ_QUEUE_ERROR   = 2,    /* end IO with error */
 
        BLK_MQ_F_SHOULD_MERGE   = 1 << 0,
-       BLK_MQ_F_SHOULD_SORT    = 1 << 1,
-       BLK_MQ_F_TAG_SHARED     = 1 << 2,
-       BLK_MQ_F_SG_MERGE       = 1 << 3,
-       BLK_MQ_F_SYSFS_UP       = 1 << 4,
+       BLK_MQ_F_TAG_SHARED     = 1 << 1,
+       BLK_MQ_F_SG_MERGE       = 1 << 2,
+       BLK_MQ_F_SYSFS_UP       = 1 << 3,
 
        BLK_MQ_S_STOPPED        = 0,
        BLK_MQ_S_TAG_ACTIVE     = 1,
index 6ff0b0b42d47d7d6f719a3c2f5f6b5f5f2e16167..08ed2b0a96e6aef0ada70da633322f36a8acfe7e 100644 (file)
@@ -24,6 +24,9 @@
 #define NULL_ADDR              ((block_t)0)    /* used as block_t addresses */
 #define NEW_ADDR               ((block_t)-1)   /* used as block_t addresses */
 
+/* 0, 1(node nid), 2(meta nid) are reserved node id */
+#define F2FS_RESERVED_NODE_NUM         3
+
 #define F2FS_ROOT_INO(sbi)     (sbi->root_ino_num)
 #define F2FS_NODE_INO(sbi)     (sbi->node_ino_num)
 #define F2FS_META_INO(sbi)     (sbi->meta_ino_num)
@@ -87,6 +90,8 @@ struct f2fs_super_block {
 #define CP_ORPHAN_PRESENT_FLAG 0x00000002
 #define CP_UMOUNT_FLAG         0x00000001
 
+#define F2FS_CP_PACKS          2       /* # of checkpoint packs */
+
 struct f2fs_checkpoint {
        __le64 checkpoint_ver;          /* checkpoint block version number */
        __le64 user_block_count;        /* # of user blocks */
@@ -123,6 +128,9 @@ struct f2fs_checkpoint {
  */
 #define F2FS_ORPHANS_PER_BLOCK 1020
 
+#define GET_ORPHAN_BLOCKS(n)   ((n + F2FS_ORPHANS_PER_BLOCK - 1) / \
+                                       F2FS_ORPHANS_PER_BLOCK)
+
 struct f2fs_orphan_block {
        __le32 ino[F2FS_ORPHANS_PER_BLOCK];     /* inode numbers */
        __le32 reserved;        /* reserved */
@@ -144,6 +152,7 @@ struct f2fs_extent {
 #define F2FS_NAME_LEN          255
 #define F2FS_INLINE_XATTR_ADDRS        50      /* 200 bytes for inline xattrs */
 #define DEF_ADDRS_PER_INODE    923     /* Address Pointers in an Inode */
+#define DEF_NIDS_PER_INODE     5       /* Node IDs in an Inode */
 #define ADDRS_PER_INODE(fi)    addrs_per_inode(fi)
 #define ADDRS_PER_BLOCK                1018    /* Address Pointers in a Direct Block */
 #define NIDS_PER_BLOCK         1018    /* Node IDs in an Indirect Block */
@@ -163,8 +172,9 @@ struct f2fs_extent {
 #define MAX_INLINE_DATA                (sizeof(__le32) * (DEF_ADDRS_PER_INODE - \
                                                F2FS_INLINE_XATTR_ADDRS - 1))
 
-#define INLINE_DATA_OFFSET     (PAGE_CACHE_SIZE - sizeof(struct node_footer) \
-                       - sizeof(__le32) * (DEF_ADDRS_PER_INODE + 5 - 1))
+#define INLINE_DATA_OFFSET     (PAGE_CACHE_SIZE - sizeof(struct node_footer) -\
+                               sizeof(__le32) * (DEF_ADDRS_PER_INODE + \
+                               DEF_NIDS_PER_INODE - 1))
 
 struct f2fs_inode {
        __le16 i_mode;                  /* file mode */
@@ -194,7 +204,7 @@ struct f2fs_inode {
 
        __le32 i_addr[DEF_ADDRS_PER_INODE];     /* Pointers to data blocks */
 
-       __le32 i_nid[5];                /* direct(2), indirect(2),
+       __le32 i_nid[DEF_NIDS_PER_INODE];       /* direct(2), indirect(2),
                                                double_indirect(1) node id */
 } __packed;
 
index c7e17de732f3eb6b4f221bb16b6a9753a9d3a85d..12f146fa660434731df9ed2d8c2f6929dcc46217 100644 (file)
@@ -38,60 +38,32 @@ enum gpiod_flags {
 struct gpio_desc *__must_check __gpiod_get(struct device *dev,
                                         const char *con_id,
                                         enum gpiod_flags flags);
-#define __gpiod_get(dev, con_id, flags, ...) __gpiod_get(dev, con_id, flags)
-#define gpiod_get(varargs...) __gpiod_get(varargs, 0)
 struct gpio_desc *__must_check __gpiod_get_index(struct device *dev,
                                               const char *con_id,
                                               unsigned int idx,
                                               enum gpiod_flags flags);
-#define __gpiod_get_index(dev, con_id, index, flags, ...)              \
-       __gpiod_get_index(dev, con_id, index, flags)
-#define gpiod_get_index(varargs...) __gpiod_get_index(varargs, 0)
 struct gpio_desc *__must_check __gpiod_get_optional(struct device *dev,
                                                  const char *con_id,
                                                  enum gpiod_flags flags);
-#define __gpiod_get_optional(dev, con_id, flags, ...)                  \
-       __gpiod_get_optional(dev, con_id, flags)
-#define gpiod_get_optional(varargs...) __gpiod_get_optional(varargs, 0)
 struct gpio_desc *__must_check __gpiod_get_index_optional(struct device *dev,
                                                        const char *con_id,
                                                        unsigned int index,
                                                        enum gpiod_flags flags);
-#define __gpiod_get_index_optional(dev, con_id, index, flags, ...)     \
-       __gpiod_get_index_optional(dev, con_id, index, flags)
-#define gpiod_get_index_optional(varargs...)                           \
-       __gpiod_get_index_optional(varargs, 0)
-
 void gpiod_put(struct gpio_desc *desc);
 
 struct gpio_desc *__must_check __devm_gpiod_get(struct device *dev,
                                              const char *con_id,
                                              enum gpiod_flags flags);
-#define __devm_gpiod_get(dev, con_id, flags, ...)                      \
-       __devm_gpiod_get(dev, con_id, flags)
-#define devm_gpiod_get(varargs...) __devm_gpiod_get(varargs, 0)
 struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev,
                                                    const char *con_id,
                                                    unsigned int idx,
                                                    enum gpiod_flags flags);
-#define __devm_gpiod_get_index(dev, con_id, index, flags, ...)         \
-       __devm_gpiod_get_index(dev, con_id, index, flags)
-#define devm_gpiod_get_index(varargs...) __devm_gpiod_get_index(varargs, 0)
 struct gpio_desc *__must_check __devm_gpiod_get_optional(struct device *dev,
                                                       const char *con_id,
                                                       enum gpiod_flags flags);
-#define __devm_gpiod_get_optional(dev, con_id, flags, ...)             \
-       __devm_gpiod_get_optional(dev, con_id, flags)
-#define devm_gpiod_get_optional(varargs...)                            \
-       __devm_gpiod_get_optional(varargs, 0)
 struct gpio_desc *__must_check
 __devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
                              unsigned int index, enum gpiod_flags flags);
-#define __devm_gpiod_get_index_optional(dev, con_id, index, flags, ...)        \
-       __devm_gpiod_get_index_optional(dev, con_id, index, flags)
-#define devm_gpiod_get_index_optional(varargs...)                      \
-       __devm_gpiod_get_index_optional(varargs, 0)
-
 void devm_gpiod_put(struct device *dev, struct gpio_desc *desc);
 
 int gpiod_get_direction(const struct gpio_desc *desc);
@@ -124,27 +96,31 @@ int desc_to_gpio(const struct gpio_desc *desc);
 
 #else /* CONFIG_GPIOLIB */
 
-static inline struct gpio_desc *__must_check gpiod_get(struct device *dev,
-                                                      const char *con_id)
+static inline struct gpio_desc *__must_check __gpiod_get(struct device *dev,
+                                               const char *con_id,
+                                               enum gpiod_flags flags)
 {
        return ERR_PTR(-ENOSYS);
 }
-static inline struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
-                                                            const char *con_id,
-                                                            unsigned int idx)
+static inline struct gpio_desc *__must_check
+__gpiod_get_index(struct device *dev,
+                 const char *con_id,
+                 unsigned int idx,
+                 enum gpiod_flags flags)
 {
        return ERR_PTR(-ENOSYS);
 }
 
 static inline struct gpio_desc *__must_check
-gpiod_get_optional(struct device *dev, const char *con_id)
+__gpiod_get_optional(struct device *dev, const char *con_id,
+                    enum gpiod_flags flags)
 {
        return ERR_PTR(-ENOSYS);
 }
 
 static inline struct gpio_desc *__must_check
-gpiod_get_index_optional(struct device *dev, const char *con_id,
-                        unsigned int index)
+__gpiod_get_index_optional(struct device *dev, const char *con_id,
+                          unsigned int index, enum gpiod_flags flags)
 {
        return ERR_PTR(-ENOSYS);
 }
@@ -157,28 +133,33 @@ static inline void gpiod_put(struct gpio_desc *desc)
        WARN_ON(1);
 }
 
-static inline struct gpio_desc *__must_check devm_gpiod_get(struct device *dev,
-                                                           const char *con_id)
+static inline struct gpio_desc *__must_check
+__devm_gpiod_get(struct device *dev,
+                const char *con_id,
+                enum gpiod_flags flags)
 {
        return ERR_PTR(-ENOSYS);
 }
 static inline
-struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
-                                                   const char *con_id,
-                                                   unsigned int idx)
+struct gpio_desc *__must_check
+__devm_gpiod_get_index(struct device *dev,
+                      const char *con_id,
+                      unsigned int idx,
+                      enum gpiod_flags flags)
 {
        return ERR_PTR(-ENOSYS);
 }
 
 static inline struct gpio_desc *__must_check
-devm_gpiod_get_optional(struct device *dev, const char *con_id)
+__devm_gpiod_get_optional(struct device *dev, const char *con_id,
+                         enum gpiod_flags flags)
 {
        return ERR_PTR(-ENOSYS);
 }
 
 static inline struct gpio_desc *__must_check
-devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
-                             unsigned int index)
+__devm_gpiod_get_index_optional(struct device *dev, const char *con_id,
+                               unsigned int index, enum gpiod_flags flags)
 {
        return ERR_PTR(-ENOSYS);
 }
@@ -303,9 +284,43 @@ static inline int desc_to_gpio(const struct gpio_desc *desc)
        return -EINVAL;
 }
 
-
 #endif /* CONFIG_GPIOLIB */
 
+/*
+ * Vararg-hacks! This is done to transition the kernel to always pass
+ * the options flags argument to the below functions. During a transition
+ * phase these vararg macros make both old-and-newstyle code compile,
+ * but when all calls to the elder API are removed, these should go away
+ * and the __gpiod_get() etc functions above be renamed just gpiod_get()
+ * etc.
+ */
+#define __gpiod_get(dev, con_id, flags, ...) __gpiod_get(dev, con_id, flags)
+#define gpiod_get(varargs...) __gpiod_get(varargs, 0)
+#define __gpiod_get_index(dev, con_id, index, flags, ...)              \
+       __gpiod_get_index(dev, con_id, index, flags)
+#define gpiod_get_index(varargs...) __gpiod_get_index(varargs, 0)
+#define __gpiod_get_optional(dev, con_id, flags, ...)                  \
+       __gpiod_get_optional(dev, con_id, flags)
+#define gpiod_get_optional(varargs...) __gpiod_get_optional(varargs, 0)
+#define __gpiod_get_index_optional(dev, con_id, index, flags, ...)     \
+       __gpiod_get_index_optional(dev, con_id, index, flags)
+#define gpiod_get_index_optional(varargs...)                           \
+       __gpiod_get_index_optional(varargs, 0)
+#define __devm_gpiod_get(dev, con_id, flags, ...)                      \
+       __devm_gpiod_get(dev, con_id, flags)
+#define devm_gpiod_get(varargs...) __devm_gpiod_get(varargs, 0)
+#define __devm_gpiod_get_index(dev, con_id, index, flags, ...)         \
+       __devm_gpiod_get_index(dev, con_id, index, flags)
+#define devm_gpiod_get_index(varargs...) __devm_gpiod_get_index(varargs, 0)
+#define __devm_gpiod_get_optional(dev, con_id, flags, ...)             \
+       __devm_gpiod_get_optional(dev, con_id, flags)
+#define devm_gpiod_get_optional(varargs...)                            \
+       __devm_gpiod_get_optional(varargs, 0)
+#define __devm_gpiod_get_index_optional(dev, con_id, index, flags, ...)        \
+       __devm_gpiod_get_index_optional(dev, con_id, index, flags)
+#define devm_gpiod_get_index_optional(varargs...)                      \
+       __devm_gpiod_get_index_optional(varargs, 0)
+
 #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS)
 
 int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
index d5b50a19463c0c1a43eaed5fb8dff41789f8f472..0dae71e9971c434cef33c13572dbd13018f3604e 100644 (file)
@@ -159,7 +159,11 @@ typedef struct journal_header_s
  * journal_block_tag (in the descriptor).  The other h_chksum* fields are
  * not used.
  *
- * Checksum v1 and v2 are mutually exclusive features.
+ * If FEATURE_INCOMPAT_CSUM_V3 is set, the descriptor block uses
+ * journal_block_tag3_t to store a full 32-bit checksum.  Everything else
+ * is the same as v2.
+ *
+ * Checksum v1, v2, and v3 are mutually exclusive features.
  */
 struct commit_header {
        __be32          h_magic;
@@ -179,6 +183,14 @@ struct commit_header {
  * raw struct shouldn't be used for pointer math or sizeof() - use
  * journal_tag_bytes(journal) instead to compute this.
  */
+typedef struct journal_block_tag3_s
+{
+       __be32          t_blocknr;      /* The on-disk block number */
+       __be32          t_flags;        /* See below */
+       __be32          t_blocknr_high; /* most-significant high 32bits. */
+       __be32          t_checksum;     /* crc32c(uuid+seq+block) */
+} journal_block_tag3_t;
+
 typedef struct journal_block_tag_s
 {
        __be32          t_blocknr;      /* The on-disk block number */
@@ -187,9 +199,6 @@ typedef struct journal_block_tag_s
        __be32          t_blocknr_high; /* most-significant high 32bits. */
 } journal_block_tag_t;
 
-#define JBD2_TAG_SIZE32 (offsetof(journal_block_tag_t, t_blocknr_high))
-#define JBD2_TAG_SIZE64 (sizeof(journal_block_tag_t))
-
 /* Tail of descriptor block, for checksumming */
 struct jbd2_journal_block_tail {
        __be32          t_checksum;     /* crc32c(uuid+descr_block) */
@@ -284,6 +293,7 @@ typedef struct journal_superblock_s
 #define JBD2_FEATURE_INCOMPAT_64BIT            0x00000002
 #define JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT     0x00000004
 #define JBD2_FEATURE_INCOMPAT_CSUM_V2          0x00000008
+#define JBD2_FEATURE_INCOMPAT_CSUM_V3          0x00000010
 
 /* Features known to this kernel version: */
 #define JBD2_KNOWN_COMPAT_FEATURES     JBD2_FEATURE_COMPAT_CHECKSUM
@@ -291,7 +301,8 @@ typedef struct journal_superblock_s
 #define JBD2_KNOWN_INCOMPAT_FEATURES   (JBD2_FEATURE_INCOMPAT_REVOKE | \
                                        JBD2_FEATURE_INCOMPAT_64BIT | \
                                        JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT | \
-                                       JBD2_FEATURE_INCOMPAT_CSUM_V2)
+                                       JBD2_FEATURE_INCOMPAT_CSUM_V2 | \
+                                       JBD2_FEATURE_INCOMPAT_CSUM_V3)
 
 #ifdef __KERNEL__
 
@@ -1296,6 +1307,15 @@ static inline int tid_geq(tid_t x, tid_t y)
 extern int jbd2_journal_blocks_per_page(struct inode *inode);
 extern size_t journal_tag_bytes(journal_t *journal);
 
+static inline int jbd2_journal_has_csum_v2or3(journal_t *journal)
+{
+       if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V2) ||
+           JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_CSUM_V3))
+               return 1;
+
+       return 0;
+}
+
 /*
  * We reserve t_outstanding_credits >> JBD2_CONTROL_BLOCKS_SHIFT for
  * transaction control blocks.
index 6a599dce7f9d4678e4f6f7f082514308f0636942..e436864721971c81383a323bf3951e19632475a0 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/rwsem.h>
+#include <linux/timer.h>
 #include <linux/workqueue.h>
 
 struct device;
@@ -68,7 +69,7 @@ struct led_classdev {
        const char              *default_trigger;       /* Trigger to use */
 
        unsigned long            blink_delay_on, blink_delay_off;
-       struct delayed_work      blink_work;
+       struct timer_list        blink_timer;
        int                      blink_brightness;
 
        struct work_struct      set_brightness_work;
index 071f6b234604cf770ebfab55e1ec61392e364a83..511c6e0d21a9ab0045c9dd8b2dc7f9c488730279 100644 (file)
@@ -1196,6 +1196,9 @@ int mlx4_map_sw_to_hw_steering_id(struct mlx4_dev *dev,
                                  enum mlx4_net_trans_rule_id id);
 int mlx4_hw_rule_sz(struct mlx4_dev *dev, enum mlx4_net_trans_rule_id id);
 
+int mlx4_tunnel_steer_add(struct mlx4_dev *dev, unsigned char *addr,
+                         int port, int qpn, u16 prio, u64 *reg_id);
+
 void mlx4_sync_pkey_table(struct mlx4_dev *dev, int slave, int port,
                          int i, int val);
 
index 3083c53e027049196f8f18561cd1d13f51b72a07..c300db3ae2852b88321c618daeb10bdc4eb5b21b 100644 (file)
@@ -949,7 +949,7 @@ static inline int jedec_feature(struct nand_chip *chip)
                : 0;
 }
 
-/**
+/*
  * struct nand_sdr_timings - SDR NAND chip timings
  *
  * This struct defines the timing requirements of a SDR NAND chip.
index 38377392d08261291ceb1fcd177718484e05581c..c8e388e5fcccfa604d087ce33ccee5ace528e598 100644 (file)
@@ -3176,7 +3176,7 @@ static inline int __dev_uc_sync(struct net_device *dev,
 }
 
 /**
- *  __dev_uc_unsync - Remove synchonized addresses from device
+ *  __dev_uc_unsync - Remove synchronized addresses from device
  *  @dev:  device to sync
  *  @unsync: function to call if address should be removed
  *
@@ -3220,7 +3220,7 @@ static inline int __dev_mc_sync(struct net_device *dev,
 }
 
 /**
- *  __dev_mc_unsync - Remove synchonized addresses from device
+ *  __dev_mc_unsync - Remove synchronized addresses from device
  *  @dev:  device to sync
  *  @unsync: function to call if address should be removed
  *
index 2077489f98873bcbe4ca083cd1f0eb1b99eeab5e..2517ece988209a611b324a0bb8ade2b566eeb645 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/in6.h>
 #include <linux/wait.h>
 #include <linux/list.h>
+#include <linux/static_key.h>
 #include <uapi/linux/netfilter.h>
 #ifdef CONFIG_NETFILTER
 static inline int NF_DROP_GETERR(int verdict)
@@ -99,9 +100,9 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg);
 
 extern struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
 
-#if defined(CONFIG_JUMP_LABEL)
-#include <linux/static_key.h>
+#ifdef HAVE_JUMP_LABEL
 extern struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
+
 static inline bool nf_hooks_active(u_int8_t pf, unsigned int hook)
 {
        if (__builtin_constant_p(pf) &&
index 660c029d694fce72c7f3b8d53c7703d21c85f54a..16ec262dfcc804a567910dad83bb3edbe72bdc74 100644 (file)
@@ -21,8 +21,17 @@ enum nand_io {
 };
 
 enum omap_ecc {
-       /* 1-bit  ECC calculation by GPMC, Error detection by Software */
-       OMAP_ECC_HAM1_CODE_HW = 0,
+       /*
+        * 1-bit ECC: calculation and correction by SW
+        * ECC stored at end of spare area
+        */
+       OMAP_ECC_HAM1_CODE_SW = 0,
+
+       /*
+        * 1-bit ECC: calculation by GPMC, Error detection by Software
+        * ECC layout compatible with ROM code layout
+        */
+       OMAP_ECC_HAM1_CODE_HW,
        /* 4-bit  ECC calculation by GPMC, Error detection by Software */
        OMAP_ECC_BCH4_CODE_HW_DETECTION_SW,
        /* 4-bit  ECC calculation by GPMC, Error detection by ELM */
index 7c1d252b20c08de0ec725976c67b6fc13326e2e0..ebc4c76ffb737bae3d9be1a6325752745254eaed 100644 (file)
@@ -60,7 +60,7 @@ struct generic_pm_domain {
        struct mutex lock;
        struct dev_power_governor *gov;
        struct work_struct power_off_work;
-       char *name;
+       const char *name;
        unsigned int in_progress;       /* Number of devices being suspended now */
        atomic_t sd_count;      /* Number of subdomains with power "on" */
        enum gpd_status status; /* Current state of the domain */
index bbe03a1924c04182be79d128854557ebb262b6e3..4efa1ed8a2b0b92ebdd7160948e45b79b0e19fdf 100644 (file)
@@ -218,6 +218,8 @@ enum regulator_type {
  * @linear_min_sel: Minimal selector for starting linear mapping
  * @fixed_uV: Fixed voltage of rails.
  * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
+ * @linear_ranges: A constant table of possible voltage ranges.
+ * @n_linear_ranges: Number of entries in the @linear_ranges table.
  * @volt_table: Voltage mapping table (if table based mapping)
  *
  * @vsel_reg: Register for selector when using regulator_regmap_X_voltage_
index 730e638c55899ba9bfff37a045386af5ee0f5cfe..0b08d05d470b56cacec467d5368810517d4a1752 100644 (file)
@@ -85,6 +85,7 @@ struct regulator_state {
  *           bootloader then it will be enabled when the constraints are
  *           applied.
  * @apply_uV: Apply the voltage constraint when initialising.
+ * @ramp_disable: Disable ramp delay when initialising or when setting voltage.
  *
  * @input_uV: Input voltage for regulator when supplied by another regulator.
  *
index 3d6003de4b0d4e4d367231cf3ee457cf612bf5aa..a1ba6a5ccdd62c2275eb63106d2fc9d78e4cee3c 100644 (file)
@@ -62,6 +62,7 @@ to_seqno_fence(struct fence *fence)
  * @context: the execution context this fence is a part of
  * @seqno_ofs: the offset within @sync_buf
  * @seqno: the sequence # to signal on
+ * @cond: fence wait condition
  * @ops: the fence_ops for operations on this seqno fence
  *
  * This function initializes a struct seqno_fence with passed parameters,
index e713543336f12a972e3eaa200f9c73a42920ba97..46d188a9947c6401bfa91f7f32802c8d4707c025 100644 (file)
@@ -253,6 +253,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  *     the device whose settings are being modified.
  * @transfer: adds a message to the controller's transfer queue.
  * @cleanup: frees controller-specific state
+ * @can_dma: determine whether this master supports DMA
  * @queued: whether this master is providing an internal message queue
  * @kworker: thread struct for message pump
  * @kworker_task: pointer to task for message pump kworker thread
@@ -262,6 +263,7 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  * @cur_msg: the currently in-flight message
  * @cur_msg_prepared: spi_prepare_message was called for the currently
  *                    in-flight message
+ * @cur_msg_mapped: message has been mapped for DMA
  * @xfer_completion: used by core transfer_one_message()
  * @busy: message pump is busy
  * @running: message pump is running
@@ -299,6 +301,10 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv)
  * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS
  *     number. Any individual value may be -ENOENT for CS lines that
  *     are not GPIOs (driven by the SPI controller itself).
+ * @dma_tx: DMA transmit channel
+ * @dma_rx: DMA receive channel
+ * @dummy_rx: dummy receive buffer for full-duplex devices
+ * @dummy_tx: dummy transmit buffer for full-duplex devices
  *
  * Each SPI master controller can communicate with one or more @spi_device
  * children.  These make a small bus, sharing MOSI, MISO and SCK signals
@@ -632,6 +638,7 @@ struct spi_transfer {
  *     addresses for each transfer buffer
  * @complete: called to report transaction completions
  * @context: the argument to complete() when it's called
+ * @frame_length: the total number of bytes in the message
  * @actual_length: the total number of bytes that were transferred in all
  *     successful segments
  * @status: zero for success, else negative errno
index 059052306831496d88de2f143930a32593b8ac79..9a82c7dc3fdd9f1fd35d62fb2ab0734516c9ad6c 100644 (file)
@@ -183,13 +183,8 @@ static inline bool tick_nohz_full_cpu(int cpu)
 
 extern void tick_nohz_init(void);
 extern void __tick_nohz_full_check(void);
+extern void tick_nohz_full_kick(void);
 extern void tick_nohz_full_kick_cpu(int cpu);
-
-static inline void tick_nohz_full_kick(void)
-{
-       tick_nohz_full_kick_cpu(smp_processor_id());
-}
-
 extern void tick_nohz_full_kick_all(void);
 extern void __tick_nohz_task_switch(struct task_struct *tsk);
 #else
index b5d5af3aa469961af36b30b0aea2da1d4e959bac..6f884e6c731e41daccdf4119cb1f0f8a4ee9335f 100644 (file)
@@ -464,6 +464,8 @@ struct hci_conn_params {
                HCI_AUTO_CONN_ALWAYS,
                HCI_AUTO_CONN_LINK_LOSS,
        } auto_connect;
+
+       struct hci_conn *conn;
 };
 
 extern struct list_head hci_dev_list;
index e2070960bac009223c1c6caa1324d6323a478a7d..8170f8d7052b21f5b8e82d8cb7c1c52a56042378 100644 (file)
@@ -16,7 +16,6 @@ struct netns_sysctl_lowpan {
 struct netns_ieee802154_lowpan {
        struct netns_sysctl_lowpan sysctl;
        struct netns_frags      frags;
-       int                     max_dsize;
 };
 
 #endif
index 259992444e80ae0b88eaec4ff345d23fd8f81c75..dad7ab20a8cb204f08b2ecda724d5c1db5138ec8 100644 (file)
@@ -167,7 +167,7 @@ struct ieee80211_reg_rule {
 struct ieee80211_regdomain {
        struct rcu_head rcu_head;
        u32 n_reg_rules;
-       char alpha2[2];
+       char alpha2[3];
        enum nl80211_dfs_regions dfs_region;
        struct ieee80211_reg_rule reg_rules[];
 };
index f6e7397e799dbd9dd1007c8f4e494c4b3405d28e..9fbd856e67139f9525b2951b147ed6f9223f7540 100644 (file)
@@ -320,6 +320,19 @@ static inline sctp_assoc_t sctp_assoc2id(const struct sctp_association *asoc)
        return asoc ? asoc->assoc_id : 0;
 }
 
+static inline enum sctp_sstat_state
+sctp_assoc_to_state(const struct sctp_association *asoc)
+{
+       /* SCTP's uapi always had SCTP_EMPTY(=0) as a dummy state, but we
+        * got rid of it in kernel space. Therefore SCTP_CLOSED et al
+        * start at =1 in user space, but actually as =0 in kernel space.
+        * Now that we can not break user space and SCTP_EMPTY is exposed
+        * there, we need to fix it up with an ugly offset not to break
+        * applications. :(
+        */
+       return asoc->state + 1;
+}
+
 /* Look up the association by its id.  */
 struct sctp_association *sctp_id2assoc(struct sock *sk, sctp_assoc_t id);
 
index 7f2ab72f321a4bd437800ab551a5aff3a9eab44a..b9a5bd0ed9f3a6b7bc0d087b2b2ae5563b4a0304 100644 (file)
@@ -2165,9 +2165,7 @@ sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
         */
        if (sock_flag(sk, SOCK_RCVTSTAMP) ||
            (sk->sk_tsflags & SOF_TIMESTAMPING_RX_SOFTWARE) ||
-           (kt.tv64 &&
-            (sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE ||
-             skb_shinfo(skb)->tx_flags & SKBTX_ANY_SW_TSTAMP)) ||
+           (kt.tv64 && sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) ||
            (hwtstamps->hwtstamp.tv64 &&
             (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE)))
                __sock_recv_timestamp(msg, sk, skb);
index e52ef5357e088b568e958de0d8545953ab90cef5..c52b68577cb0edc0d00732cc67441a4ac30595be 100644 (file)
@@ -290,7 +290,7 @@ struct wimax_dev;
  *     This operation has to be synchronous, and return only when the
  *     reset is complete. In case of having had to resort to bus/cold
  *     reset implying a device disconnection, the call is allowed to
- *     return inmediately.
+ *     return immediately.
  *     NOTE: wimax_dev->mutex is NOT locked when this op is being
  *     called; however, wimax_dev->mutex_reset IS locked to ensure
  *     serialization of calls to wimax_reset().
index be6ecae247b0c608df5aa2554079d6bc4efca482..c83a334dd00fa9186404917183115fca3124670c 100644 (file)
        .access = SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE | \
                  SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \
        .tlv.c = (snd_soc_bytes_tlv_callback), \
-       .info = snd_soc_info_bytes_ext, \
+       .info = snd_soc_bytes_info_ext, \
        .private_value = (unsigned long)&(struct soc_bytes_ext) \
                {.max = xcount, .get = xhandler_get, .put = xhandler_put, } }
 #define SOC_SINGLE_XR_SX(xname, xregbase, xregcount, xnbits, \
index 1c09820df58564f8d0430d996998edc6f8d893c0..3608bebd3d9c5e58a0349c6240a8670bd3d8bbfb 100644 (file)
@@ -107,7 +107,7 @@ DECLARE_EVENT_CLASS(softirq,
  * @vec_nr:  softirq vector number
  *
  * When used in combination with the softirq_exit tracepoint
- * we can determine the softirq handler runtine.
+ * we can determine the softirq handler routine.
  */
 DEFINE_EVENT(softirq, softirq_entry,
 
@@ -121,7 +121,7 @@ DEFINE_EVENT(softirq, softirq_entry,
  * @vec_nr:  softirq vector number
  *
  * When used in combination with the softirq_entry tracepoint
- * we can determine the softirq handler runtine.
+ * we can determine the softirq handler routine.
  */
 DEFINE_EVENT(softirq, softirq_exit,
 
index 24e9033f8b3f9f10fde3467b9122d59c9621edcd..be88166349a128ca80e521ee2cef80ca8617a702 100644 (file)
@@ -240,6 +240,7 @@ header-y += matroxfb.h
 header-y += mdio.h
 header-y += media.h
 header-y += mei.h
+header-y += memfd.h
 header-y += mempolicy.h
 header-y += meye.h
 header-y += mic_common.h
@@ -395,6 +396,7 @@ header-y += un.h
 header-y += unistd.h
 header-y += unix_diag.h
 header-y += usbdevice_fs.h
+header-y += usbip.h
 header-y += utime.h
 header-y += utsname.h
 header-y += uuid.h
index 19df18c9b8be371ec5d13fc09f69fc33f2ff7769..1874ebe9ac1e505b0215a90f03a9b2ce57f6b2ff 100644 (file)
@@ -165,6 +165,7 @@ struct input_keymap_entry {
 #define INPUT_PROP_BUTTONPAD           0x02    /* has button(s) under pad */
 #define INPUT_PROP_SEMI_MT             0x03    /* touch rectangle only */
 #define INPUT_PROP_TOPBUTTONPAD                0x04    /* softbuttons at top of pad */
+#define INPUT_PROP_POINTING_STICK      0x05    /* is a pointing stick */
 
 #define INPUT_PROP_MAX                 0x1f
 #define INPUT_PROP_CNT                 (INPUT_PROP_MAX + 1)
diff --git a/include/uapi/linux/usbip.h b/include/uapi/linux/usbip.h
new file mode 100644 (file)
index 0000000..fa5db30
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ *     usbip.h
+ *
+ *     USBIP uapi defines and function prototypes etc.
+*/
+
+#ifndef _UAPI_LINUX_USBIP_H
+#define _UAPI_LINUX_USBIP_H
+
+/* usbip device status - exported in usbip device sysfs status */
+enum usbip_device_status {
+       /* sdev is available. */
+       SDEV_ST_AVAILABLE = 0x01,
+       /* sdev is now used. */
+       SDEV_ST_USED,
+       /* sdev is unusable because of a fatal error. */
+       SDEV_ST_ERROR,
+
+       /* vdev does not connect a remote device. */
+       VDEV_ST_NULL,
+       /* vdev is used, but the USB address is not assigned yet */
+       VDEV_ST_NOTASSIGNED,
+       VDEV_ST_USED,
+       VDEV_ST_ERROR
+};
+#endif /* _UAPI_LINUX_USBIP_H */
index c38355c1f3c9109b7d989dd1ae56ed4d06c51238..1590c49cae572f66a7172c9985b2e4d5e493a8db 100644 (file)
@@ -13,7 +13,7 @@
 #ifndef _UAPI_LINUX_XATTR_H
 #define _UAPI_LINUX_XATTR_H
 
-#ifdef __UAPI_DEF_XATTR
+#if __UAPI_DEF_XATTR
 #define __USE_KERNEL_XATTR_DEFS
 
 #define XATTR_CREATE   0x1     /* set value, fail if attr already exists */
index 131a6ccdba25693e6899b7813d99a6934e846ce4..14334d0161d5db26746af589920d10757209a5fb 100644 (file)
@@ -53,6 +53,9 @@
 /* operation as Dom0 is supported */
 #define XENFEAT_dom0                      11
 
+/* Xen also maps grant references at pfn = mfn */
+#define XENFEAT_grant_map_identity        12
+
 #define XENFEAT_NR_SUBMAPS 1
 
 #endif /* __XEN_PUBLIC_FEATURES_H__ */
index 7dc8788cfd52dd222856057840a8d0a45a19816e..940aced4ed00ca5c1de330c6609c78f6a7c5b3c2 100644 (file)
@@ -1035,6 +1035,11 @@ static void cgroup_get(struct cgroup *cgrp)
        css_get(&cgrp->self);
 }
 
+static bool cgroup_tryget(struct cgroup *cgrp)
+{
+       return css_tryget(&cgrp->self);
+}
+
 static void cgroup_put(struct cgroup *cgrp)
 {
        css_put(&cgrp->self);
@@ -1147,7 +1152,8 @@ static struct cgroup *cgroup_kn_lock_live(struct kernfs_node *kn)
         * protection against removal.  Ensure @cgrp stays accessible and
         * break the active_ref protection.
         */
-       cgroup_get(cgrp);
+       if (!cgroup_tryget(cgrp))
+               return NULL;
        kernfs_break_active_protection(kn);
 
        mutex_lock(&cgroup_mutex);
@@ -3271,8 +3277,17 @@ int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
 {
        struct cftype *cft;
 
-       for (cft = cfts; cft && cft->name[0] != '\0'; cft++)
-               cft->flags |= __CFTYPE_NOT_ON_DFL;
+       /*
+        * If legacy_flies_on_dfl, we want to show the legacy files on the
+        * dfl hierarchy but iff the target subsystem hasn't been updated
+        * for the dfl hierarchy yet.
+        */
+       if (!cgroup_legacy_files_on_dfl ||
+           ss->dfl_cftypes != ss->legacy_cftypes) {
+               for (cft = cfts; cft && cft->name[0] != '\0'; cft++)
+                       cft->flags |= __CFTYPE_NOT_ON_DFL;
+       }
+
        return cgroup_add_cftypes(ss, cfts);
 }
 
@@ -4387,6 +4402,15 @@ static void css_release_work_fn(struct work_struct *work)
                /* cgroup release path */
                cgroup_idr_remove(&cgrp->root->cgroup_idr, cgrp->id);
                cgrp->id = -1;
+
+               /*
+                * There are two control paths which try to determine
+                * cgroup from dentry without going through kernfs -
+                * cgroupstats_build() and css_tryget_online_from_dir().
+                * Those are supported by RCU protecting clearing of
+                * cgrp->kn->priv backpointer.
+                */
+               RCU_INIT_POINTER(*(void __rcu __force **)&cgrp->kn->priv, NULL);
        }
 
        mutex_unlock(&cgroup_mutex);
@@ -4543,6 +4567,11 @@ static int cgroup_mkdir(struct kernfs_node *parent_kn, const char *name,
        struct cftype *base_files;
        int ssid, ret;
 
+       /* Do not accept '\n' to prevent making /proc/<pid>/cgroup unparsable.
+        */
+       if (strchr(name, '\n'))
+               return -EINVAL;
+
        parent = cgroup_kn_lock_live(parent_kn);
        if (!parent)
                return -ENODEV;
@@ -4820,16 +4849,6 @@ static int cgroup_rmdir(struct kernfs_node *kn)
 
        cgroup_kn_unlock(kn);
 
-       /*
-        * There are two control paths which try to determine cgroup from
-        * dentry without going through kernfs - cgroupstats_build() and
-        * css_tryget_online_from_dir().  Those are supported by RCU
-        * protecting clearing of cgrp->kn->priv backpointer, which should
-        * happen after all files under it have been removed.
-        */
-       if (!ret)
-               RCU_INIT_POINTER(*(void __rcu __force **)&kn->priv, NULL);
-
        cgroup_put(cgrp);
        return ret;
 }
@@ -5416,7 +5435,7 @@ struct cgroup_subsys_state *css_tryget_online_from_dir(struct dentry *dentry,
        /*
         * This path doesn't originate from kernfs and @kn could already
         * have been or be removed at any point.  @kn->priv is RCU
-        * protected for this access.  See cgroup_rmdir() for details.
+        * protected for this access.  See css_release_work_fn() for details.
         */
        cgrp = rcu_dereference(kn->priv);
        if (cgrp)
index 633394f442f8a3cf63bc30b160b5345589ea57b7..ebb3c369d03d594067bda50bdffedd32159026e3 100644 (file)
@@ -226,7 +226,7 @@ static long compat_nanosleep_restart(struct restart_block *restart)
        ret = hrtimer_nanosleep_restart(restart);
        set_fs(oldfs);
 
-       if (ret) {
+       if (ret == -ERESTART_RESTARTBLOCK) {
                rmtp = restart->nanosleep.compat_rmtp;
 
                if (rmtp && compat_put_timespec(&rmt, rmtp))
@@ -256,7 +256,26 @@ COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp,
                                HRTIMER_MODE_REL, CLOCK_MONOTONIC);
        set_fs(oldfs);
 
-       if (ret) {
+       /*
+        * hrtimer_nanosleep() can only return 0 or
+        * -ERESTART_RESTARTBLOCK here because:
+        *
+        * - we call it with HRTIMER_MODE_REL and therefor exclude the
+        *   -ERESTARTNOHAND return path.
+        *
+        * - we supply the rmtp argument from the task stack (due to
+        *   the necessary compat conversion. So the update cannot
+        *   fail, which excludes the -EFAULT return path as well. If
+        *   it fails nevertheless we have a bigger problem and wont
+        *   reach this place anymore.
+        *
+        * - if the return value is 0, we do not have to update rmtp
+        *    because there is no remaining time.
+        *
+        * We check for -ERESTART_RESTARTBLOCK nevertheless if the
+        * core implementation decides to return random nonsense.
+        */
+       if (ret == -ERESTART_RESTARTBLOCK) {
                struct restart_block *restart
                        = &current_thread_info()->restart_block;
 
@@ -266,7 +285,6 @@ COMPAT_SYSCALL_DEFINE2(nanosleep, struct compat_timespec __user *, rqtp,
                if (rmtp && compat_put_timespec(&rmt, rmtp))
                        return -EFAULT;
        }
-
        return ret;
 }
 
index a2b28a2fd7b16d270c45b3c40719a35d0034c58d..6223fab9a9d22b7bedd5e6b1f23ccd8a0347d6d1 100644 (file)
@@ -517,6 +517,7 @@ out:
                chip->irq_eoi(&desc->irq_data);
        raw_spin_unlock(&desc->lock);
 }
+EXPORT_SYMBOL_GPL(handle_fasteoi_irq);
 
 /**
  *     handle_edge_irq - edge type IRQ handler
index e30ac0fe61c3ded5533cb4db8e95b2d41dcf2ac8..0aa69ea1d8fdcfa68046aa75b03c4373783a02fa 100644 (file)
@@ -44,11 +44,12 @@ static long kptr_obfuscate(long v, int type)
  */
 static int kcmp_ptr(void *v1, void *v2, enum kcmp_type type)
 {
-       long ret;
+       long t1, t2;
 
-       ret = kptr_obfuscate((long)v1, type) - kptr_obfuscate((long)v2, type);
+       t1 = kptr_obfuscate((long)v1, type);
+       t2 = kptr_obfuscate((long)v2, type);
 
-       return (ret < 0) | ((ret > 0) << 1);
+       return (t1 < t2) | ((t1 > t2) << 1);
 }
 
 /* The caller must have pinned the task */
index 0b49a0a5810200da0925350e3d55dd1fc70b8638..2bee072268d94da0b7e19e60ee5ee90267ea2b63 100644 (file)
@@ -64,7 +64,9 @@ bool kexec_in_progress = false;
 char __weak kexec_purgatory[0];
 size_t __weak kexec_purgatory_size = 0;
 
+#ifdef CONFIG_KEXEC_FILE
 static int kexec_calculate_store_digests(struct kimage *image);
+#endif
 
 /* Location of the reserved area for the crash kernel */
 struct resource crashk_res = {
@@ -341,6 +343,7 @@ out_free_image:
        return ret;
 }
 
+#ifdef CONFIG_KEXEC_FILE
 static int copy_file_from_fd(int fd, void **buf, unsigned long *buf_len)
 {
        struct fd f = fdget(fd);
@@ -612,6 +615,9 @@ out_free_image:
        kfree(image);
        return ret;
 }
+#else /* CONFIG_KEXEC_FILE */
+static inline void kimage_file_post_load_cleanup(struct kimage *image) { }
+#endif /* CONFIG_KEXEC_FILE */
 
 static int kimage_is_destination_range(struct kimage *image,
                                        unsigned long start,
@@ -1375,6 +1381,7 @@ COMPAT_SYSCALL_DEFINE4(kexec_load, compat_ulong_t, entry,
 }
 #endif
 
+#ifdef CONFIG_KEXEC_FILE
 SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd,
                unsigned long, cmdline_len, const char __user *, cmdline_ptr,
                unsigned long, flags)
@@ -1451,6 +1458,8 @@ out:
        return ret;
 }
 
+#endif /* CONFIG_KEXEC_FILE */
+
 void crash_kexec(struct pt_regs *regs)
 {
        /* Take the kexec_mutex here to prevent sys_kexec_load
@@ -2006,6 +2015,7 @@ static int __init crash_save_vmcoreinfo_init(void)
 
 subsys_initcall(crash_save_vmcoreinfo_init);
 
+#ifdef CONFIG_KEXEC_FILE
 static int __kexec_add_segment(struct kimage *image, char *buf,
                               unsigned long bufsz, unsigned long mem,
                               unsigned long memsz)
@@ -2682,6 +2692,7 @@ int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name,
 
        return 0;
 }
+#endif /* CONFIG_KEXEC_FILE */
 
 /*
  * Move into place and start executing a preloaded standalone
index 5d49dcac2537045a6e23b4e1941164e2f59a0402..2df883a9d3cb26bcf35e2d2e2294226793a2563b 100644 (file)
@@ -179,6 +179,7 @@ extern void swsusp_show_speed(struct timeval *, struct timeval *,
 
 #ifdef CONFIG_SUSPEND
 /* kernel/power/suspend.c */
+extern const char *pm_labels[];
 extern const char *pm_states[];
 
 extern int suspend_devices_and_enter(suspend_state_t state);
index 6dadb25cb0d8023f987c2c0961f1f81b7fedb0ce..18c62195660f6c6c458d74346ee7979ec4388db4 100644 (file)
@@ -31,7 +31,7 @@
 
 #include "power.h"
 
-static const char *pm_labels[] = { "mem", "standby", "freeze", };
+const char *pm_labels[] = { "mem", "standby", "freeze", NULL };
 const char *pm_states[PM_SUSPEND_MAX];
 
 static const struct platform_suspend_ops *suspend_ops;
index 2f524928b6aac0a1e1cd108aef54d23c88a291a9..bd91bc177c93a65ca757c70467cd6e235af6a67c 100644 (file)
@@ -129,20 +129,20 @@ static int __init has_wakealarm(struct device *dev, const void *data)
  * at startup time.  They're normally disabled, for faster boot and because
  * we can't know which states really work on this particular system.
  */
-static suspend_state_t test_state __initdata = PM_SUSPEND_ON;
+static const char *test_state_label __initdata;
 
 static char warn_bad_state[] __initdata =
        KERN_WARNING "PM: can't test '%s' suspend state\n";
 
 static int __init setup_test_suspend(char *value)
 {
-       suspend_state_t i;
+       int i;
 
        /* "=mem" ==> "mem" */
        value++;
-       for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++)
-               if (!strcmp(pm_states[i], value)) {
-                       test_state = i;
+       for (i = 0; pm_labels[i]; i++)
+               if (!strcmp(pm_labels[i], value)) {
+                       test_state_label = pm_labels[i];
                        return 0;
                }
 
@@ -158,13 +158,21 @@ static int __init test_suspend(void)
 
        struct rtc_device       *rtc = NULL;
        struct device           *dev;
+       suspend_state_t test_state;
 
        /* PM is initialized by now; is that state testable? */
-       if (test_state == PM_SUSPEND_ON)
-               goto done;
-       if (!pm_states[test_state]) {
-               printk(warn_bad_state, pm_states[test_state]);
-               goto done;
+       if (!test_state_label)
+               return 0;
+
+       for (test_state = PM_SUSPEND_MIN; test_state < PM_SUSPEND_MAX; test_state++) {
+               const char *state_label = pm_states[test_state];
+
+               if (state_label && !strcmp(test_state_label, state_label))
+                       break;
+       }
+       if (test_state == PM_SUSPEND_MAX) {
+               printk(warn_bad_state, test_state_label);
+               return 0;
        }
 
        /* RTCs have initialized by now too ... can we use one? */
@@ -173,13 +181,12 @@ static int __init test_suspend(void)
                rtc = rtc_class_open(dev_name(dev));
        if (!rtc) {
                printk(warn_no_rtc);
-               goto done;
+               return 0;
        }
 
        /* go for it */
        test_wakealarm(rtc, test_state);
        rtc_class_close(rtc);
-done:
        return 0;
 }
 late_initcall(test_suspend);
index e04c455a0e3860b2aa5784d4c2522a21300525e4..1ce770687ea83c6a05c562591fe475b5f2cc52d0 100644 (file)
@@ -1665,15 +1665,15 @@ asmlinkage int vprintk_emit(int facility, int level,
        raw_spin_lock(&logbuf_lock);
        logbuf_cpu = this_cpu;
 
-       if (recursion_bug) {
+       if (unlikely(recursion_bug)) {
                static const char recursion_msg[] =
                        "BUG: recent printk recursion!";
 
                recursion_bug = 0;
-               text_len = strlen(recursion_msg);
                /* emit KERN_CRIT message */
                printed_len += log_store(0, 2, LOG_PREFIX|LOG_NEWLINE, 0,
-                                        NULL, 0, recursion_msg, text_len);
+                                        NULL, 0, recursion_msg,
+                                        strlen(recursion_msg));
        }
 
        /*
index 71e64c718f75d3f4d419c31f4546cf3fab76a4f4..6a86eb7bac45e7b540f1ab9ead7d412cf6ef60fa 100644 (file)
@@ -358,7 +358,7 @@ struct rcu_data {
        struct rcu_head **nocb_gp_tail;
        long nocb_gp_count;
        long nocb_gp_count_lazy;
-       bool nocb_leader_wake;          /* Is the nocb leader thread awake? */
+       bool nocb_leader_sleep;         /* Is the nocb leader thread asleep? */
        struct rcu_data *nocb_next_follower;
                                        /* Next follower in wakeup chain. */
 
index 00dc411e9676f92db54e0bbb3489bea9b87e731a..a7997e272564916d8ec2232b32867add334b6c77 100644 (file)
@@ -2074,9 +2074,9 @@ static void wake_nocb_leader(struct rcu_data *rdp, bool force)
 
        if (!ACCESS_ONCE(rdp_leader->nocb_kthread))
                return;
-       if (!ACCESS_ONCE(rdp_leader->nocb_leader_wake) || force) {
+       if (ACCESS_ONCE(rdp_leader->nocb_leader_sleep) || force) {
                /* Prior xchg orders against prior callback enqueue. */
-               ACCESS_ONCE(rdp_leader->nocb_leader_wake) = true;
+               ACCESS_ONCE(rdp_leader->nocb_leader_sleep) = false;
                wake_up(&rdp_leader->nocb_wq);
        }
 }
@@ -2253,7 +2253,7 @@ wait_again:
        if (!rcu_nocb_poll) {
                trace_rcu_nocb_wake(my_rdp->rsp->name, my_rdp->cpu, "Sleep");
                wait_event_interruptible(my_rdp->nocb_wq,
-                                        ACCESS_ONCE(my_rdp->nocb_leader_wake));
+                               !ACCESS_ONCE(my_rdp->nocb_leader_sleep));
                /* Memory barrier handled by smp_mb() calls below and repoll. */
        } else if (firsttime) {
                firsttime = false; /* Don't drown trace log with "Poll"! */
@@ -2292,12 +2292,12 @@ wait_again:
                schedule_timeout_interruptible(1);
 
                /* Rescan in case we were a victim of memory ordering. */
-               my_rdp->nocb_leader_wake = false;
-               smp_mb();  /* Ensure _wake false before scan. */
+               my_rdp->nocb_leader_sleep = true;
+               smp_mb();  /* Ensure _sleep true before scan. */
                for (rdp = my_rdp; rdp; rdp = rdp->nocb_next_follower)
                        if (ACCESS_ONCE(rdp->nocb_head)) {
                                /* Found CB, so short-circuit next wait. */
-                               my_rdp->nocb_leader_wake = true;
+                               my_rdp->nocb_leader_sleep = false;
                                break;
                        }
                goto wait_again;
@@ -2307,17 +2307,17 @@ wait_again:
        rcu_nocb_wait_gp(my_rdp);
 
        /*
-        * We left ->nocb_leader_wake set to reduce cache thrashing.
-        * We clear it now, but recheck for new callbacks while
+        * We left ->nocb_leader_sleep unset to reduce cache thrashing.
+        * We set it now, but recheck for new callbacks while
         * traversing our follower list.
         */
-       my_rdp->nocb_leader_wake = false;
-       smp_mb(); /* Ensure _wake false before scan of ->nocb_head. */
+       my_rdp->nocb_leader_sleep = true;
+       smp_mb(); /* Ensure _sleep true before scan of ->nocb_head. */
 
        /* Each pass through the following loop wakes a follower, if needed. */
        for (rdp = my_rdp; rdp; rdp = rdp->nocb_next_follower) {
                if (ACCESS_ONCE(rdp->nocb_head))
-                       my_rdp->nocb_leader_wake = true; /* No need to wait. */
+                       my_rdp->nocb_leader_sleep = false;/* No need to sleep.*/
                if (!rdp->nocb_gp_head)
                        continue; /* No CBs, so no need to wake follower. */
 
index da14b8d092961bf5680bf06004f980ad1ec43859..60c5a3856ab7a5266fabd7eef844b9d1a636d0a8 100644 (file)
@@ -351,15 +351,12 @@ static int find_next_iomem_res(struct resource *res, char *name,
        end = res->end;
        BUG_ON(start >= end);
 
-       read_lock(&resource_lock);
-
-       if (first_level_children_only) {
-               p = iomem_resource.child;
+       if (first_level_children_only)
                sibling_only = true;
-       } else
-               p = &iomem_resource;
 
-       while ((p = next_resource(p, sibling_only))) {
+       read_lock(&resource_lock);
+
+       for (p = iomem_resource.child; p; p = next_resource(p, sibling_only)) {
                if (p->flags != res->flags)
                        continue;
                if (name && strcmp(p->name, name))
index 99aa6ee3908fbbff83923b2a8bb4c72b06e3f281..f654a8a298fad5cac36465bdcb23fddeb854f2ef 100644 (file)
@@ -224,6 +224,20 @@ static DEFINE_PER_CPU(struct irq_work, nohz_full_kick_work) = {
        .func = nohz_full_kick_work_func,
 };
 
+/*
+ * Kick this CPU if it's full dynticks in order to force it to
+ * re-evaluate its dependency on the tick and restart it if necessary.
+ * This kick, unlike tick_nohz_full_kick_cpu() and tick_nohz_full_kick_all(),
+ * is NMI safe.
+ */
+void tick_nohz_full_kick(void)
+{
+       if (!tick_nohz_full_cpu(smp_processor_id()))
+               return;
+
+       irq_work_queue(&__get_cpu_var(nohz_full_kick_work));
+}
+
 /*
  * Kick the CPU if it's full dynticks in order to force it to
  * re-evaluate its dependency on the tick and restart it if necessary.
index fb4a9c2cf8d98db2256a6268fb8bbfb37673b2fe..ec1791fae96575ffe49c9aa1a2f42cbc6b21df2a 100644 (file)
@@ -442,11 +442,12 @@ static void timekeeping_update(struct timekeeper *tk, unsigned int action)
                tk->ntp_error = 0;
                ntp_clear();
        }
-       update_vsyscall(tk);
-       update_pvclock_gtod(tk, action & TK_CLOCK_WAS_SET);
 
        tk_update_ktime_data(tk);
 
+       update_vsyscall(tk);
+       update_pvclock_gtod(tk, action & TK_CLOCK_WAS_SET);
+
        if (action & TK_MIRROR)
                memcpy(&shadow_timekeeper, &tk_core.timekeeper,
                       sizeof(tk_core.timekeeper));
index afb04b9b818a473f8b38e0aa94ee12ad84c44d1a..b38fb2b9e23772d3f3360ef556cf0714d4a44803 100644 (file)
@@ -626,8 +626,22 @@ int ring_buffer_poll_wait(struct ring_buffer *buffer, int cpu,
                work = &cpu_buffer->irq_work;
        }
 
-       work->waiters_pending = true;
        poll_wait(filp, &work->waiters, poll_table);
+       work->waiters_pending = true;
+       /*
+        * There's a tight race between setting the waiters_pending and
+        * checking if the ring buffer is empty.  Once the waiters_pending bit
+        * is set, the next event will wake the task up, but we can get stuck
+        * if there's only a single event in.
+        *
+        * FIXME: Ideally, we need a memory barrier on the writer side as well,
+        * but adding a memory barrier to all events will cause too much of a
+        * performance hit in the fast path.  We only need a memory barrier when
+        * the buffer goes from empty to having content.  But as this race is
+        * extremely small, and it's not a problem if another event comes in, we
+        * will fix it later.
+        */
+       smp_mb();
 
        if ((cpu == RING_BUFFER_ALL_CPUS && !ring_buffer_empty(buffer)) ||
            (cpu != RING_BUFFER_ALL_CPUS && !ring_buffer_empty_cpu(buffer, cpu)))
index 07c28323f88fe99d08900d82e3eacec6ca88fb91..a28590083622705dd007bffd5d3a57f87f133fed 100644 (file)
@@ -892,6 +892,10 @@ config DEBUG_WW_MUTEX_SLOWPATH
         the full mutex checks enabled with (CONFIG_PROVE_LOCKING) this
         will test all possible w/w mutex interface abuse with the
         exception of simply not acquiring all the required locks.
+        Note that this feature can introduce significant overhead, so
+        it really should not be enabled in a production or distro kernel,
+        even a debug kernel.  If you are a driver writer, enable it.  If
+        you are a distro, do not.
 
 config DEBUG_LOCK_ALLOC
        bool "Lock debugging: detect incorrect freeing of live locks"
@@ -1032,8 +1036,13 @@ config TRACE_IRQFLAGS
          either tracing or lock debugging.
 
 config STACKTRACE
-       bool
+       bool "Stack backtrace support"
        depends on STACKTRACE_SUPPORT
+       help
+         This option causes the kernel to create a /proc/pid/stack for
+         every process, showing its current stack trace.
+         It is also used by various kernel debugging features that require
+         stack trace generation.
 
 config DEBUG_KOBJECT
        bool "kobject debugging"
index c0b1007011e188836616509deef5876c207d32d4..2404d03e251a64ae7634d30c46aa22a08f9b4538 100644 (file)
@@ -1723,11 +1723,13 @@ ascend_old_tree:
                shortcut = assoc_array_ptr_to_shortcut(ptr);
                slot = shortcut->parent_slot;
                cursor = shortcut->back_pointer;
+               if (!cursor)
+                       goto gc_complete;
        } else {
                slot = node->parent_slot;
                cursor = ptr;
        }
-       BUG_ON(!ptr);
+       BUG_ON(!cursor);
        node = assoc_array_ptr_to_node(cursor);
        slot++;
        goto continue_node;
@@ -1735,7 +1737,7 @@ ascend_old_tree:
 gc_complete:
        edit->set[0].to = new_root;
        assoc_array_apply_edit(edit);
-       edit->array->nr_leaves_on_tree = nr_leaves_on_tree;
+       array->nr_leaves_on_tree = nr_leaves_on_tree;
        return 0;
 
 enomem:
index 9eebfadeeee17f1f3650162dd1e34a88157ef39e..a67c26e0f360211f21fdb6b19f0f54fc9d3fe726 100644 (file)
@@ -217,7 +217,7 @@ void hugetlb_cgroup_uncharge_page(int idx, unsigned long nr_pages,
 
        if (hugetlb_cgroup_disabled())
                return;
-       VM_BUG_ON(!spin_is_locked(&hugetlb_lock));
+       lockdep_assert_held(&hugetlb_lock);
        h_cg = hugetlb_cgroup_from_page(page);
        if (unlikely(!h_cg))
                return;
index 6d2f219a48b01d371c1eb763f611d29a346890d9..6ecb0d937fb5f9bde4015d20b620484f5c965f84 100644 (file)
@@ -192,8 +192,7 @@ phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size,
                                        phys_addr_t align, phys_addr_t start,
                                        phys_addr_t end, int nid)
 {
-       int ret;
-       phys_addr_t kernel_end;
+       phys_addr_t kernel_end, ret;
 
        /* pump up @end */
        if (end == MEMBLOCK_ALLOC_ACCESSIBLE)
@@ -817,6 +816,10 @@ void __init_memblock __next_mem_range(u64 *idx, int nid,
                if (nid != NUMA_NO_NODE && nid != m_nid)
                        continue;
 
+               /* skip hotpluggable memory regions if needed */
+               if (movable_node_is_enabled() && memblock_is_hotpluggable(m))
+                       continue;
+
                if (!type_b) {
                        if (out_start)
                                *out_start = m_start;
index ec4dcf1b9562b6299f215e754768da18a36b156e..085dc6d2f876374c07a518866ecb1d25a2e8c419 100644 (file)
@@ -2534,6 +2534,8 @@ static int try_charge(struct mem_cgroup *memcg, gfp_t gfp_mask,
        unsigned long long size;
        int ret = 0;
 
+       if (mem_cgroup_is_root(memcg))
+               goto done;
 retry:
        if (consume_stock(memcg, nr_pages))
                goto done;
@@ -2611,9 +2613,7 @@ nomem:
        if (!(gfp_mask & __GFP_NOFAIL))
                return -ENOMEM;
 bypass:
-       memcg = root_mem_cgroup;
-       ret = -EINTR;
-       goto retry;
+       return -EINTR;
 
 done_restock:
        if (batch > nr_pages)
@@ -2626,6 +2626,9 @@ static void cancel_charge(struct mem_cgroup *memcg, unsigned int nr_pages)
 {
        unsigned long bytes = nr_pages * PAGE_SIZE;
 
+       if (mem_cgroup_is_root(memcg))
+               return;
+
        res_counter_uncharge(&memcg->res, bytes);
        if (do_swap_account)
                res_counter_uncharge(&memcg->memsw, bytes);
@@ -2640,6 +2643,9 @@ static void __mem_cgroup_cancel_local_charge(struct mem_cgroup *memcg,
 {
        unsigned long bytes = nr_pages * PAGE_SIZE;
 
+       if (mem_cgroup_is_root(memcg))
+               return;
+
        res_counter_uncharge_until(&memcg->res, memcg->res.parent, bytes);
        if (do_swap_account)
                res_counter_uncharge_until(&memcg->memsw,
@@ -4093,6 +4099,46 @@ out:
        return retval;
 }
 
+static unsigned long mem_cgroup_recursive_stat(struct mem_cgroup *memcg,
+                                              enum mem_cgroup_stat_index idx)
+{
+       struct mem_cgroup *iter;
+       long val = 0;
+
+       /* Per-cpu values can be negative, use a signed accumulator */
+       for_each_mem_cgroup_tree(iter, memcg)
+               val += mem_cgroup_read_stat(iter, idx);
+
+       if (val < 0) /* race ? */
+               val = 0;
+       return val;
+}
+
+static inline u64 mem_cgroup_usage(struct mem_cgroup *memcg, bool swap)
+{
+       u64 val;
+
+       if (!mem_cgroup_is_root(memcg)) {
+               if (!swap)
+                       return res_counter_read_u64(&memcg->res, RES_USAGE);
+               else
+                       return res_counter_read_u64(&memcg->memsw, RES_USAGE);
+       }
+
+       /*
+        * Transparent hugepages are still accounted for in MEM_CGROUP_STAT_RSS
+        * as well as in MEM_CGROUP_STAT_RSS_HUGE.
+        */
+       val = mem_cgroup_recursive_stat(memcg, MEM_CGROUP_STAT_CACHE);
+       val += mem_cgroup_recursive_stat(memcg, MEM_CGROUP_STAT_RSS);
+
+       if (swap)
+               val += mem_cgroup_recursive_stat(memcg, MEM_CGROUP_STAT_SWAP);
+
+       return val << PAGE_SHIFT;
+}
+
+
 static u64 mem_cgroup_read_u64(struct cgroup_subsys_state *css,
                               struct cftype *cft)
 {
@@ -4102,8 +4148,12 @@ static u64 mem_cgroup_read_u64(struct cgroup_subsys_state *css,
 
        switch (type) {
        case _MEM:
+               if (name == RES_USAGE)
+                       return mem_cgroup_usage(memcg, false);
                return res_counter_read_u64(&memcg->res, name);
        case _MEMSWAP:
+               if (name == RES_USAGE)
+                       return mem_cgroup_usage(memcg, true);
                return res_counter_read_u64(&memcg->memsw, name);
        case _KMEM:
                return res_counter_read_u64(&memcg->kmem, name);
@@ -4572,10 +4622,7 @@ static void __mem_cgroup_threshold(struct mem_cgroup *memcg, bool swap)
        if (!t)
                goto unlock;
 
-       if (!swap)
-               usage = res_counter_read_u64(&memcg->res, RES_USAGE);
-       else
-               usage = res_counter_read_u64(&memcg->memsw, RES_USAGE);
+       usage = mem_cgroup_usage(memcg, swap);
 
        /*
         * current_threshold points to threshold just below or equal to usage.
@@ -4673,10 +4720,10 @@ static int __mem_cgroup_usage_register_event(struct mem_cgroup *memcg,
 
        if (type == _MEM) {
                thresholds = &memcg->thresholds;
-               usage = res_counter_read_u64(&memcg->res, RES_USAGE);
+               usage = mem_cgroup_usage(memcg, false);
        } else if (type == _MEMSWAP) {
                thresholds = &memcg->memsw_thresholds;
-               usage = res_counter_read_u64(&memcg->memsw, RES_USAGE);
+               usage = mem_cgroup_usage(memcg, true);
        } else
                BUG();
 
@@ -4762,10 +4809,10 @@ static void __mem_cgroup_usage_unregister_event(struct mem_cgroup *memcg,
 
        if (type == _MEM) {
                thresholds = &memcg->thresholds;
-               usage = res_counter_read_u64(&memcg->res, RES_USAGE);
+               usage = mem_cgroup_usage(memcg, false);
        } else if (type == _MEMSWAP) {
                thresholds = &memcg->memsw_thresholds;
-               usage = res_counter_read_u64(&memcg->memsw, RES_USAGE);
+               usage = mem_cgroup_usage(memcg, true);
        } else
                BUG();
 
@@ -5525,9 +5572,9 @@ mem_cgroup_css_online(struct cgroup_subsys_state *css)
                 * core guarantees its existence.
                 */
        } else {
-               res_counter_init(&memcg->res, &root_mem_cgroup->res);
-               res_counter_init(&memcg->memsw, &root_mem_cgroup->memsw);
-               res_counter_init(&memcg->kmem, &root_mem_cgroup->kmem);
+               res_counter_init(&memcg->res, NULL);
+               res_counter_init(&memcg->memsw, NULL);
+               res_counter_init(&memcg->kmem, NULL);
                /*
                 * Deeper hierachy with use_hierarchy == false doesn't make
                 * much sense so let cgroup subsystem know about this
@@ -5969,8 +6016,9 @@ static void __mem_cgroup_clear_mc(void)
        /* we must fixup refcnts and charges */
        if (mc.moved_swap) {
                /* uncharge swap account from the old cgroup */
-               res_counter_uncharge(&mc.from->memsw,
-                                    PAGE_SIZE * mc.moved_swap);
+               if (!mem_cgroup_is_root(mc.from))
+                       res_counter_uncharge(&mc.from->memsw,
+                                            PAGE_SIZE * mc.moved_swap);
 
                for (i = 0; i < mc.moved_swap; i++)
                        css_put(&mc.from->css);
@@ -5979,8 +6027,9 @@ static void __mem_cgroup_clear_mc(void)
                 * we charged both to->res and to->memsw, so we should
                 * uncharge to->res.
                 */
-               res_counter_uncharge(&mc.to->res,
-                                    PAGE_SIZE * mc.moved_swap);
+               if (!mem_cgroup_is_root(mc.to))
+                       res_counter_uncharge(&mc.to->res,
+                                            PAGE_SIZE * mc.moved_swap);
                /* we've already done css_get(mc.to) */
                mc.moved_swap = 0;
        }
@@ -6345,7 +6394,8 @@ void mem_cgroup_uncharge_swap(swp_entry_t entry)
        rcu_read_lock();
        memcg = mem_cgroup_lookup(id);
        if (memcg) {
-               res_counter_uncharge(&memcg->memsw, PAGE_SIZE);
+               if (!mem_cgroup_is_root(memcg))
+                       res_counter_uncharge(&memcg->memsw, PAGE_SIZE);
                mem_cgroup_swap_statistics(memcg, false);
                css_put(&memcg->css);
        }
@@ -6509,12 +6559,15 @@ static void uncharge_batch(struct mem_cgroup *memcg, unsigned long pgpgout,
 {
        unsigned long flags;
 
-       if (nr_mem)
-               res_counter_uncharge(&memcg->res, nr_mem * PAGE_SIZE);
-       if (nr_memsw)
-               res_counter_uncharge(&memcg->memsw, nr_memsw * PAGE_SIZE);
-
-       memcg_oom_recover(memcg);
+       if (!mem_cgroup_is_root(memcg)) {
+               if (nr_mem)
+                       res_counter_uncharge(&memcg->res,
+                                            nr_mem * PAGE_SIZE);
+               if (nr_memsw)
+                       res_counter_uncharge(&memcg->memsw,
+                                            nr_memsw * PAGE_SIZE);
+               memcg_oom_recover(memcg);
+       }
 
        local_irq_save(flags);
        __this_cpu_sub(memcg->stat->count[MEM_CGROUP_STAT_RSS], nr_anon);
index ab3537bcfed2334fd1636cfc8e74ff634e54c943..adeac306610f7d7895e9d361d11649fb31f0a914 100644 (file)
@@ -751,7 +751,7 @@ struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
        unsigned long pfn = pte_pfn(pte);
 
        if (HAVE_PTE_SPECIAL) {
-               if (likely(!pte_special(pte) || pte_numa(pte)))
+               if (likely(!pte_special(pte)))
                        goto check_pfn;
                if (vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP))
                        return NULL;
@@ -777,15 +777,14 @@ struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
                }
        }
 
+       if (is_zero_pfn(pfn))
+               return NULL;
 check_pfn:
        if (unlikely(pfn > highest_memmap_pfn)) {
                print_bad_pte(vma, addr, pte, NULL);
                return NULL;
        }
 
-       if (is_zero_pfn(pfn))
-               return NULL;
-
        /*
         * NOTE! We still have PageReserved() pages in the page tables.
         * eg. VDSO mappings can cause them to exist.
index c1f2ea4a0b9960d39940c82f4ba329dad2df74df..c0a3637cdb645b0eed66c18edcd10431bfd5417b 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -369,20 +369,20 @@ static int browse_rb(struct rb_root *root)
                struct vm_area_struct *vma;
                vma = rb_entry(nd, struct vm_area_struct, vm_rb);
                if (vma->vm_start < prev) {
-                       pr_info("vm_start %lx prev %lx\n", vma->vm_start, prev);
+                       pr_emerg("vm_start %lx prev %lx\n", vma->vm_start, prev);
                        bug = 1;
                }
                if (vma->vm_start < pend) {
-                       pr_info("vm_start %lx pend %lx\n", vma->vm_start, pend);
+                       pr_emerg("vm_start %lx pend %lx\n", vma->vm_start, pend);
                        bug = 1;
                }
                if (vma->vm_start > vma->vm_end) {
-                       pr_info("vm_end %lx < vm_start %lx\n",
+                       pr_emerg("vm_end %lx < vm_start %lx\n",
                                vma->vm_end, vma->vm_start);
                        bug = 1;
                }
                if (vma->rb_subtree_gap != vma_compute_subtree_gap(vma)) {
-                       pr_info("free gap %lx, correct %lx\n",
+                       pr_emerg("free gap %lx, correct %lx\n",
                               vma->rb_subtree_gap,
                               vma_compute_subtree_gap(vma));
                        bug = 1;
@@ -396,7 +396,7 @@ static int browse_rb(struct rb_root *root)
        for (nd = pn; nd; nd = rb_prev(nd))
                j++;
        if (i != j) {
-               pr_info("backwards %d, forwards %d\n", j, i);
+               pr_emerg("backwards %d, forwards %d\n", j, i);
                bug = 1;
        }
        return bug ? -1 : i;
@@ -431,17 +431,17 @@ static void validate_mm(struct mm_struct *mm)
                i++;
        }
        if (i != mm->map_count) {
-               pr_info("map_count %d vm_next %d\n", mm->map_count, i);
+               pr_emerg("map_count %d vm_next %d\n", mm->map_count, i);
                bug = 1;
        }
        if (highest_address != mm->highest_vm_end) {
-               pr_info("mm->highest_vm_end %lx, found %lx\n",
+               pr_emerg("mm->highest_vm_end %lx, found %lx\n",
                       mm->highest_vm_end, highest_address);
                bug = 1;
        }
        i = browse_rb(&mm->mm_rb);
        if (i != mm->map_count) {
-               pr_info("map_count %d rb %d\n", mm->map_count, i);
+               pr_emerg("map_count %d rb %d\n", mm->map_count, i);
                bug = 1;
        }
        BUG_ON(bug);
index 7ed58602e71b186c46db4bf8857558f6e08ac60a..7c7ab32ee5032dad07354f438b5832649aaa044b 100644 (file)
@@ -119,6 +119,8 @@ static unsigned long __init free_low_memory_core_early(void)
        phys_addr_t start, end;
        u64 i;
 
+       memblock_clear_hotplug(0, -1);
+
        for_each_free_mem_range(i, NUMA_NO_NODE, &start, &end, NULL)
                count += __free_memory_core(start, end);
 
index 3707c71ae4cddbec027eac857291185c662c760a..51108165f829d777e4c69abe6109cb88ca4d7e14 100644 (file)
@@ -108,7 +108,7 @@ static int pcpu_alloc_pages(struct pcpu_chunk *chunk,
                            int page_start, int page_end)
 {
        const gfp_t gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_COLD;
-       unsigned int cpu;
+       unsigned int cpu, tcpu;
        int i;
 
        for_each_possible_cpu(cpu) {
@@ -116,14 +116,23 @@ static int pcpu_alloc_pages(struct pcpu_chunk *chunk,
                        struct page **pagep = &pages[pcpu_page_idx(cpu, i)];
 
                        *pagep = alloc_pages_node(cpu_to_node(cpu), gfp, 0);
-                       if (!*pagep) {
-                               pcpu_free_pages(chunk, pages, populated,
-                                               page_start, page_end);
-                               return -ENOMEM;
-                       }
+                       if (!*pagep)
+                               goto err;
                }
        }
        return 0;
+
+err:
+       while (--i >= page_start)
+               __free_page(pages[pcpu_page_idx(cpu, i)]);
+
+       for_each_possible_cpu(tcpu) {
+               if (tcpu == cpu)
+                       break;
+               for (i = page_start; i < page_end; i++)
+                       __free_page(pages[pcpu_page_idx(tcpu, i)]);
+       }
+       return -ENOMEM;
 }
 
 /**
@@ -263,6 +272,7 @@ err:
                __pcpu_unmap_pages(pcpu_chunk_addr(chunk, tcpu, page_start),
                                   page_end - page_start);
        }
+       pcpu_post_unmap_tlb_flush(chunk, page_start, page_end);
        return err;
 }
 
index 2139e30a4b4490da90c2e2811d5ecc901ff07d61..da997f9800bdeab14b47b694b09593de89db4a17 100644 (file)
@@ -1932,6 +1932,8 @@ void __init setup_per_cpu_areas(void)
 
        if (pcpu_setup_first_chunk(ai, fc) < 0)
                panic("Failed to initialize percpu areas.");
+
+       pcpu_free_alloc_info(ai);
 }
 
 #endif /* CONFIG_SMP */
index a8b9199259342df9cafb84be53010eb2206ebece..dfb79e028ecbf225c626d971179954a4918b646e 100644 (file)
@@ -195,7 +195,7 @@ void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
        pmd_t entry = *pmdp;
        if (pmd_numa(entry))
                entry = pmd_mknonnuma(entry);
-       set_pmd_at(vma->vm_mm, address, pmdp, pmd_mknotpresent(*pmdp));
+       set_pmd_at(vma->vm_mm, address, pmdp, pmd_mknotpresent(entry));
        flush_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
 }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
index a05790b1915eb4faba938cd0264c8a5ccfd2aa9e..f26e7fcc7fa25c7316f60235e8c402ff6bec4f26 100644 (file)
--- a/mm/zbud.c
+++ b/mm/zbud.c
@@ -195,6 +195,7 @@ static struct zpool_driver zbud_zpool_driver = {
        .total_size =   zbud_zpool_total_size,
 };
 
+MODULE_ALIAS("zpool-zbud");
 #endif /* CONFIG_ZPOOL */
 
 /*****************
index e40612a1df00b62c9a9728867d45fd7275bb2b0f..739cdf0d183ac0e51571d16f5b6321ccc837e7d1 100644 (file)
@@ -150,7 +150,7 @@ struct zpool *zpool_create_pool(char *type, gfp_t gfp, struct zpool_ops *ops)
        driver = zpool_get_driver(type);
 
        if (!driver) {
-               request_module(type);
+               request_module("zpool-%s", type);
                driver = zpool_get_driver(type);
        }
 
index 4e2fc83cb394b9b53384fdc82288e7b6ab793b3a..94f38fac5e81eb451d61e6561000c354103c0589 100644 (file)
@@ -315,6 +315,7 @@ static struct zpool_driver zs_zpool_driver = {
        .total_size =   zs_zpool_total_size,
 };
 
+MODULE_ALIAS("zpool-zsmalloc");
 #endif /* CONFIG_ZPOOL */
 
 /* per-cpu VM mapping areas for zspage accesses that cross page boundaries */
index b50dabb3f86ab49667cb939af29cef53a03b2ac2..faff6247ac8fb8769bf58f235fd92c0deab6aaf1 100644 (file)
@@ -589,6 +589,14 @@ EXPORT_SYMBOL(hci_get_route);
 void hci_le_conn_failed(struct hci_conn *conn, u8 status)
 {
        struct hci_dev *hdev = conn->hdev;
+       struct hci_conn_params *params;
+
+       params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst,
+                                          conn->dst_type);
+       if (params && params->conn) {
+               hci_conn_drop(params->conn);
+               params->conn = NULL;
+       }
 
        conn->state = BT_CLOSED;
 
index c32d361c0cf766478f80fb9ed8a4884f53451122..1d9c29a00568d9b6ac3eea93848ec6637e5a5a5d 100644 (file)
@@ -2536,8 +2536,13 @@ static void hci_pend_le_actions_clear(struct hci_dev *hdev)
 {
        struct hci_conn_params *p;
 
-       list_for_each_entry(p, &hdev->le_conn_params, list)
+       list_for_each_entry(p, &hdev->le_conn_params, list) {
+               if (p->conn) {
+                       hci_conn_drop(p->conn);
+                       p->conn = NULL;
+               }
                list_del_init(&p->action);
+       }
 
        BT_DBG("All LE pending actions cleared");
 }
@@ -2578,8 +2583,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
 
        hci_dev_lock(hdev);
        hci_inquiry_cache_flush(hdev);
-       hci_conn_hash_flush(hdev);
        hci_pend_le_actions_clear(hdev);
+       hci_conn_hash_flush(hdev);
        hci_dev_unlock(hdev);
 
        hci_notify(hdev, HCI_DEV_DOWN);
@@ -3727,6 +3732,9 @@ void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type)
        if (!params)
                return;
 
+       if (params->conn)
+               hci_conn_drop(params->conn);
+
        list_del(&params->action);
        list_del(&params->list);
        kfree(params);
@@ -3757,6 +3765,8 @@ void hci_conn_params_clear_all(struct hci_dev *hdev)
        struct hci_conn_params *params, *tmp;
 
        list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) {
+               if (params->conn)
+                       hci_conn_drop(params->conn);
                list_del(&params->action);
                list_del(&params->list);
                kfree(params);
index be35598984d9b9b3120cd178f67f0418858b2774..a6000823f0ff34d938631bed2e39a6b17a26ac13 100644 (file)
@@ -4221,8 +4221,13 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
        hci_proto_connect_cfm(conn, ev->status);
 
        params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
-       if (params)
+       if (params) {
                list_del_init(&params->action);
+               if (params->conn) {
+                       hci_conn_drop(params->conn);
+                       params->conn = NULL;
+               }
+       }
 
 unlock:
        hci_update_background_scan(hdev);
@@ -4304,8 +4309,16 @@ static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
 
        conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
                              HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER);
-       if (!IS_ERR(conn))
+       if (!IS_ERR(conn)) {
+               /* Store the pointer since we don't really have any
+                * other owner of the object besides the params that
+                * triggered it. This way we can abort the connection if
+                * the parameters get removed and keep the reference
+                * count consistent once the connection is established.
+                */
+               params->conn = conn;
                return;
+       }
 
        switch (PTR_ERR(conn)) {
        case -EBUSY:
index 96238ba95f2b6954c598294243b8f65931a82284..de6662b14e1f5d7110ac1316c1362e4db6bffc5f 100644 (file)
@@ -13,8 +13,6 @@
 #include "auth_x.h"
 #include "auth_x_protocol.h"
 
-#define TEMP_TICKET_BUF_LEN    256
-
 static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed);
 
 static int ceph_x_is_authenticated(struct ceph_auth_client *ac)
@@ -64,7 +62,7 @@ static int ceph_x_encrypt(struct ceph_crypto_key *secret,
 }
 
 static int ceph_x_decrypt(struct ceph_crypto_key *secret,
-                         void **p, void *end, void *obuf, size_t olen)
+                         void **p, void *end, void **obuf, size_t olen)
 {
        struct ceph_x_encrypt_header head;
        size_t head_len = sizeof(head);
@@ -75,8 +73,14 @@ static int ceph_x_decrypt(struct ceph_crypto_key *secret,
                return -EINVAL;
 
        dout("ceph_x_decrypt len %d\n", len);
-       ret = ceph_decrypt2(secret, &head, &head_len, obuf, &olen,
-                           *p, len);
+       if (*obuf == NULL) {
+               *obuf = kmalloc(len, GFP_NOFS);
+               if (!*obuf)
+                       return -ENOMEM;
+               olen = len;
+       }
+
+       ret = ceph_decrypt2(secret, &head, &head_len, *obuf, &olen, *p, len);
        if (ret)
                return ret;
        if (head.struct_v != 1 || le64_to_cpu(head.magic) != CEPHX_ENC_MAGIC)
@@ -129,139 +133,120 @@ static void remove_ticket_handler(struct ceph_auth_client *ac,
        kfree(th);
 }
 
-static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
-                                   struct ceph_crypto_key *secret,
-                                   void *buf, void *end)
+static int process_one_ticket(struct ceph_auth_client *ac,
+                             struct ceph_crypto_key *secret,
+                             void **p, void *end)
 {
        struct ceph_x_info *xi = ac->private;
-       int num;
-       void *p = buf;
+       int type;
+       u8 tkt_struct_v, blob_struct_v;
+       struct ceph_x_ticket_handler *th;
+       void *dbuf = NULL;
+       void *dp, *dend;
+       int dlen;
+       char is_enc;
+       struct timespec validity;
+       struct ceph_crypto_key old_key;
+       void *ticket_buf = NULL;
+       void *tp, *tpend;
+       struct ceph_timespec new_validity;
+       struct ceph_crypto_key new_session_key;
+       struct ceph_buffer *new_ticket_blob;
+       unsigned long new_expires, new_renew_after;
+       u64 new_secret_id;
        int ret;
-       char *dbuf;
-       char *ticket_buf;
-       u8 reply_struct_v;
 
-       dbuf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
-       if (!dbuf)
-               return -ENOMEM;
+       ceph_decode_need(p, end, sizeof(u32) + 1, bad);
 
-       ret = -ENOMEM;
-       ticket_buf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS);
-       if (!ticket_buf)
-               goto out_dbuf;
+       type = ceph_decode_32(p);
+       dout(" ticket type %d %s\n", type, ceph_entity_type_name(type));
 
-       ceph_decode_need(&p, end, 1 + sizeof(u32), bad);
-       reply_struct_v = ceph_decode_8(&p);
-       if (reply_struct_v != 1)
+       tkt_struct_v = ceph_decode_8(p);
+       if (tkt_struct_v != 1)
                goto bad;
-       num = ceph_decode_32(&p);
-       dout("%d tickets\n", num);
-       while (num--) {
-               int type;
-               u8 tkt_struct_v, blob_struct_v;
-               struct ceph_x_ticket_handler *th;
-               void *dp, *dend;
-               int dlen;
-               char is_enc;
-               struct timespec validity;
-               struct ceph_crypto_key old_key;
-               void *tp, *tpend;
-               struct ceph_timespec new_validity;
-               struct ceph_crypto_key new_session_key;
-               struct ceph_buffer *new_ticket_blob;
-               unsigned long new_expires, new_renew_after;
-               u64 new_secret_id;
-
-               ceph_decode_need(&p, end, sizeof(u32) + 1, bad);
-
-               type = ceph_decode_32(&p);
-               dout(" ticket type %d %s\n", type, ceph_entity_type_name(type));
-
-               tkt_struct_v = ceph_decode_8(&p);
-               if (tkt_struct_v != 1)
-                       goto bad;
-
-               th = get_ticket_handler(ac, type);
-               if (IS_ERR(th)) {
-                       ret = PTR_ERR(th);
-                       goto out;
-               }
 
-               /* blob for me */
-               dlen = ceph_x_decrypt(secret, &p, end, dbuf,
-                                     TEMP_TICKET_BUF_LEN);
-               if (dlen <= 0) {
-                       ret = dlen;
-                       goto out;
-               }
-               dout(" decrypted %d bytes\n", dlen);
-               dend = dbuf + dlen;
-               dp = dbuf;
+       th = get_ticket_handler(ac, type);
+       if (IS_ERR(th)) {
+               ret = PTR_ERR(th);
+               goto out;
+       }
 
-               tkt_struct_v = ceph_decode_8(&dp);
-               if (tkt_struct_v != 1)
-                       goto bad;
+       /* blob for me */
+       dlen = ceph_x_decrypt(secret, p, end, &dbuf, 0);
+       if (dlen <= 0) {
+               ret = dlen;
+               goto out;
+       }
+       dout(" decrypted %d bytes\n", dlen);
+       dp = dbuf;
+       dend = dp + dlen;
 
-               memcpy(&old_key, &th->session_key, sizeof(old_key));
-               ret = ceph_crypto_key_decode(&new_session_key, &dp, dend);
-               if (ret)
-                       goto out;
+       tkt_struct_v = ceph_decode_8(&dp);
+       if (tkt_struct_v != 1)
+               goto bad;
 
-               ceph_decode_copy(&dp, &new_validity, sizeof(new_validity));
-               ceph_decode_timespec(&validity, &new_validity);
-               new_expires = get_seconds() + validity.tv_sec;
-               new_renew_after = new_expires - (validity.tv_sec / 4);
-               dout(" expires=%lu renew_after=%lu\n", new_expires,
-                    new_renew_after);
+       memcpy(&old_key, &th->session_key, sizeof(old_key));
+       ret = ceph_crypto_key_decode(&new_session_key, &dp, dend);
+       if (ret)
+               goto out;
 
-               /* ticket blob for service */
-               ceph_decode_8_safe(&p, end, is_enc, bad);
-               tp = ticket_buf;
-               if (is_enc) {
-                       /* encrypted */
-                       dout(" encrypted ticket\n");
-                       dlen = ceph_x_decrypt(&old_key, &p, end, ticket_buf,
-                                             TEMP_TICKET_BUF_LEN);
-                       if (dlen < 0) {
-                               ret = dlen;
-                               goto out;
-                       }
-                       dlen = ceph_decode_32(&tp);
-               } else {
-                       /* unencrypted */
-                       ceph_decode_32_safe(&p, end, dlen, bad);
-                       ceph_decode_need(&p, end, dlen, bad);
-                       ceph_decode_copy(&p, ticket_buf, dlen);
+       ceph_decode_copy(&dp, &new_validity, sizeof(new_validity));
+       ceph_decode_timespec(&validity, &new_validity);
+       new_expires = get_seconds() + validity.tv_sec;
+       new_renew_after = new_expires - (validity.tv_sec / 4);
+       dout(" expires=%lu renew_after=%lu\n", new_expires,
+            new_renew_after);
+
+       /* ticket blob for service */
+       ceph_decode_8_safe(p, end, is_enc, bad);
+       if (is_enc) {
+               /* encrypted */
+               dout(" encrypted ticket\n");
+               dlen = ceph_x_decrypt(&old_key, p, end, &ticket_buf, 0);
+               if (dlen < 0) {
+                       ret = dlen;
+                       goto out;
                }
-               tpend = tp + dlen;
-               dout(" ticket blob is %d bytes\n", dlen);
-               ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad);
-               blob_struct_v = ceph_decode_8(&tp);
-               new_secret_id = ceph_decode_64(&tp);
-               ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend);
-               if (ret)
+               tp = ticket_buf;
+               dlen = ceph_decode_32(&tp);
+       } else {
+               /* unencrypted */
+               ceph_decode_32_safe(p, end, dlen, bad);
+               ticket_buf = kmalloc(dlen, GFP_NOFS);
+               if (!ticket_buf) {
+                       ret = -ENOMEM;
                        goto out;
-
-               /* all is well, update our ticket */
-               ceph_crypto_key_destroy(&th->session_key);
-               if (th->ticket_blob)
-                       ceph_buffer_put(th->ticket_blob);
-               th->session_key = new_session_key;
-               th->ticket_blob = new_ticket_blob;
-               th->validity = new_validity;
-               th->secret_id = new_secret_id;
-               th->expires = new_expires;
-               th->renew_after = new_renew_after;
-               dout(" got ticket service %d (%s) secret_id %lld len %d\n",
-                    type, ceph_entity_type_name(type), th->secret_id,
-                    (int)th->ticket_blob->vec.iov_len);
-               xi->have_keys |= th->service;
+               }
+               tp = ticket_buf;
+               ceph_decode_need(p, end, dlen, bad);
+               ceph_decode_copy(p, ticket_buf, dlen);
        }
+       tpend = tp + dlen;
+       dout(" ticket blob is %d bytes\n", dlen);
+       ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad);
+       blob_struct_v = ceph_decode_8(&tp);
+       new_secret_id = ceph_decode_64(&tp);
+       ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend);
+       if (ret)
+               goto out;
+
+       /* all is well, update our ticket */
+       ceph_crypto_key_destroy(&th->session_key);
+       if (th->ticket_blob)
+               ceph_buffer_put(th->ticket_blob);
+       th->session_key = new_session_key;
+       th->ticket_blob = new_ticket_blob;
+       th->validity = new_validity;
+       th->secret_id = new_secret_id;
+       th->expires = new_expires;
+       th->renew_after = new_renew_after;
+       dout(" got ticket service %d (%s) secret_id %lld len %d\n",
+            type, ceph_entity_type_name(type), th->secret_id,
+            (int)th->ticket_blob->vec.iov_len);
+       xi->have_keys |= th->service;
 
-       ret = 0;
 out:
        kfree(ticket_buf);
-out_dbuf:
        kfree(dbuf);
        return ret;
 
@@ -270,6 +255,34 @@ bad:
        goto out;
 }
 
+static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac,
+                                   struct ceph_crypto_key *secret,
+                                   void *buf, void *end)
+{
+       void *p = buf;
+       u8 reply_struct_v;
+       u32 num;
+       int ret;
+
+       ceph_decode_8_safe(&p, end, reply_struct_v, bad);
+       if (reply_struct_v != 1)
+               return -EINVAL;
+
+       ceph_decode_32_safe(&p, end, num, bad);
+       dout("%d tickets\n", num);
+
+       while (num--) {
+               ret = process_one_ticket(ac, secret, &p, end);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+
+bad:
+       return -EINVAL;
+}
+
 static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
                                   struct ceph_x_ticket_handler *th,
                                   struct ceph_x_authorizer *au)
@@ -583,13 +596,14 @@ static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac,
        struct ceph_x_ticket_handler *th;
        int ret = 0;
        struct ceph_x_authorize_reply reply;
+       void *preply = &reply;
        void *p = au->reply_buf;
        void *end = p + sizeof(au->reply_buf);
 
        th = get_ticket_handler(ac, au->service);
        if (IS_ERR(th))
                return PTR_ERR(th);
-       ret = ceph_x_decrypt(&th->session_key, &p, end, &reply, sizeof(reply));
+       ret = ceph_x_decrypt(&th->session_key, &p, end, &preply, sizeof(reply));
        if (ret < 0)
                return ret;
        if (ret != sizeof(reply))
index 067d3af2eaf61be41d601dc4324fc1a1565ab27d..61fcfc304f6869959b2ff510026ccb2e33700f21 100644 (file)
@@ -1181,7 +1181,15 @@ static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con,
        if (!m) {
                pr_info("alloc_msg unknown type %d\n", type);
                *skip = 1;
+       } else if (front_len > m->front_alloc_len) {
+               pr_warning("mon_alloc_msg front %d > prealloc %d (%u#%llu)\n",
+                          front_len, m->front_alloc_len,
+                          (unsigned int)con->peer_name.type,
+                          le64_to_cpu(con->peer_name.num));
+               ceph_msg_put(m);
+               m = ceph_msg_new(type, front_len, GFP_NOFS, false);
        }
+
        return m;
 }
 
index 488dd1a825c05b704a26d8c88582454f1745be4c..fdbc9a81d4c2033565c36815d425d0a7d80372b7 100644 (file)
@@ -775,7 +775,7 @@ __sum16 __skb_checksum_complete(struct sk_buff *skb)
 EXPORT_SYMBOL(__skb_checksum_complete);
 
 /**
- *     skb_copy_and_csum_datagram_iovec - Copy and checkum skb to user iovec.
+ *     skb_copy_and_csum_datagram_iovec - Copy and checksum skb to user iovec.
  *     @skb: skbuff
  *     @hlen: hardware length
  *     @iov: io vector
index b65a5051361f2dea31a0fac078b3dd656e126cc8..ab9a16530c3684b2e1ff39f6f0587fb6e4aa7f24 100644 (file)
@@ -2587,13 +2587,19 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
                return harmonize_features(skb, features);
        }
 
-       features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX |
-                                              NETIF_F_HW_VLAN_STAG_TX);
+       features = netdev_intersect_features(features,
+                                            skb->dev->vlan_features |
+                                            NETIF_F_HW_VLAN_CTAG_TX |
+                                            NETIF_F_HW_VLAN_STAG_TX);
 
        if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD))
-               features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST |
-                               NETIF_F_GEN_CSUM | NETIF_F_HW_VLAN_CTAG_TX |
-                               NETIF_F_HW_VLAN_STAG_TX;
+               features = netdev_intersect_features(features,
+                                                    NETIF_F_SG |
+                                                    NETIF_F_HIGHDMA |
+                                                    NETIF_F_FRAGLIST |
+                                                    NETIF_F_GEN_CSUM |
+                                                    NETIF_F_HW_VLAN_CTAG_TX |
+                                                    NETIF_F_HW_VLAN_STAG_TX);
 
        return harmonize_features(skb, features);
 }
@@ -4889,7 +4895,8 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev,
        if (adj->master)
                sysfs_remove_link(&(dev->dev.kobj), "master");
 
-       if (netdev_adjacent_is_neigh_list(dev, dev_list))
+       if (netdev_adjacent_is_neigh_list(dev, dev_list) &&
+           net_eq(dev_net(dev),dev_net(adj_dev)))
                netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list);
 
        list_del_rcu(&adj->list);
@@ -5159,11 +5166,65 @@ void netdev_upper_dev_unlink(struct net_device *dev,
 }
 EXPORT_SYMBOL(netdev_upper_dev_unlink);
 
+void netdev_adjacent_add_links(struct net_device *dev)
+{
+       struct netdev_adjacent *iter;
+
+       struct net *net = dev_net(dev);
+
+       list_for_each_entry(iter, &dev->adj_list.upper, list) {
+               if (!net_eq(net,dev_net(iter->dev)))
+                       continue;
+               netdev_adjacent_sysfs_add(iter->dev, dev,
+                                         &iter->dev->adj_list.lower);
+               netdev_adjacent_sysfs_add(dev, iter->dev,
+                                         &dev->adj_list.upper);
+       }
+
+       list_for_each_entry(iter, &dev->adj_list.lower, list) {
+               if (!net_eq(net,dev_net(iter->dev)))
+                       continue;
+               netdev_adjacent_sysfs_add(iter->dev, dev,
+                                         &iter->dev->adj_list.upper);
+               netdev_adjacent_sysfs_add(dev, iter->dev,
+                                         &dev->adj_list.lower);
+       }
+}
+
+void netdev_adjacent_del_links(struct net_device *dev)
+{
+       struct netdev_adjacent *iter;
+
+       struct net *net = dev_net(dev);
+
+       list_for_each_entry(iter, &dev->adj_list.upper, list) {
+               if (!net_eq(net,dev_net(iter->dev)))
+                       continue;
+               netdev_adjacent_sysfs_del(iter->dev, dev->name,
+                                         &iter->dev->adj_list.lower);
+               netdev_adjacent_sysfs_del(dev, iter->dev->name,
+                                         &dev->adj_list.upper);
+       }
+
+       list_for_each_entry(iter, &dev->adj_list.lower, list) {
+               if (!net_eq(net,dev_net(iter->dev)))
+                       continue;
+               netdev_adjacent_sysfs_del(iter->dev, dev->name,
+                                         &iter->dev->adj_list.upper);
+               netdev_adjacent_sysfs_del(dev, iter->dev->name,
+                                         &dev->adj_list.lower);
+       }
+}
+
 void netdev_adjacent_rename_links(struct net_device *dev, char *oldname)
 {
        struct netdev_adjacent *iter;
 
+       struct net *net = dev_net(dev);
+
        list_for_each_entry(iter, &dev->adj_list.upper, list) {
+               if (!net_eq(net,dev_net(iter->dev)))
+                       continue;
                netdev_adjacent_sysfs_del(iter->dev, oldname,
                                          &iter->dev->adj_list.lower);
                netdev_adjacent_sysfs_add(iter->dev, dev,
@@ -5171,6 +5232,8 @@ void netdev_adjacent_rename_links(struct net_device *dev, char *oldname)
        }
 
        list_for_each_entry(iter, &dev->adj_list.lower, list) {
+               if (!net_eq(net,dev_net(iter->dev)))
+                       continue;
                netdev_adjacent_sysfs_del(iter->dev, oldname,
                                          &iter->dev->adj_list.upper);
                netdev_adjacent_sysfs_add(iter->dev, dev,
@@ -6773,6 +6836,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
 
        /* Send a netdev-removed uevent to the old namespace */
        kobject_uevent(&dev->dev.kobj, KOBJ_REMOVE);
+       netdev_adjacent_del_links(dev);
 
        /* Actually switch the network namespace */
        dev_net_set(dev, net);
@@ -6787,6 +6851,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
 
        /* Send a netdev-add uevent to the new namespace */
        kobject_uevent(&dev->dev.kobj, KOBJ_ADD);
+       netdev_adjacent_add_links(dev);
 
        /* Fixup kobjects */
        err = device_rename(&dev->dev, dev->name);
index 6b5b6e7013cafec8a7b3767ed97a610bf35f1ae6..9d33dfffca19a992baf28e07ade0c7029c413ad0 100644 (file)
@@ -197,7 +197,7 @@ struct gen_estimator *gen_find_node(const struct gnet_stats_basic_packed *bstats
  * as destination. A new timer with the interval specified in the
  * configuration TLV is created. Upon each interval, the latest statistics
  * will be read from &bstats and the estimated rate will be stored in
- * &rate_est with the statistics lock grabed during this period.
+ * &rate_est with the statistics lock grabbed during this period.
  *
  * Returns 0 on success or a negative error code.
  *
index 9d3d9e78397b0f90f379addab25c7fd78294b3bc..2ddbce4cce144f62e8fed9dd39209fb3429b82a7 100644 (file)
@@ -206,7 +206,7 @@ EXPORT_SYMBOL(gnet_stats_copy_queue);
  * @st: application specific statistics data
  * @len: length of data
  *
- * Appends the application sepecific statistics to the top level TLV created by
+ * Appends the application specific statistics to the top level TLV created by
  * gnet_stats_start_copy() and remembers the data for XSTATS if the dumping
  * handle is in backward compatibility mode.
  *
index 163b673f9e62d212230abd1c9b848c35ba923a0d..da1378a3e2c72e0f23e9e21581dfd2ece5491d09 100644 (file)
@@ -2647,7 +2647,7 @@ EXPORT_SYMBOL(skb_prepare_seq_read);
  * skb_seq_read() will return the remaining part of the block.
  *
  * Note 1: The size of each block of data returned can be arbitrary,
- *       this limitation is the cost for zerocopy seqeuental
+ *       this limitation is the cost for zerocopy sequential
  *       reads of potentially non linear data.
  *
  * Note 2: Fragment lists within fragments are not implemented
@@ -2781,7 +2781,7 @@ EXPORT_SYMBOL(skb_find_text);
 /**
  * skb_append_datato_frags - append the user data to a skb
  * @sk: sock  structure
- * @skb: skb structure to be appened with user data.
+ * @skb: skb structure to be appended with user data.
  * @getfrag: call back function to be used for getting the user data
  * @from: pointer to user message iov
  * @length: length of the iov message
index 2714811afbd8bd3d35b5bd8619179eafaa71e19b..d372b4bd3f996dd3248e86748b7d16c912c9b5d7 100644 (file)
@@ -166,7 +166,7 @@ EXPORT_SYMBOL(sk_ns_capable);
 /**
  * sk_capable - Socket global capability test
  * @sk: Socket to use a capability on or through
- * @cap: The global capbility to use
+ * @cap: The global capability to use
  *
  * Test to see if the opener of the socket had when the socket was
  * created and the current process has the capability @cap in all user
@@ -183,7 +183,7 @@ EXPORT_SYMBOL(sk_capable);
  * @sk: Socket to use a capability on or through
  * @cap: The capability to use
  *
- * Test to see if the opener of the socket had when the socke was created
+ * Test to see if the opener of the socket had when the socket was created
  * and the current process has the capability @cap over the network namespace
  * the socket is a member of.
  */
@@ -1822,6 +1822,9 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
                                                           order);
                                        if (page)
                                                goto fill_page;
+                                       /* Do not retry other high order allocations */
+                                       order = 1;
+                                       max_page_order = 0;
                                }
                                order--;
                        }
@@ -1869,10 +1872,8 @@ EXPORT_SYMBOL(sock_alloc_send_skb);
  * no guarantee that allocations succeed. Therefore, @sz MUST be
  * less or equal than PAGE_SIZE.
  */
-bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio)
+bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t gfp)
 {
-       int order;
-
        if (pfrag->page) {
                if (atomic_read(&pfrag->page->_count) == 1) {
                        pfrag->offset = 0;
@@ -1883,20 +1884,21 @@ bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio)
                put_page(pfrag->page);
        }
 
-       order = SKB_FRAG_PAGE_ORDER;
-       do {
-               gfp_t gfp = prio;
-
-               if (order)
-                       gfp |= __GFP_COMP | __GFP_NOWARN | __GFP_NORETRY;
-               pfrag->page = alloc_pages(gfp, order);
+       pfrag->offset = 0;
+       if (SKB_FRAG_PAGE_ORDER) {
+               pfrag->page = alloc_pages(gfp | __GFP_COMP |
+                                         __GFP_NOWARN | __GFP_NORETRY,
+                                         SKB_FRAG_PAGE_ORDER);
                if (likely(pfrag->page)) {
-                       pfrag->offset = 0;
-                       pfrag->size = PAGE_SIZE << order;
+                       pfrag->size = PAGE_SIZE << SKB_FRAG_PAGE_ORDER;
                        return true;
                }
-       } while (--order >= 0);
-
+       }
+       pfrag->page = alloc_page(gfp);
+       if (likely(pfrag->page)) {
+               pfrag->size = PAGE_SIZE;
+               return true;
+       }
        return false;
 }
 EXPORT_SYMBOL(skb_page_frag_refill);
index 016b77ee88f0e2f1394c0456f67e9e01ec190d9f..6591d27e53a43413656a18a6eedb25d7bb5fe034 100644 (file)
@@ -246,7 +246,7 @@ lowpan_alloc_frag(struct sk_buff *skb, int size,
                        return ERR_PTR(-rc);
                }
        } else {
-               frag = ERR_PTR(ENOMEM);
+               frag = ERR_PTR(-ENOMEM);
        }
 
        return frag;
@@ -437,7 +437,7 @@ static void lowpan_setup(struct net_device *dev)
        /* Frame Control + Sequence Number + Address fields + Security Header */
        dev->hard_header_len    = 2 + 1 + 20 + 14;
        dev->needed_tailroom    = 2; /* FCS */
-       dev->mtu                = 1281;
+       dev->mtu                = IPV6_MIN_MTU;
        dev->tx_queue_len       = 0;
        dev->flags              = IFF_BROADCAST | IFF_MULTICAST;
        dev->watchdog_timeo     = 0;
index ffec6ce510056960bb92d6ef0c3e44bc9493676f..32755cb7e64e3c02f77c85bdad6982d31311bcc5 100644 (file)
@@ -355,8 +355,6 @@ int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type)
        struct net *net = dev_net(skb->dev);
        struct lowpan_frag_info *frag_info = lowpan_cb(skb);
        struct ieee802154_addr source, dest;
-       struct netns_ieee802154_lowpan *ieee802154_lowpan =
-               net_ieee802154_lowpan(net);
        int err;
 
        source = mac_cb(skb)->source;
@@ -366,8 +364,10 @@ int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type)
        if (err < 0)
                goto err;
 
-       if (frag_info->d_size > ieee802154_lowpan->max_dsize)
+       if (frag_info->d_size > IPV6_MIN_MTU) {
+               net_warn_ratelimited("lowpan_frag_rcv: datagram size exceeds MTU\n");
                goto err;
+       }
 
        fq = fq_find(net, frag_info, &source, &dest);
        if (fq != NULL) {
@@ -415,13 +415,6 @@ static struct ctl_table lowpan_frags_ns_ctl_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec_jiffies,
        },
-       {
-               .procname       = "6lowpanfrag_max_datagram_size",
-               .data           = &init_net.ieee802154_lowpan.max_dsize,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec
-       },
        { }
 };
 
@@ -458,7 +451,6 @@ static int __net_init lowpan_frags_ns_sysctl_register(struct net *net)
                table[1].data = &ieee802154_lowpan->frags.low_thresh;
                table[1].extra2 = &ieee802154_lowpan->frags.high_thresh;
                table[2].data = &ieee802154_lowpan->frags.timeout;
-               table[3].data = &ieee802154_lowpan->max_dsize;
 
                /* Don't export sysctls to unprivileged users */
                if (net->user_ns != &init_user_ns)
@@ -533,7 +525,6 @@ static int __net_init lowpan_frags_init_net(struct net *net)
        ieee802154_lowpan->frags.high_thresh = IPV6_FRAG_HIGH_THRESH;
        ieee802154_lowpan->frags.low_thresh = IPV6_FRAG_LOW_THRESH;
        ieee802154_lowpan->frags.timeout = IPV6_FRAG_TIMEOUT;
-       ieee802154_lowpan->max_dsize = 0xFFFF;
 
        inet_frags_init_net(&ieee802154_lowpan->frags);
 
index fb173126f03dfb19ef5a215693a1985cc00450a2..7cbcaf4f0194f22b797f04b1fca1029a0a4e159e 100644 (file)
@@ -82,6 +82,52 @@ config NF_TABLES_ARP
        help
          This option enables the ARP support for nf_tables.
 
+config NF_NAT_IPV4
+       tristate "IPv4 NAT"
+       depends on NF_CONNTRACK_IPV4
+       default m if NETFILTER_ADVANCED=n
+       select NF_NAT
+       help
+         The IPv4 NAT option allows masquerading, port forwarding and other
+         forms of full Network Address Port Translation. This can be
+         controlled by iptables or nft.
+
+if NF_NAT_IPV4
+
+config NF_NAT_SNMP_BASIC
+       tristate "Basic SNMP-ALG support"
+       depends on NF_CONNTRACK_SNMP
+       depends on NETFILTER_ADVANCED
+       default NF_NAT && NF_CONNTRACK_SNMP
+       ---help---
+
+         This module implements an Application Layer Gateway (ALG) for
+         SNMP payloads.  In conjunction with NAT, it allows a network
+         management system to access multiple private networks with
+         conflicting addresses.  It works by modifying IP addresses
+         inside SNMP payloads to match IP-layer NAT mapping.
+
+         This is the "basic" form of SNMP-ALG, as described in RFC 2962
+
+         To compile it as a module, choose M here.  If unsure, say N.
+
+config NF_NAT_PROTO_GRE
+       tristate
+       depends on NF_CT_PROTO_GRE
+
+config NF_NAT_PPTP
+       tristate
+       depends on NF_CONNTRACK
+       default NF_CONNTRACK_PPTP
+       select NF_NAT_PROTO_GRE
+
+config NF_NAT_H323
+       tristate
+       depends on NF_CONNTRACK
+       default NF_CONNTRACK_H323
+
+endif # NF_NAT_IPV4
+
 config IP_NF_IPTABLES
        tristate "IP tables support (required for filtering/masq/NAT)"
        default m if NETFILTER_ADVANCED=n
@@ -170,19 +216,21 @@ config IP_NF_TARGET_SYNPROXY
          To compile it as a module, choose M here. If unsure, say N.
 
 # NAT + specific targets: nf_conntrack
-config NF_NAT_IPV4
-       tristate "IPv4 NAT"
+config IP_NF_NAT
+       tristate "iptables NAT support"
        depends on NF_CONNTRACK_IPV4
        default m if NETFILTER_ADVANCED=n
        select NF_NAT
+       select NF_NAT_IPV4
+       select NETFILTER_XT_NAT
        help
-         The IPv4 NAT option allows masquerading, port forwarding and other
-         forms of full Network Address Port Translation.  It is controlled by
-         the `nat' table in iptables: see the man page for iptables(8).
+         This enables the `nat' table in iptables. This allows masquerading,
+         port forwarding and other forms of full Network Address Port
+         Translation.
 
          To compile it as a module, choose M here.  If unsure, say N.
 
-if NF_NAT_IPV4
+if IP_NF_NAT
 
 config IP_NF_TARGET_MASQUERADE
        tristate "MASQUERADE target support"
@@ -214,47 +262,7 @@ config IP_NF_TARGET_REDIRECT
        (e.g. when running oldconfig). It selects
        CONFIG_NETFILTER_XT_TARGET_REDIRECT.
 
-endif
-
-config NF_NAT_SNMP_BASIC
-       tristate "Basic SNMP-ALG support"
-       depends on NF_CONNTRACK_SNMP && NF_NAT_IPV4
-       depends on NETFILTER_ADVANCED
-       default NF_NAT && NF_CONNTRACK_SNMP
-       ---help---
-
-         This module implements an Application Layer Gateway (ALG) for
-         SNMP payloads.  In conjunction with NAT, it allows a network
-         management system to access multiple private networks with
-         conflicting addresses.  It works by modifying IP addresses
-         inside SNMP payloads to match IP-layer NAT mapping.
-
-         This is the "basic" form of SNMP-ALG, as described in RFC 2962
-
-         To compile it as a module, choose M here.  If unsure, say N.
-
-# If they want FTP, set to $CONFIG_IP_NF_NAT (m or y),
-# or $CONFIG_IP_NF_FTP (m or y), whichever is weaker.
-# From kconfig-language.txt:
-#
-#           <expr> '&&' <expr>                   (6)
-#
-# (6) Returns the result of min(/expr/, /expr/).
-
-config NF_NAT_PROTO_GRE
-       tristate
-       depends on NF_NAT_IPV4 && NF_CT_PROTO_GRE
-
-config NF_NAT_PPTP
-       tristate
-       depends on NF_CONNTRACK && NF_NAT_IPV4
-       default NF_NAT_IPV4 && NF_CONNTRACK_PPTP
-       select NF_NAT_PROTO_GRE
-
-config NF_NAT_H323
-       tristate
-       depends on NF_CONNTRACK && NF_NAT_IPV4
-       default NF_NAT_IPV4 && NF_CONNTRACK_H323
+endif # IP_NF_NAT
 
 # mangle + specific targets
 config IP_NF_MANGLE
index 33001621465b8d131e59cfce8920f87f3e46c7fc..edf4af32e9f28fcdb3a391abbb0d651b4a16af38 100644 (file)
@@ -43,7 +43,7 @@ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
 # the three instances of ip_tables
 obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
 obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
-obj-$(CONFIG_NF_NAT_IPV4) += iptable_nat.o
+obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o
 obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
 obj-$(CONFIG_IP_NF_SECURITY) += iptable_security.o
 
index 0b239fc1816ed828862f19cdde0f08720a0b43ca..fc1fac2a052856e5c1b2476dc469d261a6558e5e 100644 (file)
@@ -1690,14 +1690,12 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp)
        addrconf_mod_dad_work(ifp, 0);
 }
 
-/* Join to solicited addr multicast group. */
-
+/* Join to solicited addr multicast group.
+ * caller must hold RTNL */
 void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr)
 {
        struct in6_addr maddr;
 
-       ASSERT_RTNL();
-
        if (dev->flags&(IFF_LOOPBACK|IFF_NOARP))
                return;
 
@@ -1705,12 +1703,11 @@ void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr)
        ipv6_dev_mc_inc(dev, &maddr);
 }
 
+/* caller must hold RTNL */
 void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr)
 {
        struct in6_addr maddr;
 
-       ASSERT_RTNL();
-
        if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP))
                return;
 
@@ -1718,12 +1715,11 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr)
        __ipv6_dev_mc_dec(idev, &maddr);
 }
 
+/* caller must hold RTNL */
 static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
 {
        struct in6_addr addr;
 
-       ASSERT_RTNL();
-
        if (ifp->prefix_len >= 127) /* RFC 6164 */
                return;
        ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
@@ -1732,12 +1728,11 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp)
        ipv6_dev_ac_inc(ifp->idev->dev, &addr);
 }
 
+/* caller must hold RTNL */
 static void addrconf_leave_anycast(struct inet6_ifaddr *ifp)
 {
        struct in6_addr addr;
 
-       ASSERT_RTNL();
-
        if (ifp->prefix_len >= 127) /* RFC 6164 */
                return;
        ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len);
@@ -4773,15 +4768,11 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
                addrconf_leave_solict(ifp->idev, &ifp->addr);
                if (!ipv6_addr_any(&ifp->peer_addr)) {
                        struct rt6_info *rt;
-                       struct net_device *dev = ifp->idev->dev;
-
-                       rt = rt6_lookup(dev_net(dev), &ifp->peer_addr, NULL,
-                                       dev->ifindex, 1);
-                       if (rt) {
-                               dst_hold(&rt->dst);
-                               if (ip6_del_rt(rt))
-                                       dst_free(&rt->dst);
-                       }
+
+                       rt = addrconf_get_prefix_route(&ifp->peer_addr, 128,
+                                                      ifp->idev->dev, 0, 0);
+                       if (rt && ip6_del_rt(rt))
+                               dst_free(&rt->dst);
                }
                dst_hold(&ifp->rt->dst);
 
index 2101832446896245e54b608bb24f27d83e42a005..ff2de7d9d8e6553de407b7aa5a490fc5c9a40461 100644 (file)
@@ -77,6 +77,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
        pac->acl_next = NULL;
        pac->acl_addr = *addr;
 
+       rtnl_lock();
        rcu_read_lock();
        if (ifindex == 0) {
                struct rt6_info *rt;
@@ -137,6 +138,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
 
 error:
        rcu_read_unlock();
+       rtnl_unlock();
        if (pac)
                sock_kfree_s(sk, pac, sizeof(*pac));
        return err;
@@ -171,11 +173,13 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
 
        spin_unlock_bh(&ipv6_sk_ac_lock);
 
+       rtnl_lock();
        rcu_read_lock();
        dev = dev_get_by_index_rcu(net, pac->acl_ifindex);
        if (dev)
                ipv6_dev_ac_dec(dev, &pac->acl_addr);
        rcu_read_unlock();
+       rtnl_unlock();
 
        sock_kfree_s(sk, pac, sizeof(*pac));
        return 0;
@@ -198,6 +202,7 @@ void ipv6_sock_ac_close(struct sock *sk)
        spin_unlock_bh(&ipv6_sk_ac_lock);
 
        prev_index = 0;
+       rtnl_lock();
        rcu_read_lock();
        while (pac) {
                struct ipv6_ac_socklist *next = pac->acl_next;
@@ -212,6 +217,7 @@ void ipv6_sock_ac_close(struct sock *sk)
                pac = next;
        }
        rcu_read_unlock();
+       rtnl_unlock();
 }
 
 static void aca_put(struct ifacaddr6 *ac)
@@ -233,6 +239,8 @@ int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr)
        struct rt6_info *rt;
        int err;
 
+       ASSERT_RTNL();
+
        idev = in6_dev_get(dev);
 
        if (idev == NULL)
@@ -302,6 +310,8 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr)
 {
        struct ifacaddr6 *aca, *prev_aca;
 
+       ASSERT_RTNL();
+
        write_lock_bh(&idev->lock);
        prev_aca = NULL;
        for (aca = idev->ac_list; aca; aca = aca->aca_next) {
index 617f0958e164e7893ca70e80e09d1ed933c95b69..a23b655a7627a69046d956139946c00dda8825f4 100644 (file)
@@ -172,6 +172,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
        mc_lst->next = NULL;
        mc_lst->addr = *addr;
 
+       rtnl_lock();
        rcu_read_lock();
        if (ifindex == 0) {
                struct rt6_info *rt;
@@ -185,6 +186,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
 
        if (dev == NULL) {
                rcu_read_unlock();
+               rtnl_unlock();
                sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
                return -ENODEV;
        }
@@ -202,6 +204,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
 
        if (err) {
                rcu_read_unlock();
+               rtnl_unlock();
                sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
                return err;
        }
@@ -212,6 +215,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
        spin_unlock(&ipv6_sk_mc_lock);
 
        rcu_read_unlock();
+       rtnl_unlock();
 
        return 0;
 }
@@ -229,6 +233,7 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
        if (!ipv6_addr_is_multicast(addr))
                return -EINVAL;
 
+       rtnl_lock();
        spin_lock(&ipv6_sk_mc_lock);
        for (lnk = &np->ipv6_mc_list;
             (mc_lst = rcu_dereference_protected(*lnk,
@@ -252,12 +257,15 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
                        } else
                                (void) ip6_mc_leave_src(sk, mc_lst, NULL);
                        rcu_read_unlock();
+                       rtnl_unlock();
+
                        atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc);
                        kfree_rcu(mc_lst, rcu);
                        return 0;
                }
        }
        spin_unlock(&ipv6_sk_mc_lock);
+       rtnl_unlock();
 
        return -EADDRNOTAVAIL;
 }
@@ -302,6 +310,7 @@ void ipv6_sock_mc_close(struct sock *sk)
        if (!rcu_access_pointer(np->ipv6_mc_list))
                return;
 
+       rtnl_lock();
        spin_lock(&ipv6_sk_mc_lock);
        while ((mc_lst = rcu_dereference_protected(np->ipv6_mc_list,
                                lockdep_is_held(&ipv6_sk_mc_lock))) != NULL) {
@@ -328,6 +337,7 @@ void ipv6_sock_mc_close(struct sock *sk)
                spin_lock(&ipv6_sk_mc_lock);
        }
        spin_unlock(&ipv6_sk_mc_lock);
+       rtnl_unlock();
 }
 
 int ip6_mc_source(int add, int omode, struct sock *sk,
@@ -845,6 +855,8 @@ int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr)
        struct ifmcaddr6 *mc;
        struct inet6_dev *idev;
 
+       ASSERT_RTNL();
+
        /* we need to take a reference on idev */
        idev = in6_dev_get(dev);
 
@@ -916,6 +928,8 @@ int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr)
 {
        struct ifmcaddr6 *ma, **map;
 
+       ASSERT_RTNL();
+
        write_lock_bh(&idev->lock);
        for (map = &idev->mc_list; (ma=*map) != NULL; map = &ma->next) {
                if (ipv6_addr_equal(&ma->mca_addr, addr)) {
index ac93df16f5af678f8724346343517ef241a415f3..2812816aabdc0a2918b183094ac4a119b4c0f1fa 100644 (file)
@@ -57,9 +57,19 @@ config NFT_REJECT_IPV6
 
 config NF_LOG_IPV6
        tristate "IPv6 packet logging"
-       depends on NETFILTER_ADVANCED
+       default m if NETFILTER_ADVANCED=n
        select NF_LOG_COMMON
 
+config NF_NAT_IPV6
+       tristate "IPv6 NAT"
+       depends on NF_CONNTRACK_IPV6
+       depends on NETFILTER_ADVANCED
+       select NF_NAT
+       help
+         The IPv6 NAT option allows masquerading, port forwarding and other
+         forms of full Network Address Port Translation. This can be
+         controlled by iptables or nft.
+
 config IP6_NF_IPTABLES
        tristate "IP6 tables support (required for filtering)"
        depends on INET && IPV6
@@ -232,19 +242,21 @@ config IP6_NF_SECURITY
 
          If unsure, say N.
 
-config NF_NAT_IPV6
-       tristate "IPv6 NAT"
+config IP6_NF_NAT
+       tristate "ip6tables NAT support"
        depends on NF_CONNTRACK_IPV6
        depends on NETFILTER_ADVANCED
        select NF_NAT
+       select NF_NAT_IPV6
+       select NETFILTER_XT_NAT
        help
-         The IPv6 NAT option allows masquerading, port forwarding and other
-         forms of full Network Address Port Translation. It is controlled by
-         the `nat' table in ip6tables, see the man page for ip6tables(8).
+         This enables the `nat' table in ip6tables. This allows masquerading,
+         port forwarding and other forms of full Network Address Port
+         Translation.
 
          To compile it as a module, choose M here.  If unsure, say N.
 
-if NF_NAT_IPV6
+if IP6_NF_NAT
 
 config IP6_NF_TARGET_MASQUERADE
        tristate "MASQUERADE target support"
@@ -265,7 +277,7 @@ config IP6_NF_TARGET_NPT
 
          To compile it as a module, choose M here.  If unsure, say N.
 
-endif # NF_NAT_IPV6
+endif # IP6_NF_NAT
 
 endif # IP6_NF_IPTABLES
 
index c0b263104ed23170e15b3278408fe95f36c77da9..c3d3286db4bb804546ee8b0488ecdad1441bb06b 100644 (file)
@@ -8,7 +8,7 @@ obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
 obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
 obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
 obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o
-obj-$(CONFIG_NF_NAT_IPV6) += ip6table_nat.o
+obj-$(CONFIG_IP6_NF_NAT) += ip6table_nat.o
 
 # objects for l3 independent conntrack
 nf_conntrack_ipv6-y  :=  nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o
index 13752d96275e8b9142539a201ea1ac6f45f883ba..b704a9356208f5cc3064085b9d82eab52542dd5a 100644 (file)
@@ -755,7 +755,8 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
        /* If PMTU discovery was enabled, use the MTU that was discovered */
        dst = sk_dst_get(tunnel->sock);
        if (dst != NULL) {
-               u32 pmtu = dst_mtu(__sk_dst_get(tunnel->sock));
+               u32 pmtu = dst_mtu(dst);
+
                if (pmtu != 0)
                        session->mtu = session->mru = pmtu -
                                PPPOL2TP_HEADER_OVERHEAD;
index 0375009ddc0db39fd5a365db8cb5e4122219d864..399ad82c997f99c33833c03c67e6acddf7019b6f 100644 (file)
@@ -541,6 +541,8 @@ static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local,
                        continue;
                if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf)
                        continue;
+               if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+                       continue;
 
                if (!compat)
                        compat = &sdata->vif.bss_conf.chandef;
index 3db96648b45a02c0e0235b724210a15ba32747b7..86173c0de40e91d658e883514232c720a4c51e0e 100644 (file)
@@ -167,7 +167,7 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
        p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n",
                        sta->ampdu_mlme.dialog_token_allocator + 1);
        p += scnprintf(p, sizeof(buf) + buf - p,
-                      "TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tpending\n");
+                      "TID\t\tRX\tDTKN\tSSN\t\tTX\tDTKN\tpending\n");
 
        for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
                tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[i]);
index 01eede7406a55610e771c7cd906cbedcfff1fa6a..f75e5f132c5ad4a816fc933defedda38f0695e66 100644 (file)
@@ -1175,8 +1175,8 @@ static void ieee80211_iface_work(struct work_struct *work)
                        if (sta) {
                                u16 last_seq;
 
-                               last_seq = le16_to_cpu(
-                                       sta->last_seq_ctrl[rx_agg->tid]);
+                               last_seq = IEEE80211_SEQ_TO_SN(le16_to_cpu(
+                                       sta->last_seq_ctrl[rx_agg->tid]));
 
                                __ieee80211_start_rx_ba_session(sta,
                                                0, 0,
index 63b874101b2763d5997dc561073e96807596c11a..c47194d2714933bd8e1dc3658ffd165cd50a5a4a 100644 (file)
@@ -959,7 +959,8 @@ mesh_plink_get_event(struct ieee80211_sub_if_data *sdata,
                if (!matches_local)
                        event = CNF_RJCT;
                if (!mesh_plink_free_count(sdata) ||
-                   (sta->llid != llid || sta->plid != plid))
+                   sta->llid != llid ||
+                   (sta->plid && sta->plid != plid))
                        event = CNF_IGNR;
                else
                        event = CNF_ACPT;
@@ -1080,6 +1081,10 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata,
                goto unlock_rcu;
        }
 
+       /* 802.11-2012 13.3.7.2 - update plid on CNF if not set */
+       if (!sta->plid && event == CNF_ACPT)
+               sta->plid = plid;
+
        changed |= mesh_plink_fsm(sdata, sta, event);
 
 unlock_rcu:
index 31a8afaf73323bc09fb99f8e960b17c3fa2e31fd..b82a12a9f0f110779756027944dce6293d1387fb 100644 (file)
@@ -4376,8 +4376,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
        rcu_read_unlock();
 
        if (bss->wmm_used && bss->uapsd_supported &&
-           (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) &&
-           sdata->wmm_acm != 0xff) {
+           (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) {
                assoc_data->uapsd = true;
                ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED;
        } else {
index c6ee2139fbc579bab35e8cc5bfb6f3b4994930d2..441875f03750ca5a41255faaf9e062c8af1efc32 100644 (file)
@@ -1094,8 +1094,11 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
        unsigned long flags;
        struct ps_data *ps;
 
-       if (sdata->vif.type == NL80211_IFTYPE_AP ||
-           sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+       if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+               sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
+                                    u.ap);
+
+       if (sdata->vif.type == NL80211_IFTYPE_AP)
                ps = &sdata->bss->ps;
        else if (ieee80211_vif_is_mesh(&sdata->vif))
                ps = &sdata->u.mesh.ps;
index 3c3069fd69718277fc719e82d7bf2c51bb9747db..547838822d5e9c0d7064d72e2dc3be1ff2c14e14 100644 (file)
@@ -462,7 +462,10 @@ mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb,
                        skb->pkt_type = PACKET_OTHERHOST;
                break;
        default:
-               break;
+               spin_unlock_bh(&sdata->mib_lock);
+               pr_debug("invalid dest mode\n");
+               kfree_skb(skb);
+               return NET_RX_DROP;
        }
 
        spin_unlock_bh(&sdata->mib_lock);
@@ -573,6 +576,7 @@ void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb)
        ret = mac802154_parse_frame_start(skb, &hdr);
        if (ret) {
                pr_debug("got invalid frame\n");
+               kfree_skb(skb);
                return;
        }
 
index ad751fe2e82b8ca017bc83f07d3dd7e9f04229f5..b5c1d3aadb41569d95728d9eca5faf6831caa9dc 100644 (file)
@@ -499,7 +499,7 @@ config NFT_LIMIT
 config NFT_NAT
        depends on NF_TABLES
        depends on NF_CONNTRACK
-       depends on NF_NAT
+       select NF_NAT
        tristate "Netfilter nf_tables nat module"
        help
          This option adds the "nat" expression that you can use to perform
@@ -747,7 +747,9 @@ config NETFILTER_XT_TARGET_LED
 
 config NETFILTER_XT_TARGET_LOG
        tristate "LOG target support"
-       depends on NF_LOG_IPV4 && NF_LOG_IPV6
+       select NF_LOG_COMMON
+       select NF_LOG_IPV4
+       select NF_LOG_IPV6 if IPV6
        default m if NETFILTER_ADVANCED=n
        help
          This option adds a `LOG' target, which allows you to create rules in
@@ -764,6 +766,14 @@ config NETFILTER_XT_TARGET_MARK
        (e.g. when running oldconfig). It selects
        CONFIG_NETFILTER_XT_MARK (combined mark/MARK module).
 
+config NETFILTER_XT_NAT
+       tristate '"SNAT and DNAT" targets support'
+       depends on NF_NAT
+       ---help---
+       This option enables the SNAT and DNAT targets.
+
+       To compile it as a module, choose M here. If unsure, say N.
+
 config NETFILTER_XT_TARGET_NETMAP
        tristate '"NETMAP" target support'
        depends on NF_NAT
index 8308624a406ac0d891338e73c44abe6a5fa4c8b0..fad5fdba34e5873c0535037bf709c343ebfd55e3 100644 (file)
@@ -95,7 +95,7 @@ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
 obj-$(CONFIG_NETFILTER_XT_MARK) += xt_mark.o
 obj-$(CONFIG_NETFILTER_XT_CONNMARK) += xt_connmark.o
 obj-$(CONFIG_NETFILTER_XT_SET) += xt_set.o
-obj-$(CONFIG_NF_NAT) += xt_nat.o
+obj-$(CONFIG_NETFILTER_XT_NAT) += xt_nat.o
 
 # targets
 obj-$(CONFIG_NETFILTER_XT_TARGET_AUDIT) += xt_AUDIT.o
index a93c97f106d4a5022cd0e1196ee70ecdfd8c2873..024a2e25c8a49448afbeed4f780912b24a6318a3 100644 (file)
@@ -54,7 +54,7 @@ EXPORT_SYMBOL_GPL(nf_unregister_afinfo);
 struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS] __read_mostly;
 EXPORT_SYMBOL(nf_hooks);
 
-#if defined(CONFIG_JUMP_LABEL)
+#ifdef HAVE_JUMP_LABEL
 struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
 EXPORT_SYMBOL(nf_hooks_needed);
 #endif
@@ -72,7 +72,7 @@ int nf_register_hook(struct nf_hook_ops *reg)
        }
        list_add_rcu(&reg->list, elem->list.prev);
        mutex_unlock(&nf_hook_mutex);
-#if defined(CONFIG_JUMP_LABEL)
+#ifdef HAVE_JUMP_LABEL
        static_key_slow_inc(&nf_hooks_needed[reg->pf][reg->hooknum]);
 #endif
        return 0;
@@ -84,7 +84,7 @@ void nf_unregister_hook(struct nf_hook_ops *reg)
        mutex_lock(&nf_hook_mutex);
        list_del_rcu(&reg->list);
        mutex_unlock(&nf_hook_mutex);
-#if defined(CONFIG_JUMP_LABEL)
+#ifdef HAVE_JUMP_LABEL
        static_key_slow_dec(&nf_hooks_needed[reg->pf][reg->hooknum]);
 #endif
        synchronize_net();
index e6836755c45d4168bb6ccc9ab6f12708e9e17f3d..5c34e8d42e0190a14ec31c1238bde5929fdf0539 100644 (file)
@@ -1906,7 +1906,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
        {
                .hook           = ip_vs_local_reply6,
                .owner          = THIS_MODULE,
-               .pf             = NFPROTO_IPV4,
+               .pf             = NFPROTO_IPV6,
                .hooknum        = NF_INET_LOCAL_OUT,
                .priority       = NF_IP6_PRI_NAT_DST + 1,
        },
index 6f70bdd3a90ad85c72cb100de997d2f5b5bc40a1..56896a412bcec7ae01726734115d19bc04079274 100644 (file)
@@ -38,6 +38,7 @@
 #include <net/route.h>                  /* for ip_route_output */
 #include <net/ipv6.h>
 #include <net/ip6_route.h>
+#include <net/ip_tunnels.h>
 #include <net/addrconf.h>
 #include <linux/icmpv6.h>
 #include <linux/netfilter.h>
@@ -862,11 +863,15 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
                old_iph = ip_hdr(skb);
        }
 
-       skb->transport_header = skb->network_header;
-
        /* fix old IP header checksum */
        ip_send_check(old_iph);
 
+       skb = iptunnel_handle_offloads(skb, false, SKB_GSO_IPIP);
+       if (IS_ERR(skb))
+               goto tx_error;
+
+       skb->transport_header = skb->network_header;
+
        skb_push(skb, sizeof(struct iphdr));
        skb_reset_network_header(skb);
        memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
@@ -900,7 +905,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
        return NF_STOLEN;
 
   tx_error:
-       kfree_skb(skb);
+       if (!IS_ERR(skb))
+               kfree_skb(skb);
        rcu_read_unlock();
        LeaveFunction(10);
        return NF_STOLEN;
@@ -953,6 +959,11 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
                old_iph = ipv6_hdr(skb);
        }
 
+       /* GSO: we need to provide proper SKB_GSO_ value for IPv6 */
+       skb = iptunnel_handle_offloads(skb, false, 0); /* SKB_GSO_SIT/IPV6 */
+       if (IS_ERR(skb))
+               goto tx_error;
+
        skb->transport_header = skb->network_header;
 
        skb_push(skb, sizeof(struct ipv6hdr));
@@ -988,7 +999,8 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
        return NF_STOLEN;
 
 tx_error:
-       kfree_skb(skb);
+       if (!IS_ERR(skb))
+               kfree_skb(skb);
        rcu_read_unlock();
        LeaveFunction(10);
        return NF_STOLEN;
index f4e833005320fa7da4c0deb41bba272e8c54bd8e..7198d660b4dea1e9e79c6f9a13f4e6669bca569d 100644 (file)
@@ -31,7 +31,7 @@ static int cgroup_mt_check(const struct xt_mtchk_param *par)
        if (info->invert & ~1)
                return -EINVAL;
 
-       return info->id ? 0 : -EINVAL;
+       return 0;
 }
 
 static bool
index 7228ec3faf19cdc02a685caa04ccbf04ddf8005a..91d66b7e64ac71f31dcc78208857a20ce7a97f79 100644 (file)
@@ -265,8 +265,11 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
                upcall.key = &key;
                upcall.userdata = NULL;
                upcall.portid = ovs_vport_find_upcall_portid(p, skb);
-               ovs_dp_upcall(dp, skb, &upcall);
-               consume_skb(skb);
+               error = ovs_dp_upcall(dp, skb, &upcall);
+               if (unlikely(error))
+                       kfree_skb(skb);
+               else
+                       consume_skb(skb);
                stats_counter = &stats->n_missed;
                goto out;
        }
@@ -404,7 +407,7 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
 {
        struct ovs_header *upcall;
        struct sk_buff *nskb = NULL;
-       struct sk_buff *user_skb; /* to be queued to userspace */
+       struct sk_buff *user_skb = NULL; /* to be queued to userspace */
        struct nlattr *nla;
        struct genl_info info = {
                .dst_sk = ovs_dp_get_net(dp)->genl_sock,
@@ -494,9 +497,11 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
        ((struct nlmsghdr *) user_skb->data)->nlmsg_len = user_skb->len;
 
        err = genlmsg_unicast(ovs_dp_get_net(dp), user_skb, upcall_info->portid);
+       user_skb = NULL;
 out:
        if (err)
                skb_tx_error(skb);
+       kfree_skb(user_skb);
        kfree_skb(nskb);
        return err;
 }
index 14c98e48f261ee49656eabb198d62648890b63b3..02a86a27fd846602dd0c9aafd0a045f196e246b4 100644 (file)
@@ -158,6 +158,7 @@ static const struct acpi_device_id rfkill_acpi_match[] = {
        { "BCM2E1A", RFKILL_TYPE_BLUETOOTH },
        { "BCM2E39", RFKILL_TYPE_BLUETOOTH },
        { "BCM2E3D", RFKILL_TYPE_BLUETOOTH },
+       { "BCM2E64", RFKILL_TYPE_BLUETOOTH },
        { "BCM4752", RFKILL_TYPE_GPS },
        { "LNV4752", RFKILL_TYPE_GPS },
        { },
index eb71d49e76537f17d48e3eeaa43661fb09788f41..634a2abb5f3a25f15ca99c4737190c1e5e17b27a 100644 (file)
@@ -4243,7 +4243,7 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len,
        transport = asoc->peer.primary_path;
 
        status.sstat_assoc_id = sctp_assoc2id(asoc);
-       status.sstat_state = asoc->state;
+       status.sstat_state = sctp_assoc_to_state(asoc);
        status.sstat_rwnd =  asoc->peer.rwnd;
        status.sstat_unackdata = asoc->unack_data;
 
index 95ee7d8682e7447f45f5ddb0ddbde5fff196c84e..2e2586e2dee19184e07e01c528563c7000cf912e 100644 (file)
@@ -734,8 +734,7 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
        }
 
        memset(&tss, 0, sizeof(tss));
-       if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE ||
-            skb_shinfo(skb)->tx_flags & SKBTX_ANY_SW_TSTAMP) &&
+       if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) &&
            ktime_to_timespec_cond(skb->tstamp, tss.ts + 0))
                empty = 0;
        if (shhwtstamps &&
@@ -2602,7 +2601,7 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
  *
  *     This function is called by a protocol handler that wants to
  *     advertise its address family, and have it linked into the
- *     socket interface. The value ops->family coresponds to the
+ *     socket interface. The value ops->family corresponds to the
  *     socket system call protocol family.
  */
 int sock_register(const struct net_proto_family *ops)
index 31a731e06f5022afd7c040d5688840491b228e9d..4d08b398411fdec9b6707b4cd0db2fd73f1b13fa 100755 (executable)
@@ -2133,7 +2133,10 @@ sub process {
 # Check for improperly formed commit descriptions
                if ($in_commit_log &&
                    $line =~ /\bcommit\s+[0-9a-f]{5,}/i &&
-                   $line !~ /\b[Cc]ommit [0-9a-f]{12,16} \("/) {
+                   !($line =~ /\b[Cc]ommit [0-9a-f]{12,40} \("/ ||
+                     ($line =~ /\b[Cc]ommit [0-9a-f]{12,40}\s*$/ &&
+                      defined $rawlines[$linenr] &&
+                      $rawlines[$linenr] =~ /^\s*\("/))) {
                        $line =~ /\b(c)ommit\s+([0-9a-f]{5,})/i;
                        my $init_char = $1;
                        my $orig_commit = lc($2);
@@ -2141,7 +2144,7 @@ sub process {
                        my $desc = 'commit description';
                        ($id, $desc) = git_commit_info($orig_commit, $id, $desc);
                        ERROR("GIT_COMMIT_ID",
-                             "Please use 12 to 16 chars for the git commit ID like: '${init_char}ommit $id (\"$desc\")'\n" . $herecurr);
+                             "Please use 12 or more chars for the git commit ID like: '${init_char}ommit $id (\"$desc\")'\n" . $herecurr);
                }
 
 # Check for added, moved or deleted files
index 16a07cfa4d3469d0a386cc1264afb07c6241bcea..70bea942b4135b6a607bdb8ded0f50f0142aba40 100755 (executable)
@@ -2085,6 +2085,7 @@ sub dump_function($$) {
     $prototype =~ s/^noinline +//;
     $prototype =~ s/__init +//;
     $prototype =~ s/__init_or_module +//;
+    $prototype =~ s/__meminit +//;
     $prototype =~ s/__must_check +//;
     $prototype =~ s/__weak +//;
     my $define = $prototype =~ s/^#\s*define\s+//; #ak added
index b90a68c4e2c4277035b21f873af64efcd95bf782..6d0cad16f00265a1dc31d8a0804984040fb47995 100644 (file)
@@ -27,8 +27,8 @@ DEFINE_SPINLOCK(key_serial_lock);
 struct rb_root key_user_tree; /* tree of quota records indexed by UID */
 DEFINE_SPINLOCK(key_user_lock);
 
-unsigned int key_quota_root_maxkeys = 200;     /* root's key count quota */
-unsigned int key_quota_root_maxbytes = 20000;  /* root's key space quota */
+unsigned int key_quota_root_maxkeys = 1000000; /* root's key count quota */
+unsigned int key_quota_root_maxbytes = 25000000; /* root's key space quota */
 unsigned int key_quota_maxkeys = 200;          /* general key count quota */
 unsigned int key_quota_maxbytes = 20000;       /* general key space quota */
 
index a3386d119425eb8367194063470efe017eef622b..bed745c8b1a30d47a173fd7d96322aebb2d09c9c 100644 (file)
@@ -173,7 +173,7 @@ static char *tomoyo_get_local_path(struct dentry *dentry, char * const buffer,
                 * Use filesystem name if filesystem does not support rename()
                 * operation.
                 */
-               if (!inode->i_op->rename)
+               if (!inode->i_op->rename && !inode->i_op->rename2)
                        goto prepend_filesystem_name;
        }
        /* Prepend device name. */
@@ -282,7 +282,8 @@ char *tomoyo_realpath_from_path(struct path *path)
                 * Get local name for filesystems without rename() operation
                 * or dentry without vfsmount.
                 */
-               if (!path->mnt || !inode->i_op->rename)
+               if (!path->mnt ||
+                   (!inode->i_op->rename && !inode->i_op->rename2))
                        pos = tomoyo_get_local_path(path->dentry, buf,
                                                    buf_len - 1);
                /* Get absolute name for the rest. */
index 051d55b05521216d31a1d011d58560744e930672..9f404e965ea26366e6ad9ec65e4946263650fd37 100644 (file)
@@ -684,7 +684,7 @@ int snd_info_card_free(struct snd_card *card)
  * snd_info_get_line - read one line from the procfs buffer
  * @buffer: the procfs buffer
  * @line: the buffer to store
- * @len: the max. buffer size - 1
+ * @len: the max. buffer size
  *
  * Reads one line from the buffer and stores the string.
  *
@@ -704,7 +704,7 @@ int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len)
                        buffer->stop = 1;
                if (c == '\n')
                        break;
-               if (len) {
+               if (len > 1) {
                        len--;
                        *line++ = c;
                }
index 4560ca0e5651ac6c515c589efa18fc8d308b1910..2c6fd80e0bd1fd0042848bdc3e68bd2734c4a0c5 100644 (file)
@@ -142,11 +142,11 @@ static struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = {
        },
        [SNDRV_PCM_FORMAT_DSD_U8] = {
                .width = 8, .phys = 8, .le = 1, .signd = 0,
-               .silence = {},
+               .silence = { 0x69 },
        },
        [SNDRV_PCM_FORMAT_DSD_U16_LE] = {
                .width = 16, .phys = 16, .le = 1, .signd = 0,
-               .silence = {},
+               .silence = { 0x69, 0x69 },
        },
        /* FIXME: the following three formats are not defined properly yet */
        [SNDRV_PCM_FORMAT_MPEG] = {
index f96bf4c7c23236a773f13a0c318ddb5b6f275977..95fc2eaf11dc0f91bcb235a2929b300c39448052 100644 (file)
@@ -507,7 +507,16 @@ static void amdtp_pull_midi(struct amdtp_stream *s,
 static void update_pcm_pointers(struct amdtp_stream *s,
                                struct snd_pcm_substream *pcm,
                                unsigned int frames)
-{      unsigned int ptr;
+{
+       unsigned int ptr;
+
+       /*
+        * In IEC 61883-6, one data block represents one event. In ALSA, one
+        * event equals to one PCM frame. But Dice has a quirk to transfer
+        * two PCM frames in one data block.
+        */
+       if (s->double_pcm_frames)
+               frames *= 2;
 
        ptr = s->pcm_buffer_pointer + frames;
        if (ptr >= pcm->runtime->buffer_size)
index d8ee7b0e938629a828571fcd45ce5da5edc02469..4823c08196ac775f150656b712dd7839b5428a29 100644 (file)
@@ -125,6 +125,7 @@ struct amdtp_stream {
        unsigned int pcm_buffer_pointer;
        unsigned int pcm_period_pointer;
        bool pointer_flush;
+       bool double_pcm_frames;
 
        struct snd_rawmidi_substream *midi[AMDTP_MAX_CHANNELS_FOR_MIDI * 8];
 
index a9a30c0161f17be87e9c79403d1c913f85ab4c86..e3a04d69c85363dfffdc6bebf5400b95cff401fa 100644 (file)
@@ -567,10 +567,14 @@ static int dice_hw_params(struct snd_pcm_substream *substream,
                return err;
 
        /*
-        * At rates above 96 kHz, pretend that the stream runs at half the
-        * actual sample rate with twice the number of channels; two samples
-        * of a channel are stored consecutively in the packet. Requires
-        * blocking mode and PCM buffer size should be aligned to SYT_INTERVAL.
+        * At 176.4/192.0 kHz, Dice has a quirk to transfer two PCM frames in
+        * one data block of AMDTP packet. Thus sampling transfer frequency is
+        * a half of PCM sampling frequency, i.e. PCM frames at 192.0 kHz are
+        * transferred on AMDTP packets at 96 kHz. Two successive samples of a
+        * channel are stored consecutively in the packet. This quirk is called
+        * as 'Dual Wire'.
+        * For this quirk, blocking mode is required and PCM buffer size should
+        * be aligned to SYT_INTERVAL.
         */
        channels = params_channels(hw_params);
        if (rate_index > 4) {
@@ -579,18 +583,25 @@ static int dice_hw_params(struct snd_pcm_substream *substream,
                        return err;
                }
 
-               for (i = 0; i < channels; i++) {
-                       dice->stream.pcm_positions[i * 2] = i;
-                       dice->stream.pcm_positions[i * 2 + 1] = i + channels;
-               }
-
                rate /= 2;
                channels *= 2;
+               dice->stream.double_pcm_frames = true;
+       } else {
+               dice->stream.double_pcm_frames = false;
        }
 
        mode = rate_index_to_mode(rate_index);
        amdtp_stream_set_parameters(&dice->stream, rate, channels,
                                    dice->rx_midi_ports[mode]);
+       if (rate_index > 4) {
+               channels /= 2;
+
+               for (i = 0; i < channels; i++) {
+                       dice->stream.pcm_positions[i] = i * 2;
+                       dice->stream.pcm_positions[i + channels] = i * 2 + 1;
+               }
+       }
+
        amdtp_stream_set_pcm_format(&dice->stream,
                                    params_format(hw_params));
 
index f2e34e3f27eef6336d5798ae634b5f5ecc8aed70..5851249f11d912a318af26b9fc2ac6d933efe492 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #ifndef CT20K1REG_H
-#define CT20k1REG_H
+#define CT20K1REG_H
 
 /* 20k1 registers */
 #define        DSPXRAM_START                   0x000000
 #define I2SD_R    0x19L
 
 #endif /* CT20K1REG_H */
-
-
index 07e760937d3c0fc83bc7214f775a3a621173bdc9..8371274aa8116b90fe14dc03c712aac48b2c2897 100644 (file)
@@ -20,7 +20,7 @@
  */
 
 #ifndef __CA0132_REGS_H
-#define __CA0312_REGS_H
+#define __CA0132_REGS_H
 
 #define DSP_CHIP_OFFSET                0x100000
 #define DSP_DBGCNTL_MODULE_OFFSET      0xE30
index 6f2fa838b63532852ab535ab9ff189b99c52edea..6e5d0cb4e3d737ff43f0eb63e298de817552d224 100644 (file)
@@ -217,6 +217,7 @@ enum {
        CXT_FIXUP_HEADPHONE_MIC_PIN,
        CXT_FIXUP_HEADPHONE_MIC,
        CXT_FIXUP_GPIO1,
+       CXT_FIXUP_ASPIRE_DMIC,
        CXT_FIXUP_THINKPAD_ACPI,
        CXT_FIXUP_OLPC_XO,
        CXT_FIXUP_CAP_MIX_AMP,
@@ -664,6 +665,12 @@ static const struct hda_fixup cxt_fixups[] = {
                        { }
                },
        },
+       [CXT_FIXUP_ASPIRE_DMIC] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = cxt_fixup_stereo_dmic,
+               .chained = true,
+               .chain_id = CXT_FIXUP_GPIO1,
+       },
        [CXT_FIXUP_THINKPAD_ACPI] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = hda_fixup_thinkpad_acpi,
@@ -744,7 +751,7 @@ static const struct hda_model_fixup cxt5051_fixup_models[] = {
 
 static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC),
-       SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_GPIO1),
+       SND_PCI_QUIRK(0x1025, 0x054c, "Acer Aspire 3830TG", CXT_FIXUP_ASPIRE_DMIC),
        SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN),
        SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
index d71270a3f73f7ec1826397fe45c00e53fa143a1a..1ba22fb527c288b751d3064e041759e881013605 100644 (file)
@@ -328,6 +328,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
                case 0x10ec0885:
                case 0x10ec0887:
                /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
+               case 0x10ec0900:
                        alc889_coef_init(codec);
                        break;
                case 0x10ec0888:
@@ -2350,6 +2351,7 @@ static int patch_alc882(struct hda_codec *codec)
        switch (codec->vendor_id) {
        case 0x10ec0882:
        case 0x10ec0885:
+       case 0x10ec0900:
                break;
        default:
                /* ALC883 and variants */
@@ -4408,6 +4410,7 @@ enum {
        ALC292_FIXUP_TPT440_DOCK,
        ALC283_FIXUP_BXBT2807_MIC,
        ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED,
+       ALC282_FIXUP_ASPIRE_V5_PINS,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -4855,6 +4858,22 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained_before = true,
                .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
        },
+       [ALC282_FIXUP_ASPIRE_V5_PINS] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x12, 0x90a60130 },
+                       { 0x14, 0x90170110 },
+                       { 0x17, 0x40000008 },
+                       { 0x18, 0x411111f0 },
+                       { 0x19, 0x411111f0 },
+                       { 0x1a, 0x411111f0 },
+                       { 0x1b, 0x411111f0 },
+                       { 0x1d, 0x40f89b2d },
+                       { 0x1e, 0x411111f0 },
+                       { 0x21, 0x0321101f },
+                       { },
+               },
+       },
 
 };
 
@@ -4866,6 +4885,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
        SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
        SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
+       SND_PCI_QUIRK(0x1025, 0x079b, "Acer Aspire V5-573G", ALC282_FIXUP_ASPIRE_V5_PINS),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
        SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x05be, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
index a20b30ca52c09dc13507d55afef7854a23f29e40..98523209f7391852cb0e517fb373c6635e2ded99 100644 (file)
@@ -282,10 +282,10 @@ static const struct cs4265_clk_para clk_map_table[] = {
 
        /*64k*/
        {8192000, 64000, 1, 0},
-       {1228800, 64000, 1, 1},
-       {1693440, 64000, 1, 2},
-       {2457600, 64000, 1, 3},
-       {3276800, 64000, 1, 4},
+       {12288000, 64000, 1, 1},
+       {16934400, 64000, 1, 2},
+       {24576000, 64000, 1, 3},
+       {32768000, 64000, 1, 4},
 
        /* 88.2k */
        {11289600, 88200, 1, 0},
@@ -435,10 +435,10 @@ static int cs4265_pcm_hw_params(struct snd_pcm_substream *substream,
        index = cs4265_get_clk_index(cs4265->sysclk, params_rate(params));
        if (index >= 0) {
                snd_soc_update_bits(codec, CS4265_ADC_CTL,
-                       CS4265_ADC_FM, clk_map_table[index].fm_mode);
+                       CS4265_ADC_FM, clk_map_table[index].fm_mode << 6);
                snd_soc_update_bits(codec, CS4265_MCLK_FREQ,
                        CS4265_MCLK_FREQ_MASK,
-                       clk_map_table[index].mclkdiv);
+                       clk_map_table[index].mclkdiv << 4);
 
        } else {
                dev_err(codec->dev, "can't get correct mclk\n");
index 1dceafeec4151b4ae85b629aaa61e0737de73c34..f586cbd30b776ead146eb7f0edb4d11f7c74f013 100644 (file)
@@ -11,7 +11,7 @@
  */
 
 #ifndef __DA732X_H_
-#define __DA732X_H
+#define __DA732X_H_
 
 #include <sound/soc.h>
 
index 6bc6efdec550db684e4f8bfa32bd88107902d9cd..f1ec6e6bd08aced4be7c38d868ccba94a655c5f7 100644 (file)
@@ -2059,6 +2059,7 @@ static struct snd_soc_codec_driver soc_codec_dev_rt5640 = {
 static const struct regmap_config rt5640_regmap = {
        .reg_bits = 8,
        .val_bits = 16,
+       .use_single_rw = true,
 
        .max_register = RT5640_VENDOR_ID2 + 1 + (ARRAY_SIZE(rt5640_ranges) *
                                               RT5640_PR_SPACING),
index 67f14556462ff35bd6601062fc55a40ec2a96310..5337c448b5e365de204a95e3a945291dd228844b 100644 (file)
@@ -2135,10 +2135,10 @@ static const struct snd_soc_dapm_route rt5677_dapm_routes[] = {
        { "BST2", NULL, "IN2P" },
        { "BST2", NULL, "IN2N" },
 
-       { "IN1P", NULL, "micbias1" },
-       { "IN1N", NULL, "micbias1" },
-       { "IN2P", NULL, "micbias1" },
-       { "IN2N", NULL, "micbias1" },
+       { "IN1P", NULL, "MICBIAS1" },
+       { "IN1N", NULL, "MICBIAS1" },
+       { "IN2P", NULL, "MICBIAS1" },
+       { "IN2N", NULL, "MICBIAS1" },
 
        { "ADC 1", NULL, "BST1" },
        { "ADC 1", NULL, "ADC 1 power" },
index 159e517fa09aa6ee5d061e658cafcd9d0f8f12a5..cef7776b712cff43f37f81648a6fe2a59256ddd9 100644 (file)
@@ -481,12 +481,19 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
        snd_soc_card_set_drvdata(&priv->snd_card, priv);
 
        ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card);
+       if (ret >= 0)
+               return ret;
 
 err:
        asoc_simple_card_unref(pdev);
        return ret;
 }
 
+static int asoc_simple_card_remove(struct platform_device *pdev)
+{
+       return asoc_simple_card_unref(pdev);
+}
+
 static const struct of_device_id asoc_simple_of_match[] = {
        { .compatible = "simple-audio-card", },
        {},
@@ -500,6 +507,7 @@ static struct platform_driver asoc_simple_card = {
                .of_match_table = asoc_simple_of_match,
        },
        .probe = asoc_simple_card_probe,
+       .remove = asoc_simple_card_remove,
 };
 
 module_platform_driver(asoc_simple_card);
index f8a6adc2d81ca8cecec98a3b768cbc1ccef9b0c0..4336d1831485f77787f384d77ad4785fce6ad02a 100644 (file)
@@ -260,7 +260,7 @@ static struct snd_soc_dai_link omap_twl4030_dai_links[] = {
                .stream_name = "TWL4030 Voice",
                .cpu_dai_name = "omap-mcbsp.3",
                .codec_dai_name = "twl4030-voice",
-               .platform_name = "omap-mcbsp.2",
+               .platform_name = "omap-mcbsp.3",
                .codec_name = "twl4030-codec",
                .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF |
                           SND_SOC_DAIFMT_CBM_CFM,
index 3fdf3be7b99ab558e41fd26080b3bb80c5d53b59..f95e7ab135e83266f958c49801284a6e780744a3 100644 (file)
@@ -247,7 +247,7 @@ rsnd_gen2_dma_addr(struct rsnd_priv *priv,
        };
 
        /* it shouldn't happen */
-       if (use_dvc & !use_src)
+       if (use_dvc && !use_src)
                dev_err(dev, "DVC is selected without SRC\n");
 
        /* use SSIU or SSI ? */
index d4bfd4a9076fe02fd50495e0fee6f97471500bb5..889f4e3d35dc53548f59f159666fbc668f7bd39b 100644 (file)
@@ -1325,7 +1325,7 @@ static int soc_post_component_init(struct snd_soc_pcm_runtime *rtd,
        device_initialize(rtd->dev);
        rtd->dev->parent = rtd->card->dev;
        rtd->dev->release = rtd_release;
-       rtd->dev->init_name = name;
+       dev_set_name(rtd->dev, "%s", name);
        dev_set_drvdata(rtd->dev, rtd);
        mutex_init(&rtd->pcm_mutex);
        INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].be_clients);
index 9577121ce971247407b6d04957de548a5b3fd67d..ca8037634100b0a814927f52da9d77fca28fd657 100644 (file)
@@ -21,7 +21,7 @@
  */
 
 #ifndef __TEGRA_ASOC_UTILS_H__
-#define __TEGRA_ASOC_UTILS_H_
+#define __TEGRA_ASOC_UTILS_H__
 
 struct clk;
 struct device;
index 5386fd7c43ae984094c3a09ad48478fbc58d343f..74bbefdeaf4c187b07c02e67fedd74619f6215d6 100644 (file)
@@ -1,18 +1,18 @@
 uname_M := $(shell uname -m 2>/dev/null || echo not)
 ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/)
 ifeq ($(ARCH),i386)
-        ARCH := X86
+        ARCH := x86
        CFLAGS := -DCONFIG_X86_32 -D__i386__
 endif
 ifeq ($(ARCH),x86_64)
-       ARCH := X86
+       ARCH := x86
        CFLAGS := -DCONFIG_X86_64 -D__x86_64__
 endif
 
 CFLAGS += -I../../../../usr/include/
 
 all:
-ifeq ($(ARCH),X86)
+ifeq ($(ARCH),x86)
        gcc $(CFLAGS) msgque.c -o msgque_test
 else
        echo "Not an x86 target, can't build msgque selftest"
index d7d6bbeeff2f22a175939d218bce02398ce206c8..8aabd82db9e4a3028c6f8b594304e8896f427c77 100644 (file)
@@ -1,11 +1,11 @@
 uname_M := $(shell uname -m 2>/dev/null || echo not)
 ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/)
 ifeq ($(ARCH),i386)
-        ARCH := X86
+        ARCH := x86
        CFLAGS := -DCONFIG_X86_32 -D__i386__
 endif
 ifeq ($(ARCH),x86_64)
-       ARCH := X86
+       ARCH := x86
        CFLAGS := -DCONFIG_X86_64 -D__x86_64__
 endif
 
@@ -15,7 +15,7 @@ CFLAGS += -I../../../../usr/include/
 CFLAGS += -I../../../../arch/x86/include/
 
 all:
-ifeq ($(ARCH),X86)
+ifeq ($(ARCH),x86)
        gcc $(CFLAGS) kcmp_test.c -o kcmp_test
 else
        echo "Not an x86 target, can't build kcmp selftest"
index 6816c491c5ffcbdecec409fd10592455fb603b62..ad4ab01cd28ffabed4f290e34b195e4895f7a400 100644 (file)
@@ -1,10 +1,10 @@
 uname_M := $(shell uname -m 2>/dev/null || echo not)
 ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/)
 ifeq ($(ARCH),i386)
-       ARCH := X86
+       ARCH := x86
 endif
 ifeq ($(ARCH),x86_64)
-       ARCH := X86
+       ARCH := x86
 endif
 
 CFLAGS += -D_FILE_OFFSET_BITS=64
@@ -14,20 +14,20 @@ CFLAGS += -I../../../../include/uapi/
 CFLAGS += -I../../../../include/
 
 all:
-ifeq ($(ARCH),X86)
+ifeq ($(ARCH),x86)
        gcc $(CFLAGS) memfd_test.c -o memfd_test
 else
        echo "Not an x86 target, can't build memfd selftest"
 endif
 
 run_tests: all
-ifeq ($(ARCH),X86)
+ifeq ($(ARCH),x86)
        gcc $(CFLAGS) memfd_test.c -o memfd_test
 endif
        @./memfd_test || echo "memfd_test: [FAIL]"
 
 build_fuse:
-ifeq ($(ARCH),X86)
+ifeq ($(ARCH),x86)
        gcc $(CFLAGS) fuse_mnt.c `pkg-config fuse --cflags --libs` -o fuse_mnt
        gcc $(CFLAGS) fuse_test.c -o fuse_test
 else
diff --git a/tools/usb/usbip/.gitignore b/tools/usb/usbip/.gitignore
new file mode 100644 (file)
index 0000000..9aad9e3
--- /dev/null
@@ -0,0 +1,28 @@
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache/
+config.guess
+config.h
+config.h.in
+config.log
+config.status
+config.sub
+configure
+depcomp
+install-sh
+libsrc/Makefile
+libsrc/Makefile.in
+libtool
+ltmain.sh
+missing
+src/Makefile
+src/Makefile.in
+stamp-h1
+libsrc/libusbip.la
+libsrc/libusbip_la-names.lo
+libsrc/libusbip_la-usbip_common.lo
+libsrc/libusbip_la-usbip_host_driver.lo
+libsrc/libusbip_la-vhci_driver.lo
+src/usbip
+src/usbipd
diff --git a/tools/usb/usbip/AUTHORS b/tools/usb/usbip/AUTHORS
new file mode 100644 (file)
index 0000000..a27ea8d
--- /dev/null
@@ -0,0 +1,3 @@
+Takahiro Hirofuchi
+Robert Leibl
+matt mooney <mfm@muteddisk.com>
diff --git a/tools/usb/usbip/COPYING b/tools/usb/usbip/COPYING
new file mode 100644 (file)
index 0000000..c5611e4
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/tools/usb/usbip/INSTALL b/tools/usb/usbip/INSTALL
new file mode 100644 (file)
index 0000000..d3c5b40
--- /dev/null
@@ -0,0 +1,237 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
+2006, 2007 Free Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+Briefly, the shell commands `./configure; make; make install' should
+configure, build, and install this package.  The following
+more-detailed instructions are generic; see the `README' file for
+instructions specific to this package.
+
+   The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation.  It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions.  Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+   It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring.  Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.
+
+   If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release.  If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+   The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'.  You need `configure.ac' if
+you want to change it or regenerate `configure' using a newer version
+of `autoconf'.
+
+The simplest way to compile this package is:
+
+  1. `cd' to the directory containing the package's source code and type
+     `./configure' to configure the package for your system.
+
+     Running `configure' might take a while.  While running, it prints
+     some messages telling which features it is checking for.
+
+  2. Type `make' to compile the package.
+
+  3. Optionally, type `make check' to run any self-tests that come with
+     the package.
+
+  4. Type `make install' to install the programs and any data files and
+     documentation.
+
+  5. You can remove the program binaries and object files from the
+     source code directory by typing `make clean'.  To also remove the
+     files that `configure' created (so you can compile the package for
+     a different kind of computer), type `make distclean'.  There is
+     also a `make maintainer-clean' target, but that is intended mainly
+     for the package's developers.  If you use it, you may have to get
+     all sorts of other programs in order to regenerate files that came
+     with the distribution.
+
+  6. Often, you can also type `make uninstall' to remove the installed
+     files again.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about.  Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+   You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment.  Here
+is an example:
+
+     ./configure CC=c99 CFLAGS=-g LIBS=-lposix
+
+   *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory.  To do this, you can use GNU `make'.  `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script.  `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+   With a non-GNU `make', it is safer to compile the package for one
+architecture at a time in the source code directory.  After you have
+installed the package for one architecture, use `make distclean' before
+reconfiguring for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc.  You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+   You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files.  If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+   In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files.  Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+   If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System).  The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+   For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option.  TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+     CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+     OS KERNEL-OS
+
+   See the file `config.sub' for the possible values of each field.  If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+   If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+   If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists.  Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'.  However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost.  In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'.  For example:
+
+     ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).
+
+Unfortunately, this technique does not work for `CONFIG_SHELL' due to
+an Autoconf bug.  Until the bug is fixed you can use this workaround:
+
+     CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+     Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+     Print the version of Autoconf used to generate the `configure'
+     script, and exit.
+
+`--cache-file=FILE'
+     Enable the cache: use and save the results of the tests in FILE,
+     traditionally `config.cache'.  FILE defaults to `/dev/null' to
+     disable caching.
+
+`--config-cache'
+`-C'
+     Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+     Do not print messages saying which checks are being made.  To
+     suppress all normal output, redirect it to `/dev/null' (any error
+     messages will still be shown).
+
+`--srcdir=DIR'
+     Look for the package's source code in directory DIR.  Usually
+     `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options.  Run
+`configure --help' for more details.
+
diff --git a/tools/usb/usbip/Makefile.am b/tools/usb/usbip/Makefile.am
new file mode 100644 (file)
index 0000000..66f8bf0
--- /dev/null
@@ -0,0 +1,6 @@
+SUBDIRS := libsrc src
+includedir = @includedir@/usbip
+include_HEADERS := $(addprefix libsrc/, \
+                    usbip_common.h vhci_driver.h usbip_host_driver.h)
+
+dist_man_MANS := $(addprefix doc/, usbip.8 usbipd.8)
diff --git a/tools/usb/usbip/README b/tools/usb/usbip/README
new file mode 100644 (file)
index 0000000..831f49f
--- /dev/null
@@ -0,0 +1,202 @@
+#
+# README for usbip-utils
+#
+# Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+#               2005-2008 Takahiro Hirofuchi
+
+
+[Requirements]
+    - USB/IP device drivers
+       Found in the staging directory of the Linux kernel.
+
+    - libudev >= 2.0
+       libudev library
+
+    - libwrap0-dev
+       tcp wrapper library
+
+    - gcc >= 4.0
+
+    - libtool, automake >= 1.9, autoconf >= 2.5.0, pkg-config
+
+[Optional]
+    - hwdata
+        Contains USB device identification data.
+
+
+[Install]
+    0. Generate configuration scripts.
+       $ ./autogen.sh
+
+    1. Compile & install the userspace utilities.
+       $ ./configure [--with-tcp-wrappers=no] [--with-usbids-dir=<dir>]
+       $ make install
+
+    2. Compile & install USB/IP drivers.
+
+
+[Usage]
+    server:# (Physically attach your USB device.)
+
+    server:# insmod usbip-core.ko
+    server:# insmod usbip-host.ko
+
+    server:# usbipd -D
+       - Start usbip daemon.
+
+    server:# usbip list -l
+       - List driver assignments for USB devices.
+
+    server:# usbip bind --busid 1-2
+       - Bind usbip-host.ko to the device with busid 1-2.
+       - The USB device 1-2 is now exportable to other hosts!
+       - Use `usbip unbind --busid 1-2' to stop exporting the device.
+
+    client:# insmod usbip-core.ko
+    client:# insmod vhci-hcd.ko
+
+    client:# usbip list --remote <host>
+       - List exported USB devices on the <host>.
+
+    client:# usbip attach --remote <host> --busid 1-2
+       - Connect the remote USB device.
+
+    client:# usbip port
+       - Show virtual port status.
+
+    client:# usbip detach --port <port>
+       - Detach the USB device.
+
+
+[Example]
+---------------------------
+       SERVER SIDE
+---------------------------
+Physically attach your USB devices to this host.
+
+    trois:# insmod path/to/usbip-core.ko
+    trois:# insmod path/to/usbip-host.ko
+    trois:# usbipd -D
+
+In another terminal, let's look up what USB devices are physically
+attached to this host.
+
+    trois:# usbip list -l
+    Local USB devices
+    =================
+     - busid 1-1 (05a9:a511)
+            1-1:1.0 -> ov511
+
+     - busid 3-2 (0711:0902)
+            3-2:1.0 -> none
+
+     - busid 3-3.1 (08bb:2702)
+            3-3.1:1.0 -> snd-usb-audio
+            3-3.1:1.1 -> snd-usb-audio
+
+     - busid 3-3.2 (04bb:0206)
+            3-3.2:1.0 -> usb-storage
+
+     - busid 3-3 (0409:0058)
+            3-3:1.0 -> hub
+
+     - busid 4-1 (046d:08b2)
+            4-1:1.0 -> none
+            4-1:1.1 -> none
+            4-1:1.2 -> none
+
+     - busid 5-2 (058f:9254)
+            5-2:1.0 -> hub
+
+A USB storage device of busid 3-3.2 is now bound to the usb-storage
+driver. To export this device, we first mark the device as
+"exportable"; the device is bound to the usbip-host driver. Please
+remember you can not export a USB hub.
+
+Mark the device of busid 3-3.2 as exportable:
+
+    trois:# usbip --debug bind --busid 3-3.2
+    ...
+    usbip debug: usbip_bind.c:162:[unbind_other] 3-3.2:1.0 -> usb-storage
+    ...
+    bind device on busid 3-3.2: complete
+
+    trois:# usbip list -l
+    Local USB devices
+    =================
+    ...
+
+     - busid 3-3.2 (04bb:0206)
+            3-3.2:1.0 -> usbip-host
+    ...
+
+---------------------------
+       CLIENT SIDE
+---------------------------
+First, let's list available remote devices that are marked as
+exportable on the host.
+
+    deux:# insmod path/to/usbip-core.ko
+    deux:# insmod path/to/vhci-hcd.ko
+
+    deux:# usbip list --remote 10.0.0.3
+    Exportable USB devices
+    ======================
+     - 10.0.0.3
+           1-1: Prolific Technology, Inc. : unknown product (067b:3507)
+              : /sys/devices/pci0000:00/0000:00:1f.2/usb1/1-1
+              : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
+              :  0 - Mass Storage / SCSI / Bulk (Zip) (08/06/50)
+
+       1-2.2.1: Apple Computer, Inc. : unknown product (05ac:0203)
+              : /sys/devices/pci0000:00/0000:00:1f.2/usb1/1-2/1-2.2/1-2.2.1
+              : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
+              :  0 - Human Interface Devices / Boot Interface Subclass / Keyboard (03/01/01)
+
+       1-2.2.3: OmniVision Technologies, Inc. : OV511+ WebCam (05a9:a511)
+              : /sys/devices/pci0000:00/0000:00:1f.2/usb1/1-2/1-2.2/1-2.2.3
+              : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
+              :  0 - Vendor Specific Class / unknown subclass / unknown protocol (ff/00/00)
+
+           3-1: Logitech, Inc. : QuickCam Pro 4000 (046d:08b2)
+              : /sys/devices/pci0000:00/0000:00:1e.0/0000:02:0a.0/usb3/3-1
+              : (Defined at Interface level) / unknown subclass / unknown protocol (00/00/00)
+              :  0 - Data / unknown subclass / unknown protocol (0a/ff/00)
+              :  1 - Audio / Control Device / unknown protocol (01/01/00)
+              :  2 - Audio / Streaming / unknown protocol (01/02/00)
+
+Attach a remote USB device:
+
+    deux:# usbip attach --remote 10.0.0.3 --busid 1-1
+    port 0 attached
+
+Show the devices attached to this client:
+
+    deux:# usbip port
+    Port 00: <Port in Use> at Full Speed(12Mbps)
+          Prolific Technology, Inc. : unknown product (067b:3507)
+          6-1 -> usbip://10.0.0.3:3240/1-1  (remote bus/dev 001/004)
+          6-1:1.0 used by usb-storage
+                         /sys/class/scsi_device/0:0:0:0/device
+                         /sys/class/scsi_host/host0/device
+                         /sys/block/sda/device
+
+Detach the imported device:
+
+    deux:# usbip detach --port 0
+    port 0 detached
+
+
+[Checklist]
+    - See 'Debug Tips' on the project wiki.
+       - http://usbip.wiki.sourceforge.net/how-to-debug-usbip
+    - usbip-host.ko must be bound to the target device.
+       - See /proc/bus/usb/devices and find "Driver=..." lines of the device.
+    - Shutdown firewall.
+       - usbip now uses TCP port 3240.
+    - Disable SELinux.
+    - Check the kernel and daemon messages.
+
+
+[Contact]
+    Mailing List: linux-usb@vger.kernel.org
diff --git a/tools/usb/usbip/autogen.sh b/tools/usb/usbip/autogen.sh
new file mode 100755 (executable)
index 0000000..e1112d3
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh -x
+
+#aclocal
+#autoheader
+#libtoolize --copy --force
+#automake-1.9 -acf
+#autoconf
+
+autoreconf -i -f -v
diff --git a/tools/usb/usbip/cleanup.sh b/tools/usb/usbip/cleanup.sh
new file mode 100755 (executable)
index 0000000..955c3cc
--- /dev/null
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+if [ -r Makefile ]; then
+       make distclean
+fi
+
+FILES="aclocal.m4 autom4te.cache compile config.guess config.h.in config.log \
+       config.status config.sub configure cscope.out depcomp install-sh      \
+       libsrc/Makefile libsrc/Makefile.in libtool ltmain.sh Makefile         \
+       Makefile.in missing src/Makefile src/Makefile.in"
+
+rm -vRf $FILES
diff --git a/tools/usb/usbip/configure.ac b/tools/usb/usbip/configure.ac
new file mode 100644 (file)
index 0000000..607d05c
--- /dev/null
@@ -0,0 +1,111 @@
+dnl Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.59)
+AC_INIT([usbip-utils], [2.0], [linux-usb@vger.kernel.org])
+AC_DEFINE([USBIP_VERSION], [0x00000111], [binary-coded decimal version number])
+
+CURRENT=0
+REVISION=1
+AGE=0
+AC_SUBST([LIBUSBIP_VERSION], [$CURRENT:$REVISION:$AGE], [library version])
+
+AC_CONFIG_SRCDIR([src/usbipd.c])
+AC_CONFIG_HEADERS([config.h])
+
+AM_INIT_AUTOMAKE([foreign])
+LT_INIT
+
+# Silent build for automake >= 1.11
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+AC_SUBST([EXTRA_CFLAGS], ["-Wall -Werror -Wextra -std=gnu99"])
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_MAKE_SET
+
+# Checks for header files.
+AC_HEADER_DIRENT
+AC_HEADER_STDC
+AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdint.h stdlib.h dnl
+                 string.h sys/socket.h syslog.h unistd.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_TYPE_INT32_T
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+AC_TYPE_UINT16_T
+AC_TYPE_UINT32_T
+AC_TYPE_UINT8_T
+
+# Checks for library functions.
+AC_FUNC_REALLOC
+AC_CHECK_FUNCS([memset mkdir regcomp socket strchr strerror strstr dnl
+               strtoul])
+
+AC_CHECK_HEADER([libudev.h],
+               [AC_CHECK_LIB([udev], [udev_new],
+                             [LIBS="$LIBS -ludev"],
+                             [AC_MSG_ERROR([Missing udev library!])])],
+               [AC_MSG_ERROR([Missing /usr/include/libudev.h])])
+
+# Checks for libwrap library.
+AC_MSG_CHECKING([whether to use the libwrap (TCP wrappers) library])
+AC_ARG_WITH([tcp-wrappers],
+           [AS_HELP_STRING([--with-tcp-wrappers],
+                           [use the libwrap (TCP wrappers) library])],
+           dnl [ACTION-IF-GIVEN]
+           [if test "$withval" = "yes"; then
+                    AC_MSG_RESULT([yes])
+                    AC_MSG_CHECKING([for hosts_access in -lwrap])
+                    saved_LIBS="$LIBS"
+                    LIBS="-lwrap $saved_LIBS"
+                    AC_TRY_LINK(
+                      [int hosts_access(); int allow_severity, deny_severity;],
+                      [hosts_access()],
+                      [AC_MSG_RESULT([yes]);
+                       AC_DEFINE([HAVE_LIBWRAP], [1],
+                                 [use tcp wrapper]) wrap_LIB="-lwrap"],
+                      [AC_MSG_RESULT([not found]); exit 1])
+            else
+                    AC_MSG_RESULT([no]);
+            fi],
+           dnl [ACTION-IF-NOT-GIVEN]
+           [AC_MSG_RESULT([(default)])
+            AC_MSG_CHECKING([for hosts_access in -lwrap])
+            saved_LIBS="$LIBS"
+            LIBS="-lwrap $saved_LIBS"
+            AC_TRY_LINK(
+              [int hosts_access(); int allow_severity, deny_severity;],
+              [hosts_access()],
+              [AC_MSG_RESULT([yes]);
+               AC_DEFINE([HAVE_LIBWRAP], [1], [use tcp wrapper])],
+              [AC_MSG_RESULT([no]); LIBS="$saved_LIBS"])])
+
+# Sets directory containing usb.ids.
+AC_ARG_WITH([usbids-dir],
+           [AS_HELP_STRING([--with-usbids-dir=DIR],
+              [where usb.ids is found (default /usr/share/hwdata/)])],
+           [USBIDS_DIR=$withval], [USBIDS_DIR="/usr/share/hwdata/"])
+AC_SUBST([USBIDS_DIR])
+
+# use _FORTIFY_SOURCE
+AC_MSG_CHECKING([whether to use fortify])
+AC_ARG_WITH([fortify],
+           [AS_HELP_STRING([--with-fortify],
+                           [use _FORTIFY_SROUCE option when compiling)])],
+                           dnl [ACTION-IF-GIVEN]
+                           [if test "$withval" = "yes"; then
+                               AC_MSG_RESULT([yes])
+                               CFLAGS="$CFLAGS -D_FORTIFY_SOURCE -O"
+                            else
+                               AC_MSG_RESULT([no])
+                               CFLAGS="$CFLAGS -U_FORTIFY_SOURCE"
+                            fi
+                           ],
+                           dnl [ACTION-IF-NOT-GIVEN]
+                           [AC_MSG_RESULT([default])])
+
+AC_CONFIG_FILES([Makefile libsrc/Makefile src/Makefile])
+AC_OUTPUT
diff --git a/tools/usb/usbip/doc/usbip.8 b/tools/usb/usbip/doc/usbip.8
new file mode 100644 (file)
index 0000000..a6097be
--- /dev/null
@@ -0,0 +1,95 @@
+.TH USBIP "8" "February 2009" "usbip" "System Administration Utilities"
+.SH NAME
+usbip \- manage USB/IP devices
+.SH SYNOPSIS
+.B usbip
+[\fIoptions\fR] <\fIcommand\fR> <\fIargs\fR>
+
+.SH DESCRIPTION
+On a USB/IP server, devices can be listed, bound, and unbound using
+this program.  On a USB/IP client, devices exported by USB/IP servers
+can be listed, attached and detached.
+
+.SH OPTIONS
+.HP
+\fB\-\-debug\fR
+.IP
+Print debugging information.
+.PP
+
+.HP
+\fB\-\-log\fR
+.IP
+Log to syslog.
+.PP
+
+.HP
+\fB\-\-tcp-port PORT\fR
+.IP
+Connect to PORT on remote host (used for attach and list --remote).
+.PP
+
+.SH COMMANDS
+.HP
+\fBversion\fR
+.IP
+Show version and exit.
+.PP
+
+.HP
+\fBhelp\fR [\fIcommand\fR]
+.IP
+Print the program help message, or help on a specific command, and
+then exit.
+.PP
+
+.HP
+\fBattach\fR \-\-remote=<\fIhost\fR> \-\-busid=<\fIbus_id\fR>
+.IP
+Attach a remote USB device.
+.PP
+
+.HP
+\fBdetach\fR \-\-port=<\fIport\fR>
+.IP
+Detach an imported USB device.
+.PP
+
+.HP
+\fBbind\fR \-\-busid=<\fIbusid\fR>
+.IP
+Make a device exportable.
+.PP
+
+.HP
+\fBunbind\fR \-\-busid=<\fIbusid\fR>
+.IP
+Stop exporting a device so it can be used by a local driver.
+.PP
+
+.HP
+\fBlist\fR \-\-remote=<\fIhost\fR>
+.IP
+List USB devices exported by a remote host.
+.PP
+
+.HP
+\fBlist\fR \-\-local
+.IP
+List local USB devices.
+.PP
+
+
+.SH EXAMPLES
+
+    client:# usbip list --remote=server
+        - List exportable usb devices on the server.
+
+    client:# usbip attach --remote=server --busid=1-2
+        - Connect the remote USB device.
+
+    client:# usbip detach --port=0
+        - Detach the usb device.
+
+.SH "SEE ALSO"
+\fBusbipd\fP\fB(8)\fB\fP
diff --git a/tools/usb/usbip/doc/usbipd.8 b/tools/usb/usbip/doc/usbipd.8
new file mode 100644 (file)
index 0000000..ac4635d
--- /dev/null
@@ -0,0 +1,91 @@
+.TH USBIP "8" "February 2009" "usbip" "System Administration Utilities"
+.SH NAME
+usbipd \- USB/IP server daemon
+.SH SYNOPSIS
+.B usbipd
+[\fIoptions\fR]
+
+.SH DESCRIPTION
+.B usbipd
+provides USB/IP clients access to exported USB devices.
+
+Devices have to explicitly be exported using
+.B usbip bind
+before usbipd makes them available to other hosts.
+
+The daemon accepts connections from USB/IP clients
+on TCP port 3240 by default.
+
+.SH OPTIONS
+.HP
+\fB\-4\fR, \fB\-\-ipv4\fR
+.IP
+Bind to IPv4. Default is both.
+.PP
+
+.HP
+\fB\-6\fR, \fB\-\-ipv6\fR
+.IP
+Bind to IPv6. Default is both.
+.PP
+
+.HP
+\fB\-D\fR, \fB\-\-daemon\fR
+.IP
+Run as a daemon process.
+.PP
+
+.HP
+\fB\-d\fR, \fB\-\-debug\fR
+.IP
+Print debugging information.
+.PP
+
+.HP
+\fB\-PFILE\fR, \fB\-\-pid FILE\fR
+.IP
+Write process id to FILE.
+.br
+If no FILE specified, use /var/run/usbipd.pid
+.PP
+
+\fB\-tPORT\fR, \fB\-\-tcp\-port PORT\fR
+.IP
+Listen on TCP/IP port PORT.
+.PP
+
+\fB\-h\fR, \fB\-\-help\fR
+.IP
+Print the program help message and exit.
+.PP
+
+.HP
+\fB\-v\fR, \fB\-\-version\fR
+.IP
+Show version.
+.PP
+
+.SH LIMITATIONS
+
+.B usbipd
+offers no authentication or authorization for USB/IP. Any
+USB/IP client can connect and use exported devices.
+
+.SH EXAMPLES
+
+    server:# modprobe usbip
+
+    server:# usbipd -D
+        - Start usbip daemon.
+
+    server:# usbip list --local
+        - List driver assignments for usb devices.
+
+    server:# usbip bind --busid=1-2
+        - Bind usbip-host.ko to the device of busid 1-2.
+        - A usb device 1-2 is now exportable to other hosts!
+        - Use 'usbip unbind --busid=1-2' when you want to shutdown exporting and use the device locally.
+
+.SH "SEE ALSO"
+\fBusbip\fP\fB(8)\fB\fP
+
diff --git a/tools/usb/usbip/libsrc/Makefile.am b/tools/usb/usbip/libsrc/Makefile.am
new file mode 100644 (file)
index 0000000..7c8f8a4
--- /dev/null
@@ -0,0 +1,8 @@
+libusbip_la_CPPFLAGS = -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"'
+libusbip_la_CFLAGS   = @EXTRA_CFLAGS@
+libusbip_la_LDFLAGS  = -version-info @LIBUSBIP_VERSION@
+
+lib_LTLIBRARIES := libusbip.la
+libusbip_la_SOURCES := names.c names.h usbip_host_driver.c usbip_host_driver.h \
+                      usbip_common.c usbip_common.h vhci_driver.c vhci_driver.h \
+                      sysfs_utils.c sysfs_utils.h
diff --git a/tools/usb/usbip/libsrc/list.h b/tools/usb/usbip/libsrc/list.h
new file mode 100644 (file)
index 0000000..8d0c936
--- /dev/null
@@ -0,0 +1,136 @@
+#ifndef _LIST_H
+#define _LIST_H
+
+/* Stripped down implementation of linked list taken
+ * from the Linux Kernel.
+ */
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+       struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+       struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void INIT_LIST_HEAD(struct list_head *list)
+{
+       list->next = list;
+       list->prev = list;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+                             struct list_head *prev,
+                             struct list_head *next)
+{
+       next->prev = new;
+       new->next = next;
+       new->prev = prev;
+       prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+       __list_add(new, head, head->next);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+       next->prev = prev;
+       prev->next = next;
+}
+
+#define POISON_POINTER_DELTA 0
+#define LIST_POISON1  ((void *) 0x00100100 + POISON_POINTER_DELTA)
+#define LIST_POISON2  ((void *) 0x00200200 + POISON_POINTER_DELTA)
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty() on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void __list_del_entry(struct list_head *entry)
+{
+       __list_del(entry->prev, entry->next);
+}
+
+static inline void list_del(struct list_head *entry)
+{
+       __list_del(entry->prev, entry->next);
+       entry->next = LIST_POISON1;
+       entry->prev = LIST_POISON2;
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:       the &struct list_head pointer.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+       container_of(ptr, type, member)
+/**
+ * list_for_each       -       iterate over a list
+ * @pos:       the &struct list_head to use as a loop cursor.
+ * @head:      the head for your list.
+ */
+#define list_for_each(pos, head) \
+       for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_safe - iterate over a list safe against removal of list entry
+ * @pos:       the &struct list_head to use as a loop cursor.
+ * @n:         another &struct list_head to use as temporary storage
+ * @head:      the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+       for (pos = (head)->next, n = pos->next; pos != (head); \
+               pos = n, n = pos->next)
+
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr:       the pointer to the member.
+ * @type:      the type of the container struct this is embedded in.
+ * @member:    the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({                     \
+       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+       (type *)( (char *)__mptr - offsetof(type,member) );})
+
+#endif
diff --git a/tools/usb/usbip/libsrc/names.c b/tools/usb/usbip/libsrc/names.c
new file mode 100644 (file)
index 0000000..81ff852
--- /dev/null
@@ -0,0 +1,504 @@
+/*
+ *      names.c  --  USB name database manipulation routines
+ *
+ *      Copyright (C) 1999, 2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ *
+ *
+ *
+ *     Copyright (C) 2005 Takahiro Hirofuchi
+ *             - names_deinit() is added.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "names.h"
+#include "usbip_common.h"
+
+struct vendor {
+       struct vendor *next;
+       u_int16_t vendorid;
+       char name[1];
+};
+
+struct product {
+       struct product *next;
+       u_int16_t vendorid, productid;
+       char name[1];
+};
+
+struct class {
+       struct class *next;
+       u_int8_t classid;
+       char name[1];
+};
+
+struct subclass {
+       struct subclass *next;
+       u_int8_t classid, subclassid;
+       char name[1];
+};
+
+struct protocol {
+       struct protocol *next;
+       u_int8_t classid, subclassid, protocolid;
+       char name[1];
+};
+
+struct genericstrtable {
+       struct genericstrtable *next;
+       unsigned int num;
+       char name[1];
+};
+
+
+#define HASH1  0x10
+#define HASH2  0x02
+#define HASHSZ 16
+
+static unsigned int hashnum(unsigned int num)
+{
+       unsigned int mask1 = HASH1 << 27, mask2 = HASH2 << 27;
+
+       for (; mask1 >= HASH1; mask1 >>= 1, mask2 >>= 1)
+               if (num & mask1)
+                       num ^= mask2;
+       return num & (HASHSZ-1);
+}
+
+
+static struct vendor *vendors[HASHSZ] = { NULL, };
+static struct product *products[HASHSZ] = { NULL, };
+static struct class *classes[HASHSZ] = { NULL, };
+static struct subclass *subclasses[HASHSZ] = { NULL, };
+static struct protocol *protocols[HASHSZ] = { NULL, };
+
+const char *names_vendor(u_int16_t vendorid)
+{
+       struct vendor *v;
+
+       v = vendors[hashnum(vendorid)];
+       for (; v; v = v->next)
+               if (v->vendorid == vendorid)
+                       return v->name;
+       return NULL;
+}
+
+const char *names_product(u_int16_t vendorid, u_int16_t productid)
+{
+       struct product *p;
+
+       p = products[hashnum((vendorid << 16) | productid)];
+       for (; p; p = p->next)
+               if (p->vendorid == vendorid && p->productid == productid)
+                       return p->name;
+       return NULL;
+}
+
+const char *names_class(u_int8_t classid)
+{
+       struct class *c;
+
+       c = classes[hashnum(classid)];
+       for (; c; c = c->next)
+               if (c->classid == classid)
+                       return c->name;
+       return NULL;
+}
+
+const char *names_subclass(u_int8_t classid, u_int8_t subclassid)
+{
+       struct subclass *s;
+
+       s = subclasses[hashnum((classid << 8) | subclassid)];
+       for (; s; s = s->next)
+               if (s->classid == classid && s->subclassid == subclassid)
+                       return s->name;
+       return NULL;
+}
+
+const char *names_protocol(u_int8_t classid, u_int8_t subclassid,
+                          u_int8_t protocolid)
+{
+       struct protocol *p;
+
+       p = protocols[hashnum((classid << 16) | (subclassid << 8)
+                             | protocolid)];
+       for (; p; p = p->next)
+               if (p->classid == classid && p->subclassid == subclassid &&
+                   p->protocolid == protocolid)
+                       return p->name;
+       return NULL;
+}
+
+/* add a cleanup function by takahiro */
+struct pool {
+       struct pool *next;
+       void *mem;
+};
+
+static struct pool *pool_head;
+
+static void *my_malloc(size_t size)
+{
+       struct pool *p;
+
+       p = calloc(1, sizeof(struct pool));
+       if (!p)
+               return NULL;
+
+       p->mem = calloc(1, size);
+       if (!p->mem) {
+               free(p);
+               return NULL;
+       }
+
+       p->next = pool_head;
+       pool_head = p;
+
+       return p->mem;
+}
+
+void names_free(void)
+{
+       struct pool *pool;
+
+       if (!pool_head)
+               return;
+
+       for (pool = pool_head; pool != NULL; ) {
+               struct pool *tmp;
+
+               if (pool->mem)
+                       free(pool->mem);
+
+               tmp = pool;
+               pool = pool->next;
+               free(tmp);
+       }
+}
+
+static int new_vendor(const char *name, u_int16_t vendorid)
+{
+       struct vendor *v;
+       unsigned int h = hashnum(vendorid);
+
+       v = vendors[h];
+       for (; v; v = v->next)
+               if (v->vendorid == vendorid)
+                       return -1;
+       v = my_malloc(sizeof(struct vendor) + strlen(name));
+       if (!v)
+               return -1;
+       strcpy(v->name, name);
+       v->vendorid = vendorid;
+       v->next = vendors[h];
+       vendors[h] = v;
+       return 0;
+}
+
+static int new_product(const char *name, u_int16_t vendorid,
+                      u_int16_t productid)
+{
+       struct product *p;
+       unsigned int h = hashnum((vendorid << 16) | productid);
+
+       p = products[h];
+       for (; p; p = p->next)
+               if (p->vendorid == vendorid && p->productid == productid)
+                       return -1;
+       p = my_malloc(sizeof(struct product) + strlen(name));
+       if (!p)
+               return -1;
+       strcpy(p->name, name);
+       p->vendorid = vendorid;
+       p->productid = productid;
+       p->next = products[h];
+       products[h] = p;
+       return 0;
+}
+
+static int new_class(const char *name, u_int8_t classid)
+{
+       struct class *c;
+       unsigned int h = hashnum(classid);
+
+       c = classes[h];
+       for (; c; c = c->next)
+               if (c->classid == classid)
+                       return -1;
+       c = my_malloc(sizeof(struct class) + strlen(name));
+       if (!c)
+               return -1;
+       strcpy(c->name, name);
+       c->classid = classid;
+       c->next = classes[h];
+       classes[h] = c;
+       return 0;
+}
+
+static int new_subclass(const char *name, u_int8_t classid, u_int8_t subclassid)
+{
+       struct subclass *s;
+       unsigned int h = hashnum((classid << 8) | subclassid);
+
+       s = subclasses[h];
+       for (; s; s = s->next)
+               if (s->classid == classid && s->subclassid == subclassid)
+                       return -1;
+       s = my_malloc(sizeof(struct subclass) + strlen(name));
+       if (!s)
+               return -1;
+       strcpy(s->name, name);
+       s->classid = classid;
+       s->subclassid = subclassid;
+       s->next = subclasses[h];
+       subclasses[h] = s;
+       return 0;
+}
+
+static int new_protocol(const char *name, u_int8_t classid, u_int8_t subclassid,
+                       u_int8_t protocolid)
+{
+       struct protocol *p;
+       unsigned int h = hashnum((classid << 16) | (subclassid << 8)
+                                | protocolid);
+
+       p = protocols[h];
+       for (; p; p = p->next)
+               if (p->classid == classid && p->subclassid == subclassid
+                   && p->protocolid == protocolid)
+                       return -1;
+       p = my_malloc(sizeof(struct protocol) + strlen(name));
+       if (!p)
+               return -1;
+       strcpy(p->name, name);
+       p->classid = classid;
+       p->subclassid = subclassid;
+       p->protocolid = protocolid;
+       p->next = protocols[h];
+       protocols[h] = p;
+       return 0;
+}
+
+static void parse(FILE *f)
+{
+       char buf[512], *cp;
+       unsigned int linectr = 0;
+       int lastvendor = -1;
+       int lastclass = -1;
+       int lastsubclass = -1;
+       int lasthut = -1;
+       int lastlang = -1;
+       unsigned int u;
+
+       while (fgets(buf, sizeof(buf), f)) {
+               linectr++;
+               /* remove line ends */
+               cp = strchr(buf, '\r');
+               if (cp)
+                       *cp = 0;
+               cp = strchr(buf, '\n');
+               if (cp)
+                       *cp = 0;
+               if (buf[0] == '#' || !buf[0])
+                       continue;
+               cp = buf;
+               if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' &&
+                   buf[3] == 'S' && buf[4] == 'D' &&
+                   buf[5] == 'E' && buf[6] == 'S' && /*isspace(buf[7])*/
+                   buf[7] == ' ') {
+                       continue;
+               }
+               if (buf[0] == 'P' && buf[1] == 'H' &&
+                   buf[2] == 'Y' && /*isspace(buf[3])*/ buf[3] == ' ') {
+                       continue;
+               }
+               if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A' &&
+                   buf[3] == 'S' && /*isspace(buf[4])*/ buf[4] == ' ') {
+                       continue;
+               }
+               if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') {
+                       lasthut = lastclass = lastvendor = lastsubclass = -1;
+                       /*
+                        * set 1 as pseudo-id to indicate that the parser is
+                        * in a `L' section.
+                        */
+                       lastlang = 1;
+                       continue;
+               }
+               if (buf[0] == 'C' && /*isspace(buf[1])*/ buf[1] == ' ') {
+                       /* class spec */
+                       cp = buf+2;
+                       while (isspace(*cp))
+                               cp++;
+                       if (!isxdigit(*cp)) {
+                               err("Invalid class spec at line %u", linectr);
+                               continue;
+                       }
+                       u = strtoul(cp, &cp, 16);
+                       while (isspace(*cp))
+                               cp++;
+                       if (!*cp) {
+                               err("Invalid class spec at line %u", linectr);
+                               continue;
+                       }
+                       if (new_class(cp, u))
+                               err("Duplicate class spec at line %u class %04x %s",
+                                   linectr, u, cp);
+                       dbg("line %5u class %02x %s", linectr, u, cp);
+                       lasthut = lastlang = lastvendor = lastsubclass = -1;
+                       lastclass = u;
+                       continue;
+               }
+               if (buf[0] == 'A' && buf[1] == 'T' && isspace(buf[2])) {
+                       /* audio terminal type spec */
+                       continue;
+               }
+               if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C'
+                   && isspace(buf[3])) {
+                       /* HID Descriptor bCountryCode */
+                       continue;
+               }
+               if (isxdigit(*cp)) {
+                       /* vendor */
+                       u = strtoul(cp, &cp, 16);
+                       while (isspace(*cp))
+                               cp++;
+                       if (!*cp) {
+                               err("Invalid vendor spec at line %u", linectr);
+                               continue;
+                       }
+                       if (new_vendor(cp, u))
+                               err("Duplicate vendor spec at line %u vendor %04x %s",
+                                   linectr, u, cp);
+                       dbg("line %5u vendor %04x %s", linectr, u, cp);
+                       lastvendor = u;
+                       lasthut = lastlang = lastclass = lastsubclass = -1;
+                       continue;
+               }
+               if (buf[0] == '\t' && isxdigit(buf[1])) {
+                       /* product or subclass spec */
+                       u = strtoul(buf+1, &cp, 16);
+                       while (isspace(*cp))
+                               cp++;
+                       if (!*cp) {
+                               err("Invalid product/subclass spec at line %u",
+                                   linectr);
+                               continue;
+                       }
+                       if (lastvendor != -1) {
+                               if (new_product(cp, lastvendor, u))
+                                       err("Duplicate product spec at line %u product %04x:%04x %s",
+                                           linectr, lastvendor, u, cp);
+                               dbg("line %5u product %04x:%04x %s", linectr,
+                                   lastvendor, u, cp);
+                               continue;
+                       }
+                       if (lastclass != -1) {
+                               if (new_subclass(cp, lastclass, u))
+                                       err("Duplicate subclass spec at line %u class %02x:%02x %s",
+                                           linectr, lastclass, u, cp);
+                               dbg("line %5u subclass %02x:%02x %s", linectr,
+                                   lastclass, u, cp);
+                               lastsubclass = u;
+                               continue;
+                       }
+                       if (lasthut != -1) {
+                               /* do not store hut */
+                               continue;
+                       }
+                       if (lastlang != -1) {
+                               /* do not store langid */
+                               continue;
+                       }
+                       err("Product/Subclass spec without prior Vendor/Class spec at line %u",
+                           linectr);
+                       continue;
+               }
+               if (buf[0] == '\t' && buf[1] == '\t' && isxdigit(buf[2])) {
+                       /* protocol spec */
+                       u = strtoul(buf+2, &cp, 16);
+                       while (isspace(*cp))
+                               cp++;
+                       if (!*cp) {
+                               err("Invalid protocol spec at line %u",
+                                   linectr);
+                               continue;
+                       }
+                       if (lastclass != -1 && lastsubclass != -1) {
+                               if (new_protocol(cp, lastclass, lastsubclass,
+                                                u))
+                                       err("Duplicate protocol spec at line %u class %02x:%02x:%02x %s",
+                                           linectr, lastclass, lastsubclass,
+                                           u, cp);
+                               dbg("line %5u protocol %02x:%02x:%02x %s",
+                                   linectr, lastclass, lastsubclass, u, cp);
+                               continue;
+                       }
+                       err("Protocol spec without prior Class and Subclass spec at line %u",
+                           linectr);
+                       continue;
+               }
+               if (buf[0] == 'H' && buf[1] == 'I' &&
+                   buf[2] == 'D' && /*isspace(buf[3])*/ buf[3] == ' ') {
+                       continue;
+               }
+               if (buf[0] == 'H' && buf[1] == 'U' &&
+                   buf[2] == 'T' && /*isspace(buf[3])*/ buf[3] == ' ') {
+                       lastlang = lastclass = lastvendor = lastsubclass = -1;
+                       /*
+                        * set 1 as pseudo-id to indicate that the parser is
+                        * in a `HUT' section.
+                        */
+                       lasthut = 1;
+                       continue;
+               }
+               if (buf[0] == 'R' && buf[1] == ' ')
+                       continue;
+
+               if (buf[0] == 'V' && buf[1] == 'T')
+                       continue;
+
+               err("Unknown line at line %u", linectr);
+       }
+}
+
+
+int names_init(char *n)
+{
+       FILE *f;
+
+       f = fopen(n, "r");
+       if (!f)
+               return errno;
+
+       parse(f);
+       fclose(f);
+       return 0;
+}
diff --git a/tools/usb/usbip/libsrc/names.h b/tools/usb/usbip/libsrc/names.h
new file mode 100644 (file)
index 0000000..6809265
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ *      names.h  --  USB name database manipulation routines
+ *
+ *      Copyright (C) 1999, 2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
+ *
+ *      This program is free software; you can redistribute it and/or modify
+ *      it under the terms of the GNU General Public License as published by
+ *      the Free Software Foundation; either version 2 of the License, or
+ *      (at your option) any later version.
+ *
+ *      This program is distributed in the hope that it will be useful,
+ *      but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *      GNU General Public License for more details.
+ *
+ *      You should have received a copy of the GNU General Public License
+ *      along with this program; if not, write to the Free Software
+ *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ *
+ *     Copyright (C) 2005 Takahiro Hirofuchi
+ *            - names_free() is added.
+ */
+
+#ifndef _NAMES_H
+#define _NAMES_H
+
+#include <sys/types.h>
+
+/* used by usbip_common.c */
+extern const char *names_vendor(u_int16_t vendorid);
+extern const char *names_product(u_int16_t vendorid, u_int16_t productid);
+extern const char *names_class(u_int8_t classid);
+extern const char *names_subclass(u_int8_t classid, u_int8_t subclassid);
+extern const char *names_protocol(u_int8_t classid, u_int8_t subclassid,
+                                 u_int8_t protocolid);
+extern int  names_init(char *n);
+extern void names_free(void);
+
+#endif /* _NAMES_H */
diff --git a/tools/usb/usbip/libsrc/sysfs_utils.c b/tools/usb/usbip/libsrc/sysfs_utils.c
new file mode 100644 (file)
index 0000000..36ac88e
--- /dev/null
@@ -0,0 +1,31 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "sysfs_utils.h"
+#include "usbip_common.h"
+
+int write_sysfs_attribute(const char *attr_path, const char *new_value,
+                         size_t len)
+{
+       int fd;
+       int length;
+
+       fd = open(attr_path, O_WRONLY);
+       if (fd < 0) {
+               dbg("error opening attribute %s", attr_path);
+               return -1;
+       }
+
+       length = write(fd, new_value, len);
+       if (length < 0) {
+               dbg("error writing to attribute %s", attr_path);
+               close(fd);
+               return -1;
+       }
+
+       close(fd);
+
+       return 0;
+}
diff --git a/tools/usb/usbip/libsrc/sysfs_utils.h b/tools/usb/usbip/libsrc/sysfs_utils.h
new file mode 100644 (file)
index 0000000..32ac1d1
--- /dev/null
@@ -0,0 +1,8 @@
+
+#ifndef __SYSFS_UTILS_H
+#define __SYSFS_UTILS_H
+
+int write_sysfs_attribute(const char *attr_path, const char *new_value,
+                         size_t len);
+
+#endif
diff --git a/tools/usb/usbip/libsrc/usbip_common.c b/tools/usb/usbip/libsrc/usbip_common.c
new file mode 100644 (file)
index 0000000..ac73710
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2005-2007 Takahiro Hirofuchi
+ */
+
+#include <libudev.h>
+#include "usbip_common.h"
+#include "names.h"
+
+#undef  PROGNAME
+#define PROGNAME "libusbip"
+
+int usbip_use_syslog;
+int usbip_use_stderr;
+int usbip_use_debug;
+
+extern struct udev *udev_context;
+
+struct speed_string {
+       int num;
+       char *speed;
+       char *desc;
+};
+
+static const struct speed_string speed_strings[] = {
+       { USB_SPEED_UNKNOWN, "unknown", "Unknown Speed"},
+       { USB_SPEED_LOW,  "1.5", "Low Speed(1.5Mbps)"  },
+       { USB_SPEED_FULL, "12",  "Full Speed(12Mbps)" },
+       { USB_SPEED_HIGH, "480", "High Speed(480Mbps)" },
+       { USB_SPEED_WIRELESS, "53.3-480", "Wireless"},
+       { USB_SPEED_SUPER, "5000", "Super Speed(5000Mbps)" },
+       { 0, NULL, NULL }
+};
+
+struct portst_string {
+       int num;
+       char *desc;
+};
+
+static struct portst_string portst_strings[] = {
+       { SDEV_ST_AVAILABLE,    "Device Available" },
+       { SDEV_ST_USED,         "Device in Use" },
+       { SDEV_ST_ERROR,        "Device Error"},
+       { VDEV_ST_NULL,         "Port Available"},
+       { VDEV_ST_NOTASSIGNED,  "Port Initializing"},
+       { VDEV_ST_USED,         "Port in Use"},
+       { VDEV_ST_ERROR,        "Port Error"},
+       { 0, NULL}
+};
+
+const char *usbip_status_string(int32_t status)
+{
+       for (int i = 0; portst_strings[i].desc != NULL; i++)
+               if (portst_strings[i].num == status)
+                       return portst_strings[i].desc;
+
+       return "Unknown Status";
+}
+
+const char *usbip_speed_string(int num)
+{
+       for (int i = 0; speed_strings[i].speed != NULL; i++)
+               if (speed_strings[i].num == num)
+                       return speed_strings[i].desc;
+
+       return "Unknown Speed";
+}
+
+
+#define DBG_UDEV_INTEGER(name)\
+       dbg("%-20s = %x", to_string(name), (int) udev->name)
+
+#define DBG_UINF_INTEGER(name)\
+       dbg("%-20s = %x", to_string(name), (int) uinf->name)
+
+void dump_usb_interface(struct usbip_usb_interface *uinf)
+{
+       char buff[100];
+
+       usbip_names_get_class(buff, sizeof(buff),
+                       uinf->bInterfaceClass,
+                       uinf->bInterfaceSubClass,
+                       uinf->bInterfaceProtocol);
+       dbg("%-20s = %s", "Interface(C/SC/P)", buff);
+}
+
+void dump_usb_device(struct usbip_usb_device *udev)
+{
+       char buff[100];
+
+       dbg("%-20s = %s", "path",  udev->path);
+       dbg("%-20s = %s", "busid", udev->busid);
+
+       usbip_names_get_class(buff, sizeof(buff),
+                       udev->bDeviceClass,
+                       udev->bDeviceSubClass,
+                       udev->bDeviceProtocol);
+       dbg("%-20s = %s", "Device(C/SC/P)", buff);
+
+       DBG_UDEV_INTEGER(bcdDevice);
+
+       usbip_names_get_product(buff, sizeof(buff),
+                       udev->idVendor,
+                       udev->idProduct);
+       dbg("%-20s = %s", "Vendor/Product", buff);
+
+       DBG_UDEV_INTEGER(bNumConfigurations);
+       DBG_UDEV_INTEGER(bNumInterfaces);
+
+       dbg("%-20s = %s", "speed",
+                       usbip_speed_string(udev->speed));
+
+       DBG_UDEV_INTEGER(busnum);
+       DBG_UDEV_INTEGER(devnum);
+}
+
+
+int read_attr_value(struct udev_device *dev, const char *name,
+                   const char *format)
+{
+       const char *attr;
+       int num = 0;
+       int ret;
+
+       attr = udev_device_get_sysattr_value(dev, name);
+       if (!attr) {
+               err("udev_device_get_sysattr_value failed");
+               goto err;
+       }
+
+       /* The client chooses the device configuration
+        * when attaching it so right after being bound
+        * to usbip-host on the server the device will
+        * have no configuration.
+        * Therefore, attributes such as bConfigurationValue
+        * and bNumInterfaces will not exist and sscanf will
+        * fail. Check for these cases and don't treat them
+        * as errors.
+        */
+
+       ret = sscanf(attr, format, &num);
+       if (ret < 1) {
+               if (strcmp(name, "bConfigurationValue") &&
+                               strcmp(name, "bNumInterfaces")) {
+                       err("sscanf failed for attribute %s", name);
+                       goto err;
+               }
+       }
+
+err:
+
+       return num;
+}
+
+
+int read_attr_speed(struct udev_device *dev)
+{
+       const char *speed;
+
+       speed = udev_device_get_sysattr_value(dev, "speed");
+       if (!speed) {
+               err("udev_device_get_sysattr_value failed");
+               goto err;
+       }
+
+       for (int i = 0; speed_strings[i].speed != NULL; i++) {
+               if (!strcmp(speed, speed_strings[i].speed))
+                       return speed_strings[i].num;
+       }
+
+err:
+
+       return USB_SPEED_UNKNOWN;
+}
+
+#define READ_ATTR(object, type, dev, name, format)                           \
+       do {                                                                  \
+               (object)->name = (type) read_attr_value(dev, to_string(name), \
+                                                       format);              \
+       } while (0)
+
+
+int read_usb_device(struct udev_device *sdev, struct usbip_usb_device *udev)
+{
+       uint32_t busnum, devnum;
+       const char *path, *name;
+
+       READ_ATTR(udev, uint8_t,  sdev, bDeviceClass,           "%02x\n");
+       READ_ATTR(udev, uint8_t,  sdev, bDeviceSubClass,        "%02x\n");
+       READ_ATTR(udev, uint8_t,  sdev, bDeviceProtocol,        "%02x\n");
+
+       READ_ATTR(udev, uint16_t, sdev, idVendor,               "%04x\n");
+       READ_ATTR(udev, uint16_t, sdev, idProduct,              "%04x\n");
+       READ_ATTR(udev, uint16_t, sdev, bcdDevice,              "%04x\n");
+
+       READ_ATTR(udev, uint8_t,  sdev, bConfigurationValue,    "%02x\n");
+       READ_ATTR(udev, uint8_t,  sdev, bNumConfigurations,     "%02x\n");
+       READ_ATTR(udev, uint8_t,  sdev, bNumInterfaces,         "%02x\n");
+
+       READ_ATTR(udev, uint8_t,  sdev, devnum,                 "%d\n");
+       udev->speed = read_attr_speed(sdev);
+
+       path = udev_device_get_syspath(sdev);
+       name = udev_device_get_sysname(sdev);
+
+       strncpy(udev->path,  path,  SYSFS_PATH_MAX);
+       strncpy(udev->busid, name, SYSFS_BUS_ID_SIZE);
+
+       sscanf(name, "%u-%u", &busnum, &devnum);
+       udev->busnum = busnum;
+
+       return 0;
+}
+
+int read_usb_interface(struct usbip_usb_device *udev, int i,
+                      struct usbip_usb_interface *uinf)
+{
+       char busid[SYSFS_BUS_ID_SIZE];
+       struct udev_device *sif;
+
+       sprintf(busid, "%s:%d.%d", udev->busid, udev->bConfigurationValue, i);
+
+       sif = udev_device_new_from_subsystem_sysname(udev_context, "usb", busid);
+       if (!sif) {
+               err("udev_device_new_from_subsystem_sysname %s failed", busid);
+               return -1;
+       }
+
+       READ_ATTR(uinf, uint8_t,  sif, bInterfaceClass,         "%02x\n");
+       READ_ATTR(uinf, uint8_t,  sif, bInterfaceSubClass,      "%02x\n");
+       READ_ATTR(uinf, uint8_t,  sif, bInterfaceProtocol,      "%02x\n");
+
+       return 0;
+}
+
+int usbip_names_init(char *f)
+{
+       return names_init(f);
+}
+
+void usbip_names_free(void)
+{
+       names_free();
+}
+
+void usbip_names_get_product(char *buff, size_t size, uint16_t vendor,
+                            uint16_t product)
+{
+       const char *prod, *vend;
+
+       prod = names_product(vendor, product);
+       if (!prod)
+               prod = "unknown product";
+
+
+       vend = names_vendor(vendor);
+       if (!vend)
+               vend = "unknown vendor";
+
+       snprintf(buff, size, "%s : %s (%04x:%04x)", vend, prod, vendor, product);
+}
+
+void usbip_names_get_class(char *buff, size_t size, uint8_t class,
+                          uint8_t subclass, uint8_t protocol)
+{
+       const char *c, *s, *p;
+
+       if (class == 0 && subclass == 0 && protocol == 0) {
+               snprintf(buff, size, "(Defined at Interface level) (%02x/%02x/%02x)", class, subclass, protocol);
+               return;
+       }
+
+       p = names_protocol(class, subclass, protocol);
+       if (!p)
+               p = "unknown protocol";
+
+       s = names_subclass(class, subclass);
+       if (!s)
+               s = "unknown subclass";
+
+       c = names_class(class);
+       if (!c)
+               c = "unknown class";
+
+       snprintf(buff, size, "%s / %s / %s (%02x/%02x/%02x)", c, s, p, class, subclass, protocol);
+}
diff --git a/tools/usb/usbip/libsrc/usbip_common.h b/tools/usb/usbip/libsrc/usbip_common.h
new file mode 100644 (file)
index 0000000..15fe792
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2005-2007 Takahiro Hirofuchi
+ */
+
+#ifndef __USBIP_COMMON_H
+#define __USBIP_COMMON_H
+
+#include <libudev.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <syslog.h>
+#include <unistd.h>
+#include <linux/usb/ch9.h>
+#include <linux/usbip.h>
+
+#ifndef USBIDS_FILE
+#define USBIDS_FILE "/usr/share/hwdata/usb.ids"
+#endif
+
+#ifndef VHCI_STATE_PATH
+#define VHCI_STATE_PATH "/var/run/vhci_hcd"
+#endif
+
+/* kernel module names */
+#define USBIP_CORE_MOD_NAME    "usbip-core"
+#define USBIP_HOST_DRV_NAME    "usbip-host"
+#define USBIP_VHCI_DRV_NAME    "vhci_hcd"
+
+/* sysfs constants */
+#define SYSFS_MNT_PATH         "/sys"
+#define SYSFS_BUS_NAME         "bus"
+#define SYSFS_BUS_TYPE         "usb"
+#define SYSFS_DRIVERS_NAME     "drivers"
+
+#define SYSFS_PATH_MAX         256
+#define SYSFS_BUS_ID_SIZE      32
+
+extern int usbip_use_syslog;
+extern int usbip_use_stderr;
+extern int usbip_use_debug ;
+
+#define PROGNAME "usbip"
+
+#define pr_fmt(fmt)    "%s: %s: " fmt "\n", PROGNAME
+#define dbg_fmt(fmt)   pr_fmt("%s:%d:[%s] " fmt), "debug",     \
+                       __FILE__, __LINE__, __func__
+
+#define err(fmt, args...)                                              \
+       do {                                                            \
+               if (usbip_use_syslog) {                                 \
+                       syslog(LOG_ERR, pr_fmt(fmt), "error", ##args);  \
+               }                                                       \
+               if (usbip_use_stderr) {                                 \
+                       fprintf(stderr, pr_fmt(fmt), "error", ##args);  \
+               }                                                       \
+       } while (0)
+
+#define info(fmt, args...)                                             \
+       do {                                                            \
+               if (usbip_use_syslog) {                                 \
+                       syslog(LOG_INFO, pr_fmt(fmt), "info", ##args);  \
+               }                                                       \
+               if (usbip_use_stderr) {                                 \
+                       fprintf(stderr, pr_fmt(fmt), "info", ##args);   \
+               }                                                       \
+       } while (0)
+
+#define dbg(fmt, args...)                                              \
+       do {                                                            \
+       if (usbip_use_debug) {                                          \
+               if (usbip_use_syslog) {                                 \
+                       syslog(LOG_DEBUG, dbg_fmt(fmt), ##args);        \
+               }                                                       \
+               if (usbip_use_stderr) {                                 \
+                       fprintf(stderr, dbg_fmt(fmt), ##args);          \
+               }                                                       \
+       }                                                               \
+       } while (0)
+
+#define BUG()                                          \
+       do {                                            \
+               err("sorry, it's a bug!");              \
+               abort();                                \
+       } while (0)
+
+struct usbip_usb_interface {
+       uint8_t bInterfaceClass;
+       uint8_t bInterfaceSubClass;
+       uint8_t bInterfaceProtocol;
+       uint8_t padding;        /* alignment */
+} __attribute__((packed));
+
+struct usbip_usb_device {
+       char path[SYSFS_PATH_MAX];
+       char busid[SYSFS_BUS_ID_SIZE];
+
+       uint32_t busnum;
+       uint32_t devnum;
+       uint32_t speed;
+
+       uint16_t idVendor;
+       uint16_t idProduct;
+       uint16_t bcdDevice;
+
+       uint8_t bDeviceClass;
+       uint8_t bDeviceSubClass;
+       uint8_t bDeviceProtocol;
+       uint8_t bConfigurationValue;
+       uint8_t bNumConfigurations;
+       uint8_t bNumInterfaces;
+} __attribute__((packed));
+
+#define to_string(s)   #s
+
+void dump_usb_interface(struct usbip_usb_interface *);
+void dump_usb_device(struct usbip_usb_device *);
+int read_usb_device(struct udev_device *sdev, struct usbip_usb_device *udev);
+int read_attr_value(struct udev_device *dev, const char *name,
+                   const char *format);
+int read_usb_interface(struct usbip_usb_device *udev, int i,
+                      struct usbip_usb_interface *uinf);
+
+const char *usbip_speed_string(int num);
+const char *usbip_status_string(int32_t status);
+
+int usbip_names_init(char *);
+void usbip_names_free(void);
+void usbip_names_get_product(char *buff, size_t size, uint16_t vendor,
+                            uint16_t product);
+void usbip_names_get_class(char *buff, size_t size, uint8_t class,
+                          uint8_t subclass, uint8_t protocol);
+
+#endif /* __USBIP_COMMON_H */
diff --git a/tools/usb/usbip/libsrc/usbip_host_driver.c b/tools/usb/usbip/libsrc/usbip_host_driver.c
new file mode 100644 (file)
index 0000000..bef08d5
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <libudev.h>
+
+#include "usbip_common.h"
+#include "usbip_host_driver.h"
+#include "list.h"
+#include "sysfs_utils.h"
+
+#undef  PROGNAME
+#define PROGNAME "libusbip"
+
+struct usbip_host_driver *host_driver;
+struct udev *udev_context;
+
+static int32_t read_attr_usbip_status(struct usbip_usb_device *udev)
+{
+       char status_attr_path[SYSFS_PATH_MAX];
+       int fd;
+       int length;
+       char status;
+       int value = 0;
+
+       snprintf(status_attr_path, SYSFS_PATH_MAX, "%s/usbip_status",
+                udev->path);
+
+       fd = open(status_attr_path, O_RDONLY);
+       if (fd < 0) {
+               err("error opening attribute %s", status_attr_path);
+               return -1;
+       }
+
+       length = read(fd, &status, 1);
+       if (length < 0) {
+               err("error reading attribute %s", status_attr_path);
+               close(fd);
+               return -1;
+       }
+
+       value = atoi(&status);
+
+       return value;
+}
+
+static
+struct usbip_exported_device *usbip_exported_device_new(const char *sdevpath)
+{
+       struct usbip_exported_device *edev = NULL;
+       struct usbip_exported_device *edev_old;
+       size_t size;
+       int i;
+
+       edev = calloc(1, sizeof(struct usbip_exported_device));
+
+       edev->sudev = udev_device_new_from_syspath(udev_context, sdevpath);
+       if (!edev->sudev) {
+               err("udev_device_new_from_syspath: %s", sdevpath);
+               goto err;
+       }
+
+       read_usb_device(edev->sudev, &edev->udev);
+
+       edev->status = read_attr_usbip_status(&edev->udev);
+       if (edev->status < 0)
+               goto err;
+
+       /* reallocate buffer to include usb interface data */
+       size = sizeof(struct usbip_exported_device) +
+               edev->udev.bNumInterfaces * sizeof(struct usbip_usb_interface);
+
+       edev_old = edev;
+       edev = realloc(edev, size);
+       if (!edev) {
+               edev = edev_old;
+               dbg("realloc failed");
+               goto err;
+       }
+
+       for (i = 0; i < edev->udev.bNumInterfaces; i++)
+               read_usb_interface(&edev->udev, i, &edev->uinf[i]);
+
+       return edev;
+err:
+       if (edev->sudev)
+               udev_device_unref(edev->sudev);
+       if (edev)
+               free(edev);
+
+       return NULL;
+}
+
+static int refresh_exported_devices(void)
+{
+       struct usbip_exported_device *edev;
+       struct udev_enumerate *enumerate;
+       struct udev_list_entry *devices, *dev_list_entry;
+       struct udev_device *dev;
+       const char *path;
+       const char *driver;
+
+       enumerate = udev_enumerate_new(udev_context);
+       udev_enumerate_add_match_subsystem(enumerate, "usb");
+       udev_enumerate_scan_devices(enumerate);
+
+       devices = udev_enumerate_get_list_entry(enumerate);
+
+       udev_list_entry_foreach(dev_list_entry, devices) {
+               path = udev_list_entry_get_name(dev_list_entry);
+               dev = udev_device_new_from_syspath(udev_context, path);
+               if (dev == NULL)
+                       continue;
+
+               /* Check whether device uses usbip-host driver. */
+               driver = udev_device_get_driver(dev);
+               if (driver != NULL && !strcmp(driver, USBIP_HOST_DRV_NAME)) {
+                       edev = usbip_exported_device_new(path);
+                       if (!edev) {
+                               dbg("usbip_exported_device_new failed");
+                               continue;
+                       }
+
+                       list_add(&edev->node, &host_driver->edev_list);
+                       host_driver->ndevs++;
+               }
+       }
+
+       return 0;
+}
+
+static void usbip_exported_device_destroy(void)
+{
+       struct list_head *i, *tmp;
+       struct usbip_exported_device *edev;
+
+       list_for_each_safe(i, tmp, &host_driver->edev_list) {
+               edev = list_entry(i, struct usbip_exported_device, node);
+               list_del(i);
+               free(edev);
+       }
+}
+
+int usbip_host_driver_open(void)
+{
+       int rc;
+
+       udev_context = udev_new();
+       if (!udev_context) {
+               err("udev_new failed");
+               return -1;
+       }
+
+       host_driver = calloc(1, sizeof(*host_driver));
+
+       host_driver->ndevs = 0;
+       INIT_LIST_HEAD(&host_driver->edev_list);
+
+       rc = refresh_exported_devices();
+       if (rc < 0)
+               goto err_free_host_driver;
+
+       return 0;
+
+err_free_host_driver:
+       free(host_driver);
+       host_driver = NULL;
+
+       udev_unref(udev_context);
+
+       return -1;
+}
+
+void usbip_host_driver_close(void)
+{
+       if (!host_driver)
+               return;
+
+       usbip_exported_device_destroy();
+
+       free(host_driver);
+       host_driver = NULL;
+
+       udev_unref(udev_context);
+}
+
+int usbip_host_refresh_device_list(void)
+{
+       int rc;
+
+       usbip_exported_device_destroy();
+
+       host_driver->ndevs = 0;
+       INIT_LIST_HEAD(&host_driver->edev_list);
+
+       rc = refresh_exported_devices();
+       if (rc < 0)
+               return -1;
+
+       return 0;
+}
+
+int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd)
+{
+       char attr_name[] = "usbip_sockfd";
+       char sockfd_attr_path[SYSFS_PATH_MAX];
+       char sockfd_buff[30];
+       int ret;
+
+       if (edev->status != SDEV_ST_AVAILABLE) {
+               dbg("device not available: %s", edev->udev.busid);
+               switch (edev->status) {
+               case SDEV_ST_ERROR:
+                       dbg("status SDEV_ST_ERROR");
+                       break;
+               case SDEV_ST_USED:
+                       dbg("status SDEV_ST_USED");
+                       break;
+               default:
+                       dbg("status unknown: 0x%x", edev->status);
+               }
+               return -1;
+       }
+
+       /* only the first interface is true */
+       snprintf(sockfd_attr_path, sizeof(sockfd_attr_path), "%s/%s",
+                edev->udev.path, attr_name);
+
+       snprintf(sockfd_buff, sizeof(sockfd_buff), "%d\n", sockfd);
+
+       ret = write_sysfs_attribute(sockfd_attr_path, sockfd_buff,
+                                   strlen(sockfd_buff));
+       if (ret < 0) {
+               err("write_sysfs_attribute failed: sockfd %s to %s",
+                   sockfd_buff, sockfd_attr_path);
+               return ret;
+       }
+
+       info("connect: %s", edev->udev.busid);
+
+       return ret;
+}
+
+struct usbip_exported_device *usbip_host_get_device(int num)
+{
+       struct list_head *i;
+       struct usbip_exported_device *edev;
+       int cnt = 0;
+
+       list_for_each(i, &host_driver->edev_list) {
+               edev = list_entry(i, struct usbip_exported_device, node);
+               if (num == cnt)
+                       return edev;
+               else
+                       cnt++;
+       }
+
+       return NULL;
+}
diff --git a/tools/usb/usbip/libsrc/usbip_host_driver.h b/tools/usb/usbip/libsrc/usbip_host_driver.h
new file mode 100644 (file)
index 0000000..2a31f85
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __USBIP_HOST_DRIVER_H
+#define __USBIP_HOST_DRIVER_H
+
+#include <stdint.h>
+#include "usbip_common.h"
+#include "list.h"
+
+struct usbip_host_driver {
+       int ndevs;
+       /* list of exported device */
+       struct list_head edev_list;
+};
+
+struct usbip_exported_device {
+       struct udev_device *sudev;
+       int32_t status;
+       struct usbip_usb_device udev;
+       struct list_head node;
+       struct usbip_usb_interface uinf[];
+};
+
+extern struct usbip_host_driver *host_driver;
+
+int usbip_host_driver_open(void);
+void usbip_host_driver_close(void);
+
+int usbip_host_refresh_device_list(void);
+int usbip_host_export_device(struct usbip_exported_device *edev, int sockfd);
+struct usbip_exported_device *usbip_host_get_device(int num);
+
+#endif /* __USBIP_HOST_DRIVER_H */
diff --git a/tools/usb/usbip/libsrc/vhci_driver.c b/tools/usb/usbip/libsrc/vhci_driver.c
new file mode 100644 (file)
index 0000000..ad92047
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+ * Copyright (C) 2005-2007 Takahiro Hirofuchi
+ */
+
+#include "usbip_common.h"
+#include "vhci_driver.h"
+#include <limits.h>
+#include <netdb.h>
+#include <libudev.h>
+#include "sysfs_utils.h"
+
+#undef  PROGNAME
+#define PROGNAME "libusbip"
+
+struct usbip_vhci_driver *vhci_driver;
+struct udev *udev_context;
+
+static struct usbip_imported_device *
+imported_device_init(struct usbip_imported_device *idev, char *busid)
+{
+       struct udev_device *sudev;
+
+       sudev = udev_device_new_from_subsystem_sysname(udev_context,
+                                                      "usb", busid);
+       if (!sudev) {
+               dbg("udev_device_new_from_subsystem_sysname failed: %s", busid);
+               goto err;
+       }
+       read_usb_device(sudev, &idev->udev);
+       udev_device_unref(sudev);
+
+       return idev;
+
+err:
+       return NULL;
+}
+
+
+
+static int parse_status(const char *value)
+{
+       int ret = 0;
+       char *c;
+
+
+       for (int i = 0; i < vhci_driver->nports; i++)
+               memset(&vhci_driver->idev[i], 0, sizeof(vhci_driver->idev[i]));
+
+
+       /* skip a header line */
+       c = strchr(value, '\n');
+       if (!c)
+               return -1;
+       c++;
+
+       while (*c != '\0') {
+               int port, status, speed, devid;
+               unsigned long socket;
+               char lbusid[SYSFS_BUS_ID_SIZE];
+
+               ret = sscanf(c, "%d %d %d %x %lx %31s\n",
+                               &port, &status, &speed,
+                               &devid, &socket, lbusid);
+
+               if (ret < 5) {
+                       dbg("sscanf failed: %d", ret);
+                       BUG();
+               }
+
+               dbg("port %d status %d speed %d devid %x",
+                               port, status, speed, devid);
+               dbg("socket %lx lbusid %s", socket, lbusid);
+
+
+               /* if a device is connected, look at it */
+               {
+                       struct usbip_imported_device *idev = &vhci_driver->idev[port];
+
+                       idev->port      = port;
+                       idev->status    = status;
+
+                       idev->devid     = devid;
+
+                       idev->busnum    = (devid >> 16);
+                       idev->devnum    = (devid & 0x0000ffff);
+
+                       if (idev->status != VDEV_ST_NULL
+                           && idev->status != VDEV_ST_NOTASSIGNED) {
+                               idev = imported_device_init(idev, lbusid);
+                               if (!idev) {
+                                       dbg("imported_device_init failed");
+                                       return -1;
+                               }
+                       }
+               }
+
+
+               /* go to the next line */
+               c = strchr(c, '\n');
+               if (!c)
+                       break;
+               c++;
+       }
+
+       dbg("exit");
+
+       return 0;
+}
+
+static int refresh_imported_device_list(void)
+{
+       const char *attr_status;
+
+       attr_status = udev_device_get_sysattr_value(vhci_driver->hc_device,
+                                              "status");
+       if (!attr_status) {
+               err("udev_device_get_sysattr_value failed");
+               return -1;
+       }
+
+       return parse_status(attr_status);
+}
+
+static int get_nports(void)
+{
+       char *c;
+       int nports = 0;
+       const char *attr_status;
+
+       attr_status = udev_device_get_sysattr_value(vhci_driver->hc_device,
+                                              "status");
+       if (!attr_status) {
+               err("udev_device_get_sysattr_value failed");
+               return -1;
+       }
+
+       /* skip a header line */
+       c = strchr(attr_status, '\n');
+       if (!c)
+               return 0;
+       c++;
+
+       while (*c != '\0') {
+               /* go to the next line */
+               c = strchr(c, '\n');
+               if (!c)
+                       return nports;
+               c++;
+               nports += 1;
+       }
+
+       return nports;
+}
+
+/*
+ * Read the given port's record.
+ *
+ * To avoid buffer overflow we will read the entire line and
+ * validate each part's size. The initial buffer is padded by 4 to
+ * accommodate the 2 spaces, 1 newline and an additional character
+ * which is needed to properly validate the 3rd part without it being
+ * truncated to an acceptable length.
+ */
+static int read_record(int rhport, char *host, unsigned long host_len,
+               char *port, unsigned long port_len, char *busid)
+{
+       int part;
+       FILE *file;
+       char path[PATH_MAX+1];
+       char *buffer, *start, *end;
+       char delim[] = {' ', ' ', '\n'};
+       int max_len[] = {(int)host_len, (int)port_len, SYSFS_BUS_ID_SIZE};
+       size_t buffer_len = host_len + port_len + SYSFS_BUS_ID_SIZE + 4;
+
+       buffer = malloc(buffer_len);
+       if (!buffer)
+               return -1;
+
+       snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport);
+
+       file = fopen(path, "r");
+       if (!file) {
+               err("fopen");
+               free(buffer);
+               return -1;
+       }
+
+       if (fgets(buffer, buffer_len, file) == NULL) {
+               err("fgets");
+               free(buffer);
+               fclose(file);
+               return -1;
+       }
+       fclose(file);
+
+       /* validate the length of each of the 3 parts */
+       start = buffer;
+       for (part = 0; part < 3; part++) {
+               end = strchr(start, delim[part]);
+               if (end == NULL || (end - start) > max_len[part]) {
+                       free(buffer);
+                       return -1;
+               }
+               start = end + 1;
+       }
+
+       if (sscanf(buffer, "%s %s %s\n", host, port, busid) != 3) {
+               err("sscanf");
+               free(buffer);
+               return -1;
+       }
+
+       free(buffer);
+
+       return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+int usbip_vhci_driver_open(void)
+{
+       udev_context = udev_new();
+       if (!udev_context) {
+               err("udev_new failed");
+               return -1;
+       }
+
+       vhci_driver = calloc(1, sizeof(struct usbip_vhci_driver));
+
+       /* will be freed in usbip_driver_close() */
+       vhci_driver->hc_device =
+               udev_device_new_from_subsystem_sysname(udev_context,
+                                                      USBIP_VHCI_BUS_TYPE,
+                                                      USBIP_VHCI_DRV_NAME);
+       if (!vhci_driver->hc_device) {
+               err("udev_device_new_from_subsystem_sysname failed");
+               goto err;
+       }
+
+       vhci_driver->nports = get_nports();
+
+       dbg("available ports: %d", vhci_driver->nports);
+
+       if (refresh_imported_device_list())
+               goto err;
+
+       return 0;
+
+err:
+       udev_device_unref(vhci_driver->hc_device);
+
+       if (vhci_driver)
+               free(vhci_driver);
+
+       vhci_driver = NULL;
+
+       udev_unref(udev_context);
+
+       return -1;
+}
+
+
+void usbip_vhci_driver_close(void)
+{
+       if (!vhci_driver)
+               return;
+
+       udev_device_unref(vhci_driver->hc_device);
+
+       free(vhci_driver);
+
+       vhci_driver = NULL;
+
+       udev_unref(udev_context);
+}
+
+
+int usbip_vhci_refresh_device_list(void)
+{
+
+       if (refresh_imported_device_list())
+               goto err;
+
+       return 0;
+err:
+       dbg("failed to refresh device list");
+       return -1;
+}
+
+
+int usbip_vhci_get_free_port(void)
+{
+       for (int i = 0; i < vhci_driver->nports; i++) {
+               if (vhci_driver->idev[i].status == VDEV_ST_NULL)
+                       return i;
+       }
+
+       return -1;
+}
+
+int usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid,
+               uint32_t speed) {
+       char buff[200]; /* what size should be ? */
+       char attach_attr_path[SYSFS_PATH_MAX];
+       char attr_attach[] = "attach";
+       const char *path;
+       int ret;
+
+       snprintf(buff, sizeof(buff), "%u %d %u %u",
+                       port, sockfd, devid, speed);
+       dbg("writing: %s", buff);
+
+       path = udev_device_get_syspath(vhci_driver->hc_device);
+       snprintf(attach_attr_path, sizeof(attach_attr_path), "%s/%s",
+                path, attr_attach);
+       dbg("attach attribute path: %s", attach_attr_path);
+
+       ret = write_sysfs_attribute(attach_attr_path, buff, strlen(buff));
+       if (ret < 0) {
+               dbg("write_sysfs_attribute failed");
+               return -1;
+       }
+
+       dbg("attached port: %d", port);
+
+       return 0;
+}
+
+static unsigned long get_devid(uint8_t busnum, uint8_t devnum)
+{
+       return (busnum << 16) | devnum;
+}
+
+/* will be removed */
+int usbip_vhci_attach_device(uint8_t port, int sockfd, uint8_t busnum,
+               uint8_t devnum, uint32_t speed)
+{
+       int devid = get_devid(busnum, devnum);
+
+       return usbip_vhci_attach_device2(port, sockfd, devid, speed);
+}
+
+int usbip_vhci_detach_device(uint8_t port)
+{
+       char detach_attr_path[SYSFS_PATH_MAX];
+       char attr_detach[] = "detach";
+       char buff[200]; /* what size should be ? */
+       const char *path;
+       int ret;
+
+       snprintf(buff, sizeof(buff), "%u", port);
+       dbg("writing: %s", buff);
+
+       path = udev_device_get_syspath(vhci_driver->hc_device);
+       snprintf(detach_attr_path, sizeof(detach_attr_path), "%s/%s",
+                path, attr_detach);
+       dbg("detach attribute path: %s", detach_attr_path);
+
+       ret = write_sysfs_attribute(detach_attr_path, buff, strlen(buff));
+       if (ret < 0) {
+               dbg("write_sysfs_attribute failed");
+               return -1;
+       }
+
+       dbg("detached port: %d", port);
+
+       return 0;
+}
+
+int usbip_vhci_imported_device_dump(struct usbip_imported_device *idev)
+{
+       char product_name[100];
+       char host[NI_MAXHOST] = "unknown host";
+       char serv[NI_MAXSERV] = "unknown port";
+       char remote_busid[SYSFS_BUS_ID_SIZE];
+       int ret;
+       int read_record_error = 0;
+
+       if (idev->status == VDEV_ST_NULL || idev->status == VDEV_ST_NOTASSIGNED)
+               return 0;
+
+       ret = read_record(idev->port, host, sizeof(host), serv, sizeof(serv),
+                         remote_busid);
+       if (ret) {
+               err("read_record");
+               read_record_error = 1;
+       }
+
+       printf("Port %02d: <%s> at %s\n", idev->port,
+              usbip_status_string(idev->status),
+              usbip_speed_string(idev->udev.speed));
+
+       usbip_names_get_product(product_name, sizeof(product_name),
+                               idev->udev.idVendor, idev->udev.idProduct);
+
+       printf("       %s\n",  product_name);
+
+       if (!read_record_error) {
+               printf("%10s -> usbip://%s:%s/%s\n", idev->udev.busid,
+                      host, serv, remote_busid);
+               printf("%10s -> remote bus/dev %03d/%03d\n", " ",
+                      idev->busnum, idev->devnum);
+       } else {
+               printf("%10s -> unknown host, remote port and remote busid\n",
+                      idev->udev.busid);
+               printf("%10s -> remote bus/dev %03d/%03d\n", " ",
+                      idev->busnum, idev->devnum);
+       }
+
+       return 0;
+}
diff --git a/tools/usb/usbip/libsrc/vhci_driver.h b/tools/usb/usbip/libsrc/vhci_driver.h
new file mode 100644 (file)
index 0000000..fa2316c
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2005-2007 Takahiro Hirofuchi
+ */
+
+#ifndef __VHCI_DRIVER_H
+#define __VHCI_DRIVER_H
+
+#include <libudev.h>
+#include <stdint.h>
+
+#include "usbip_common.h"
+
+#define USBIP_VHCI_BUS_TYPE "platform"
+#define MAXNPORT 128
+
+struct usbip_imported_device {
+       uint8_t port;
+       uint32_t status;
+
+       uint32_t devid;
+
+       uint8_t busnum;
+       uint8_t devnum;
+
+       /* usbip_class_device list */
+       struct usbip_usb_device udev;
+};
+
+struct usbip_vhci_driver {
+
+       /* /sys/devices/platform/vhci_hcd */
+       struct udev_device *hc_device;
+
+       int nports;
+       struct usbip_imported_device idev[MAXNPORT];
+};
+
+
+extern struct usbip_vhci_driver *vhci_driver;
+
+int usbip_vhci_driver_open(void);
+void usbip_vhci_driver_close(void);
+
+int  usbip_vhci_refresh_device_list(void);
+
+
+int usbip_vhci_get_free_port(void);
+int usbip_vhci_attach_device2(uint8_t port, int sockfd, uint32_t devid,
+               uint32_t speed);
+
+/* will be removed */
+int usbip_vhci_attach_device(uint8_t port, int sockfd, uint8_t busnum,
+               uint8_t devnum, uint32_t speed);
+
+int usbip_vhci_detach_device(uint8_t port);
+
+int usbip_vhci_imported_device_dump(struct usbip_imported_device *idev);
+
+#endif /* __VHCI_DRIVER_H */
diff --git a/tools/usb/usbip/src/Makefile.am b/tools/usb/usbip/src/Makefile.am
new file mode 100644 (file)
index 0000000..e81a4eb
--- /dev/null
@@ -0,0 +1,11 @@
+AM_CPPFLAGS = -I$(top_srcdir)/libsrc -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"'
+AM_CFLAGS   = @EXTRA_CFLAGS@
+LDADD       = $(top_builddir)/libsrc/libusbip.la
+
+sbin_PROGRAMS := usbip usbipd
+
+usbip_SOURCES := usbip.h utils.h usbip.c utils.c usbip_network.c \
+                usbip_attach.c usbip_detach.c usbip_list.c \
+                usbip_bind.c usbip_unbind.c usbip_port.c
+
+usbipd_SOURCES := usbip_network.h usbipd.c usbip_network.c
diff --git a/tools/usb/usbip/src/usbip.c b/tools/usb/usbip/src/usbip.c
new file mode 100644 (file)
index 0000000..d7599d9
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * command structure borrowed from udev
+ * (git://git.kernel.org/pub/scm/linux/hotplug/udev.git)
+ *
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <getopt.h>
+#include <syslog.h>
+
+#include "usbip_common.h"
+#include "usbip_network.h"
+#include "usbip.h"
+
+static int usbip_help(int argc, char *argv[]);
+static int usbip_version(int argc, char *argv[]);
+
+static const char usbip_version_string[] = PACKAGE_STRING;
+
+static const char usbip_usage_string[] =
+       "usbip [--debug] [--log] [--tcp-port PORT] [version]\n"
+       "             [help] <command> <args>\n";
+
+static void usbip_usage(void)
+{
+       printf("usage: %s", usbip_usage_string);
+}
+
+struct command {
+       const char *name;
+       int (*fn)(int argc, char *argv[]);
+       const char *help;
+       void (*usage)(void);
+};
+
+static const struct command cmds[] = {
+       {
+               .name  = "help",
+               .fn    = usbip_help,
+               .help  = NULL,
+               .usage = NULL
+       },
+       {
+               .name  = "version",
+               .fn    = usbip_version,
+               .help  = NULL,
+               .usage = NULL
+       },
+       {
+               .name  = "attach",
+               .fn    = usbip_attach,
+               .help  = "Attach a remote USB device",
+               .usage = usbip_attach_usage
+       },
+       {
+               .name  = "detach",
+               .fn    = usbip_detach,
+               .help  = "Detach a remote USB device",
+               .usage = usbip_detach_usage
+       },
+       {
+               .name  = "list",
+               .fn    = usbip_list,
+               .help  = "List exportable or local USB devices",
+               .usage = usbip_list_usage
+       },
+       {
+               .name  = "bind",
+               .fn    = usbip_bind,
+               .help  = "Bind device to " USBIP_HOST_DRV_NAME ".ko",
+               .usage = usbip_bind_usage
+       },
+       {
+               .name  = "unbind",
+               .fn    = usbip_unbind,
+               .help  = "Unbind device from " USBIP_HOST_DRV_NAME ".ko",
+               .usage = usbip_unbind_usage
+       },
+       {
+               .name  = "port",
+               .fn    = usbip_port_show,
+               .help  = "Show imported USB devices",
+               .usage = NULL
+       },
+       { NULL, NULL, NULL, NULL }
+};
+
+static int usbip_help(int argc, char *argv[])
+{
+       const struct command *cmd;
+       int i;
+       int ret = 0;
+
+       if (argc > 1 && argv++) {
+               for (i = 0; cmds[i].name != NULL; i++)
+                       if (!strcmp(cmds[i].name, argv[0]) && cmds[i].usage) {
+                               cmds[i].usage();
+                               goto done;
+                       }
+               ret = -1;
+       }
+
+       usbip_usage();
+       printf("\n");
+       for (cmd = cmds; cmd->name != NULL; cmd++)
+               if (cmd->help != NULL)
+                       printf("  %-10s %s\n", cmd->name, cmd->help);
+       printf("\n");
+done:
+       return ret;
+}
+
+static int usbip_version(int argc, char *argv[])
+{
+       (void) argc;
+       (void) argv;
+
+       printf(PROGNAME " (%s)\n", usbip_version_string);
+       return 0;
+}
+
+static int run_command(const struct command *cmd, int argc, char *argv[])
+{
+       dbg("running command: `%s'", cmd->name);
+       return cmd->fn(argc, argv);
+}
+
+int main(int argc, char *argv[])
+{
+       static const struct option opts[] = {
+               { "debug",    no_argument,       NULL, 'd' },
+               { "log",      no_argument,       NULL, 'l' },
+               { "tcp-port", required_argument, NULL, 't' },
+               { NULL,       0,                 NULL,  0  }
+       };
+
+       char *cmd;
+       int opt;
+       int i, rc = -1;
+
+       usbip_use_stderr = 1;
+       opterr = 0;
+       for (;;) {
+               opt = getopt_long(argc, argv, "+dlt:", opts, NULL);
+
+               if (opt == -1)
+                       break;
+
+               switch (opt) {
+               case 'd':
+                       usbip_use_debug = 1;
+                       break;
+               case 'l':
+                       usbip_use_syslog = 1;
+                       openlog("", LOG_PID, LOG_USER);
+                       break;
+               case 't':
+                       usbip_setup_port_number(optarg);
+                       break;
+               case '?':
+                       printf("usbip: invalid option\n");
+               default:
+                       usbip_usage();
+                       goto out;
+               }
+       }
+
+       cmd = argv[optind];
+       if (cmd) {
+               for (i = 0; cmds[i].name != NULL; i++)
+                       if (!strcmp(cmds[i].name, cmd)) {
+                               argc -= optind;
+                               argv += optind;
+                               optind = 0;
+                               rc = run_command(&cmds[i], argc, argv);
+                               goto out;
+                       }
+       }
+
+       /* invalid command */
+       usbip_help(0, NULL);
+out:
+       return (rc > -1 ? EXIT_SUCCESS : EXIT_FAILURE);
+}
diff --git a/tools/usb/usbip/src/usbip.h b/tools/usb/usbip/src/usbip.h
new file mode 100644 (file)
index 0000000..84fe66a
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __USBIP_H
+#define __USBIP_H
+
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif
+
+/* usbip commands */
+int usbip_attach(int argc, char *argv[]);
+int usbip_detach(int argc, char *argv[]);
+int usbip_list(int argc, char *argv[]);
+int usbip_bind(int argc, char *argv[]);
+int usbip_unbind(int argc, char *argv[]);
+int usbip_port_show(int argc, char *argv[]);
+
+void usbip_attach_usage(void);
+void usbip_detach_usage(void);
+void usbip_list_usage(void);
+void usbip_bind_usage(void);
+void usbip_unbind_usage(void);
+
+#endif /* __USBIP_H */
diff --git a/tools/usb/usbip/src/usbip_attach.c b/tools/usb/usbip/src/usbip_attach.c
new file mode 100644 (file)
index 0000000..d58a14d
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/stat.h>
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <fcntl.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "vhci_driver.h"
+#include "usbip_common.h"
+#include "usbip_network.h"
+#include "usbip.h"
+
+static const char usbip_attach_usage_string[] =
+       "usbip attach <args>\n"
+       "    -r, --remote=<host>      The machine with exported USB devices\n"
+       "    -b, --busid=<busid>    Busid of the device on <host>\n";
+
+void usbip_attach_usage(void)
+{
+       printf("usage: %s", usbip_attach_usage_string);
+}
+
+#define MAX_BUFF 100
+static int record_connection(char *host, char *port, char *busid, int rhport)
+{
+       int fd;
+       char path[PATH_MAX+1];
+       char buff[MAX_BUFF+1];
+       int ret;
+
+       ret = mkdir(VHCI_STATE_PATH, 0700);
+       if (ret < 0) {
+               /* if VHCI_STATE_PATH exists, then it better be a directory */
+               if (errno == EEXIST) {
+                       struct stat s;
+
+                       ret = stat(VHCI_STATE_PATH, &s);
+                       if (ret < 0)
+                               return -1;
+                       if (!(s.st_mode & S_IFDIR))
+                               return -1;
+               } else
+                       return -1;
+       }
+
+       snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", rhport);
+
+       fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
+       if (fd < 0)
+               return -1;
+
+       snprintf(buff, MAX_BUFF, "%s %s %s\n",
+                       host, port, busid);
+
+       ret = write(fd, buff, strlen(buff));
+       if (ret != (ssize_t) strlen(buff)) {
+               close(fd);
+               return -1;
+       }
+
+       close(fd);
+
+       return 0;
+}
+
+static int import_device(int sockfd, struct usbip_usb_device *udev)
+{
+       int rc;
+       int port;
+
+       rc = usbip_vhci_driver_open();
+       if (rc < 0) {
+               err("open vhci_driver");
+               return -1;
+       }
+
+       port = usbip_vhci_get_free_port();
+       if (port < 0) {
+               err("no free port");
+               usbip_vhci_driver_close();
+               return -1;
+       }
+
+       rc = usbip_vhci_attach_device(port, sockfd, udev->busnum,
+                                     udev->devnum, udev->speed);
+       if (rc < 0) {
+               err("import device");
+               usbip_vhci_driver_close();
+               return -1;
+       }
+
+       usbip_vhci_driver_close();
+
+       return port;
+}
+
+static int query_import_device(int sockfd, char *busid)
+{
+       int rc;
+       struct op_import_request request;
+       struct op_import_reply   reply;
+       uint16_t code = OP_REP_IMPORT;
+
+       memset(&request, 0, sizeof(request));
+       memset(&reply, 0, sizeof(reply));
+
+       /* send a request */
+       rc = usbip_net_send_op_common(sockfd, OP_REQ_IMPORT, 0);
+       if (rc < 0) {
+               err("send op_common");
+               return -1;
+       }
+
+       strncpy(request.busid, busid, SYSFS_BUS_ID_SIZE-1);
+
+       PACK_OP_IMPORT_REQUEST(0, &request);
+
+       rc = usbip_net_send(sockfd, (void *) &request, sizeof(request));
+       if (rc < 0) {
+               err("send op_import_request");
+               return -1;
+       }
+
+       /* receive a reply */
+       rc = usbip_net_recv_op_common(sockfd, &code);
+       if (rc < 0) {
+               err("recv op_common");
+               return -1;
+       }
+
+       rc = usbip_net_recv(sockfd, (void *) &reply, sizeof(reply));
+       if (rc < 0) {
+               err("recv op_import_reply");
+               return -1;
+       }
+
+       PACK_OP_IMPORT_REPLY(0, &reply);
+
+       /* check the reply */
+       if (strncmp(reply.udev.busid, busid, SYSFS_BUS_ID_SIZE)) {
+               err("recv different busid %s", reply.udev.busid);
+               return -1;
+       }
+
+       /* import a device */
+       return import_device(sockfd, &reply.udev);
+}
+
+static int attach_device(char *host, char *busid)
+{
+       int sockfd;
+       int rc;
+       int rhport;
+
+       sockfd = usbip_net_tcp_connect(host, usbip_port_string);
+       if (sockfd < 0) {
+               err("tcp connect");
+               return -1;
+       }
+
+       rhport = query_import_device(sockfd, busid);
+       if (rhport < 0) {
+               err("query");
+               return -1;
+       }
+
+       close(sockfd);
+
+       rc = record_connection(host, usbip_port_string, busid, rhport);
+       if (rc < 0) {
+               err("record connection");
+               return -1;
+       }
+
+       return 0;
+}
+
+int usbip_attach(int argc, char *argv[])
+{
+       static const struct option opts[] = {
+               { "remote", required_argument, NULL, 'r' },
+               { "busid",  required_argument, NULL, 'b' },
+               { NULL, 0,  NULL, 0 }
+       };
+       char *host = NULL;
+       char *busid = NULL;
+       int opt;
+       int ret = -1;
+
+       for (;;) {
+               opt = getopt_long(argc, argv, "r:b:", opts, NULL);
+
+               if (opt == -1)
+                       break;
+
+               switch (opt) {
+               case 'r':
+                       host = optarg;
+                       break;
+               case 'b':
+                       busid = optarg;
+                       break;
+               default:
+                       goto err_out;
+               }
+       }
+
+       if (!host || !busid)
+               goto err_out;
+
+       ret = attach_device(host, busid);
+       goto out;
+
+err_out:
+       usbip_attach_usage();
+out:
+       return ret;
+}
diff --git a/tools/usb/usbip/src/usbip_bind.c b/tools/usb/usbip/src/usbip_bind.c
new file mode 100644 (file)
index 0000000..fa46141
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libudev.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <getopt.h>
+
+#include "usbip_common.h"
+#include "utils.h"
+#include "usbip.h"
+#include "sysfs_utils.h"
+
+enum unbind_status {
+       UNBIND_ST_OK,
+       UNBIND_ST_USBIP_HOST,
+       UNBIND_ST_FAILED
+};
+
+static const char usbip_bind_usage_string[] =
+       "usbip bind <args>\n"
+       "    -b, --busid=<busid>    Bind " USBIP_HOST_DRV_NAME ".ko to device "
+       "on <busid>\n";
+
+void usbip_bind_usage(void)
+{
+       printf("usage: %s", usbip_bind_usage_string);
+}
+
+/* call at unbound state */
+static int bind_usbip(char *busid)
+{
+       char attr_name[] = "bind";
+       char bind_attr_path[SYSFS_PATH_MAX];
+       int rc = -1;
+
+       snprintf(bind_attr_path, sizeof(bind_attr_path), "%s/%s/%s/%s/%s/%s",
+                SYSFS_MNT_PATH, SYSFS_BUS_NAME, SYSFS_BUS_TYPE,
+                SYSFS_DRIVERS_NAME, USBIP_HOST_DRV_NAME, attr_name);
+
+       rc = write_sysfs_attribute(bind_attr_path, busid, strlen(busid));
+       if (rc < 0) {
+               err("error binding device %s to driver: %s", busid,
+                   strerror(errno));
+               return -1;
+       }
+
+       return 0;
+}
+
+/* buggy driver may cause dead lock */
+static int unbind_other(char *busid)
+{
+       enum unbind_status status = UNBIND_ST_OK;
+
+       char attr_name[] = "unbind";
+       char unbind_attr_path[SYSFS_PATH_MAX];
+       int rc = -1;
+
+       struct udev *udev;
+       struct udev_device *dev;
+       const char *driver;
+       const char *bDevClass;
+
+       /* Create libudev context. */
+       udev = udev_new();
+
+       /* Get the device. */
+       dev = udev_device_new_from_subsystem_sysname(udev, "usb", busid);
+       if (!dev) {
+               dbg("unable to find device with bus ID %s", busid);
+               goto err_close_busid_dev;
+       }
+
+       /* Check what kind of device it is. */
+       bDevClass  = udev_device_get_sysattr_value(dev, "bDeviceClass");
+       if (!bDevClass) {
+               dbg("unable to get bDevClass device attribute");
+               goto err_close_busid_dev;
+       }
+
+       if (!strncmp(bDevClass, "09", strlen(bDevClass))) {
+               dbg("skip unbinding of hub");
+               goto err_close_busid_dev;
+       }
+
+       /* Get the device driver. */
+       driver = udev_device_get_driver(dev);
+       if (!driver) {
+               /* No driver bound to this device. */
+               goto out;
+       }
+
+       if (!strncmp(USBIP_HOST_DRV_NAME, driver,
+                               strlen(USBIP_HOST_DRV_NAME))) {
+               /* Already bound to usbip-host. */
+               status = UNBIND_ST_USBIP_HOST;
+               goto out;
+       }
+
+       /* Unbind device from driver. */
+       snprintf(unbind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",
+                SYSFS_MNT_PATH, SYSFS_BUS_NAME, SYSFS_BUS_TYPE,
+                SYSFS_DRIVERS_NAME, driver, attr_name);
+
+       rc = write_sysfs_attribute(unbind_attr_path, busid, strlen(busid));
+       if (rc < 0) {
+               err("error unbinding device %s from driver", busid);
+               goto err_close_busid_dev;
+       }
+
+       goto out;
+
+err_close_busid_dev:
+       status = UNBIND_ST_FAILED;
+out:
+       udev_device_unref(dev);
+       udev_unref(udev);
+
+       return status;
+}
+
+static int bind_device(char *busid)
+{
+       int rc;
+       struct udev *udev;
+       struct udev_device *dev;
+
+       /* Check whether the device with this bus ID exists. */
+       udev = udev_new();
+       dev = udev_device_new_from_subsystem_sysname(udev, "usb", busid);
+       if (!dev) {
+               err("device with the specified bus ID does not exist");
+               return -1;
+       }
+       udev_unref(udev);
+
+       rc = unbind_other(busid);
+       if (rc == UNBIND_ST_FAILED) {
+               err("could not unbind driver from device on busid %s", busid);
+               return -1;
+       } else if (rc == UNBIND_ST_USBIP_HOST) {
+               err("device on busid %s is already bound to %s", busid,
+                   USBIP_HOST_DRV_NAME);
+               return -1;
+       }
+
+       rc = modify_match_busid(busid, 1);
+       if (rc < 0) {
+               err("unable to bind device on %s", busid);
+               return -1;
+       }
+
+       rc = bind_usbip(busid);
+       if (rc < 0) {
+               err("could not bind device to %s", USBIP_HOST_DRV_NAME);
+               modify_match_busid(busid, 0);
+               return -1;
+       }
+
+       info("bind device on busid %s: complete", busid);
+
+       return 0;
+}
+
+int usbip_bind(int argc, char *argv[])
+{
+       static const struct option opts[] = {
+               { "busid", required_argument, NULL, 'b' },
+               { NULL,    0,                 NULL,  0  }
+       };
+
+       int opt;
+       int ret = -1;
+
+       for (;;) {
+               opt = getopt_long(argc, argv, "b:", opts, NULL);
+
+               if (opt == -1)
+                       break;
+
+               switch (opt) {
+               case 'b':
+                       ret = bind_device(optarg);
+                       goto out;
+               default:
+                       goto err_out;
+               }
+       }
+
+err_out:
+       usbip_bind_usage();
+out:
+       return ret;
+}
diff --git a/tools/usb/usbip/src/usbip_detach.c b/tools/usb/usbip/src/usbip_detach.c
new file mode 100644 (file)
index 0000000..05c6d15
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <ctype.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <getopt.h>
+#include <unistd.h>
+
+#include "vhci_driver.h"
+#include "usbip_common.h"
+#include "usbip_network.h"
+#include "usbip.h"
+
+static const char usbip_detach_usage_string[] =
+       "usbip detach <args>\n"
+       "    -p, --port=<port>    " USBIP_VHCI_DRV_NAME
+       " port the device is on\n";
+
+void usbip_detach_usage(void)
+{
+       printf("usage: %s", usbip_detach_usage_string);
+}
+
+static int detach_port(char *port)
+{
+       int ret;
+       uint8_t portnum;
+       char path[PATH_MAX+1];
+
+       for (unsigned int i = 0; i < strlen(port); i++)
+               if (!isdigit(port[i])) {
+                       err("invalid port %s", port);
+                       return -1;
+               }
+
+       /* check max port */
+
+       portnum = atoi(port);
+
+       /* remove the port state file */
+
+       snprintf(path, PATH_MAX, VHCI_STATE_PATH"/port%d", portnum);
+
+       remove(path);
+       rmdir(VHCI_STATE_PATH);
+
+       ret = usbip_vhci_driver_open();
+       if (ret < 0) {
+               err("open vhci_driver");
+               return -1;
+       }
+
+       ret = usbip_vhci_detach_device(portnum);
+       if (ret < 0)
+               return -1;
+
+       usbip_vhci_driver_close();
+
+       return ret;
+}
+
+int usbip_detach(int argc, char *argv[])
+{
+       static const struct option opts[] = {
+               { "port", required_argument, NULL, 'p' },
+               { NULL, 0, NULL, 0 }
+       };
+       int opt;
+       int ret = -1;
+
+       for (;;) {
+               opt = getopt_long(argc, argv, "p:", opts, NULL);
+
+               if (opt == -1)
+                       break;
+
+               switch (opt) {
+               case 'p':
+                       ret = detach_port(optarg);
+                       goto out;
+               default:
+                       goto err_out;
+               }
+       }
+
+err_out:
+       usbip_detach_usage();
+out:
+       return ret;
+}
diff --git a/tools/usb/usbip/src/usbip_list.c b/tools/usb/usbip/src/usbip_list.c
new file mode 100644 (file)
index 0000000..d5ce34a
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <libudev.h>
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <getopt.h>
+#include <netdb.h>
+#include <unistd.h>
+
+#include "usbip_common.h"
+#include "usbip_network.h"
+#include "usbip.h"
+
+static const char usbip_list_usage_string[] =
+       "usbip list [-p|--parsable] <args>\n"
+       "    -p, --parsable         Parsable list format\n"
+       "    -r, --remote=<host>    List the exportable USB devices on <host>\n"
+       "    -l, --local            List the local USB devices\n";
+
+void usbip_list_usage(void)
+{
+       printf("usage: %s", usbip_list_usage_string);
+}
+
+static int get_exported_devices(char *host, int sockfd)
+{
+       char product_name[100];
+       char class_name[100];
+       struct op_devlist_reply reply;
+       uint16_t code = OP_REP_DEVLIST;
+       struct usbip_usb_device udev;
+       struct usbip_usb_interface uintf;
+       unsigned int i;
+       int rc, j;
+
+       rc = usbip_net_send_op_common(sockfd, OP_REQ_DEVLIST, 0);
+       if (rc < 0) {
+               dbg("usbip_net_send_op_common failed");
+               return -1;
+       }
+
+       rc = usbip_net_recv_op_common(sockfd, &code);
+       if (rc < 0) {
+               dbg("usbip_net_recv_op_common failed");
+               return -1;
+       }
+
+       memset(&reply, 0, sizeof(reply));
+       rc = usbip_net_recv(sockfd, &reply, sizeof(reply));
+       if (rc < 0) {
+               dbg("usbip_net_recv_op_devlist failed");
+               return -1;
+       }
+       PACK_OP_DEVLIST_REPLY(0, &reply);
+       dbg("exportable devices: %d\n", reply.ndev);
+
+       if (reply.ndev == 0) {
+               info("no exportable devices found on %s", host);
+               return 0;
+       }
+
+       printf("Exportable USB devices\n");
+       printf("======================\n");
+       printf(" - %s\n", host);
+
+       for (i = 0; i < reply.ndev; i++) {
+               memset(&udev, 0, sizeof(udev));
+               rc = usbip_net_recv(sockfd, &udev, sizeof(udev));
+               if (rc < 0) {
+                       dbg("usbip_net_recv failed: usbip_usb_device[%d]", i);
+                       return -1;
+               }
+               usbip_net_pack_usb_device(0, &udev);
+
+               usbip_names_get_product(product_name, sizeof(product_name),
+                                       udev.idVendor, udev.idProduct);
+               usbip_names_get_class(class_name, sizeof(class_name),
+                                     udev.bDeviceClass, udev.bDeviceSubClass,
+                                     udev.bDeviceProtocol);
+               printf("%11s: %s\n", udev.busid, product_name);
+               printf("%11s: %s\n", "", udev.path);
+               printf("%11s: %s\n", "", class_name);
+
+               for (j = 0; j < udev.bNumInterfaces; j++) {
+                       rc = usbip_net_recv(sockfd, &uintf, sizeof(uintf));
+                       if (rc < 0) {
+                               err("usbip_net_recv failed: usbip_usb_intf[%d]",
+                                               j);
+
+                               return -1;
+                       }
+                       usbip_net_pack_usb_interface(0, &uintf);
+
+                       usbip_names_get_class(class_name, sizeof(class_name),
+                                       uintf.bInterfaceClass,
+                                       uintf.bInterfaceSubClass,
+                                       uintf.bInterfaceProtocol);
+                       printf("%11s: %2d - %s\n", "", j, class_name);
+               }
+
+               printf("\n");
+       }
+
+       return 0;
+}
+
+static int list_exported_devices(char *host)
+{
+       int rc;
+       int sockfd;
+
+       sockfd = usbip_net_tcp_connect(host, usbip_port_string);
+       if (sockfd < 0) {
+               err("could not connect to %s:%s: %s", host,
+                   usbip_port_string, gai_strerror(sockfd));
+               return -1;
+       }
+       dbg("connected to %s:%s", host, usbip_port_string);
+
+       rc = get_exported_devices(host, sockfd);
+       if (rc < 0) {
+               err("failed to get device list from %s", host);
+               return -1;
+       }
+
+       close(sockfd);
+
+       return 0;
+}
+
+static void print_device(const char *busid, const char *vendor,
+                        const char *product, bool parsable)
+{
+       if (parsable)
+               printf("busid=%s#usbid=%.4s:%.4s#", busid, vendor, product);
+       else
+               printf(" - busid %s (%.4s:%.4s)\n", busid, vendor, product);
+}
+
+static void print_product_name(char *product_name, bool parsable)
+{
+       if (!parsable)
+               printf("   %s\n", product_name);
+}
+
+static int list_devices(bool parsable)
+{
+       struct udev *udev;
+       struct udev_enumerate *enumerate;
+       struct udev_list_entry *devices, *dev_list_entry;
+       struct udev_device *dev;
+       const char *path;
+       const char *idVendor;
+       const char *idProduct;
+       const char *bConfValue;
+       const char *bNumIntfs;
+       const char *busid;
+       char product_name[128];
+       int ret = -1;
+
+       /* Create libudev context. */
+       udev = udev_new();
+
+       /* Create libudev device enumeration. */
+       enumerate = udev_enumerate_new(udev);
+
+       /* Take only USB devices that are not hubs and do not have
+        * the bInterfaceNumber attribute, i.e. are not interfaces.
+        */
+       udev_enumerate_add_match_subsystem(enumerate, "usb");
+       udev_enumerate_add_nomatch_sysattr(enumerate, "bDeviceClass", "09");
+       udev_enumerate_add_nomatch_sysattr(enumerate, "bInterfaceNumber", NULL);
+       udev_enumerate_scan_devices(enumerate);
+
+       devices = udev_enumerate_get_list_entry(enumerate);
+
+       /* Show information about each device. */
+       udev_list_entry_foreach(dev_list_entry, devices) {
+               path = udev_list_entry_get_name(dev_list_entry);
+               dev = udev_device_new_from_syspath(udev, path);
+
+               /* Get device information. */
+               idVendor = udev_device_get_sysattr_value(dev, "idVendor");
+               idProduct = udev_device_get_sysattr_value(dev, "idProduct");
+               bConfValue = udev_device_get_sysattr_value(dev, "bConfigurationValue");
+               bNumIntfs = udev_device_get_sysattr_value(dev, "bNumInterfaces");
+               busid = udev_device_get_sysname(dev);
+               if (!idVendor || !idProduct || !bConfValue || !bNumIntfs) {
+                       err("problem getting device attributes: %s",
+                           strerror(errno));
+                       goto err_out;
+               }
+
+               /* Get product name. */
+               usbip_names_get_product(product_name, sizeof(product_name),
+                                       strtol(idVendor, NULL, 16),
+                                       strtol(idProduct, NULL, 16));
+
+               /* Print information. */
+               print_device(busid, idVendor, idProduct, parsable);
+               print_product_name(product_name, parsable);
+
+               printf("\n");
+
+               udev_device_unref(dev);
+       }
+
+       ret = 0;
+
+err_out:
+       udev_enumerate_unref(enumerate);
+       udev_unref(udev);
+
+       return ret;
+}
+
+int usbip_list(int argc, char *argv[])
+{
+       static const struct option opts[] = {
+               { "parsable", no_argument,       NULL, 'p' },
+               { "remote",   required_argument, NULL, 'r' },
+               { "local",    no_argument,       NULL, 'l' },
+               { NULL,       0,                 NULL,  0  }
+       };
+
+       bool parsable = false;
+       int opt;
+       int ret = -1;
+
+       if (usbip_names_init(USBIDS_FILE))
+               err("failed to open %s", USBIDS_FILE);
+
+       for (;;) {
+               opt = getopt_long(argc, argv, "pr:l", opts, NULL);
+
+               if (opt == -1)
+                       break;
+
+               switch (opt) {
+               case 'p':
+                       parsable = true;
+                       break;
+               case 'r':
+                       ret = list_exported_devices(optarg);
+                       goto out;
+               case 'l':
+                       ret = list_devices(parsable);
+                       goto out;
+               default:
+                       goto err_out;
+               }
+       }
+
+err_out:
+       usbip_list_usage();
+out:
+       usbip_names_free();
+
+       return ret;
+}
diff --git a/tools/usb/usbip/src/usbip_network.c b/tools/usb/usbip/src/usbip_network.c
new file mode 100644 (file)
index 0000000..b4c37e7
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/socket.h>
+
+#include <string.h>
+
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/tcp.h>
+#include <unistd.h>
+
+#ifdef HAVE_LIBWRAP
+#include <tcpd.h>
+#endif
+
+#include "usbip_common.h"
+#include "usbip_network.h"
+
+int usbip_port = 3240;
+char *usbip_port_string = "3240";
+
+void usbip_setup_port_number(char *arg)
+{
+       dbg("parsing port arg '%s'", arg);
+       char *end;
+       unsigned long int port = strtoul(arg, &end, 10);
+
+       if (end == arg) {
+               err("port: could not parse '%s' as a decimal integer", arg);
+               return;
+       }
+
+       if (*end != '\0') {
+               err("port: garbage at end of '%s'", arg);
+               return;
+       }
+
+       if (port > UINT16_MAX) {
+               err("port: %s too high (max=%d)",
+                   arg, UINT16_MAX);
+               return;
+       }
+
+       usbip_port = port;
+       usbip_port_string = arg;
+       info("using port %d (\"%s\")", usbip_port, usbip_port_string);
+}
+
+void usbip_net_pack_uint32_t(int pack, uint32_t *num)
+{
+       uint32_t i;
+
+       if (pack)
+               i = htonl(*num);
+       else
+               i = ntohl(*num);
+
+       *num = i;
+}
+
+void usbip_net_pack_uint16_t(int pack, uint16_t *num)
+{
+       uint16_t i;
+
+       if (pack)
+               i = htons(*num);
+       else
+               i = ntohs(*num);
+
+       *num = i;
+}
+
+void usbip_net_pack_usb_device(int pack, struct usbip_usb_device *udev)
+{
+       usbip_net_pack_uint32_t(pack, &udev->busnum);
+       usbip_net_pack_uint32_t(pack, &udev->devnum);
+       usbip_net_pack_uint32_t(pack, &udev->speed);
+
+       usbip_net_pack_uint16_t(pack, &udev->idVendor);
+       usbip_net_pack_uint16_t(pack, &udev->idProduct);
+       usbip_net_pack_uint16_t(pack, &udev->bcdDevice);
+}
+
+void usbip_net_pack_usb_interface(int pack __attribute__((unused)),
+                                 struct usbip_usb_interface *udev
+                                 __attribute__((unused)))
+{
+       /* uint8_t members need nothing */
+}
+
+static ssize_t usbip_net_xmit(int sockfd, void *buff, size_t bufflen,
+                             int sending)
+{
+       ssize_t nbytes;
+       ssize_t total = 0;
+
+       if (!bufflen)
+               return 0;
+
+       do {
+               if (sending)
+                       nbytes = send(sockfd, buff, bufflen, 0);
+               else
+                       nbytes = recv(sockfd, buff, bufflen, MSG_WAITALL);
+
+               if (nbytes <= 0)
+                       return -1;
+
+               buff     = (void *)((intptr_t) buff + nbytes);
+               bufflen -= nbytes;
+               total   += nbytes;
+
+       } while (bufflen > 0);
+
+       return total;
+}
+
+ssize_t usbip_net_recv(int sockfd, void *buff, size_t bufflen)
+{
+       return usbip_net_xmit(sockfd, buff, bufflen, 0);
+}
+
+ssize_t usbip_net_send(int sockfd, void *buff, size_t bufflen)
+{
+       return usbip_net_xmit(sockfd, buff, bufflen, 1);
+}
+
+int usbip_net_send_op_common(int sockfd, uint32_t code, uint32_t status)
+{
+       struct op_common op_common;
+       int rc;
+
+       memset(&op_common, 0, sizeof(op_common));
+
+       op_common.version = USBIP_VERSION;
+       op_common.code    = code;
+       op_common.status  = status;
+
+       PACK_OP_COMMON(1, &op_common);
+
+       rc = usbip_net_send(sockfd, &op_common, sizeof(op_common));
+       if (rc < 0) {
+               dbg("usbip_net_send failed: %d", rc);
+               return -1;
+       }
+
+       return 0;
+}
+
+int usbip_net_recv_op_common(int sockfd, uint16_t *code)
+{
+       struct op_common op_common;
+       int rc;
+
+       memset(&op_common, 0, sizeof(op_common));
+
+       rc = usbip_net_recv(sockfd, &op_common, sizeof(op_common));
+       if (rc < 0) {
+               dbg("usbip_net_recv failed: %d", rc);
+               goto err;
+       }
+
+       PACK_OP_COMMON(0, &op_common);
+
+       if (op_common.version != USBIP_VERSION) {
+               dbg("version mismatch: %d %d", op_common.version,
+                   USBIP_VERSION);
+               goto err;
+       }
+
+       switch (*code) {
+       case OP_UNSPEC:
+               break;
+       default:
+               if (op_common.code != *code) {
+                       dbg("unexpected pdu %#0x for %#0x", op_common.code,
+                           *code);
+                       goto err;
+               }
+       }
+
+       if (op_common.status != ST_OK) {
+               dbg("request failed at peer: %d", op_common.status);
+               goto err;
+       }
+
+       *code = op_common.code;
+
+       return 0;
+err:
+       return -1;
+}
+
+int usbip_net_set_reuseaddr(int sockfd)
+{
+       const int val = 1;
+       int ret;
+
+       ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
+       if (ret < 0)
+               dbg("setsockopt: SO_REUSEADDR");
+
+       return ret;
+}
+
+int usbip_net_set_nodelay(int sockfd)
+{
+       const int val = 1;
+       int ret;
+
+       ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
+       if (ret < 0)
+               dbg("setsockopt: TCP_NODELAY");
+
+       return ret;
+}
+
+int usbip_net_set_keepalive(int sockfd)
+{
+       const int val = 1;
+       int ret;
+
+       ret = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
+       if (ret < 0)
+               dbg("setsockopt: SO_KEEPALIVE");
+
+       return ret;
+}
+
+int usbip_net_set_v6only(int sockfd)
+{
+       const int val = 1;
+       int ret;
+
+       ret = setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val));
+       if (ret < 0)
+               dbg("setsockopt: IPV6_V6ONLY");
+
+       return ret;
+}
+
+/*
+ * IPv6 Ready
+ */
+int usbip_net_tcp_connect(char *hostname, char *service)
+{
+       struct addrinfo hints, *res, *rp;
+       int sockfd;
+       int ret;
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = AF_UNSPEC;
+       hints.ai_socktype = SOCK_STREAM;
+
+       /* get all possible addresses */
+       ret = getaddrinfo(hostname, service, &hints, &res);
+       if (ret < 0) {
+               dbg("getaddrinfo: %s service %s: %s", hostname, service,
+                   gai_strerror(ret));
+               return ret;
+       }
+
+       /* try the addresses */
+       for (rp = res; rp; rp = rp->ai_next) {
+               sockfd = socket(rp->ai_family, rp->ai_socktype,
+                               rp->ai_protocol);
+               if (sockfd < 0)
+                       continue;
+
+               /* should set TCP_NODELAY for usbip */
+               usbip_net_set_nodelay(sockfd);
+               /* TODO: write code for heartbeat */
+               usbip_net_set_keepalive(sockfd);
+
+               if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) == 0)
+                       break;
+
+               close(sockfd);
+       }
+
+       freeaddrinfo(res);
+
+       if (!rp)
+               return EAI_SYSTEM;
+
+       return sockfd;
+}
diff --git a/tools/usb/usbip/src/usbip_network.h b/tools/usb/usbip/src/usbip_network.h
new file mode 100644 (file)
index 0000000..c1e875c
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2005-2007 Takahiro Hirofuchi
+ */
+
+#ifndef __USBIP_NETWORK_H
+#define __USBIP_NETWORK_H
+
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif
+
+#include <sys/types.h>
+
+#include <stdint.h>
+
+extern int usbip_port;
+extern char *usbip_port_string;
+void usbip_setup_port_number(char *arg);
+
+/* ---------------------------------------------------------------------- */
+/* Common header for all the kinds of PDUs. */
+struct op_common {
+       uint16_t version;
+
+#define OP_REQUEST     (0x80 << 8)
+#define OP_REPLY       (0x00 << 8)
+       uint16_t code;
+
+       /* add more error code */
+#define ST_OK  0x00
+#define ST_NA  0x01
+       uint32_t status; /* op_code status (for reply) */
+
+} __attribute__((packed));
+
+#define PACK_OP_COMMON(pack, op_common)  do {\
+       usbip_net_pack_uint16_t(pack, &(op_common)->version);\
+       usbip_net_pack_uint16_t(pack, &(op_common)->code);\
+       usbip_net_pack_uint32_t(pack, &(op_common)->status);\
+} while (0)
+
+/* ---------------------------------------------------------------------- */
+/* Dummy Code */
+#define OP_UNSPEC      0x00
+#define OP_REQ_UNSPEC  OP_UNSPEC
+#define OP_REP_UNSPEC  OP_UNSPEC
+
+/* ---------------------------------------------------------------------- */
+/* Retrieve USB device information. (still not used) */
+#define OP_DEVINFO     0x02
+#define OP_REQ_DEVINFO (OP_REQUEST | OP_DEVINFO)
+#define OP_REP_DEVINFO (OP_REPLY   | OP_DEVINFO)
+
+struct op_devinfo_request {
+       char busid[SYSFS_BUS_ID_SIZE];
+} __attribute__((packed));
+
+struct op_devinfo_reply {
+       struct usbip_usb_device udev;
+       struct usbip_usb_interface uinf[];
+} __attribute__((packed));
+
+/* ---------------------------------------------------------------------- */
+/* Import a remote USB device. */
+#define OP_IMPORT      0x03
+#define OP_REQ_IMPORT  (OP_REQUEST | OP_IMPORT)
+#define OP_REP_IMPORT   (OP_REPLY   | OP_IMPORT)
+
+struct op_import_request {
+       char busid[SYSFS_BUS_ID_SIZE];
+} __attribute__((packed));
+
+struct op_import_reply {
+       struct usbip_usb_device udev;
+//     struct usbip_usb_interface uinf[];
+} __attribute__((packed));
+
+#define PACK_OP_IMPORT_REQUEST(pack, request)  do {\
+} while (0)
+
+#define PACK_OP_IMPORT_REPLY(pack, reply)  do {\
+       usbip_net_pack_usb_device(pack, &(reply)->udev);\
+} while (0)
+
+/* ---------------------------------------------------------------------- */
+/* Export a USB device to a remote host. */
+#define OP_EXPORT      0x06
+#define OP_REQ_EXPORT  (OP_REQUEST | OP_EXPORT)
+#define OP_REP_EXPORT  (OP_REPLY   | OP_EXPORT)
+
+struct op_export_request {
+       struct usbip_usb_device udev;
+} __attribute__((packed));
+
+struct op_export_reply {
+       int returncode;
+} __attribute__((packed));
+
+
+#define PACK_OP_EXPORT_REQUEST(pack, request)  do {\
+       usbip_net_pack_usb_device(pack, &(request)->udev);\
+} while (0)
+
+#define PACK_OP_EXPORT_REPLY(pack, reply)  do {\
+} while (0)
+
+/* ---------------------------------------------------------------------- */
+/* un-Export a USB device from a remote host. */
+#define OP_UNEXPORT    0x07
+#define OP_REQ_UNEXPORT        (OP_REQUEST | OP_UNEXPORT)
+#define OP_REP_UNEXPORT        (OP_REPLY   | OP_UNEXPORT)
+
+struct op_unexport_request {
+       struct usbip_usb_device udev;
+} __attribute__((packed));
+
+struct op_unexport_reply {
+       int returncode;
+} __attribute__((packed));
+
+#define PACK_OP_UNEXPORT_REQUEST(pack, request)  do {\
+       usbip_net_pack_usb_device(pack, &(request)->udev);\
+} while (0)
+
+#define PACK_OP_UNEXPORT_REPLY(pack, reply)  do {\
+} while (0)
+
+/* ---------------------------------------------------------------------- */
+/* Negotiate IPSec encryption key. (still not used) */
+#define OP_CRYPKEY     0x04
+#define OP_REQ_CRYPKEY (OP_REQUEST | OP_CRYPKEY)
+#define OP_REP_CRYPKEY (OP_REPLY   | OP_CRYPKEY)
+
+struct op_crypkey_request {
+       /* 128bit key */
+       uint32_t key[4];
+} __attribute__((packed));
+
+struct op_crypkey_reply {
+       uint32_t __reserved;
+} __attribute__((packed));
+
+
+/* ---------------------------------------------------------------------- */
+/* Retrieve the list of exported USB devices. */
+#define OP_DEVLIST     0x05
+#define OP_REQ_DEVLIST (OP_REQUEST | OP_DEVLIST)
+#define OP_REP_DEVLIST (OP_REPLY   | OP_DEVLIST)
+
+struct op_devlist_request {
+} __attribute__((packed));
+
+struct op_devlist_reply {
+       uint32_t ndev;
+       /* followed by reply_extra[] */
+} __attribute__((packed));
+
+struct op_devlist_reply_extra {
+       struct usbip_usb_device    udev;
+       struct usbip_usb_interface uinf[];
+} __attribute__((packed));
+
+#define PACK_OP_DEVLIST_REQUEST(pack, request)  do {\
+} while (0)
+
+#define PACK_OP_DEVLIST_REPLY(pack, reply)  do {\
+       usbip_net_pack_uint32_t(pack, &(reply)->ndev);\
+} while (0)
+
+void usbip_net_pack_uint32_t(int pack, uint32_t *num);
+void usbip_net_pack_uint16_t(int pack, uint16_t *num);
+void usbip_net_pack_usb_device(int pack, struct usbip_usb_device *udev);
+void usbip_net_pack_usb_interface(int pack, struct usbip_usb_interface *uinf);
+
+ssize_t usbip_net_recv(int sockfd, void *buff, size_t bufflen);
+ssize_t usbip_net_send(int sockfd, void *buff, size_t bufflen);
+int usbip_net_send_op_common(int sockfd, uint32_t code, uint32_t status);
+int usbip_net_recv_op_common(int sockfd, uint16_t *code);
+int usbip_net_set_reuseaddr(int sockfd);
+int usbip_net_set_nodelay(int sockfd);
+int usbip_net_set_keepalive(int sockfd);
+int usbip_net_set_v6only(int sockfd);
+int usbip_net_tcp_connect(char *hostname, char *port);
+
+#endif /* __USBIP_NETWORK_H */
diff --git a/tools/usb/usbip/src/usbip_port.c b/tools/usb/usbip/src/usbip_port.c
new file mode 100644 (file)
index 0000000..a2e884f
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "vhci_driver.h"
+#include "usbip_common.h"
+
+static int list_imported_devices(void)
+{
+       int i;
+       struct usbip_imported_device *idev;
+       int ret;
+
+       ret = usbip_vhci_driver_open();
+       if (ret < 0) {
+               err("open vhci_driver");
+               return -1;
+       }
+
+       printf("Imported USB devices\n");
+       printf("====================\n");
+
+       for (i = 0; i < vhci_driver->nports; i++) {
+               idev = &vhci_driver->idev[i];
+
+               if (usbip_vhci_imported_device_dump(idev) < 0)
+                       ret = -1;
+       }
+
+       usbip_vhci_driver_close();
+
+       return ret;
+
+}
+
+int usbip_port_show(__attribute__((unused)) int argc,
+                   __attribute__((unused)) char *argv[])
+{
+       int ret;
+
+       ret = list_imported_devices();
+       if (ret < 0)
+               err("list imported devices");
+
+       return ret;
+}
diff --git a/tools/usb/usbip/src/usbip_unbind.c b/tools/usb/usbip/src/usbip_unbind.c
new file mode 100644 (file)
index 0000000..a4a496c
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <libudev.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <getopt.h>
+
+#include "usbip_common.h"
+#include "utils.h"
+#include "usbip.h"
+#include "sysfs_utils.h"
+
+static const char usbip_unbind_usage_string[] =
+       "usbip unbind <args>\n"
+       "    -b, --busid=<busid>    Unbind " USBIP_HOST_DRV_NAME ".ko from "
+       "device on <busid>\n";
+
+void usbip_unbind_usage(void)
+{
+       printf("usage: %s", usbip_unbind_usage_string);
+}
+
+static int unbind_device(char *busid)
+{
+       char bus_type[] = "usb";
+       int rc, ret = -1;
+
+       char unbind_attr_name[] = "unbind";
+       char unbind_attr_path[SYSFS_PATH_MAX];
+       char rebind_attr_name[] = "rebind";
+       char rebind_attr_path[SYSFS_PATH_MAX];
+
+       struct udev *udev;
+       struct udev_device *dev;
+       const char *driver;
+
+       /* Create libudev context. */
+       udev = udev_new();
+
+       /* Check whether the device with this bus ID exists. */
+       dev = udev_device_new_from_subsystem_sysname(udev, "usb", busid);
+       if (!dev) {
+               err("device with the specified bus ID does not exist");
+               goto err_close_udev;
+       }
+
+       /* Check whether the device is using usbip-host driver. */
+       driver = udev_device_get_driver(dev);
+       if (!driver || strcmp(driver, "usbip-host")) {
+               err("device is not bound to usbip-host driver");
+               goto err_close_udev;
+       }
+
+       /* Unbind device from driver. */
+       snprintf(unbind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",
+                SYSFS_MNT_PATH, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME,
+                USBIP_HOST_DRV_NAME, unbind_attr_name);
+
+       rc = write_sysfs_attribute(unbind_attr_path, busid, strlen(busid));
+       if (rc < 0) {
+               err("error unbinding device %s from driver", busid);
+               goto err_close_udev;
+       }
+
+       /* Notify driver of unbind. */
+       rc = modify_match_busid(busid, 0);
+       if (rc < 0) {
+               err("unable to unbind device on %s", busid);
+               goto err_close_udev;
+       }
+
+       /* Trigger new probing. */
+       snprintf(rebind_attr_path, sizeof(unbind_attr_path), "%s/%s/%s/%s/%s/%s",
+                       SYSFS_MNT_PATH, SYSFS_BUS_NAME, bus_type, SYSFS_DRIVERS_NAME,
+                       USBIP_HOST_DRV_NAME, rebind_attr_name);
+
+       rc = write_sysfs_attribute(rebind_attr_path, busid, strlen(busid));
+       if (rc < 0) {
+               err("error rebinding");
+               goto err_close_udev;
+       }
+
+       ret = 0;
+       info("unbind device on busid %s: complete", busid);
+
+err_close_udev:
+       udev_device_unref(dev);
+       udev_unref(udev);
+
+       return ret;
+}
+
+int usbip_unbind(int argc, char *argv[])
+{
+       static const struct option opts[] = {
+               { "busid", required_argument, NULL, 'b' },
+               { NULL,    0,                 NULL,  0  }
+       };
+
+       int opt;
+       int ret = -1;
+
+       for (;;) {
+               opt = getopt_long(argc, argv, "b:", opts, NULL);
+
+               if (opt == -1)
+                       break;
+
+               switch (opt) {
+               case 'b':
+                       ret = unbind_device(optarg);
+                       goto out;
+               default:
+                       goto err_out;
+               }
+       }
+
+err_out:
+       usbip_unbind_usage();
+out:
+       return ret;
+}
diff --git a/tools/usb/usbip/src/usbipd.c b/tools/usb/usbip/src/usbipd.c
new file mode 100644 (file)
index 0000000..2f87f2d
--- /dev/null
@@ -0,0 +1,679 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#ifdef HAVE_LIBWRAP
+#include <tcpd.h>
+#endif
+
+#include <getopt.h>
+#include <signal.h>
+#include <poll.h>
+
+#include "usbip_host_driver.h"
+#include "usbip_common.h"
+#include "usbip_network.h"
+#include "list.h"
+
+#undef  PROGNAME
+#define PROGNAME "usbipd"
+#define MAXSOCKFD 20
+
+#define MAIN_LOOP_TIMEOUT 10
+
+#define DEFAULT_PID_FILE "/var/run/" PROGNAME ".pid"
+
+static const char usbip_version_string[] = PACKAGE_STRING;
+
+static const char usbipd_help_string[] =
+       "usage: usbipd [options]\n"
+       "\n"
+       "       -4, --ipv4\n"
+       "               Bind to IPv4. Default is both.\n"
+       "\n"
+       "       -6, --ipv6\n"
+       "               Bind to IPv6. Default is both.\n"
+       "\n"
+       "       -D, --daemon\n"
+       "               Run as a daemon process.\n"
+       "\n"
+       "       -d, --debug\n"
+       "               Print debugging information.\n"
+       "\n"
+       "       -PFILE, --pid FILE\n"
+       "               Write process id to FILE.\n"
+       "               If no FILE specified, use " DEFAULT_PID_FILE "\n"
+       "\n"
+       "       -tPORT, --tcp-port PORT\n"
+       "               Listen on TCP/IP port PORT.\n"
+       "\n"
+       "       -h, --help\n"
+       "               Print this help.\n"
+       "\n"
+       "       -v, --version\n"
+       "               Show version.\n";
+
+static void usbipd_help(void)
+{
+       printf("%s\n", usbipd_help_string);
+}
+
+static int recv_request_import(int sockfd)
+{
+       struct op_import_request req;
+       struct op_common reply;
+       struct usbip_exported_device *edev;
+       struct usbip_usb_device pdu_udev;
+       struct list_head *i;
+       int found = 0;
+       int error = 0;
+       int rc;
+
+       memset(&req, 0, sizeof(req));
+       memset(&reply, 0, sizeof(reply));
+
+       rc = usbip_net_recv(sockfd, &req, sizeof(req));
+       if (rc < 0) {
+               dbg("usbip_net_recv failed: import request");
+               return -1;
+       }
+       PACK_OP_IMPORT_REQUEST(0, &req);
+
+       list_for_each(i, &host_driver->edev_list) {
+               edev = list_entry(i, struct usbip_exported_device, node);
+               if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) {
+                       info("found requested device: %s", req.busid);
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (found) {
+               /* should set TCP_NODELAY for usbip */
+               usbip_net_set_nodelay(sockfd);
+
+               /* export device needs a TCP/IP socket descriptor */
+               rc = usbip_host_export_device(edev, sockfd);
+               if (rc < 0)
+                       error = 1;
+       } else {
+               info("requested device not found: %s", req.busid);
+               error = 1;
+       }
+
+       rc = usbip_net_send_op_common(sockfd, OP_REP_IMPORT,
+                                     (!error ? ST_OK : ST_NA));
+       if (rc < 0) {
+               dbg("usbip_net_send_op_common failed: %#0x", OP_REP_IMPORT);
+               return -1;
+       }
+
+       if (error) {
+               dbg("import request busid %s: failed", req.busid);
+               return -1;
+       }
+
+       memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev));
+       usbip_net_pack_usb_device(1, &pdu_udev);
+
+       rc = usbip_net_send(sockfd, &pdu_udev, sizeof(pdu_udev));
+       if (rc < 0) {
+               dbg("usbip_net_send failed: devinfo");
+               return -1;
+       }
+
+       dbg("import request busid %s: complete", req.busid);
+
+       return 0;
+}
+
+static int send_reply_devlist(int connfd)
+{
+       struct usbip_exported_device *edev;
+       struct usbip_usb_device pdu_udev;
+       struct usbip_usb_interface pdu_uinf;
+       struct op_devlist_reply reply;
+       struct list_head *j;
+       int rc, i;
+
+       reply.ndev = 0;
+       /* number of exported devices */
+       list_for_each(j, &host_driver->edev_list) {
+               reply.ndev += 1;
+       }
+       info("exportable devices: %d", reply.ndev);
+
+       rc = usbip_net_send_op_common(connfd, OP_REP_DEVLIST, ST_OK);
+       if (rc < 0) {
+               dbg("usbip_net_send_op_common failed: %#0x", OP_REP_DEVLIST);
+               return -1;
+       }
+       PACK_OP_DEVLIST_REPLY(1, &reply);
+
+       rc = usbip_net_send(connfd, &reply, sizeof(reply));
+       if (rc < 0) {
+               dbg("usbip_net_send failed: %#0x", OP_REP_DEVLIST);
+               return -1;
+       }
+
+       list_for_each(j, &host_driver->edev_list) {
+               edev = list_entry(j, struct usbip_exported_device, node);
+               dump_usb_device(&edev->udev);
+               memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev));
+               usbip_net_pack_usb_device(1, &pdu_udev);
+
+               rc = usbip_net_send(connfd, &pdu_udev, sizeof(pdu_udev));
+               if (rc < 0) {
+                       dbg("usbip_net_send failed: pdu_udev");
+                       return -1;
+               }
+
+               for (i = 0; i < edev->udev.bNumInterfaces; i++) {
+                       dump_usb_interface(&edev->uinf[i]);
+                       memcpy(&pdu_uinf, &edev->uinf[i], sizeof(pdu_uinf));
+                       usbip_net_pack_usb_interface(1, &pdu_uinf);
+
+                       rc = usbip_net_send(connfd, &pdu_uinf,
+                                       sizeof(pdu_uinf));
+                       if (rc < 0) {
+                               err("usbip_net_send failed: pdu_uinf");
+                               return -1;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int recv_request_devlist(int connfd)
+{
+       struct op_devlist_request req;
+       int rc;
+
+       memset(&req, 0, sizeof(req));
+
+       rc = usbip_net_recv(connfd, &req, sizeof(req));
+       if (rc < 0) {
+               dbg("usbip_net_recv failed: devlist request");
+               return -1;
+       }
+
+       rc = send_reply_devlist(connfd);
+       if (rc < 0) {
+               dbg("send_reply_devlist failed");
+               return -1;
+       }
+
+       return 0;
+}
+
+static int recv_pdu(int connfd)
+{
+       uint16_t code = OP_UNSPEC;
+       int ret;
+
+       ret = usbip_net_recv_op_common(connfd, &code);
+       if (ret < 0) {
+               dbg("could not receive opcode: %#0x", code);
+               return -1;
+       }
+
+       ret = usbip_host_refresh_device_list();
+       if (ret < 0) {
+               dbg("could not refresh device list: %d", ret);
+               return -1;
+       }
+
+       info("received request: %#0x(%d)", code, connfd);
+       switch (code) {
+       case OP_REQ_DEVLIST:
+               ret = recv_request_devlist(connfd);
+               break;
+       case OP_REQ_IMPORT:
+               ret = recv_request_import(connfd);
+               break;
+       case OP_REQ_DEVINFO:
+       case OP_REQ_CRYPKEY:
+       default:
+               err("received an unknown opcode: %#0x", code);
+               ret = -1;
+       }
+
+       if (ret == 0)
+               info("request %#0x(%d): complete", code, connfd);
+       else
+               info("request %#0x(%d): failed", code, connfd);
+
+       return ret;
+}
+
+#ifdef HAVE_LIBWRAP
+static int tcpd_auth(int connfd)
+{
+       struct request_info request;
+       int rc;
+
+       request_init(&request, RQ_DAEMON, PROGNAME, RQ_FILE, connfd, 0);
+       fromhost(&request);
+       rc = hosts_access(&request);
+       if (rc == 0)
+               return -1;
+
+       return 0;
+}
+#endif
+
+static int do_accept(int listenfd)
+{
+       int connfd;
+       struct sockaddr_storage ss;
+       socklen_t len = sizeof(ss);
+       char host[NI_MAXHOST], port[NI_MAXSERV];
+       int rc;
+
+       memset(&ss, 0, sizeof(ss));
+
+       connfd = accept(listenfd, (struct sockaddr *)&ss, &len);
+       if (connfd < 0) {
+               err("failed to accept connection");
+               return -1;
+       }
+
+       rc = getnameinfo((struct sockaddr *)&ss, len, host, sizeof(host),
+                        port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV);
+       if (rc)
+               err("getnameinfo: %s", gai_strerror(rc));
+
+#ifdef HAVE_LIBWRAP
+       rc = tcpd_auth(connfd);
+       if (rc < 0) {
+               info("denied access from %s", host);
+               close(connfd);
+               return -1;
+       }
+#endif
+       info("connection from %s:%s", host, port);
+
+       return connfd;
+}
+
+int process_request(int listenfd)
+{
+       pid_t childpid;
+       int connfd;
+
+       connfd = do_accept(listenfd);
+       if (connfd < 0)
+               return -1;
+       childpid = fork();
+       if (childpid == 0) {
+               close(listenfd);
+               recv_pdu(connfd);
+               exit(0);
+       }
+       close(connfd);
+       return 0;
+}
+
+static void addrinfo_to_text(struct addrinfo *ai, char buf[],
+                            const size_t buf_size)
+{
+       char hbuf[NI_MAXHOST];
+       char sbuf[NI_MAXSERV];
+       int rc;
+
+       buf[0] = '\0';
+
+       rc = getnameinfo(ai->ai_addr, ai->ai_addrlen, hbuf, sizeof(hbuf),
+                        sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
+       if (rc)
+               err("getnameinfo: %s", gai_strerror(rc));
+
+       snprintf(buf, buf_size, "%s:%s", hbuf, sbuf);
+}
+
+static int listen_all_addrinfo(struct addrinfo *ai_head, int sockfdlist[],
+                            int maxsockfd)
+{
+       struct addrinfo *ai;
+       int ret, nsockfd = 0;
+       const size_t ai_buf_size = NI_MAXHOST + NI_MAXSERV + 2;
+       char ai_buf[ai_buf_size];
+
+       for (ai = ai_head; ai && nsockfd < maxsockfd; ai = ai->ai_next) {
+               int sock;
+
+               addrinfo_to_text(ai, ai_buf, ai_buf_size);
+               dbg("opening %s", ai_buf);
+               sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+               if (sock < 0) {
+                       err("socket: %s: %d (%s)",
+                           ai_buf, errno, strerror(errno));
+                       continue;
+               }
+
+               usbip_net_set_reuseaddr(sock);
+               usbip_net_set_nodelay(sock);
+               /* We use seperate sockets for IPv4 and IPv6
+                * (see do_standalone_mode()) */
+               usbip_net_set_v6only(sock);
+
+               if (sock >= FD_SETSIZE) {
+                       err("FD_SETSIZE: %s: sock=%d, max=%d",
+                           ai_buf, sock, FD_SETSIZE);
+                       close(sock);
+                       continue;
+               }
+
+               ret = bind(sock, ai->ai_addr, ai->ai_addrlen);
+               if (ret < 0) {
+                       err("bind: %s: %d (%s)",
+                           ai_buf, errno, strerror(errno));
+                       close(sock);
+                       continue;
+               }
+
+               ret = listen(sock, SOMAXCONN);
+               if (ret < 0) {
+                       err("listen: %s: %d (%s)",
+                           ai_buf, errno, strerror(errno));
+                       close(sock);
+                       continue;
+               }
+
+               info("listening on %s", ai_buf);
+               sockfdlist[nsockfd++] = sock;
+       }
+
+       return nsockfd;
+}
+
+static struct addrinfo *do_getaddrinfo(char *host, int ai_family)
+{
+       struct addrinfo hints, *ai_head;
+       int rc;
+
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family   = ai_family;
+       hints.ai_socktype = SOCK_STREAM;
+       hints.ai_flags    = AI_PASSIVE;
+
+       rc = getaddrinfo(host, usbip_port_string, &hints, &ai_head);
+       if (rc) {
+               err("failed to get a network address %s: %s", usbip_port_string,
+                   gai_strerror(rc));
+               return NULL;
+       }
+
+       return ai_head;
+}
+
+static void signal_handler(int i)
+{
+       dbg("received '%s' signal", strsignal(i));
+}
+
+static void set_signal(void)
+{
+       struct sigaction act;
+
+       memset(&act, 0, sizeof(act));
+       act.sa_handler = signal_handler;
+       sigemptyset(&act.sa_mask);
+       sigaction(SIGTERM, &act, NULL);
+       sigaction(SIGINT, &act, NULL);
+       act.sa_handler = SIG_IGN;
+       sigaction(SIGCLD, &act, NULL);
+}
+
+static const char *pid_file;
+
+static void write_pid_file(void)
+{
+       if (pid_file) {
+               dbg("creating pid file %s", pid_file);
+               FILE *fp;
+
+               fp = fopen(pid_file, "w");
+               if (!fp) {
+                       err("pid_file: %s: %d (%s)",
+                           pid_file, errno, strerror(errno));
+                       return;
+               }
+               fprintf(fp, "%d\n", getpid());
+               fclose(fp);
+       }
+}
+
+static void remove_pid_file(void)
+{
+       if (pid_file) {
+               dbg("removing pid file %s", pid_file);
+               unlink(pid_file);
+       }
+}
+
+static int do_standalone_mode(int daemonize, int ipv4, int ipv6)
+{
+       struct addrinfo *ai_head;
+       int sockfdlist[MAXSOCKFD];
+       int nsockfd, family;
+       int i, terminate;
+       struct pollfd *fds;
+       struct timespec timeout;
+       sigset_t sigmask;
+
+       if (usbip_host_driver_open()) {
+               err("please load " USBIP_CORE_MOD_NAME ".ko and "
+                   USBIP_HOST_DRV_NAME ".ko!");
+               return -1;
+       }
+
+       if (daemonize) {
+               if (daemon(0, 0) < 0) {
+                       err("daemonizing failed: %s", strerror(errno));
+                       usbip_host_driver_close();
+                       return -1;
+               }
+               umask(0);
+               usbip_use_syslog = 1;
+       }
+       set_signal();
+       write_pid_file();
+
+       info("starting " PROGNAME " (%s)", usbip_version_string);
+
+       /*
+        * To suppress warnings on systems with bindv6only disabled
+        * (default), we use seperate sockets for IPv6 and IPv4 and set
+        * IPV6_V6ONLY on the IPv6 sockets.
+        */
+       if (ipv4 && ipv6)
+               family = AF_UNSPEC;
+       else if (ipv4)
+               family = AF_INET;
+       else
+               family = AF_INET6;
+
+       ai_head = do_getaddrinfo(NULL, family);
+       if (!ai_head) {
+               usbip_host_driver_close();
+               return -1;
+       }
+       nsockfd = listen_all_addrinfo(ai_head, sockfdlist,
+               sizeof(sockfdlist) / sizeof(*sockfdlist));
+       freeaddrinfo(ai_head);
+       if (nsockfd <= 0) {
+               err("failed to open a listening socket");
+               usbip_host_driver_close();
+               return -1;
+       }
+
+       dbg("listening on %d address%s", nsockfd, (nsockfd == 1) ? "" : "es");
+
+       fds = calloc(nsockfd, sizeof(struct pollfd));
+       for (i = 0; i < nsockfd; i++) {
+               fds[i].fd = sockfdlist[i];
+               fds[i].events = POLLIN;
+       }
+       timeout.tv_sec = MAIN_LOOP_TIMEOUT;
+       timeout.tv_nsec = 0;
+
+       sigfillset(&sigmask);
+       sigdelset(&sigmask, SIGTERM);
+       sigdelset(&sigmask, SIGINT);
+
+       terminate = 0;
+       while (!terminate) {
+               int r;
+
+               r = ppoll(fds, nsockfd, &timeout, &sigmask);
+               if (r < 0) {
+                       dbg("%s", strerror(errno));
+                       terminate = 1;
+               } else if (r) {
+                       for (i = 0; i < nsockfd; i++) {
+                               if (fds[i].revents & POLLIN) {
+                                       dbg("read event on fd[%d]=%d",
+                                           i, sockfdlist[i]);
+                                       process_request(sockfdlist[i]);
+                               }
+                       }
+               } else {
+                       dbg("heartbeat timeout on ppoll()");
+               }
+       }
+
+       info("shutting down " PROGNAME);
+       free(fds);
+       usbip_host_driver_close();
+
+       return 0;
+}
+
+int main(int argc, char *argv[])
+{
+       static const struct option longopts[] = {
+               { "ipv4",     no_argument,       NULL, '4' },
+               { "ipv6",     no_argument,       NULL, '6' },
+               { "daemon",   no_argument,       NULL, 'D' },
+               { "daemon",   no_argument,       NULL, 'D' },
+               { "debug",    no_argument,       NULL, 'd' },
+               { "pid",      optional_argument, NULL, 'P' },
+               { "tcp-port", required_argument, NULL, 't' },
+               { "help",     no_argument,       NULL, 'h' },
+               { "version",  no_argument,       NULL, 'v' },
+               { NULL,       0,                 NULL,  0  }
+       };
+
+       enum {
+               cmd_standalone_mode = 1,
+               cmd_help,
+               cmd_version
+       } cmd;
+
+       int daemonize = 0;
+       int ipv4 = 0, ipv6 = 0;
+       int opt, rc = -1;
+
+       pid_file = NULL;
+
+       usbip_use_stderr = 1;
+       usbip_use_syslog = 0;
+
+       if (geteuid() != 0)
+               err("not running as root?");
+
+       cmd = cmd_standalone_mode;
+       for (;;) {
+               opt = getopt_long(argc, argv, "46DdP::t:hv", longopts, NULL);
+
+               if (opt == -1)
+                       break;
+
+               switch (opt) {
+               case '4':
+                       ipv4 = 1;
+                       break;
+               case '6':
+                       ipv6 = 1;
+                       break;
+               case 'D':
+                       daemonize = 1;
+                       break;
+               case 'd':
+                       usbip_use_debug = 1;
+                       break;
+               case 'h':
+                       cmd = cmd_help;
+                       break;
+               case 'P':
+                       pid_file = optarg ? optarg : DEFAULT_PID_FILE;
+                       break;
+               case 't':
+                       usbip_setup_port_number(optarg);
+                       break;
+               case 'v':
+                       cmd = cmd_version;
+                       break;
+               case '?':
+                       usbipd_help();
+               default:
+                       goto err_out;
+               }
+       }
+
+       if (!ipv4 && !ipv6)
+               ipv4 = ipv6 = 1;
+
+       switch (cmd) {
+       case cmd_standalone_mode:
+               rc = do_standalone_mode(daemonize, ipv4, ipv6);
+               remove_pid_file();
+               break;
+       case cmd_version:
+               printf(PROGNAME " (%s)\n", usbip_version_string);
+               rc = 0;
+               break;
+       case cmd_help:
+               usbipd_help();
+               rc = 0;
+               break;
+       default:
+               usbipd_help();
+               goto err_out;
+       }
+
+err_out:
+       return (rc > -1 ? EXIT_SUCCESS : EXIT_FAILURE);
+}
diff --git a/tools/usb/usbip/src/utils.c b/tools/usb/usbip/src/utils.c
new file mode 100644 (file)
index 0000000..2b3d6d2
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "usbip_common.h"
+#include "utils.h"
+#include "sysfs_utils.h"
+
+int modify_match_busid(char *busid, int add)
+{
+       char attr_name[] = "match_busid";
+       char command[SYSFS_BUS_ID_SIZE + 4];
+       char match_busid_attr_path[SYSFS_PATH_MAX];
+       int rc;
+
+       snprintf(match_busid_attr_path, sizeof(match_busid_attr_path),
+                "%s/%s/%s/%s/%s/%s", SYSFS_MNT_PATH, SYSFS_BUS_NAME,
+                SYSFS_BUS_TYPE, SYSFS_DRIVERS_NAME, USBIP_HOST_DRV_NAME,
+                attr_name);
+
+       if (add)
+               snprintf(command, SYSFS_BUS_ID_SIZE + 4, "add %s", busid);
+       else
+               snprintf(command, SYSFS_BUS_ID_SIZE + 4, "del %s", busid);
+
+       rc = write_sysfs_attribute(match_busid_attr_path, command,
+                                  sizeof(command));
+       if (rc < 0) {
+               dbg("failed to write match_busid: %s", strerror(errno));
+               return -1;
+       }
+
+       return 0;
+}
diff --git a/tools/usb/usbip/src/utils.h b/tools/usb/usbip/src/utils.h
new file mode 100644 (file)
index 0000000..5916fd3
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
+ *               2005-2007 Takahiro Hirofuchi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __UTILS_H
+#define __UTILS_H
+
+int modify_match_busid(char *busid, int add);
+
+#endif /* __UTILS_H */
+