]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
Merge branch 'work.xattr' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 11 Jan 2016 21:32:10 +0000 (13:32 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 11 Jan 2016 21:32:10 +0000 (13:32 -0800)
Pull vfs xattr updates from Al Viro:
 "Andreas' xattr cleanup series.

  It's a followup to his xattr work that went in last cycle; -0.5KLoC"

* 'work.xattr' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  xattr handlers: Simplify list operation
  ocfs2: Replace list xattr handler operations
  nfs: Move call to security_inode_listsecurity into nfs_listxattr
  xfs: Change how listxattr generates synthetic attributes
  tmpfs: listxattr should include POSIX ACL xattrs
  tmpfs: Use xattr handler infrastructure
  btrfs: Use xattr handler infrastructure
  vfs: Distinguish between full xattr names and proper prefixes
  posix acls: Remove duplicate xattr name definitions
  gfs2: Remove gfs2_xattr_acl_chmod
  vfs: Remove vfs_xattr_cmp

801 files changed:
Documentation/devicetree/bindings/dma/ti-edma.txt
Documentation/devicetree/bindings/gpio/gpio-mpc8xxx.txt
Documentation/devicetree/bindings/input/sun4i-lradc-keys.txt
Documentation/devicetree/bindings/mtd/partition.txt
Documentation/devicetree/bindings/net/cpsw.txt
Documentation/filesystems/Locking
Documentation/filesystems/porting
Documentation/filesystems/vfs.txt
Documentation/networking/e100.txt
MAINTAINERS
Makefile
arch/arc/Kconfig
arch/arc/Makefile
arch/arc/boot/dts/axs10x_mb.dtsi
arch/arc/boot/dts/nsim_hs.dts
arch/arc/include/asm/cache.h
arch/arc/include/asm/mach_desc.h
arch/arc/include/asm/smp.h
arch/arc/include/asm/unwind.h
arch/arc/kernel/intc-arcv2.c
arch/arc/kernel/irq.c
arch/arc/kernel/mcip.c
arch/arc/kernel/perf_event.c
arch/arc/kernel/setup.c
arch/arc/kernel/smp.c
arch/arc/kernel/unwind.c
arch/arc/mm/highmem.c
arch/arc/mm/init.c
arch/arm/boot/dts/am4372.dtsi
arch/arm/boot/dts/am43xx-clocks.dtsi
arch/arm/boot/dts/at91-sama5d2_xplained.dts
arch/arm/boot/dts/berlin2q.dtsi
arch/arm/boot/dts/dm816x.dtsi
arch/arm/boot/dts/imx6q-gw5400-a.dts
arch/arm/boot/dts/imx6qdl-gw51xx.dtsi
arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
arch/arm/boot/dts/omap4-duovero-parlor.dts
arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
arch/arm/boot/dts/sun6i-a31s-primo81.dts
arch/arm/boot/dts/tegra124-nyan.dtsi
arch/arm/boot/dts/versatile-ab.dts
arch/arm/boot/dts/versatile-pb.dts
arch/arm/boot/dts/vf610-colibri.dtsi
arch/arm/boot/dts/vf610.dtsi
arch/arm/boot/dts/vfxxx.dtsi
arch/arm/boot/dts/wm8650.dtsi
arch/arm/configs/multi_v7_defconfig
arch/arm/configs/sunxi_defconfig
arch/arm/include/asm/arch_gicv3.h
arch/arm/include/asm/uaccess.h
arch/arm/kernel/process.c
arch/arm/kernel/swp_emulate.c
arch/arm/kernel/sys_oabi-compat.c
arch/arm/lib/uaccess_with_memcpy.c
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/pm.c
arch/arm/mach-exynos/pmu.c
arch/arm/mach-ixp4xx/include/mach/io.h
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/gpmc-onenand.c
arch/arm/mach-omap2/timer.c
arch/arm/mach-pxa/ezx.c
arch/arm/mach-s3c24xx/pll-s3c2440-12000000.c
arch/arm/mach-s3c24xx/pll-s3c2440-16934400.c
arch/arm/mm/context.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/init.c
arch/arm/mm/proc-v7.S
arch/arm/net/bpf_jit_32.c
arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
arch/arm64/include/asm/arch_gicv3.h
arch/arm64/include/asm/pgtable.h
arch/arm64/kernel/vmlinux.lds.S
arch/blackfin/kernel/perf_event.c
arch/ia64/include/asm/unistd.h
arch/ia64/include/uapi/asm/unistd.h
arch/ia64/kernel/entry.S
arch/m32r/include/asm/Kbuild
arch/m32r/include/asm/io.h
arch/microblaze/kernel/dma.c
arch/mips/include/asm/uaccess.h
arch/mips/kernel/cps-vec.S
arch/mips/kernel/mips_ksyms.c
arch/mips/lib/memset.S
arch/mips/mm/dma-default.c
arch/mips/net/bpf_jit.c
arch/mips/pci/pci-rt2880.c
arch/mips/pmcs-msp71xx/msp_setup.c
arch/mips/sni/reset.c
arch/mips/vdso/Makefile
arch/parisc/include/asm/pgtable.h
arch/parisc/include/uapi/asm/unistd.h
arch/parisc/kernel/pci.c
arch/parisc/kernel/signal.c
arch/parisc/kernel/syscall_table.S
arch/powerpc/boot/dts/sbc8641d.dts
arch/powerpc/include/asm/systbl.h
arch/powerpc/include/uapi/asm/unistd.h
arch/powerpc/kernel/eeh_driver.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/net/bpf_jit_comp.c
arch/powerpc/platforms/powernv/opal-irqchip.c
arch/powerpc/platforms/powernv/opal.c
arch/s390/kernel/dis.c
arch/sh/include/uapi/asm/unistd_64.h
arch/sh/kernel/perf_event.c
arch/sparc/include/asm/elf_64.h
arch/sparc/include/uapi/asm/unistd.h
arch/sparc/kernel/head_64.S
arch/sparc/kernel/perf_event.c
arch/sparc/kernel/rtrap_64.S
arch/sparc/kernel/setup_64.c
arch/sparc/kernel/systbls_32.S
arch/sparc/kernel/systbls_64.S
arch/sparc/lib/NG2copy_from_user.S
arch/sparc/lib/NG2copy_to_user.S
arch/sparc/lib/NG2memcpy.S
arch/sparc/lib/NG4copy_from_user.S
arch/sparc/lib/NG4copy_to_user.S
arch/sparc/lib/NG4memcpy.S
arch/sparc/lib/U1copy_from_user.S
arch/sparc/lib/U1copy_to_user.S
arch/sparc/lib/U1memcpy.S
arch/sparc/lib/U3copy_from_user.S
arch/sparc/lib/U3copy_to_user.S
arch/sparc/lib/U3memcpy.S
arch/sparc/net/bpf_jit_comp.c
arch/tile/Kconfig
arch/tile/include/asm/page.h
arch/tile/kernel/perf_event.c
arch/um/Makefile
arch/um/drivers/net_user.c
arch/um/kernel/signal.c
arch/x86/entry/common.c
arch/x86/entry/entry_32.S
arch/x86/entry/entry_64_compat.S
arch/x86/entry/vdso/vdso32/system_call.S
arch/x86/include/asm/cpufeature.h
arch/x86/include/asm/paravirt.h
arch/x86/include/asm/paravirt_types.h
arch/x86/include/asm/processor.h
arch/x86/kernel/apic/apic_numachip.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event.h
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_intel_cqm.c
arch/x86/kernel/cpu/perf_event_intel_lbr.c
arch/x86/kernel/irq_work.c
arch/x86/kernel/rtc.c
arch/x86/kvm/cpuid.h
arch/x86/kvm/i8254.c
arch/x86/kvm/mtrr.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/lguest/boot.c
arch/x86/mm/dump_pagetables.c
arch/x86/um/signal.c
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/x86/xen/suspend.c
block/blk-cgroup.c
block/blk-core.c
crypto/ablkcipher.c
crypto/algif_skcipher.c
crypto/async_tx/async_memcpy.c
crypto/async_tx/async_pq.c
crypto/async_tx/async_raid6_recov.c
crypto/async_tx/async_xor.c
crypto/blkcipher.c
drivers/acpi/device_sysfs.c
drivers/acpi/nfit.c
drivers/acpi/processor_driver.c
drivers/ata/ahci.c
drivers/ata/ahci_mvebu.c
drivers/ata/libahci.c
drivers/ata/libata-eh.c
drivers/ata/sata_fsl.c
drivers/ata/sata_sil.c
drivers/base/memory.c
drivers/base/power/domain.c
drivers/block/null_blk.c
drivers/block/xen-blkback/blkback.c
drivers/block/xen-blkback/common.h
drivers/bus/sunxi-rsb.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/clk/clk-gpio.c
drivers/clk/clk-qoriq.c
drivers/clk/clk-scpi.c
drivers/clk/imx/clk-pllv1.c
drivers/clk/imx/clk-pllv2.c
drivers/clk/imx/clk-vf610.c
drivers/clk/mmp/clk-mmp2.c
drivers/clk/mmp/clk-pxa168.c
drivers/clk/mmp/clk-pxa910.c
drivers/clk/sunxi/clk-a10-pll2.c
drivers/clk/ti/clk-816x.c
drivers/clk/ti/clkt_dpll.c
drivers/clk/ti/divider.c
drivers/clk/ti/fapll.c
drivers/clk/ti/mux.c
drivers/clocksource/mmio.c
drivers/connector/connector.c
drivers/cpufreq/Kconfig.arm
drivers/cpufreq/intel_pstate.c
drivers/cpufreq/s3c24xx-cpufreq.c
drivers/cpufreq/scpi-cpufreq.c
drivers/dma/at_xdmac.c
drivers/dma/bcm2835-dma.c
drivers/dma/edma.c
drivers/dma/xgene-dma.c
drivers/firmware/dmi_scan.c
drivers/fpga/fpga-mgr.c
drivers/gpio/gpio-ath79.c
drivers/gpio/gpio-generic.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
drivers/gpu/drm/drm_probe_helper.c
drivers/gpu/drm/exynos/exynos_drm_crtc.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_context.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gem_stolen.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/nouveau/include/nvkm/core/device.h
drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c
drivers/gpu/drm/nouveau/nvkm/subdev/bios/fan.c
drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c
drivers/gpu/drm/omapdrm/omap_fbdev.c
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/radeon_vce.c
drivers/gpu/drm/ttm/ttm_lock.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
drivers/gpu/vga/vgaarb.c
drivers/hid/hid-ids.h
drivers/hid/usbhid/hid-quirks.c
drivers/hwmon/Kconfig
drivers/hwmon/tmp102.c
drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-designware-core.c
drivers/i2c/busses/i2c-designware-core.h
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-rcar.c
drivers/i2c/busses/i2c-rk3x.c
drivers/i2c/busses/i2c-st.c
drivers/iio/adc/qcom-spmi-vadc.c
drivers/iio/industrialio-buffer.c
drivers/iio/industrialio-core.c
drivers/iio/light/apds9960.c
drivers/iio/proximity/pulsedlight-lidar-lite-v2.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/mad.c
drivers/infiniband/core/sa_query.c
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx4/qp.c
drivers/infiniband/hw/mlx4/srq.c
drivers/infiniband/hw/mlx5/mr.c
drivers/infiniband/hw/ocrdma/ocrdma.h
drivers/infiniband/hw/ocrdma/ocrdma_hw.c
drivers/infiniband/hw/ocrdma/ocrdma_hw.h
drivers/infiniband/hw/ocrdma/ocrdma_main.c
drivers/infiniband/hw/ocrdma/ocrdma_sli.h
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
drivers/infiniband/hw/qib/qib_qsfp.c
drivers/infiniband/hw/qib/qib_verbs.h
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/infiniband/ulp/isert/ib_isert.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/infiniband/ulp/srp/ib_srp.h
drivers/input/joystick/db9.c
drivers/input/joystick/gamecon.c
drivers/input/joystick/turbografx.c
drivers/input/joystick/walkera0701.c
drivers/input/misc/arizona-haptics.c
drivers/input/mouse/elan_i2c_core.c
drivers/input/serio/parkbd.c
drivers/input/tablet/aiptek.c
drivers/input/touchscreen/atmel_mxt_ts.c
drivers/input/touchscreen/elants_i2c.c
drivers/iommu/amd_iommu_v2.c
drivers/iommu/dma-iommu.c
drivers/iommu/intel-iommu.c
drivers/iommu/intel-svm.c
drivers/iommu/iommu.c
drivers/iommu/ipmmu-vmsa.c
drivers/irqchip/irq-versatile-fpga.c
drivers/isdn/gigaset/ser-gigaset.c
drivers/isdn/hardware/mISDN/mISDNipac.c
drivers/lightnvm/Kconfig
drivers/lightnvm/core.c
drivers/lightnvm/gennvm.c
drivers/lightnvm/rrpc.c
drivers/md/dm-thin-metadata.c
drivers/md/md.c
drivers/md/md.h
drivers/md/persistent-data/dm-btree.c
drivers/md/persistent-data/dm-btree.h
drivers/md/persistent-data/dm-space-map-metadata.c
drivers/md/raid10.c
drivers/media/pci/ivtv/ivtv-driver.c
drivers/media/usb/airspy/airspy.c
drivers/media/usb/hackrf/hackrf.c
drivers/memory/fsl_ifc.c
drivers/misc/cxl/native.c
drivers/mtd/mtdcore.c
drivers/mtd/ofpart.c
drivers/mtd/spi-nor/spi-nor.c
drivers/mtd/ubi/debug.c
drivers/mtd/ubi/io.c
drivers/mtd/ubi/wl.c
drivers/net/ethernet/amd/xgbe/xgbe-dev.c
drivers/net/ethernet/apm/xgene/xgene_enet_main.c
drivers/net/ethernet/apm/xgene/xgene_enet_main.h
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
drivers/net/ethernet/aurora/Kconfig
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
drivers/net/ethernet/cavium/thunder/nic_main.c
drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/emulex/benet/be_roce.c
drivers/net/ethernet/emulex/benet/be_roce.h
drivers/net/ethernet/ezchip/nps_enet.c
drivers/net/ethernet/freescale/fs_enet/mac-fcc.c
drivers/net/ethernet/freescale/fsl_pq_mdio.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/freescale/gianfar.h
drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h
drivers/net/ethernet/intel/i40e/i40e_adminq.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40evf/i40e_adminq.c
drivers/net/ethernet/intel/i40evf/i40evf_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/marvell/mvpp2.c
drivers/net/ethernet/mellanox/mlx4/cmd.c
drivers/net/ethernet/mellanox/mlx4/en_clock.c
drivers/net/ethernet/mellanox/mlx4/en_main.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/natsemi/natsemi.c
drivers/net/ethernet/qlogic/qed/qed.h
drivers/net/ethernet/qlogic/qed/qed_dev.c
drivers/net/ethernet/qlogic/qed/qed_int.c
drivers/net/ethernet/qlogic/qed/qed_int.h
drivers/net/ethernet/qlogic/qed/qed_main.c
drivers/net/ethernet/qlogic/qed/qed_reg_addr.h
drivers/net/ethernet/qlogic/qed/qed_sp.h
drivers/net/ethernet/qlogic/qed/qed_spq.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
drivers/net/ethernet/qlogic/qlge/qlge_main.c
drivers/net/ethernet/qualcomm/qca_spi.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/renesas/sh_eth.h
drivers/net/ethernet/sfc/ef10.c
drivers/net/ethernet/sfc/efx.h
drivers/net/ethernet/sfc/farch.c
drivers/net/ethernet/sfc/txc43128_phy.c
drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/geneve.c
drivers/net/hamradio/6pack.c
drivers/net/hamradio/mkiss.c
drivers/net/phy/mdio-mux.c
drivers/net/phy/micrel.c
drivers/net/ppp/pppoe.c
drivers/net/ppp/pptp.c
drivers/net/usb/cdc_mbim.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/r8152.c
drivers/net/veth.c
drivers/net/virtio_net.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vmxnet3/vmxnet3_int.h
drivers/net/vrf.c
drivers/net/vxlan.c
drivers/net/wireless/iwlwifi/iwl-7000.c
drivers/net/wireless/iwlwifi/mvm/sta.c
drivers/net/xen-netback/netback.c
drivers/nvme/host/lightnvm.c
drivers/nvme/host/pci.c
drivers/of/address.c
drivers/of/fdt.c
drivers/of/irq.c
drivers/of/of_reserved_mem.c
drivers/parisc/iommu-helpers.h
drivers/pci/host/Kconfig
drivers/pci/host/pcie-altera.c
drivers/pci/host/pcie-hisi.c
drivers/pci/msi.c
drivers/phy/Kconfig
drivers/phy/phy-bcm-cygnus-pcie.c
drivers/phy/phy-berlin-sata.c
drivers/phy/phy-brcmstb-sata.c
drivers/phy/phy-core.c
drivers/phy/phy-miphy28lp.c
drivers/phy/phy-miphy365x.c
drivers/phy/phy-mt65xx-usb3.c
drivers/phy/phy-rockchip-usb.c
drivers/pinctrl/bcm/pinctrl-bcm2835.c
drivers/pinctrl/freescale/pinctrl-vf610.c
drivers/pinctrl/intel/pinctrl-broxton.c
drivers/pinctrl/intel/pinctrl-intel.c
drivers/pinctrl/intel/pinctrl-intel.h
drivers/pinctrl/intel/pinctrl-sunrisepoint.c
drivers/powercap/intel_rapl.c
drivers/rtc/rtc-da9063.c
drivers/rtc/rtc-rk808.c
drivers/s390/crypto/ap_bus.c
drivers/s390/virtio/virtio_ccw.c
drivers/scsi/scsi_pm.c
drivers/scsi/sd.c
drivers/scsi/ses.c
drivers/spi/spi-fsl-dspi.c
drivers/spi/spi.c
drivers/spi/spidev.c
drivers/staging/android/ion/ion_chunk_heap.c
drivers/staging/iio/iio_simple_dummy_events.c
drivers/staging/lustre/lustre/llite/symlink.c
drivers/staging/lustre/lustre/obdecho/echo_client.c
drivers/tty/n_tty.c
drivers/tty/serial/8250/8250_uniphier.c
drivers/tty/serial/earlycon.c
drivers/tty/serial/sh-sci.c
drivers/tty/serial/sunhv.c
drivers/tty/tty_buffer.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/config.c
drivers/usb/core/hub.c
drivers/usb/core/port.c
drivers/usb/core/quirks.c
drivers/usb/dwc2/platform.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/f_midi.c
drivers/usb/gadget/function/uvc_configfs.c
drivers/usb/gadget/udc/pxa27x_udc.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/whci/qset.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/musb/Kconfig
drivers/usb/musb/musb_core.c
drivers/usb/phy/phy-msm-usb.c
drivers/usb/phy/phy-mxs-usb.c
drivers/usb/renesas_usbhs/mod_gadget.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/ipaq.c
drivers/usb/serial/usb-serial-simple.c
drivers/usb/storage/uas.c
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/unusual_uas.h
drivers/vfio/Kconfig
drivers/vfio/pci/vfio_pci.c
drivers/vfio/platform/vfio_platform.c
drivers/vfio/platform/vfio_platform_common.c
drivers/vfio/vfio.c
drivers/vhost/vhost.c
drivers/video/fbdev/fsl-diu-fb.c
drivers/video/fbdev/omap2/dss/venc.c
drivers/virtio/virtio.c
drivers/virtio/virtio_ring.c
drivers/xen/events/events_fifo.c
drivers/xen/xen-pciback/pciback.h
drivers/xen/xen-pciback/pciback_ops.c
drivers/xen/xen-pciback/xenbus.c
drivers/xen/xen-scsiback.c
fs/9p/vfs_inode.c
fs/9p/vfs_inode_dotl.c
fs/affs/inode.c
fs/affs/namei.c
fs/affs/symlink.c
fs/afs/inode.c
fs/autofs4/symlink.c
fs/befs/linuxvfs.c
fs/block_dev.c
fs/btrfs/extent-tree.c
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/inode.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h
fs/btrfs/volumes.c
fs/ceph/inode.c
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/inode.c
fs/cifs/link.c
fs/coda/cnode.c
fs/coda/symlink.c
fs/compat_ioctl.c
fs/configfs/symlink.c
fs/cramfs/inode.c
fs/dcache.c
fs/direct-io.c
fs/ecryptfs/inode.c
fs/efs/inode.c
fs/efs/symlink.c
fs/exofs/inode.c
fs/exofs/namei.c
fs/ext2/inode.c
fs/ext2/namei.c
fs/ext2/symlink.c
fs/ext4/crypto.c
fs/ext4/ext4.h
fs/ext4/inode.c
fs/ext4/namei.c
fs/ext4/symlink.c
fs/ext4/sysfs.c
fs/f2fs/inode.c
fs/f2fs/namei.c
fs/freevxfs/vxfs_inode.c
fs/fuse/cuse.c
fs/fuse/dir.c
fs/fuse/file.c
fs/gfs2/inode.c
fs/hfsplus/inode.c
fs/hostfs/hostfs_kern.c
fs/hpfs/inode.c
fs/hpfs/namei.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/internal.h
fs/ioctl.c
fs/isofs/inode.c
fs/isofs/rock.c
fs/jbd2/transaction.c
fs/jffs2/symlink.c
fs/jfs/inode.c
fs/jfs/namei.c
fs/jfs/symlink.c
fs/kernfs/symlink.c
fs/libfs.c
fs/logfs/dir.c
fs/logfs/inode.c
fs/logfs/logfs.h
fs/minix/inode.c
fs/namei.c
fs/ncpfs/inode.c
fs/nfs/callback_xdr.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/objlayout/objio_osd.c
fs/nfs/pagelist.c
fs/nfs/pnfs.c
fs/nfs/symlink.c
fs/nfsd/nfs4layouts.c
fs/nilfs2/inode.c
fs/nilfs2/namei.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/inode.c
fs/ocfs2/locks.c
fs/ocfs2/namei.c
fs/ocfs2/resize.c
fs/ocfs2/symlink.c
fs/overlayfs/inode.c
fs/proc/base.c
fs/proc/inode.c
fs/proc/namespaces.c
fs/proc/self.c
fs/proc/thread_self.c
fs/qnx4/inode.c
fs/qnx6/inode.c
fs/ramfs/inode.c
fs/reiserfs/inode.c
fs/reiserfs/namei.c
fs/romfs/super.c
fs/squashfs/inode.c
fs/squashfs/symlink.c
fs/sysv/inode.c
fs/ubifs/file.c
fs/udf/inode.c
fs/udf/namei.c
fs/udf/symlink.c
fs/udf/udfdecl.h
fs/ufs/Makefile
fs/ufs/inode.c
fs/ufs/namei.c
fs/ufs/symlink.c [deleted file]
fs/ufs/ufs.h
fs/xfs/xfs_iops.c
include/asm-generic/tlb.h
include/linux/bitops.h
include/linux/blkdev.h
include/linux/cgroup-defs.h
include/linux/cgroup.h
include/linux/delayed_call.h [new file with mode: 0644]
include/linux/enclosure.h
include/linux/filter.h
include/linux/fs.h
include/linux/ftrace.h
include/linux/irqchip/arm-gic-v3.h
include/linux/jump_label.h
include/linux/kmemleak.h
include/linux/libata.h
include/linux/lightnvm.h
include/linux/lockdep.h
include/linux/mlx4/device.h
include/linux/mmdebug.h
include/linux/mtd/spi-nor.h
include/linux/netdevice.h
include/linux/netfilter/nfnetlink.h
include/linux/nfs_fs.h
include/linux/of_irq.h
include/linux/perf_event.h
include/linux/platform_data/edma.h
include/linux/proportions.h
include/linux/qed/common_hsi.h
include/linux/qed/qed_chain.h
include/linux/rhashtable.h
include/linux/sched.h
include/linux/stop_machine.h
include/linux/uprobes.h
include/linux/usb/cdc_ncm.h
include/linux/usb/quirks.h
include/linux/vfio.h
include/linux/vmstat.h
include/linux/wait.h
include/net/dst.h
include/net/inet_sock.h
include/net/inetpeer.h
include/net/l3mdev.h
include/net/route.h
include/net/sctp/structs.h
include/net/sock.h
include/net/vxlan.h
include/net/xfrm.h
include/rdma/ib_mad.h
include/rdma/ib_verbs.h
include/sound/hda_register.h
include/sound/soc.h
include/uapi/linux/Kbuild
include/uapi/linux/openvswitch.h
include/uapi/linux/vfio.h
include/xen/interface/io/ring.h
init/Kconfig
kernel/cgroup.c
kernel/cgroup_freezer.c
kernel/cgroup_pids.c
kernel/cpuset.c
kernel/events/callchain.c
kernel/events/core.c
kernel/events/ring_buffer.c
kernel/events/uprobes.c
kernel/fork.c
kernel/irq/manage.c
kernel/irq_work.c
kernel/jump_label.c
kernel/locking/lockdep.c
kernel/locking/lockdep_proc.c
kernel/locking/osq_lock.c
kernel/module.c
kernel/sched/clock.c
kernel/sched/core.c
kernel/sched/fair.c
kernel/sched/wait.c
kernel/stop_machine.c
kernel/trace/trace_event_perf.c
kernel/trace/trace_printk.c
lib/btree.c
lib/dma-debug.c
lib/proportions.c
lib/rhashtable.c
mm/backing-dev.c
mm/hugetlb.c
mm/memcontrol.c
mm/memory_hotplug.c
mm/oom_kill.c
mm/page-writeback.c
mm/page_alloc.c
mm/shmem.c
mm/vmstat.c
mm/zswap.c
net/ax25/af_ax25.c
net/batman-adv/distributed-arp-table.c
net/batman-adv/routing.c
net/batman-adv/translation-table.c
net/bluetooth/sco.c
net/bridge/br_stp_if.c
net/core/dst.c
net/core/netclassid_cgroup.c
net/core/netprio_cgroup.c
net/core/skbuff.c
net/core/sock.c
net/decnet/af_decnet.c
net/ipv4/af_inet.c
net/ipv4/fib_frontend.c
net/ipv4/fou.c
net/ipv4/ipip.c
net/ipv4/netfilter/Kconfig
net/ipv4/raw.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv4/udp.c
net/ipv4/xfrm4_policy.c
net/ipv6/addrconf.c
net/ipv6/addrlabel.c
net/ipv6/af_inet6.c
net/ipv6/ip6_gre.c
net/ipv6/ndisc.c
net/ipv6/netfilter/Kconfig
net/ipv6/tcp_ipv6.c
net/ipv6/xfrm6_policy.c
net/irda/af_irda.c
net/mac80211/cfg.c
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/util.c
net/mac80211/vht.c
net/mpls/af_mpls.c
net/mpls/mpls_iptunnel.c
net/netfilter/nf_tables_api.c
net/netfilter/nf_tables_netdev.c
net/netfilter/nfnetlink.c
net/netfilter/nfnetlink_queue.c
net/netfilter/nft_ct.c
net/openvswitch/conntrack.c
net/openvswitch/flow_netlink.c
net/rfkill/core.c
net/sched/sch_api.c
net/sched/sch_generic.c
net/sctp/ipv6.c
net/sctp/outqueue.c
net/sctp/sm_make_chunk.c
net/sctp/sm_statefuns.c
net/sctp/socket.c
net/socket.c
net/sunrpc/backchannel_rqst.c
net/sunrpc/sched.c
net/sunrpc/svc.c
net/unix/af_unix.c
net/wireless/nl80211.c
net/wireless/reg.c
net/xfrm/xfrm_policy.c
scripts/link-vmlinux.sh
scripts/recordmcount.c
security/keys/keyctl.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_realtek.c
sound/pci/rme96.c
sound/soc/codecs/arizona.c
sound/soc/codecs/es8328.c
sound/soc/codecs/es8328.h
sound/soc/codecs/rt5645.c
sound/soc/codecs/rt5645.h
sound/soc/codecs/sgtl5000.c
sound/soc/codecs/wm8974.c
sound/soc/davinci/davinci-mcasp.c
sound/soc/fsl/fsl_sai.c
sound/soc/intel/skylake/skl-topology.c
sound/soc/intel/skylake/skl.c
sound/soc/intel/skylake/skl.h
sound/soc/rockchip/rockchip_spdif.c
sound/soc/rockchip/rockchip_spdif.h
sound/usb/mixer.c
sound/usb/mixer_maps.c
sound/usb/mixer_quirks.c
sound/usb/mixer_quirks.h
sound/usb/quirks.c
tools/perf/builtin-buildid-list.c
tools/perf/ui/browsers/hists.c
tools/perf/util/build-id.c
tools/perf/util/parse-events.c
tools/virtio/linux/kernel.h
tools/virtio/linux/virtio.h
tools/virtio/linux/virtio_config.h
virt/kvm/arm/vgic.c

index d3d0a4fb1c733b8288884869088fda088328546d..079b42a81d7cf3c5af086872fc86127023ab2c15 100644 (file)
@@ -22,8 +22,7 @@ Required properties:
 Optional properties:
 - ti,hwmods:   Name of the hwmods associated to the eDMA CC
 - ti,edma-memcpy-channels: List of channels allocated to be used for memcpy, iow
-               these channels will be SW triggered channels. The list must
-               contain 16 bits numbers, see example.
+               these channels will be SW triggered channels. See example.
 - ti,edma-reserved-slot-ranges: PaRAM slot ranges which should not be used by
                the driver, they are allocated to be used by for example the
                DSP. See example.
@@ -56,10 +55,9 @@ edma: edma@49000000 {
        ti,tptcs = <&edma_tptc0 7>, <&edma_tptc1 7>, <&edma_tptc2 0>;
 
        /* Channel 20 and 21 is allocated for memcpy */
-       ti,edma-memcpy-channels = /bits/ 16 <20 21>;
-       /* The following PaRAM slots are reserved: 35-45 and 100-110 */
-       ti,edma-reserved-slot-ranges = /bits/ 16 <35 10>,
-                                      /bits/ 16 <100 10>;
+       ti,edma-memcpy-channels = <20 21>;
+       /* The following PaRAM slots are reserved: 35-44 and 100-109 */
+       ti,edma-reserved-slot-ranges = <35 10>, <100 10>;
 };
 
 edma_tptc0: tptc@49800000 {
index f2455c50533d6c7388ebfacbe572d164e5d11314..120bc4971cf3ed92cf9590af16643645e5c89234 100644 (file)
@@ -11,6 +11,10 @@ Required properties:
       0 = active high
       1 = active low
 
+Optional properties:
+- little-endian : GPIO registers are used as little endian. If not
+                  present registers are used as big endian by default.
+
 Example:
 
 gpio0: gpio@1100 {
index b9c32f6fd687b04a3737c871bcf5c694665d3b84..4357e498ef0422d5fdc2715e3daf065ac80e41f4 100644 (file)
@@ -12,7 +12,7 @@ Each key is represented as a sub-node of "allwinner,sun4i-a10-lradc-keys":
 Required subnode-properties:
        - label: Descriptive name of the key.
        - linux,code: Keycode to emit.
-       - channel: Channel this key is attached to, mut be 0 or 1.
+       - channel: Channel this key is attached to, must be 0 or 1.
        - voltage: Voltage in ÂµV at lradc input when this key is pressed.
 
 Example:
index f1e2a02381a498a8f94e379870a8dcb1d2dec4ca..1c63e40659fcaada93e54ec81e8a12f62dca1f83 100644 (file)
@@ -6,7 +6,9 @@ used for what purposes, but which don't use an on-flash partition table such
 as RedBoot.
 
 The partition table should be a subnode of the mtd node and should be named
-'partitions'. Partitions are defined in subnodes of the partitions node.
+'partitions'. This node should have the following property:
+- compatible : (required) must be "fixed-partitions"
+Partitions are then defined in subnodes of the partitions node.
 
 For backwards compatibility partitions as direct subnodes of the mtd device are
 supported. This use is discouraged.
@@ -36,6 +38,7 @@ Examples:
 
 flash@0 {
        partitions {
+               compatible = "fixed-partitions";
                #address-cells = <1>;
                #size-cells = <1>;
 
@@ -53,6 +56,7 @@ flash@0 {
 
 flash@1 {
        partitions {
+               compatible = "fixed-partitions";
                #address-cells = <1>;
                #size-cells = <2>;
 
@@ -66,6 +70,7 @@ flash@1 {
 
 flash@2 {
        partitions {
+               compatible = "fixed-partitions";
                #address-cells = <2>;
                #size-cells = <2>;
 
index 9853f8e7096613e990c28cc545b39ab7f26afddc..28a4781ab6d7b9d6a1ab553ed96857f0f509e250 100644 (file)
@@ -40,18 +40,18 @@ Optional properties:
 
 Slave Properties:
 Required properties:
-- phy_id               : Specifies slave phy id
 - phy-mode             : See ethernet.txt file in the same directory
 
 Optional properties:
 - dual_emac_res_vlan   : Specifies VID to be used to segregate the ports
 - mac-address          : See ethernet.txt file in the same directory
+- phy_id               : Specifies slave phy id
 - phy-handle           : See ethernet.txt file in the same directory
 
 Slave sub-nodes:
 - fixed-link           : See fixed-link.txt file in the same directory
-                         Either the properties phy_id and phy-mode,
-                         or the sub-node fixed-link can be specified
+                         Either the property phy_id, or the sub-node
+                         fixed-link can be specified
 
 Note: "ti,hwmods" field is used to fetch the base address and irq
 resources from TI, omap hwmod data base during device registration.
index 06d443450f2138fc8595ef43be0e64ebc33f66f7..619af9bfdcb3eb4baceac7824c655fd9ba495950 100644 (file)
@@ -50,8 +50,7 @@ prototypes:
        int (*rename2) (struct inode *, struct dentry *,
                        struct inode *, struct dentry *, unsigned int);
        int (*readlink) (struct dentry *, char __user *,int);
-       const char *(*follow_link) (struct dentry *, void **);
-       void (*put_link) (struct inode *, void *);
+       const char *(*get_link) (struct dentry *, struct inode *, void **);
        void (*truncate) (struct inode *);
        int (*permission) (struct inode *, int, unsigned int);
        int (*get_acl)(struct inode *, int);
@@ -83,8 +82,7 @@ rmdir:                yes (both)      (see below)
 rename:                yes (all)       (see below)
 rename2:       yes (all)       (see below)
 readlink:      no
-follow_link:   no
-put_link:      no
+get_link:      no
 setattr:       yes
 permission:    no (may not block if called in rcu-walk mode)
 get_acl:       no
index f24d1b8339576e96c46045f5da8f275ee9250056..0f88e6020487ff9d08836e28b7e9ae780b4ebc5a 100644 (file)
@@ -504,3 +504,20 @@ in your dentry operations instead.
 [mandatory]
        __fd_install() & fd_install() can now sleep. Callers should not
        hold a spinlock or other resources that do not allow a schedule.
+--
+[mandatory]
+       any symlink that might use page_follow_link_light/page_put_link() must
+       have inode_nohighmem(inode) called before anything might start playing with
+       its pagecache.
+--
+[mandatory]
+       ->follow_link() is replaced with ->get_link(); same API, except that
+               * ->get_link() gets inode as a separate argument
+               * ->get_link() may be called in RCU mode - in that case NULL
+                 dentry is passed
+--
+[mandatory]
+       ->get_link() gets struct delayed_call *done now, and should do
+       set_delayed_call() where it used to set *cookie.
+       ->put_link() is gone - just give the destructor to set_delayed_call()
+       in ->get_link().
index 8c6f07ad373aa6b8402e457e0705cdebd0f3271d..b02a7d598258542e890eae7ab3b4b4503db251e2 100644 (file)
@@ -350,8 +350,8 @@ struct inode_operations {
        int (*rename2) (struct inode *, struct dentry *,
                        struct inode *, struct dentry *, unsigned int);
        int (*readlink) (struct dentry *, char __user *,int);
-       const char *(*follow_link) (struct dentry *, void **);
-       void (*put_link) (struct inode *, void *);
+       const char *(*get_link) (struct dentry *, struct inode *,
+                                struct delayed_call *);
        int (*permission) (struct inode *, int);
        int (*get_acl)(struct inode *, int);
        int (*setattr) (struct dentry *, struct iattr *);
@@ -434,20 +434,19 @@ otherwise noted.
   readlink: called by the readlink(2) system call. Only required if
        you want to support reading symbolic links
 
-  follow_link: called by the VFS to follow a symbolic link to the
+  get_link: called by the VFS to follow a symbolic link to the
        inode it points to.  Only required if you want to support
        symbolic links.  This method returns the symlink body
        to traverse (and possibly resets the current position with
        nd_jump_link()).  If the body won't go away until the inode
        is gone, nothing else is needed; if it needs to be otherwise
-       pinned, the data needed to release whatever we'd grabbed
-       is to be stored in void * variable passed by address to
-       follow_link() instance.
-
-  put_link: called by the VFS to release resources allocated by
-       follow_link().  The cookie stored by follow_link() is passed
-       to this method as the last parameter; only called when
-       cookie isn't NULL.
+       pinned, arrange for its release by having get_link(..., ..., done)
+       do set_delayed_call(done, destructor, argument).
+       In that case destructor(argument) will be called once VFS is
+       done with the body you've returned.
+       May be called in RCU mode; that is indicated by NULL dentry
+       argument.  If request can't be handled without leaving RCU mode,
+       have it return ERR_PTR(-ECHILD).
 
   permission: called by the VFS to check for access rights on a POSIX-like
        filesystem.
index f862cf3aff3495d96f699cd666af6dbf3d18a453..42ddbd4b52a9d646a539ad154d7400c0a61c02c7 100644 (file)
@@ -181,17 +181,3 @@ For general information, go to the Intel support website at:
 If an issue is identified with the released source code on the supported
 kernel with a supported adapter, email the specific information related to the
 issue to e1000-devel@lists.sourceforge.net.
-
-
-License
-=======
-
-This software program is released under the terms of a license agreement
-between you ('Licensee') and Intel. Do not use or load this software or any
-associated materials (collectively, the 'Software') until you have carefully
-read the full terms and conditions of the file COPYING located in this software
-package. By loading or using the Software, you agree to the terms of this
-Agreement. If you do not agree with the terms of this Agreement, do not install
-or use the Software.
-
-* Other names and brands may be claimed as the property of others.
index 69c8a9c3289adbe64a7e68e134372515d1fd2e0f..233f83464814f138c4c68f0815d2dbeace552ef6 100644 (file)
@@ -2975,6 +2975,7 @@ F:        kernel/cpuset.c
 CONTROL GROUP - MEMORY RESOURCE CONTROLLER (MEMCG)
 M:     Johannes Weiner <hannes@cmpxchg.org>
 M:     Michal Hocko <mhocko@kernel.org>
+M:     Vladimir Davydov <vdavydov@virtuozzo.com>
 L:     cgroups@vger.kernel.org
 L:     linux-mm@kvack.org
 S:     Maintained
@@ -5577,7 +5578,7 @@ R:        Jesse Brandeburg <jesse.brandeburg@intel.com>
 R:     Shannon Nelson <shannon.nelson@intel.com>
 R:     Carolyn Wyborny <carolyn.wyborny@intel.com>
 R:     Don Skidmore <donald.c.skidmore@intel.com>
-R:     Matthew Vick <matthew.vick@intel.com>
+R:     Bruce Allan <bruce.w.allan@intel.com>
 R:     John Ronciak <john.ronciak@intel.com>
 R:     Mitch Williams <mitch.a.williams@intel.com>
 L:     intel-wired-lan@lists.osuosl.org
@@ -8286,7 +8287,7 @@ F:        include/linux/delayacct.h
 F:     kernel/delayacct.c
 
 PERFORMANCE EVENTS SUBSYSTEM
-M:     Peter Zijlstra <a.p.zijlstra@chello.nl>
+M:     Peter Zijlstra <peterz@infradead.org>
 M:     Ingo Molnar <mingo@redhat.com>
 M:     Arnaldo Carvalho de Melo <acme@kernel.org>
 L:     linux-kernel@vger.kernel.org
@@ -8379,6 +8380,14 @@ L:       linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
 S:     Maintained
 F:     drivers/pinctrl/samsung/
 
+PIN CONTROLLER - SINGLE
+M:     Tony Lindgren <tony@atomide.com>
+M:     Haojian Zhuang <haojian.zhuang@linaro.org>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L:     linux-omap@vger.kernel.org
+S:     Maintained
+F:     drivers/pinctrl/pinctrl-single.c
+
 PIN CONTROLLER - ST SPEAR
 M:     Viresh Kumar <vireshk@kernel.org>
 L:     spear-devel@list.st.com
@@ -8945,6 +8954,13 @@ F:       drivers/rpmsg/
 F:     Documentation/rpmsg.txt
 F:     include/linux/rpmsg.h
 
+RENESAS ETHERNET DRIVERS
+R:     Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+L:     netdev@vger.kernel.org
+L:     linux-sh@vger.kernel.org
+F:     drivers/net/ethernet/renesas/
+F:     include/linux/sh_eth.h
+
 RESET CONTROLLER FRAMEWORK
 M:     Philipp Zabel <p.zabel@pengutronix.de>
 S:     Maintained
index d644f6e92cf653be39a981d7ca6b021084c7eaa5..70dea02f1346d4fa8253fb4d22aac60c7718e0c7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 4
 PATCHLEVEL = 4
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION =
 NAME = Blurry Fish Butt
 
 # *DOCUMENTATION*
index 2c2ac3f3ff80370bd6bad9fffc9dfb8c8f6931e8..6312f607932fd2241782827cce2ec7968ea3c8b6 100644 (file)
@@ -445,6 +445,7 @@ config LINUX_LINK_BASE
          However some customers have peripherals mapped at this addr, so
          Linux needs to be scooted a bit.
          If you don't know what the above means, leave this setting alone.
+         This needs to match memory start address specified in Device Tree
 
 config HIGHMEM
        bool "High Memory Support"
index cf0cf34eeb24b14ef070735e83d25b0f7f6aecec..aeb19021099e315967ba95524e9528c48da0d159 100644 (file)
@@ -81,7 +81,7 @@ endif
 LIBGCC := $(shell $(CC) $(cflags-y) --print-libgcc-file-name)
 
 # Modules with short calls might break for calls into builtin-kernel
-KBUILD_CFLAGS_MODULE   += -mlong-calls
+KBUILD_CFLAGS_MODULE   += -mlong-calls -mno-millicode
 
 # Finally dump eveything into kernel build system
 KBUILD_CFLAGS  += $(cflags-y)
index f3db32154973718268c1998e9f16bb03d1af7e7f..44a578c10732cd1ab79558415e3c66f6825c98bd 100644 (file)
@@ -46,6 +46,7 @@
                        snps,pbl = < 32 >;
                        clocks = <&apbclk>;
                        clock-names = "stmmaceth";
+                       max-speed = <100>;
                };
 
                ehci@0x40000 {
index b0eb0e7fe21d8a66b1d0ef5267f24dd6a1f8f254..fc81879bc1f5800e5efe8eb43395eb2c5509f481 100644 (file)
@@ -17,7 +17,8 @@
 
        memory {
                device_type = "memory";
-               reg = <0x0 0x80000000 0x0 0x40000000    /* 1 GB low mem */
+               /* CONFIG_LINUX_LINK_BASE needs to match low mem start */
+               reg = <0x0 0x80000000 0x0 0x20000000    /* 512 MB low mem */
                       0x1 0x00000000 0x0 0x40000000>;  /* 1 GB highmem */
        };
 
index abf06e81c9290f6eafc441b563061e3389032922..210ef3e7233224b099bd40e85106d2d864e70987 100644 (file)
@@ -62,9 +62,7 @@ extern int ioc_exists;
 #define ARC_REG_IC_IVIC                0x10
 #define ARC_REG_IC_CTRL                0x11
 #define ARC_REG_IC_IVIL                0x19
-#if defined(CONFIG_ARC_MMU_V3) || defined(CONFIG_ARC_MMU_V4)
 #define ARC_REG_IC_PTAG                0x1E
-#endif
 #define ARC_REG_IC_PTAG_HI     0x1F
 
 /* Bit val in IC_CTRL */
index 6ff657a904b61e700421b60423991273df93e1e1..c28e6c347b4900217ad48053c69679bb3da8b607 100644 (file)
@@ -23,7 +23,7 @@
  * @dt_compat:         Array of device tree 'compatible' strings
  *                     (XXX: although only 1st entry is looked at)
  * @init_early:                Very early callback [called from setup_arch()]
- * @init_cpu_smp:      for each CPU as it is coming up (SMP as well as UP)
+ * @init_per_cpu:      for each CPU as it is coming up (SMP as well as UP)
  *                     [(M):init_IRQ(), (o):start_kernel_secondary()]
  * @init_machine:      arch initcall level callback (e.g. populate static
  *                     platform devices or parse Devicetree)
@@ -35,7 +35,7 @@ struct machine_desc {
        const char              **dt_compat;
        void                    (*init_early)(void);
 #ifdef CONFIG_SMP
-       void                    (*init_cpu_smp)(unsigned int);
+       void                    (*init_per_cpu)(unsigned int);
 #endif
        void                    (*init_machine)(void);
        void                    (*init_late)(void);
index 133c867d15af0a627576d9faf89c0569220a6f47..991380438d6bfd6af03e6fff4748b8c5342b6a70 100644 (file)
@@ -48,7 +48,7 @@ extern int smp_ipi_irq_setup(int cpu, int irq);
  * @init_early_smp:    A SMP specific h/w block can init itself
  *                     Could be common across platforms so not covered by
  *                     mach_desc->init_early()
- * @init_irq_cpu:      Called for each core so SMP h/w block driver can do
+ * @init_per_cpu:      Called for each core so SMP h/w block driver can do
  *                     any needed setup per cpu (e.g. IPI request)
  * @cpu_kick:          For Master to kickstart a cpu (optionally at a PC)
  * @ipi_send:          To send IPI to a @cpu
@@ -57,7 +57,7 @@ extern int smp_ipi_irq_setup(int cpu, int irq);
 struct plat_smp_ops {
        const char      *info;
        void            (*init_early_smp)(void);
-       void            (*init_irq_cpu)(int cpu);
+       void            (*init_per_cpu)(int cpu);
        void            (*cpu_kick)(int cpu, unsigned long pc);
        void            (*ipi_send)(int cpu);
        void            (*ipi_clear)(int irq);
index 7ca628b6ee2aa6d1e02f6ad01363990439ec10b7..c11a25bb8158dee7f60a5f00ca8ec0addaf54b56 100644 (file)
@@ -112,7 +112,6 @@ struct unwind_frame_info {
 
 extern int arc_unwind(struct unwind_frame_info *frame);
 extern void arc_unwind_init(void);
-extern void arc_unwind_setup(void);
 extern void *unwind_add_table(struct module *module, const void *table_start,
                              unsigned long table_size);
 extern void unwind_remove_table(void *handle, int init_only);
@@ -152,9 +151,6 @@ static inline void arc_unwind_init(void)
 {
 }
 
-static inline void arc_unwind_setup(void)
-{
-}
 #define unwind_add_table(a, b, c)
 #define unwind_remove_table(a, b)
 
index 26c15682747960d3b5b1c412f76dff3c2ebc7780..0394f9f61b466dea018af3ec371c65a8dbc17acb 100644 (file)
@@ -106,10 +106,21 @@ static struct irq_chip arcv2_irq_chip = {
 static int arcv2_irq_map(struct irq_domain *d, unsigned int irq,
                         irq_hw_number_t hw)
 {
-       if (irq == TIMER0_IRQ || irq == IPI_IRQ)
+       /*
+        * core intc IRQs [16, 23]:
+        * Statically assigned always private-per-core (Timers, WDT, IPI, PCT)
+        */
+       if (hw < 24) {
+               /*
+                * A subsequent request_percpu_irq() fails if percpu_devid is
+                * not set. That in turns sets NOAUTOEN, meaning each core needs
+                * to call enable_percpu_irq()
+                */
+               irq_set_percpu_devid(irq);
                irq_set_chip_and_handler(irq, &arcv2_irq_chip, handle_percpu_irq);
-       else
+       } else {
                irq_set_chip_and_handler(irq, &arcv2_irq_chip, handle_level_irq);
+       }
 
        return 0;
 }
index 2ee226546c6a821f739a079326ed92ad52fe16b8..ba17f85285cfe85c53ba6c93db08d620c7109fb9 100644 (file)
@@ -29,11 +29,11 @@ void __init init_IRQ(void)
 
 #ifdef CONFIG_SMP
        /* a SMP H/w block could do IPI IRQ request here */
-       if (plat_smp_ops.init_irq_cpu)
-               plat_smp_ops.init_irq_cpu(smp_processor_id());
+       if (plat_smp_ops.init_per_cpu)
+               plat_smp_ops.init_per_cpu(smp_processor_id());
 
-       if (machine_desc->init_cpu_smp)
-               machine_desc->init_cpu_smp(smp_processor_id());
+       if (machine_desc->init_per_cpu)
+               machine_desc->init_per_cpu(smp_processor_id());
 #endif
 }
 
@@ -51,6 +51,18 @@ void arch_do_IRQ(unsigned int irq, struct pt_regs *regs)
        set_irq_regs(old_regs);
 }
 
+/*
+ * API called for requesting percpu interrupts - called by each CPU
+ *  - For boot CPU, actually request the IRQ with genirq core + enables
+ *  - For subsequent callers only enable called locally
+ *
+ * Relies on being called by boot cpu first (i.e. request called ahead) of
+ * any enable as expected by genirq. Hence Suitable only for TIMER, IPI
+ * which are guaranteed to be setup on boot core first.
+ * Late probed peripherals such as perf can't use this as there no guarantee
+ * of being called on boot CPU first.
+ */
+
 void arc_request_percpu_irq(int irq, int cpu,
                             irqreturn_t (*isr)(int irq, void *dev),
                             const char *irq_nm,
@@ -60,14 +72,17 @@ void arc_request_percpu_irq(int irq, int cpu,
        if (!cpu) {
                int rc;
 
+#ifdef CONFIG_ISA_ARCOMPACT
                /*
-                * These 2 calls are essential to making percpu IRQ APIs work
-                * Ideally these details could be hidden in irq chip map function
-                * but the issue is IPIs IRQs being static (non-DT) and platform
-                * specific, so we can't identify them there.
+                * A subsequent request_percpu_irq() fails if percpu_devid is
+                * not set. That in turns sets NOAUTOEN, meaning each core needs
+                * to call enable_percpu_irq()
+                *
+                * For ARCv2, this is done in irq map function since we know
+                * which irqs are strictly per cpu
                 */
                irq_set_percpu_devid(irq);
-               irq_modify_status(irq, IRQ_NOAUTOEN, 0);  /* @irq, @clr, @set */
+#endif
 
                rc = request_percpu_irq(irq, isr, irq_nm, percpu_dev);
                if (rc)
index 74a9b074ac3e4e64d97ef8e069f73a9104531682..bd237acdf4f2f9601efbf4c25c45067ddd2b69d9 100644 (file)
@@ -132,7 +132,7 @@ static void mcip_probe_n_setup(void)
 struct plat_smp_ops plat_smp_ops = {
        .info           = smp_cpuinfo_buf,
        .init_early_smp = mcip_probe_n_setup,
-       .init_irq_cpu   = mcip_setup_per_cpu,
+       .init_per_cpu   = mcip_setup_per_cpu,
        .ipi_send       = mcip_ipi_send,
        .ipi_clear      = mcip_ipi_clear,
 };
index 0c08bb1ce15aab114c344609879eaa86bfa59a9d..8b134cfe5e1f11023b559639497f7e1a35d2ee79 100644 (file)
@@ -428,12 +428,11 @@ static irqreturn_t arc_pmu_intr(int irq, void *dev)
 
 #endif /* CONFIG_ISA_ARCV2 */
 
-void arc_cpu_pmu_irq_init(void)
+static void arc_cpu_pmu_irq_init(void *data)
 {
-       struct arc_pmu_cpu *pmu_cpu = this_cpu_ptr(&arc_pmu_cpu);
+       int irq = *(int *)data;
 
-       arc_request_percpu_irq(arc_pmu->irq, smp_processor_id(), arc_pmu_intr,
-                              "ARC perf counters", pmu_cpu);
+       enable_percpu_irq(irq, IRQ_TYPE_NONE);
 
        /* Clear all pending interrupt flags */
        write_aux_reg(ARC_REG_PCT_INT_ACT, 0xffffffff);
@@ -515,7 +514,6 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
 
        if (has_interrupts) {
                int irq = platform_get_irq(pdev, 0);
-               unsigned long flags;
 
                if (irq < 0) {
                        pr_err("Cannot get IRQ number for the platform\n");
@@ -524,24 +522,12 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
 
                arc_pmu->irq = irq;
 
-               /*
-                * arc_cpu_pmu_irq_init() needs to be called on all cores for
-                * their respective local PMU.
-                * However we use opencoded on_each_cpu() to ensure it is called
-                * on core0 first, so that arc_request_percpu_irq() sets up
-                * AUTOEN etc. Otherwise enable_percpu_irq() fails to enable
-                * perf IRQ on non master cores.
-                * see arc_request_percpu_irq()
-                */
-               preempt_disable();
-               local_irq_save(flags);
-               arc_cpu_pmu_irq_init();
-               local_irq_restore(flags);
-               smp_call_function((smp_call_func_t)arc_cpu_pmu_irq_init, 0, 1);
-               preempt_enable();
-
-               /* Clean all pending interrupt flags */
-               write_aux_reg(ARC_REG_PCT_INT_ACT, 0xffffffff);
+               /* intc map function ensures irq_set_percpu_devid() called */
+               request_percpu_irq(irq, arc_pmu_intr, "ARC perf counters",
+                                  this_cpu_ptr(&arc_pmu_cpu));
+
+               on_each_cpu(arc_cpu_pmu_irq_init, &irq, 1);
+
        } else
                arc_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
 
index c33e77c0ad3e9eb60367b6c2510c4e35c60d3b52..e1b87444ea9a0740b9651ad6b68fd39f701121a0 100644 (file)
@@ -429,7 +429,6 @@ void __init setup_arch(char **cmdline_p)
 #endif
 
        arc_unwind_init();
-       arc_unwind_setup();
 }
 
 static int __init customize_machine(void)
index 580587805fa302d0d28f7adc89434b920b3be651..ef6e9e15b82abf72d946ab45c3e20096854605c5 100644 (file)
@@ -132,11 +132,11 @@ void start_kernel_secondary(void)
        pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu);
 
        /* Some SMP H/w setup - for each cpu */
-       if (plat_smp_ops.init_irq_cpu)
-               plat_smp_ops.init_irq_cpu(cpu);
+       if (plat_smp_ops.init_per_cpu)
+               plat_smp_ops.init_per_cpu(cpu);
 
-       if (machine_desc->init_cpu_smp)
-               machine_desc->init_cpu_smp(cpu);
+       if (machine_desc->init_per_cpu)
+               machine_desc->init_per_cpu(cpu);
 
        arc_local_timer_setup();
 
index 7352475451f6c3798885c97b04c11ddd53146990..5eb707640e9c48c9939c3fcfd0022f8cfc897684 100644 (file)
@@ -170,6 +170,23 @@ static struct unwind_table *find_table(unsigned long pc)
 
 static unsigned long read_pointer(const u8 **pLoc,
                                  const void *end, signed ptrType);
+static void init_unwind_hdr(struct unwind_table *table,
+                           void *(*alloc) (unsigned long));
+
+/*
+ * wrappers for header alloc (vs. calling one vs. other at call site)
+ * to elide section mismatches warnings
+ */
+static void *__init unw_hdr_alloc_early(unsigned long sz)
+{
+       return __alloc_bootmem_nopanic(sz, sizeof(unsigned int),
+                                      MAX_DMA_ADDRESS);
+}
+
+static void *unw_hdr_alloc(unsigned long sz)
+{
+       return kmalloc(sz, GFP_KERNEL);
+}
 
 static void init_unwind_table(struct unwind_table *table, const char *name,
                              const void *core_start, unsigned long core_size,
@@ -209,6 +226,8 @@ void __init arc_unwind_init(void)
                          __start_unwind, __end_unwind - __start_unwind,
                          NULL, 0);
          /*__start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr);*/
+
+       init_unwind_hdr(&root_table, unw_hdr_alloc_early);
 }
 
 static const u32 bad_cie, not_fde;
@@ -241,8 +260,8 @@ static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size)
        e2->fde = v;
 }
 
-static void __init setup_unwind_table(struct unwind_table *table,
-                                     void *(*alloc) (unsigned long))
+static void init_unwind_hdr(struct unwind_table *table,
+                           void *(*alloc) (unsigned long))
 {
        const u8 *ptr;
        unsigned long tableSize = table->size, hdrSize;
@@ -277,10 +296,10 @@ static void __init setup_unwind_table(struct unwind_table *table,
                if (cie == &not_fde)
                        continue;
                if (cie == NULL || cie == &bad_cie)
-                       return;
+                       goto ret_err;
                ptrType = fde_pointer_type(cie);
                if (ptrType < 0)
-                       return;
+                       goto ret_err;
 
                ptr = (const u8 *)(fde + 2);
                if (!read_pointer(&ptr, (const u8 *)(fde + 1) + *fde,
@@ -296,13 +315,15 @@ static void __init setup_unwind_table(struct unwind_table *table,
        }
 
        if (tableSize || !n)
-               return;
+               goto ret_err;
 
        hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int)
            + 2 * n * sizeof(unsigned long);
+
        header = alloc(hdrSize);
        if (!header)
-               return;
+               goto ret_err;
+
        header->version = 1;
        header->eh_frame_ptr_enc = DW_EH_PE_abs | DW_EH_PE_native;
        header->fde_count_enc = DW_EH_PE_abs | DW_EH_PE_data4;
@@ -340,18 +361,10 @@ static void __init setup_unwind_table(struct unwind_table *table,
        table->hdrsz = hdrSize;
        smp_wmb();
        table->header = (const void *)header;
-}
-
-static void *__init balloc(unsigned long sz)
-{
-       return __alloc_bootmem_nopanic(sz,
-                                      sizeof(unsigned int),
-                                      __pa(MAX_DMA_ADDRESS));
-}
+       return;
 
-void __init arc_unwind_setup(void)
-{
-       setup_unwind_table(&root_table, balloc);
+ret_err:
+       panic("Attention !!! Dwarf FDE parsing errors\n");;
 }
 
 #ifdef CONFIG_MODULES
@@ -377,6 +390,8 @@ void *unwind_add_table(struct module *module, const void *table_start,
                          table_start, table_size,
                          NULL, 0);
 
+       init_unwind_hdr(table, unw_hdr_alloc);
+
 #ifdef UNWIND_DEBUG
        unw_debug("Table added for [%s] %lx %lx\n",
                module->name, table->core.pc, table->core.range);
@@ -439,6 +454,7 @@ void unwind_remove_table(void *handle, int init_only)
        info.init_only = init_only;
 
        unlink_table(&info); /* XXX: SMP */
+       kfree(table->header);
        kfree(table);
 }
 
@@ -588,9 +604,6 @@ static signed fde_pointer_type(const u32 *cie)
        const u8 *ptr = (const u8 *)(cie + 2);
        unsigned version = *ptr;
 
-       if (version != 1)
-               return -1;      /* unsupported */
-
        if (*++ptr) {
                const char *aug;
                const u8 *end = (const u8 *)(cie + 1) + *cie;
@@ -1002,9 +1015,7 @@ int arc_unwind(struct unwind_frame_info *frame)
                ptr = (const u8 *)(cie + 2);
                end = (const u8 *)(cie + 1) + *cie;
                frame->call_frame = 1;
-               if ((state.version = *ptr) != 1)
-                       cie = NULL;     /* unsupported version */
-               else if (*++ptr) {
+               if (*++ptr) {
                        /* check if augmentation size is first (thus present) */
                        if (*ptr == 'z') {
                                while (++ptr < end && *ptr) {
index 065ee6bfa82a2463ee60c790f08c5b60382715f3..92dd92cad7f92db32f9ecc1b73992e1ea0a5f74d 100644 (file)
@@ -111,7 +111,7 @@ void __kunmap_atomic(void *kv)
 }
 EXPORT_SYMBOL(__kunmap_atomic);
 
-noinline pte_t *alloc_kmap_pgtable(unsigned long kvaddr)
+static noinline pte_t * __init alloc_kmap_pgtable(unsigned long kvaddr)
 {
        pgd_t *pgd_k;
        pud_t *pud_k;
@@ -127,7 +127,7 @@ noinline pte_t *alloc_kmap_pgtable(unsigned long kvaddr)
        return pte_k;
 }
 
-void kmap_init(void)
+void __init kmap_init(void)
 {
        /* Due to recursive include hell, we can't do this in processor.h */
        BUILD_BUG_ON(PAGE_OFFSET < (VMALLOC_END + FIXMAP_SIZE + PKMAP_SIZE));
index a9305b5a2cd4ba091f7ae18914f6ef5e64d5236c..7d2c4fbf4f22eb1402bc666c077c652c40f38361 100644 (file)
@@ -51,7 +51,9 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size)
        int in_use = 0;
 
        if (!low_mem_sz) {
-               BUG_ON(base != low_mem_start);
+               if (base != low_mem_start)
+                       panic("CONFIG_LINUX_LINK_BASE != DT memory { }");
+
                low_mem_sz = size;
                in_use = 1;
        } else {
index d83ff9c9701e36d5d837c87ce292d89c421c4a70..de8791a4d1311883577f51e243769a3c6906a61a 100644 (file)
@@ -74,7 +74,7 @@
                reg = <0x48240200 0x100>;
                interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>;
                interrupt-parent = <&gic>;
-               clocks = <&dpll_mpu_m2_ck>;
+               clocks = <&mpu_periphclk>;
        };
 
        local_timer: timer@48240600 {
@@ -82,7 +82,7 @@
                reg = <0x48240600 0x100>;
                interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>;
                interrupt-parent = <&gic>;
-               clocks = <&dpll_mpu_m2_ck>;
+               clocks = <&mpu_periphclk>;
        };
 
        l2-cache-controller@48242000 {
index cc88728d751de587bcb86abbe179921c493779e9..a38af2bfbfcfbd51f223409e48231d04e73cd7e5 100644 (file)
                ti,invert-autoidle-bit;
        };
 
+       mpu_periphclk: mpu_periphclk {
+               #clock-cells = <0>;
+               compatible = "fixed-factor-clock";
+               clocks = <&dpll_mpu_m2_ck>;
+               clock-mult = <1>;
+               clock-div = <2>;
+       };
+
        dpll_ddr_ck: dpll_ddr_ck {
                #clock-cells = <0>;
                compatible = "ti,am3-dpll-clock";
index ad6de73ed5a5fd2f6b1cd7c19e325d60c21537c9..e74df327cdd3b8d5776cb5d6deb269042f463bdb 100644 (file)
                                                        regulator-name = "VDD_SDHC_1V8";
                                                        regulator-min-microvolt = <1800000>;
                                                        regulator-max-microvolt = <1800000>;
+                                                       regulator-always-on;
                                                };
                                        };
                                };
index 8ea177f375ddd652c98339ac2cc8ef8935396442..fb1da99996ea43f9c3492591e9faf800030d5989 100644 (file)
                sdhci0: sdhci@ab0000 {
                        compatible = "mrvl,pxav3-mmc";
                        reg = <0xab0000 0x200>;
-                       clocks = <&chip_clk CLKID_SDIO1XIN>;
+                       clocks = <&chip_clk CLKID_SDIO1XIN>, <&chip_clk CLKID_SDIO>;
+                       clock-names = "io", "core";
                        interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
                        status = "disabled";
                };
                sdhci1: sdhci@ab0800 {
                        compatible = "mrvl,pxav3-mmc";
                        reg = <0xab0800 0x200>;
-                       clocks = <&chip_clk CLKID_SDIO1XIN>;
+                       clocks = <&chip_clk CLKID_SDIO1XIN>, <&chip_clk CLKID_SDIO>;
+                       clock-names = "io", "core";
                        interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
                        status = "disabled";
                };
                        compatible = "mrvl,pxav3-mmc";
                        reg = <0xab1000 0x200>;
                        interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&chip_clk CLKID_NFC_ECC>, <&chip_clk CLKID_NFC>;
+                       clocks = <&chip_clk CLKID_NFC_ECC>, <&chip_clk CLKID_SDIO>;
                        clock-names = "io", "core";
                        status = "disabled";
                };
index 3c99cfa1a8761604a409b9d0525f143c494571b0..eee636de4cd844237f5490b71c5f00d56dd9f06c 100644 (file)
                        reg = <0x480c8000 0x2000>;
                        interrupts = <77>;
                        ti,hwmods = "mailbox";
+                       #mbox-cells = <1>;
                        ti,mbox-num-users = <4>;
                        ti,mbox-num-fifos = <12>;
                        mbox_dsp: mbox_dsp {
                        ti,spi-num-cs = <4>;
                        ti,hwmods = "mcspi1";
                        dmas = <&edma 16 &edma 17
-                               &edma 18 &edma 19>;
-                       dma-names = "tx0", "rx0", "tx1", "rx1";
+                               &edma 18 &edma 19
+                               &edma 20 &edma 21
+                               &edma 22 &edma 23>;
+                       dma-names = "tx0", "rx0", "tx1", "rx1",
+                                   "tx2", "rx2", "tx3", "rx3";
                };
 
                mmc1: mmc@48060000 {
index 58adf176425a69fc48d16731973f93827b080bab..a51834e1dd2789ed0bfeed69b2dbddc08aa946fc 100644 (file)
 &fec {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-reset-gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>;
        status = "okay";
 };
index 7b31fdb79ced5cbac2eecff792fa8d56b1a9a010..dc0cebfe22d7b9a8f0500e1313c67ede2718234d 100644 (file)
@@ -94,7 +94,7 @@
 &fec {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-reset-gpios = <&gpio1 30 GPIO_ACTIVE_LOW>;
        status = "okay";
 };
index 1b66328a84987a1040b0406e1b4dfe29a87707ed..18cd4114a23e85a82f724c3b8773c04399826129 100644 (file)
 &fec {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-reset-gpios = <&gpio1 30 GPIO_ACTIVE_LOW>;
        status = "okay";
 };
index 7c51839ff93467d209e0f3809b3ed9e8bc541c54..eea90f37bbb8c236ebc97e2e1c90b439e4aed2ed 100644 (file)
 &fec {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-reset-gpios = <&gpio1 30 GPIO_ACTIVE_LOW>;
        status = "okay";
 };
index 929e0b37bd9e542e252be1159e6e588dd34b94e1..6c11a2ae35ef98b0f2adcb218d20543cead8f399 100644 (file)
 &fec {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_enet>;
-       phy-mode = "rgmii";
+       phy-mode = "rgmii-id";
        phy-reset-gpios = <&gpio1 30 GPIO_ACTIVE_LOW>;
        status = "okay";
 };
index 8263fc18a7d95ff88b470ae57fd5e2e89036f99f..d354d406954da437071db41de61e349a48644802 100644 (file)
 &clks {
        assigned-clocks = <&clks IMX6QDL_PLL4_BYPASS_SRC>,
                          <&clks IMX6QDL_PLL4_BYPASS>,
-                         <&clks IMX6QDL_CLK_PLL4_POST_DIV>,
                          <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
-                         <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
+                         <&clks IMX6QDL_CLK_LDB_DI1_SEL>,
+                         <&clks IMX6QDL_CLK_PLL4_POST_DIV>;
        assigned-clock-parents = <&clks IMX6QDL_CLK_LVDS2_IN>,
                                 <&clks IMX6QDL_PLL4_BYPASS_SRC>,
                                 <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
                                 <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
-       assigned-clock-rates = <0>, <0>, <24576000>;
+       assigned-clock-rates = <0>, <0>, <0>, <0>, <24576000>;
 };
 
 &ecspi1 {
index 1a78f013f37ab8e2ee4de5361dc16bdeec2b2516..b75f7b2b7c4ac9e0aca7c4c44e3f1b8e2bd09c28 100644 (file)
        };
 };
 
+&uart3 {
+       interrupts-extended = <&wakeupgen GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH
+                              &omap4_pmx_core OMAP4_UART3_RX>;
+};
index 314f59c121620868fae063a8c9fc13d323b5400b..d0c74385331803383d5296d7157516aa63c63758 100644 (file)
@@ -25,9 +25,9 @@
                cache-sets = <512>;
                cache-line-size = <32>;
                /* At full speed latency must be >=2 */
-               arm,tag-latency = <2>;
-               arm,data-latency = <2 2>;
-               arm,dirty-latency = <2>;
+               arm,tag-latency = <8>;
+               arm,data-latency = <8 8>;
+               arm,dirty-latency = <8>;
        };
 
        mtu0: mtu@101e2000 {
index 2d4250b1faf80040e3e6c3477fe64b7431141627..68b479b8772c6f3eadc16f2ad6c3d33e35d39c5f 100644 (file)
@@ -83,6 +83,7 @@
                reg = <0x5d>;
                interrupt-parent = <&pio>;
                interrupts = <0 3 IRQ_TYPE_LEVEL_HIGH>; /* PA3 */
+               touchscreen-swapped-x-y;
        };
 };
 
index 40c23a0b7cfc2adf8517e28ac51b0078423a0c61..ec1aa64ded681a1a4f834343b3fc45d0c4946819 100644 (file)
 
        /* CPU DFLL clock */
        clock@0,70110000 {
-               status = "okay";
+               status = "disabled";
                vdd-cpu-supply = <&vdd_cpu>;
                nvidia,i2c-fs-rate = <400000>;
        };
index 01f40197ea13c4cc03691ef65a18c7ee20eb1990..3279bf1a17a123ac26448eaf4b9055884793eca4 100644 (file)
                        interrupt-parent = <&vic>;
                        interrupts = <31>; /* Cascaded to vic */
                        clear-mask = <0xffffffff>;
-                       valid-mask = <0xffc203f8>;
+                       /*
+                        * Valid interrupt lines mask according to
+                        * table 4-36 page 4-50 of ARM DUI 0225D
+                        */
+                       valid-mask = <0x0760031b>;
                };
 
                dma@10130000 {
                        };
                        mmc@5000 {
                                compatible = "arm,pl180", "arm,primecell";
-                               reg = < 0x5000 0x1000>;
-                               interrupts-extended = <&vic 22 &sic 2>;
+                               reg = <0x5000 0x1000>;
+                               interrupts-extended = <&vic 22 &sic 1>;
                                clocks = <&xtal24mhz>, <&pclk>;
                                clock-names = "mclk", "apb_pclk";
                        };
index b83137f66034016d2580dfaeaf63b162cc0ab5c4..33a8eb28374eaa8d3b8aca95d8801227bedd87ca 100644 (file)
@@ -5,6 +5,16 @@
        compatible = "arm,versatile-pb";
 
        amba {
+               /* The Versatile PB is using more SIC IRQ lines than the AB */
+               sic: intc@10003000 {
+                       clear-mask = <0xffffffff>;
+                       /*
+                        * Valid interrupt lines mask according to
+                        * figure 3-30 page 3-74 of ARM DUI 0224B
+                        */
+                       valid-mask = <0x7fe003ff>;
+               };
+
                gpio2: gpio@101e6000 {
                        compatible = "arm,pl061", "arm,primecell";
                        reg = <0x101e6000 0x1000>;
                };
 
                fpga {
+                       mmc@5000 {
+                               /*
+                                * Overrides the interrupt assignment from
+                                * the Versatile AB board file.
+                                */
+                               interrupts-extended = <&sic 22 &sic 23>;
+                       };
                        uart@9000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0x9000 0x1000>;
                        mmc@b000 {
                                compatible = "arm,pl180", "arm,primecell";
                                reg = <0xb000 0x1000>;
-                               interrupts-extended = <&vic 23 &sic 2>;
+                               interrupt-parent = <&sic>;
+                               interrupts = <1>, <2>;
                                clocks = <&xtal24mhz>, <&pclk>;
                                clock-names = "mclk", "apb_pclk";
                        };
index 19fe045b83342a6ee0f55a02b1490c291b9537dd..2d7eab7552100225efcf2cb5d52a5443459f6a58 100644 (file)
@@ -18,8 +18,3 @@
                reg = <0x80000000 0x10000000>;
        };
 };
-
-&L2 {
-       arm,data-latency = <2 1 2>;
-       arm,tag-latency = <3 2 3>;
-};
index 5f8eb1bd782bf01a6454aa7cb63682835c179650..58bc6e448be5601ed8d04106fbcc193793f040f1 100644 (file)
@@ -19,7 +19,7 @@
                reg = <0x40006000 0x1000>;
                cache-unified;
                cache-level = <2>;
-               arm,data-latency = <1 1 1>;
+               arm,data-latency = <3 3 3>;
                arm,tag-latency = <2 2 2>;
        };
 };
index 0d5acc2cdc8ef93008fc308ac8f3c9c8c1813771..3cd1b27f269780b99d1dbc4af64644bcaa45cce5 100644 (file)
                                compatible = "fsl,vf610-sai";
                                reg = <0x40031000 0x1000>;
                                interrupts = <86 IRQ_TYPE_LEVEL_HIGH>;
-                               clocks = <&clks VF610_CLK_SAI2>;
-                               clock-names = "sai";
+                               clocks = <&clks VF610_CLK_SAI2>,
+                                       <&clks VF610_CLK_SAI2_DIV>,
+                                       <&clks 0>, <&clks 0>;
+                               clock-names = "bus", "mclk1", "mclk2", "mclk3";
                                dma-names = "tx", "rx";
                                dmas = <&edma0 0 21>,
                                        <&edma0 0 20>;
index b1c59a766a13381a693d897eb3349db4ac9d3c16..e12213d16693b890d0440e2da264a25b591e789a 100644 (file)
                        interrupts = <43>;
                };
 
+               sdhc@d800a000 {
+                       compatible = "wm,wm8505-sdhc";
+                       reg = <0xd800a000 0x400>;
+                       interrupts = <20>, <21>;
+                       clocks = <&clksdhc>;
+                       bus-width = <4>;
+                       sdon-inverted;
+               };
+
                fb: fb@d8050800 {
                        compatible = "wm,wm8505-fb";
                        reg = <0xd8050800 0x200>;
index 69a22fdb52a5a49ecb26760ed4163989e2f735e4..cd7b198fc79e220a1a082ada1889f919751a123f 100644 (file)
@@ -366,6 +366,7 @@ CONFIG_BATTERY_MAX17042=m
 CONFIG_CHARGER_MAX14577=m
 CONFIG_CHARGER_MAX77693=m
 CONFIG_CHARGER_TPS65090=y
+CONFIG_AXP20X_POWER=m
 CONFIG_POWER_RESET_AS3722=y
 CONFIG_POWER_RESET_GPIO=y
 CONFIG_POWER_RESET_GPIO_RESTART=y
index 3c36e16fcacf7d44f7e8ce76f32a2cbc20f2b1d4..b503a89441bf25ce5cda365a17cb7a172c28b4e2 100644 (file)
@@ -84,6 +84,7 @@ CONFIG_SPI_SUN4I=y
 CONFIG_SPI_SUN6I=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_POWER_SUPPLY=y
+CONFIG_AXP20X_POWER=y
 CONFIG_THERMAL=y
 CONFIG_CPU_THERMAL=y
 CONFIG_WATCHDOG=y
index 6607d976e07d0998639457745ca364cf1305da85..7da5503c0591411f43df6bc767fb8c4eef314789 100644 (file)
@@ -21,6 +21,7 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/io.h>
+#include <asm/barrier.h>
 
 #define __ACCESS_CP15(CRn, Op1, CRm, Op2)      p15, Op1, %0, CRn, CRm, Op2
 #define __ACCESS_CP15_64(Op1, CRm)             p15, Op1, %Q0, %R0, CRm
index 8cc85a4ebec20a1223f966bb868e5def5f70928e..35c9db857ebe9c7d53715ec42518a6e9fbe1dc6e 100644 (file)
@@ -510,10 +510,14 @@ __copy_to_user_std(void __user *to, const void *from, unsigned long n);
 static inline unsigned long __must_check
 __copy_to_user(void __user *to, const void *from, unsigned long n)
 {
+#ifndef CONFIG_UACCESS_WITH_MEMCPY
        unsigned int __ua_flags = uaccess_save_and_enable();
        n = arm_copy_to_user(to, from, n);
        uaccess_restore(__ua_flags);
        return n;
+#else
+       return arm_copy_to_user(to, from, n);
+#endif
 }
 
 extern unsigned long __must_check
index 7a7c4cea55231b1c793982ab63d6c5598004b14b..4adfb46e3ee93276ea506b723eb11e33c57459f4 100644 (file)
@@ -95,6 +95,22 @@ void __show_regs(struct pt_regs *regs)
 {
        unsigned long flags;
        char buf[64];
+#ifndef CONFIG_CPU_V7M
+       unsigned int domain;
+#ifdef CONFIG_CPU_SW_DOMAIN_PAN
+       /*
+        * Get the domain register for the parent context. In user
+        * mode, we don't save the DACR, so lets use what it should
+        * be. For other modes, we place it after the pt_regs struct.
+        */
+       if (user_mode(regs))
+               domain = DACR_UACCESS_ENABLE;
+       else
+               domain = *(unsigned int *)(regs + 1);
+#else
+       domain = get_domain();
+#endif
+#endif
 
        show_regs_print_info(KERN_DEFAULT);
 
@@ -123,21 +139,8 @@ void __show_regs(struct pt_regs *regs)
 
 #ifndef CONFIG_CPU_V7M
        {
-               unsigned int domain = get_domain();
                const char *segment;
 
-#ifdef CONFIG_CPU_SW_DOMAIN_PAN
-               /*
-                * Get the domain register for the parent context. In user
-                * mode, we don't save the DACR, so lets use what it should
-                * be. For other modes, we place it after the pt_regs struct.
-                */
-               if (user_mode(regs))
-                       domain = DACR_UACCESS_ENABLE;
-               else
-                       domain = *(unsigned int *)(regs + 1);
-#endif
-
                if ((domain & domain_mask(DOMAIN_USER)) ==
                    domain_val(DOMAIN_USER, DOMAIN_NOACCESS))
                        segment = "none";
@@ -163,11 +166,11 @@ void __show_regs(struct pt_regs *regs)
                buf[0] = '\0';
 #ifdef CONFIG_CPU_CP15_MMU
                {
-                       unsigned int transbase, dac = get_domain();
+                       unsigned int transbase;
                        asm("mrc p15, 0, %0, c2, c0\n\t"
                            : "=r" (transbase));
                        snprintf(buf, sizeof(buf), "  Table: %08x  DAC: %08x",
-                               transbase, dac);
+                               transbase, domain);
                }
 #endif
                asm("mrc p15, 0, %0, c1, c0\n" : "=r" (ctrl));
index 5b26e7efa9ea415967b63ede27ab1edf2bc8e888..c3fe769d75584c7248015b855bca904589f3e29f 100644 (file)
  */
 #define __user_swpX_asm(data, addr, res, temp, B)              \
        __asm__ __volatile__(                                   \
-       "       mov             %2, %1\n"                       \
-       "0:     ldrex"B"        %1, [%3]\n"                     \
-       "1:     strex"B"        %0, %2, [%3]\n"                 \
+       "0:     ldrex"B"        %2, [%3]\n"                     \
+       "1:     strex"B"        %0, %1, [%3]\n"                 \
        "       cmp             %0, #0\n"                       \
+       "       moveq           %1, %2\n"                       \
        "       movne           %0, %4\n"                       \
        "2:\n"                                                  \
        "       .section         .text.fixup,\"ax\"\n"          \
index b83f3b7737fb9dce2a18c66a086aac2430e98cf6..087acb569b63a4bd90982e0c9b15fc2313636c53 100644 (file)
@@ -193,15 +193,44 @@ struct oabi_flock64 {
        pid_t   l_pid;
 } __attribute__ ((packed,aligned(4)));
 
-asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd,
+static long do_locks(unsigned int fd, unsigned int cmd,
                                 unsigned long arg)
 {
-       struct oabi_flock64 user;
        struct flock64 kernel;
-       mm_segment_t fs = USER_DS; /* initialized to kill a warning */
-       unsigned long local_arg = arg;
-       int ret;
+       struct oabi_flock64 user;
+       mm_segment_t fs;
+       long ret;
+
+       if (copy_from_user(&user, (struct oabi_flock64 __user *)arg,
+                          sizeof(user)))
+               return -EFAULT;
+       kernel.l_type   = user.l_type;
+       kernel.l_whence = user.l_whence;
+       kernel.l_start  = user.l_start;
+       kernel.l_len    = user.l_len;
+       kernel.l_pid    = user.l_pid;
+
+       fs = get_fs();
+       set_fs(KERNEL_DS);
+       ret = sys_fcntl64(fd, cmd, (unsigned long)&kernel);
+       set_fs(fs);
+
+       if (!ret && (cmd == F_GETLK64 || cmd == F_OFD_GETLK)) {
+               user.l_type     = kernel.l_type;
+               user.l_whence   = kernel.l_whence;
+               user.l_start    = kernel.l_start;
+               user.l_len      = kernel.l_len;
+               user.l_pid      = kernel.l_pid;
+               if (copy_to_user((struct oabi_flock64 __user *)arg,
+                                &user, sizeof(user)))
+                       ret = -EFAULT;
+       }
+       return ret;
+}
 
+asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd,
+                                unsigned long arg)
+{
        switch (cmd) {
        case F_OFD_GETLK:
        case F_OFD_SETLK:
@@ -209,39 +238,11 @@ asmlinkage long sys_oabi_fcntl64(unsigned int fd, unsigned int cmd,
        case F_GETLK64:
        case F_SETLK64:
        case F_SETLKW64:
-               if (copy_from_user(&user, (struct oabi_flock64 __user *)arg,
-                                  sizeof(user)))
-                       return -EFAULT;
-               kernel.l_type   = user.l_type;
-               kernel.l_whence = user.l_whence;
-               kernel.l_start  = user.l_start;
-               kernel.l_len    = user.l_len;
-               kernel.l_pid    = user.l_pid;
-               local_arg = (unsigned long)&kernel;
-               fs = get_fs();
-               set_fs(KERNEL_DS);
-       }
-
-       ret = sys_fcntl64(fd, cmd, local_arg);
+               return do_locks(fd, cmd, arg);
 
-       switch (cmd) {
-       case F_GETLK64:
-               if (!ret) {
-                       user.l_type     = kernel.l_type;
-                       user.l_whence   = kernel.l_whence;
-                       user.l_start    = kernel.l_start;
-                       user.l_len      = kernel.l_len;
-                       user.l_pid      = kernel.l_pid;
-                       if (copy_to_user((struct oabi_flock64 __user *)arg,
-                                        &user, sizeof(user)))
-                               ret = -EFAULT;
-               }
-       case F_SETLK64:
-       case F_SETLKW64:
-               set_fs(fs);
+       default:
+               return sys_fcntl64(fd, cmd, arg);
        }
-
-       return ret;
 }
 
 struct oabi_epoll_event {
index d72b90905132487257220939a255ac7ed1d3754d..588bbc288396ae52fe0d801bc537906b3e5dbfce 100644 (file)
@@ -88,6 +88,7 @@ pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp)
 static unsigned long noinline
 __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
 {
+       unsigned long ua_flags;
        int atomic;
 
        if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
@@ -118,7 +119,9 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
                if (tocopy > n)
                        tocopy = n;
 
+               ua_flags = uaccess_save_and_enable();
                memcpy((void *)to, from, tocopy);
+               uaccess_restore(ua_flags);
                to += tocopy;
                from += tocopy;
                n -= tocopy;
@@ -145,14 +148,21 @@ arm_copy_to_user(void __user *to, const void *from, unsigned long n)
         * With frame pointer disabled, tail call optimization kicks in
         * as well making this test almost invisible.
         */
-       if (n < 64)
-               return __copy_to_user_std(to, from, n);
-       return __copy_to_user_memcpy(to, from, n);
+       if (n < 64) {
+               unsigned long ua_flags = uaccess_save_and_enable();
+               n = __copy_to_user_std(to, from, n);
+               uaccess_restore(ua_flags);
+       } else {
+               n = __copy_to_user_memcpy(to, from, n);
+       }
+       return n;
 }
        
 static unsigned long noinline
 __clear_user_memset(void __user *addr, unsigned long n)
 {
+       unsigned long ua_flags;
+
        if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
                memset((void *)addr, 0, n);
                return 0;
@@ -175,7 +185,9 @@ __clear_user_memset(void __user *addr, unsigned long n)
                if (tocopy > n)
                        tocopy = n;
 
+               ua_flags = uaccess_save_and_enable();
                memset((void *)addr, 0, tocopy);
+               uaccess_restore(ua_flags);
                addr += tocopy;
                n -= tocopy;
 
@@ -193,9 +205,14 @@ out:
 unsigned long arm_clear_user(void __user *addr, unsigned long n)
 {
        /* See rational for this in __copy_to_user() above. */
-       if (n < 64)
-               return __clear_user_std(addr, n);
-       return __clear_user_memset(addr, n);
+       if (n < 64) {
+               unsigned long ua_flags = uaccess_save_and_enable();
+               n = __clear_user_std(addr, n);
+               uaccess_restore(ua_flags);
+       } else {
+               n = __clear_user_memset(addr, n);
+       }
+       return n;
 }
 
 #if 0
index 92673006e55c410ad27f60675c8e74bbf1433861..28656c2b54a0baadcc0aeaa6564cd1d91b592259 100644 (file)
@@ -4,7 +4,6 @@ menuconfig ARCH_AT91
        select ARCH_REQUIRE_GPIOLIB
        select COMMON_CLK_AT91
        select PINCTRL
-       select PINCTRL_AT91
        select SOC_BUS
 
 if ARCH_AT91
@@ -17,6 +16,7 @@ config SOC_SAMA5D2
        select HAVE_AT91_USB_CLK
        select HAVE_AT91_H32MX
        select HAVE_AT91_GENERATED_CLK
+       select PINCTRL_AT91PIO4
        help
          Select this if ou are using one of Atmel's SAMA5D2 family SoC.
 
@@ -27,6 +27,7 @@ config SOC_SAMA5D3
        select HAVE_AT91_UTMI
        select HAVE_AT91_SMD
        select HAVE_AT91_USB_CLK
+       select PINCTRL_AT91
        help
          Select this if you are using one of Atmel's SAMA5D3 family SoC.
          This support covers SAMA5D31, SAMA5D33, SAMA5D34, SAMA5D35, SAMA5D36.
@@ -40,6 +41,7 @@ config SOC_SAMA5D4
        select HAVE_AT91_SMD
        select HAVE_AT91_USB_CLK
        select HAVE_AT91_H32MX
+       select PINCTRL_AT91
        help
          Select this if you are using one of Atmel's SAMA5D4 family SoC.
 
@@ -50,6 +52,7 @@ config SOC_AT91RM9200
        select CPU_ARM920T
        select HAVE_AT91_USB_CLK
        select MIGHT_HAVE_PCI
+       select PINCTRL_AT91
        select SOC_SAM_V4_V5
        select SRAM if PM
        help
@@ -65,6 +68,7 @@ config SOC_AT91SAM9
        select HAVE_AT91_UTMI
        select HAVE_FB_ATMEL
        select MEMORY
+       select PINCTRL_AT91
        select SOC_SAM_V4_V5
        select SRAM if PM
        help
index 80e277cfcc8b6965d954473d877b66f91cdec52c..23726fb31741ea1479733ef91e88ac5585f7fe52 100644 (file)
  * implementation should be moved down into the pinctrl driver and get
  * called as part of the generic suspend/resume path.
  */
+#ifdef CONFIG_PINCTRL_AT91
 extern void at91_pinctrl_gpio_suspend(void);
 extern void at91_pinctrl_gpio_resume(void);
+#endif
 
 static struct {
        unsigned long uhp_udp_mask;
@@ -151,8 +153,9 @@ static void at91_pm_suspend(suspend_state_t state)
 
 static int at91_pm_enter(suspend_state_t state)
 {
+#ifdef CONFIG_PINCTRL_AT91
        at91_pinctrl_gpio_suspend();
-
+#endif
        switch (state) {
        /*
         * Suspend-to-RAM is like STANDBY plus slow clock mode, so
@@ -192,7 +195,9 @@ static int at91_pm_enter(suspend_state_t state)
 error:
        target_state = PM_SUSPEND_ON;
 
+#ifdef CONFIG_PINCTRL_AT91
        at91_pinctrl_gpio_resume();
+#endif
        return 0;
 }
 
index de68938ee6aa89a070c910c6de1cf1f5035cf0a4..c21e41dad19c14a66b83bcee65af4b504d8172c7 100644 (file)
@@ -748,8 +748,12 @@ static void exynos5_powerdown_conf(enum sys_powerdown mode)
 void exynos_sys_powerdown_conf(enum sys_powerdown mode)
 {
        unsigned int i;
+       const struct exynos_pmu_data *pmu_data;
+
+       if (!pmu_context)
+               return;
 
-       const struct exynos_pmu_data *pmu_data = pmu_context->pmu_data;
+       pmu_data = pmu_context->pmu_data;
 
        if (pmu_data->powerdown_conf)
                pmu_data->powerdown_conf(mode);
index b024390199639ca31201730ccdbcfceae577be2b..7a0c13bf42694b724e0fcb35439070eefde0a646 100644 (file)
@@ -143,7 +143,7 @@ static inline void __indirect_writesl(volatile void __iomem *bus_addr,
                writel(*vaddr++, bus_addr);
 }
 
-static inline unsigned char __indirect_readb(const volatile void __iomem *p)
+static inline u8 __indirect_readb(const volatile void __iomem *p)
 {
        u32 addr = (u32)p;
        u32 n, byte_enables, data;
@@ -166,7 +166,7 @@ static inline void __indirect_readsb(const volatile void __iomem *bus_addr,
                *vaddr++ = readb(bus_addr);
 }
 
-static inline unsigned short __indirect_readw(const volatile void __iomem *p)
+static inline u16 __indirect_readw(const volatile void __iomem *p)
 {
        u32 addr = (u32)p;
        u32 n, byte_enables, data;
@@ -189,7 +189,7 @@ static inline void __indirect_readsw(const volatile void __iomem *bus_addr,
                *vaddr++ = readw(bus_addr);
 }
 
-static inline unsigned long __indirect_readl(const volatile void __iomem *p)
+static inline u32 __indirect_readl(const volatile void __iomem *p)
 {
        u32 addr = (__force u32)p;
        u32 data;
@@ -350,7 +350,7 @@ static inline void insl(u32 io_addr, void *p, u32 count)
                                        ((unsigned long)p <= (PIO_MASK + PIO_OFFSET)))
 
 #define        ioread8(p)                      ioread8(p)
-static inline unsigned int ioread8(const void __iomem *addr)
+static inline u8 ioread8(const void __iomem *addr)
 {
        unsigned long port = (unsigned long __force)addr;
        if (__is_io_address(port))
@@ -378,7 +378,7 @@ static inline void ioread8_rep(const void __iomem *addr, void *vaddr, u32 count)
 }
 
 #define        ioread16(p)                     ioread16(p)
-static inline unsigned int ioread16(const void __iomem *addr)
+static inline u16 ioread16(const void __iomem *addr)
 {
        unsigned long port = (unsigned long __force)addr;
        if (__is_io_address(port))
@@ -407,7 +407,7 @@ static inline void ioread16_rep(const void __iomem *addr, void *vaddr,
 }
 
 #define        ioread32(p)                     ioread32(p)
-static inline unsigned int ioread32(const void __iomem *addr)
+static inline u32 ioread32(const void __iomem *addr)
 {
        unsigned long port = (unsigned long __force)addr;
        if (__is_io_address(port))
index 5076d3f334d28753e697b9e801b050c5807cadad..0517f0c1581a71091539c5c1abe47473f4b789ef 100644 (file)
@@ -65,6 +65,8 @@ config SOC_AM43XX
        select MACH_OMAP_GENERIC
        select MIGHT_HAVE_CACHE_L2X0
        select HAVE_ARM_SCU
+       select GENERIC_CLOCKEVENTS_BROADCAST
+       select HAVE_ARM_TWD
 
 config SOC_DRA7XX
        bool "TI DRA7XX"
@@ -121,6 +123,7 @@ config ARCH_OMAP2PLUS_TYPICAL
        select NEON if CPU_V7
        select PM
        select REGULATOR
+       select REGULATOR_FIXED_VOLTAGE
        select TWL4030_CORE if ARCH_OMAP3 || ARCH_OMAP4
        select TWL4030_POWER if ARCH_OMAP3 || ARCH_OMAP4
        select VFP
@@ -201,7 +204,6 @@ config MACH_OMAP3_PANDORA
        depends on ARCH_OMAP3
        default y
        select OMAP_PACKAGE_CBB
-       select REGULATOR_FIXED_VOLTAGE if REGULATOR
 
 config MACH_NOKIA_N810
        bool
index 17a6f752a43631c59eb5fd65371672bb26757b00..7b76ce01c21dd3aa3b4cad36ce2431f3c8350900 100644 (file)
@@ -149,8 +149,8 @@ static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg,
                freq = 104;
                break;
        default:
-               freq = 54;
-               break;
+               pr_err("onenand rate not detected, bad GPMC async timings?\n");
+               freq = 0;
        }
 
        return freq;
@@ -271,6 +271,11 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base)
        struct gpmc_timings t;
        int ret;
 
+       /*
+        * Note that we need to keep sync_write set for the call to
+        * omap2_onenand_set_async_mode() to work to detect the onenand
+        * supported clock rate for the sync timings.
+        */
        if (gpmc_onenand_data->of_node) {
                gpmc_read_settings_dt(gpmc_onenand_data->of_node,
                                      &onenand_async);
@@ -281,12 +286,9 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base)
                        else
                                gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
                        onenand_async.sync_read = false;
-                       onenand_async.sync_write = false;
                }
        }
 
-       omap2_onenand_set_async_mode(onenand_base);
-
        omap2_onenand_calc_async_timings(&t);
 
        ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_async);
@@ -310,6 +312,8 @@ static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr)
        if (!freq) {
                /* Very first call freq is not known */
                freq = omap2_onenand_get_freq(gpmc_onenand_data, onenand_base);
+               if (!freq)
+                       return -ENODEV;
                set_onenand_cfg(onenand_base);
        }
 
index b18ebbefae09577e20b19e53167aca5ef11b8d86..f86692dbcfd56efce7250b3a659891ad57a45725 100644 (file)
@@ -320,6 +320,12 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
        return r;
 }
 
+#if !defined(CONFIG_SMP) && defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
+void tick_broadcast(const struct cpumask *mask)
+{
+}
+#endif
+
 static void __init omap2_gp_clockevent_init(int gptimer_id,
                                                const char *fck_source,
                                                const char *property)
index 9a9c15bfcd3451f02c115238813b2193db266844..7c0d5618be5e8b6f394cec5f4d797ad931675735 100644 (file)
@@ -889,6 +889,7 @@ static void __init e680_init(void)
 
        pxa_set_keypad_info(&e680_keypad_platform_data);
 
+       pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup));
        platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
        platform_add_devices(ARRAY_AND_SIZE(e680_devices));
 }
@@ -956,6 +957,7 @@ static void __init a1200_init(void)
 
        pxa_set_keypad_info(&a1200_keypad_platform_data);
 
+       pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup));
        platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
        platform_add_devices(ARRAY_AND_SIZE(a1200_devices));
 }
@@ -1148,6 +1150,7 @@ static void __init a910_init(void)
                platform_device_register(&a910_camera);
        }
 
+       pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup));
        platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
        platform_add_devices(ARRAY_AND_SIZE(a910_devices));
 }
@@ -1215,6 +1218,7 @@ static void __init e6_init(void)
 
        pxa_set_keypad_info(&e6_keypad_platform_data);
 
+       pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup));
        platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
        platform_add_devices(ARRAY_AND_SIZE(e6_devices));
 }
@@ -1256,6 +1260,7 @@ static void __init e2_init(void)
 
        pxa_set_keypad_info(&e2_keypad_platform_data);
 
+       pwm_add_table(ezx_pwm_lookup, ARRAY_SIZE(ezx_pwm_lookup));
        platform_add_devices(ARRAY_AND_SIZE(ezx_devices));
        platform_add_devices(ARRAY_AND_SIZE(e2_devices));
 }
index a19460e6e7b0ec9317e8db98ed9aea2cf6290421..b355fca6cc2efb1a3fccd3763c91430acb66fd69 100644 (file)
@@ -20,7 +20,7 @@
 #include <plat/cpu.h>
 #include <plat/cpu-freq-core.h>
 
-static struct cpufreq_frequency_table s3c2440_plls_12[] __initdata = {
+static struct cpufreq_frequency_table s3c2440_plls_12[] = {
        { .frequency = 75000000,        .driver_data = PLLVAL(0x75, 3, 3),  },  /* FVco 600.000000 */
        { .frequency = 80000000,        .driver_data = PLLVAL(0x98, 4, 3),  },  /* FVco 640.000000 */
        { .frequency = 90000000,        .driver_data = PLLVAL(0x70, 2, 3),  },  /* FVco 720.000000 */
index 1191b29056252e49eee5cc041e0757247dab1bdf..be9a248b5ce901b5eaed665ec4f5d75632775ebc 100644 (file)
@@ -20,7 +20,7 @@
 #include <plat/cpu.h>
 #include <plat/cpu-freq-core.h>
 
-static struct cpufreq_frequency_table s3c2440_plls_169344[] __initdata = {
+static struct cpufreq_frequency_table s3c2440_plls_169344[] = {
        { .frequency = 78019200,        .driver_data = PLLVAL(121, 5, 3),       },      /* FVco 624.153600 */
        { .frequency = 84067200,        .driver_data = PLLVAL(131, 5, 3),       },      /* FVco 672.537600 */
        { .frequency = 90115200,        .driver_data = PLLVAL(141, 5, 3),       },      /* FVco 720.921600 */
index 845769e413323120b6d7b4afed7640746413bc98..c8c8b9ed02e09b57a79bee1ab5db9c337be0d338 100644 (file)
@@ -165,13 +165,28 @@ static void flush_context(unsigned int cpu)
                __flush_icache_all();
 }
 
-static int is_reserved_asid(u64 asid)
+static bool check_update_reserved_asid(u64 asid, u64 newasid)
 {
        int cpu;
-       for_each_possible_cpu(cpu)
-               if (per_cpu(reserved_asids, cpu) == asid)
-                       return 1;
-       return 0;
+       bool hit = false;
+
+       /*
+        * Iterate over the set of reserved ASIDs looking for a match.
+        * If we find one, then we can update our mm to use newasid
+        * (i.e. the same ASID in the current generation) but we can't
+        * exit the loop early, since we need to ensure that all copies
+        * of the old ASID are updated to reflect the mm. Failure to do
+        * so could result in us missing the reserved ASID in a future
+        * generation.
+        */
+       for_each_possible_cpu(cpu) {
+               if (per_cpu(reserved_asids, cpu) == asid) {
+                       hit = true;
+                       per_cpu(reserved_asids, cpu) = newasid;
+               }
+       }
+
+       return hit;
 }
 
 static u64 new_context(struct mm_struct *mm, unsigned int cpu)
@@ -181,12 +196,14 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu)
        u64 generation = atomic64_read(&asid_generation);
 
        if (asid != 0) {
+               u64 newasid = generation | (asid & ~ASID_MASK);
+
                /*
                 * If our current ASID was active during a rollover, we
                 * can continue to use it and this was just a false alarm.
                 */
-               if (is_reserved_asid(asid))
-                       return generation | (asid & ~ASID_MASK);
+               if (check_update_reserved_asid(asid, newasid))
+                       return newasid;
 
                /*
                 * We had a valid ASID in a previous life, so try to re-use
@@ -194,7 +211,7 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu)
                 */
                asid &= ~ASID_MASK;
                if (!__test_and_set_bit(asid, asid_map))
-                       goto bump_gen;
+                       return newasid;
        }
 
        /*
@@ -216,11 +233,8 @@ static u64 new_context(struct mm_struct *mm, unsigned int cpu)
 
        __set_bit(asid, asid_map);
        cur_idx = asid;
-
-bump_gen:
-       asid |= generation;
        cpumask_clear(mm_cpumask(mm));
-       return asid;
+       return asid | generation;
 }
 
 void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk)
index e62400e5fb99fdbf864af966e718a98decf85e29..534a60ae282e702d3b06e8dad289d8f109cd80ef 100644 (file)
@@ -1521,7 +1521,7 @@ static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
                return -ENOMEM;
 
        for (count = 0, s = sg; count < (size >> PAGE_SHIFT); s = sg_next(s)) {
-               phys_addr_t phys = sg_phys(s) & PAGE_MASK;
+               phys_addr_t phys = page_to_phys(sg_page(s));
                unsigned int len = PAGE_ALIGN(s->offset + s->length);
 
                if (!is_coherent &&
index 8a63b4cdc0f27d0fa7cf69f0bb1ffa51b6289e39..7f8cd1b3557f071a64dafc05eba4c481ef82c79d 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/memblock.h>
 #include <linux/dma-contiguous.h>
 #include <linux/sizes.h>
+#include <linux/stop_machine.h>
 
 #include <asm/cp15.h>
 #include <asm/mach-types.h>
@@ -627,12 +628,10 @@ static struct section_perm ro_perms[] = {
  * safe to be called with preemption disabled, as under stop_machine().
  */
 static inline void section_update(unsigned long addr, pmdval_t mask,
-                                 pmdval_t prot)
+                                 pmdval_t prot, struct mm_struct *mm)
 {
-       struct mm_struct *mm;
        pmd_t *pmd;
 
-       mm = current->active_mm;
        pmd = pmd_offset(pud_offset(pgd_offset(mm, addr), addr), addr);
 
 #ifdef CONFIG_ARM_LPAE
@@ -656,49 +655,82 @@ static inline bool arch_has_strict_perms(void)
        return !!(get_cr() & CR_XP);
 }
 
-#define set_section_perms(perms, field)        {                               \
-       size_t i;                                                       \
-       unsigned long addr;                                             \
-                                                                       \
-       if (!arch_has_strict_perms())                                   \
-               return;                                                 \
-                                                                       \
-       for (i = 0; i < ARRAY_SIZE(perms); i++) {                       \
-               if (!IS_ALIGNED(perms[i].start, SECTION_SIZE) ||        \
-                   !IS_ALIGNED(perms[i].end, SECTION_SIZE)) {          \
-                       pr_err("BUG: section %lx-%lx not aligned to %lx\n", \
-                               perms[i].start, perms[i].end,           \
-                               SECTION_SIZE);                          \
-                       continue;                                       \
-               }                                                       \
-                                                                       \
-               for (addr = perms[i].start;                             \
-                    addr < perms[i].end;                               \
-                    addr += SECTION_SIZE)                              \
-                       section_update(addr, perms[i].mask,             \
-                                      perms[i].field);                 \
-       }                                                               \
+void set_section_perms(struct section_perm *perms, int n, bool set,
+                       struct mm_struct *mm)
+{
+       size_t i;
+       unsigned long addr;
+
+       if (!arch_has_strict_perms())
+               return;
+
+       for (i = 0; i < n; i++) {
+               if (!IS_ALIGNED(perms[i].start, SECTION_SIZE) ||
+                   !IS_ALIGNED(perms[i].end, SECTION_SIZE)) {
+                       pr_err("BUG: section %lx-%lx not aligned to %lx\n",
+                               perms[i].start, perms[i].end,
+                               SECTION_SIZE);
+                       continue;
+               }
+
+               for (addr = perms[i].start;
+                    addr < perms[i].end;
+                    addr += SECTION_SIZE)
+                       section_update(addr, perms[i].mask,
+                               set ? perms[i].prot : perms[i].clear, mm);
+       }
+
 }
 
-static inline void fix_kernmem_perms(void)
+static void update_sections_early(struct section_perm perms[], int n)
 {
-       set_section_perms(nx_perms, prot);
+       struct task_struct *t, *s;
+
+       read_lock(&tasklist_lock);
+       for_each_process(t) {
+               if (t->flags & PF_KTHREAD)
+                       continue;
+               for_each_thread(t, s)
+                       set_section_perms(perms, n, true, s->mm);
+       }
+       read_unlock(&tasklist_lock);
+       set_section_perms(perms, n, true, current->active_mm);
+       set_section_perms(perms, n, true, &init_mm);
+}
+
+int __fix_kernmem_perms(void *unused)
+{
+       update_sections_early(nx_perms, ARRAY_SIZE(nx_perms));
+       return 0;
+}
+
+void fix_kernmem_perms(void)
+{
+       stop_machine(__fix_kernmem_perms, NULL, NULL);
 }
 
 #ifdef CONFIG_DEBUG_RODATA
+int __mark_rodata_ro(void *unused)
+{
+       update_sections_early(ro_perms, ARRAY_SIZE(ro_perms));
+       return 0;
+}
+
 void mark_rodata_ro(void)
 {
-       set_section_perms(ro_perms, prot);
+       stop_machine(__mark_rodata_ro, NULL, NULL);
 }
 
 void set_kernel_text_rw(void)
 {
-       set_section_perms(ro_perms, clear);
+       set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), false,
+                               current->active_mm);
 }
 
 void set_kernel_text_ro(void)
 {
-       set_section_perms(ro_perms, prot);
+       set_section_perms(ro_perms, ARRAY_SIZE(ro_perms), true,
+                               current->active_mm);
 }
 #endif /* CONFIG_DEBUG_RODATA */
 
index de2b246fed3808fce444b560a725ed4007464174..8e1ea433c3f1e321d7ed4e91fe582a5be4eb85be 100644 (file)
@@ -95,7 +95,7 @@ ENDPROC(cpu_v7_dcache_clean_area)
 .equ   cpu_v7_suspend_size, 4 * 9
 #ifdef CONFIG_ARM_CPU_SUSPEND
 ENTRY(cpu_v7_do_suspend)
-       stmfd   sp!, {r4 - r10, lr}
+       stmfd   sp!, {r4 - r11, lr}
        mrc     p15, 0, r4, c13, c0, 0  @ FCSE/PID
        mrc     p15, 0, r5, c13, c0, 3  @ User r/o thread ID
        stmia   r0!, {r4 - r5}
@@ -112,7 +112,7 @@ ENTRY(cpu_v7_do_suspend)
        mrc     p15, 0, r9, c1, c0, 1   @ Auxiliary control register
        mrc     p15, 0, r10, c1, c0, 2  @ Co-processor access control
        stmia   r0, {r5 - r11}
-       ldmfd   sp!, {r4 - r10, pc}
+       ldmfd   sp!, {r4 - r11, pc}
 ENDPROC(cpu_v7_do_suspend)
 
 ENTRY(cpu_v7_do_resume)
index 591f9db3bf4048a4d727f195e4e2fb95e4ca06c4..93d0b6d0b63eede5f36de91428bb181bab2e0971 100644 (file)
@@ -187,19 +187,6 @@ static inline int mem_words_used(struct jit_ctx *ctx)
        return fls(ctx->seen & SEEN_MEM);
 }
 
-static inline bool is_load_to_a(u16 inst)
-{
-       switch (inst) {
-       case BPF_LD | BPF_W | BPF_LEN:
-       case BPF_LD | BPF_W | BPF_ABS:
-       case BPF_LD | BPF_H | BPF_ABS:
-       case BPF_LD | BPF_B | BPF_ABS:
-               return true;
-       default:
-               return false;
-       }
-}
-
 static void jit_fill_hole(void *area, unsigned int size)
 {
        u32 *ptr;
@@ -211,7 +198,6 @@ static void jit_fill_hole(void *area, unsigned int size)
 static void build_prologue(struct jit_ctx *ctx)
 {
        u16 reg_set = saved_regs(ctx);
-       u16 first_inst = ctx->skf->insns[0].code;
        u16 off;
 
 #ifdef CONFIG_FRAME_POINTER
@@ -241,7 +227,7 @@ static void build_prologue(struct jit_ctx *ctx)
                emit(ARM_MOV_I(r_X, 0), ctx);
 
        /* do not leak kernel data to userspace */
-       if ((first_inst != (BPF_RET | BPF_K)) && !(is_load_to_a(first_inst)))
+       if (bpf_needs_clear_a(&ctx->skf->insns[0]))
                emit(ARM_MOV_I(r_A, 0), ctx);
 
        /* stack space for the BPF_MEM words */
@@ -770,7 +756,8 @@ load_ind:
                case BPF_ALU | BPF_RSH | BPF_K:
                        if (unlikely(k > 31))
                                return -1;
-                       emit(ARM_LSR_I(r_A, r_A, k), ctx);
+                       if (k)
+                               emit(ARM_LSR_I(r_A, r_A, k), ctx);
                        break;
                case BPF_ALU | BPF_RSH | BPF_X:
                        update_on_xread(ctx);
index e81cd48d6245eace97978c58057a022d105d990d..925552e7b4f3eaf6ce23fc1e8dd2d77f50073121 100644 (file)
                        clock-frequency = <0>;  /* Updated by bootloader */
                        voltage-ranges = <1800 1800 3300 3300>;
                        sdhci,auto-cmd12;
+                       little-endian;
                        bus-width = <4>;
                };
 
                        reg = <0x0 0x2300000 0x0 0x10000>;
                        interrupts = <0 36 0x4>; /* Level high type */
                        gpio-controller;
+                       little-endian;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
                        reg = <0x0 0x2310000 0x0 0x10000>;
                        interrupts = <0 36 0x4>; /* Level high type */
                        gpio-controller;
+                       little-endian;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
                        reg = <0x0 0x2320000 0x0 0x10000>;
                        interrupts = <0 37 0x4>; /* Level high type */
                        gpio-controller;
+                       little-endian;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
                        reg = <0x0 0x2330000 0x0 0x10000>;
                        interrupts = <0 37 0x4>; /* Level high type */
                        gpio-controller;
+                       little-endian;
                        #gpio-cells = <2>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
index 030cdcb46c6bdabd8bb49901ed231fcdbb5c25fd..2731d3b25ed2e338e76966b5efd86658b7e22263 100644 (file)
@@ -77,6 +77,7 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/stringify.h>
+#include <asm/barrier.h>
 
 /*
  * Low-level accessors
index 7e074f93f383fea1891ce79d4048c22f647841a7..63f52b55defe1041a7913217db490528c441c6f3 100644 (file)
@@ -276,10 +276,14 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
         * hardware updates of the pte (ptep_set_access_flags safely changes
         * valid ptes without going through an invalid entry).
         */
-       if (IS_ENABLED(CONFIG_DEBUG_VM) && IS_ENABLED(CONFIG_ARM64_HW_AFDBM) &&
-           pte_valid(*ptep)) {
-               BUG_ON(!pte_young(pte));
-               BUG_ON(pte_write(*ptep) && !pte_dirty(pte));
+       if (IS_ENABLED(CONFIG_ARM64_HW_AFDBM) &&
+           pte_valid(*ptep) && pte_valid(pte)) {
+               VM_WARN_ONCE(!pte_young(pte),
+                            "%s: racy access flag clearing: 0x%016llx -> 0x%016llx",
+                            __func__, pte_val(*ptep), pte_val(pte));
+               VM_WARN_ONCE(pte_write(*ptep) && !pte_dirty(pte),
+                            "%s: racy dirty state clearing: 0x%016llx -> 0x%016llx",
+                            __func__, pte_val(*ptep), pte_val(pte));
        }
 
        set_pte(ptep, pte);
index 1ee2c3937d4e8badf3ccec9a816ad23f9814506f..71426a78db123d13e98acf8659d65155ff342a06 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <asm-generic/vmlinux.lds.h>
+#include <asm/cache.h>
 #include <asm/kernel-pgtable.h>
 #include <asm/thread_info.h>
 #include <asm/memory.h>
@@ -140,7 +141,7 @@ SECTIONS
                ARM_EXIT_KEEP(EXIT_DATA)
        }
 
-       PERCPU_SECTION(64)
+       PERCPU_SECTION(L1_CACHE_BYTES)
 
        . = ALIGN(PAGE_SIZE);
        __init_end = .;
@@ -158,7 +159,7 @@ SECTIONS
        . = ALIGN(PAGE_SIZE);
        _data = .;
        _sdata = .;
-       RW_DATA_SECTION(64, PAGE_SIZE, THREAD_SIZE)
+       RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
        PECOFF_EDATA_PADDING
        _edata = .;
 
index 1e9c8b0bf48666cfba1ee19d8731eb71cf68a77e..170d786807c460eda342f4383dc379e5279a215d 100644 (file)
@@ -14,7 +14,7 @@
  *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
  *  Copyright (C) 2009 Jaswinder Singh Rajput
  *  Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
- *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra
  *  Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
  *
  * ppc:
index db73390568c8dd873fc045cd35773714bd35f8e1..74c132d901bd290bcc803b7c0a0266428a2ec1cb 100644 (file)
@@ -11,7 +11,7 @@
 
 
 
-#define NR_syscalls                    322 /* length of syscall table */
+#define NR_syscalls                    323 /* length of syscall table */
 
 /*
  * The following defines stop scripts/checksyscalls.sh from complaining about
index 9038726e7d26777bf8f704f101ff86090e4d5059..762edce7572eb33f03a3402e4357de69626764c9 100644 (file)
 #define __NR_userfaultfd               1343
 #define __NR_membarrier                        1344
 #define __NR_kcmp                      1345
+#define __NR_mlock2                    1346
 
 #endif /* _UAPI_ASM_IA64_UNISTD_H */
index dcd97f84d065435a8eca5c041f33bb67c3912797..534a74acb849d736726b5f066675f0a3a4c87ed4 100644 (file)
@@ -1771,5 +1771,6 @@ sys_call_table:
        data8 sys_userfaultfd
        data8 sys_membarrier
        data8 sys_kcmp                          // 1345
+       data8 sys_mlock2
 
        .org sys_call_table + 8*NR_syscalls     // guard against failures to increase NR_syscalls
index fd104bd221ced1dff2c9485bdcb1be520171df7f..860e440611c98f7e0c2a9882c18dc73cf166f35e 100644 (file)
@@ -3,6 +3,7 @@ generic-y += clkdev.h
 generic-y += cputime.h
 generic-y += exec.h
 generic-y += irq_work.h
+generic-y += kvm_para.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += module.h
index 61b8931bc19250df3af7b42b4e667749332b6be1..4b0f5e001d4d5ab2a545e62dcc276b9815df5821 100644 (file)
@@ -168,13 +168,21 @@ static inline void _writel(unsigned long l, unsigned long addr)
 #define writew_relaxed writew
 #define writel_relaxed writel
 
-#define ioread8 read
+#define ioread8 readb
 #define ioread16 readw
 #define ioread32 readl
 #define iowrite8 writeb
 #define iowrite16 writew
 #define iowrite32 writel
 
+#define ioread8_rep(p, dst, count) insb((unsigned long)(p), (dst), (count))
+#define ioread16_rep(p, dst, count) insw((unsigned long)(p), (dst), (count))
+#define ioread32_rep(p, dst, count) insl((unsigned long)(p), (dst), (count))
+
+#define iowrite8_rep(p, src, count) outsb((unsigned long)(p), (src), (count))
+#define iowrite16_rep(p, src, count) outsw((unsigned long)(p), (src), (count))
+#define iowrite32_rep(p, src, count) outsl((unsigned long)(p), (src), (count))
+
 #define ioread16be(addr)       be16_to_cpu(readw(addr))
 #define ioread32be(addr)       be32_to_cpu(readl(addr))
 #define iowrite16be(v, addr)   writew(cpu_to_be16(v), (addr))
index c89da63129545a9c300e61062e9d958d4c786790..bf4dec229437a836ee1829504be7bf603ce73b37 100644 (file)
@@ -61,7 +61,8 @@ static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl,
        /* FIXME this part of code is untested */
        for_each_sg(sgl, sg, nents, i) {
                sg->dma_address = sg_phys(sg);
-               __dma_sync(sg_phys(sg), sg->length, direction);
+               __dma_sync(page_to_phys(sg_page(sg)) + sg->offset,
+                                                       sg->length, direction);
        }
 
        return nents;
index 5305d694ffe52010f19a110fd072341a44e4ae85..095ecafe6bd3525444c27812937e2d085bf69b2a 100644 (file)
@@ -599,7 +599,7 @@ extern void __put_user_unknown(void);
  * On error, the variable @x is set to zero.
  */
 #define __get_user_unaligned(x,ptr) \
-       __get_user__unalignednocheck((x),(ptr),sizeof(*(ptr)))
+       __get_user_unaligned_nocheck((x),(ptr),sizeof(*(ptr)))
 
 /*
  * Yuck.  We need two variants, one for 64bit operation and one
@@ -620,8 +620,8 @@ extern void __get_user_unaligned_unknown(void);
 do {                                                                   \
        switch (size) {                                                 \
        case 1: __get_data_asm(val, "lb", ptr); break;                  \
-       case 2: __get_user_unaligned_asm(val, "ulh", ptr); break;       \
-       case 4: __get_user_unaligned_asm(val, "ulw", ptr); break;       \
+       case 2: __get_data_unaligned_asm(val, "ulh", ptr); break;       \
+       case 4: __get_data_unaligned_asm(val, "ulw", ptr); break;       \
        case 8: __GET_USER_UNALIGNED_DW(val, ptr); break;               \
        default: __get_user_unaligned_unknown(); break;                 \
        }                                                               \
@@ -1122,9 +1122,15 @@ extern size_t __copy_in_user_eva(void *__to, const void *__from, size_t __n);
        __cu_to = (to);                                                 \
        __cu_from = (from);                                             \
        __cu_len = (n);                                                 \
-       might_fault();                                                  \
-       __cu_len = __invoke_copy_from_user(__cu_to, __cu_from,          \
-                                          __cu_len);                   \
+       if (eva_kernel_access()) {                                      \
+               __cu_len = __invoke_copy_from_kernel(__cu_to,           \
+                                                    __cu_from,         \
+                                                    __cu_len);         \
+       } else {                                                        \
+               might_fault();                                          \
+               __cu_len = __invoke_copy_from_user(__cu_to, __cu_from,  \
+                                                  __cu_len);           \
+       }                                                               \
        __cu_len;                                                       \
 })
 
@@ -1229,16 +1235,28 @@ __clear_user(void __user *addr, __kernel_size_t size)
 {
        __kernel_size_t res;
 
-       might_fault();
-       __asm__ __volatile__(
-               "move\t$4, %1\n\t"
-               "move\t$5, $0\n\t"
-               "move\t$6, %2\n\t"
-               __MODULE_JAL(__bzero)
-               "move\t%0, $6"
-               : "=r" (res)
-               : "r" (addr), "r" (size)
-               : "$4", "$5", "$6", __UA_t0, __UA_t1, "$31");
+       if (eva_kernel_access()) {
+               __asm__ __volatile__(
+                       "move\t$4, %1\n\t"
+                       "move\t$5, $0\n\t"
+                       "move\t$6, %2\n\t"
+                       __MODULE_JAL(__bzero_kernel)
+                       "move\t%0, $6"
+                       : "=r" (res)
+                       : "r" (addr), "r" (size)
+                       : "$4", "$5", "$6", __UA_t0, __UA_t1, "$31");
+       } else {
+               might_fault();
+               __asm__ __volatile__(
+                       "move\t$4, %1\n\t"
+                       "move\t$5, $0\n\t"
+                       "move\t$6, %2\n\t"
+                       __MODULE_JAL(__bzero)
+                       "move\t%0, $6"
+                       : "=r" (res)
+                       : "r" (addr), "r" (size)
+                       : "$4", "$5", "$6", __UA_t0, __UA_t1, "$31");
+       }
 
        return res;
 }
@@ -1384,7 +1402,7 @@ static inline long strlen_user(const char __user *s)
                might_fault();
                __asm__ __volatile__(
                        "move\t$4, %1\n\t"
-                       __MODULE_JAL(__strlen_kernel_asm)
+                       __MODULE_JAL(__strlen_user_asm)
                        "move\t%0, $2"
                        : "=r" (res)
                        : "r" (s)
index 8fd5a276cad23493f6500d0f4b01515ee20062f5..ac81edd44563119dbf6cf6fa0c9154afb9c47b98 100644 (file)
@@ -257,7 +257,6 @@ LEAF(mips_cps_core_init)
        has_mt  t0, 3f
 
        .set    push
-       .set    mips64r2
        .set    mt
 
        /* Only allow 1 TC per VPE to execute... */
@@ -376,7 +375,6 @@ LEAF(mips_cps_boot_vpes)
         nop
 
        .set    push
-       .set    mips64r2
        .set    mt
 
 1:     /* Enter VPE configuration state */
index 291af0b5c4828adaa22ff0fc065f37c6a094fd85..e2b6ab74643dba93b403dbba2dcfb4eced3e6d9e 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/fpu.h>
 #include <asm/msa.h>
 
+extern void *__bzero_kernel(void *__s, size_t __count);
 extern void *__bzero(void *__s, size_t __count);
 extern long __strncpy_from_kernel_nocheck_asm(char *__to,
                                              const char *__from, long __len);
@@ -64,6 +65,7 @@ EXPORT_SYMBOL(__copy_from_user_eva);
 EXPORT_SYMBOL(__copy_in_user_eva);
 EXPORT_SYMBOL(__copy_to_user_eva);
 EXPORT_SYMBOL(__copy_user_inatomic_eva);
+EXPORT_SYMBOL(__bzero_kernel);
 #endif
 EXPORT_SYMBOL(__bzero);
 EXPORT_SYMBOL(__strncpy_from_kernel_nocheck_asm);
index b8e63fd0037547cb9939907696da7ae55d699a95..8f0019a2e5c84bcd4f439559dad479b44903269a 100644 (file)
@@ -283,6 +283,8 @@ LEAF(memset)
 1:
 #ifndef CONFIG_EVA
 FEXPORT(__bzero)
+#else
+FEXPORT(__bzero_kernel)
 #endif
        __BUILD_BZERO LEGACY_MODE
 
index d8117be729a20ee26d2df8bb42a6f58b9670f513..730d394ce5f017991146084f9df53794242c970d 100644 (file)
@@ -145,7 +145,7 @@ static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
 
        gfp = massage_gfp_flags(dev, gfp);
 
-       if (IS_ENABLED(CONFIG_DMA_CMA) && !(gfp & GFP_ATOMIC))
+       if (IS_ENABLED(CONFIG_DMA_CMA) && gfpflags_allow_blocking(gfp))
                page = dma_alloc_from_contiguous(dev,
                                        count, get_order(size));
        if (!page)
index 77cb27309db27f781ec9862037074d39e928401a..1a8c96035716a2dfb76f724b6190b33954bee8c8 100644 (file)
@@ -521,19 +521,6 @@ static inline u16 align_sp(unsigned int num)
        return num;
 }
 
-static bool is_load_to_a(u16 inst)
-{
-       switch (inst) {
-       case BPF_LD | BPF_W | BPF_LEN:
-       case BPF_LD | BPF_W | BPF_ABS:
-       case BPF_LD | BPF_H | BPF_ABS:
-       case BPF_LD | BPF_B | BPF_ABS:
-               return true;
-       default:
-               return false;
-       }
-}
-
 static void save_bpf_jit_regs(struct jit_ctx *ctx, unsigned offset)
 {
        int i = 0, real_off = 0;
@@ -614,7 +601,6 @@ static unsigned int get_stack_depth(struct jit_ctx *ctx)
 
 static void build_prologue(struct jit_ctx *ctx)
 {
-       u16 first_inst = ctx->skf->insns[0].code;
        int sp_off;
 
        /* Calculate the total offset for the stack pointer */
@@ -641,7 +627,7 @@ static void build_prologue(struct jit_ctx *ctx)
                emit_jit_reg_move(r_X, r_zero, ctx);
 
        /* Do not leak kernel data to userspace */
-       if ((first_inst != (BPF_RET | BPF_K)) && !(is_load_to_a(first_inst)))
+       if (bpf_needs_clear_a(&ctx->skf->insns[0]))
                emit_jit_reg_move(r_A, r_zero, ctx);
 }
 
index dbbeccc3d714add203aae3ebb5b3a0cd1522f0ae..a245cad4372a4a84094b88eed05ba3080a146190 100644 (file)
@@ -221,7 +221,6 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 static int rt288x_pci_probe(struct platform_device *pdev)
 {
        void __iomem *io_map_base;
-       int i;
 
        rt2880_pci_base = ioremap_nocache(RT2880_PCI_BASE, PAGE_SIZE);
 
index 78b2ef49dbc7a45adc720264f66cc9922453ceb2..9d293b3e9130152af49f964e530ece27e482fd7b 100644 (file)
@@ -39,7 +39,6 @@ extern void msp_serial_setup(void);
 void msp7120_reset(void)
 {
        void *start, *end, *iptr;
-       register int i;
 
        /* Diasble all interrupts */
        local_irq_disable();
index db8f88b6a3af9cb52dcb2a2a23df94a49cc0eccd..6afa34346b8148040a84e0a54ecd7af8d7ac608c 100644 (file)
@@ -26,7 +26,7 @@ static inline void kb_wait(void)
 /* XXX This ends up at the ARC firmware prompt ...  */
 void sni_machine_restart(char *command)
 {
-       int i, j;
+       int i;
 
        /* This does a normal via the keyboard controller like a PC.
           We can do that easier ...  */
index ef5f348f386a1ec4c5aef0a566a334a40e8f763b..14568900fc1d14ec2e0ff6b2d7152232c8b867bb 100644 (file)
@@ -26,8 +26,8 @@ aflags-vdso := $(ccflags-vdso) \
 # the comments on that file.
 #
 ifndef CONFIG_CPU_MIPSR6
-  ifeq ($(call ld-ifversion, -gt, 22400000, y),)
-    $(warning MIPS VDSO requires binutils > 2.24)
+  ifeq ($(call ld-ifversion, -lt, 22500000, y),y)
+    $(warning MIPS VDSO requires binutils >= 2.25)
     obj-vdso-y := $(filter-out gettimeofday.o, $(obj-vdso-y))
     ccflags-vdso += -DDISABLE_MIPS_VDSO
   endif
index d8534f95915a3754c233fd14466aef6cbfba40dc..291cee28ccb60da84576ba1d9e103a0dc6e78ba5 100644 (file)
@@ -372,7 +372,8 @@ static inline pte_t pte_mkspecial(pte_t pte)        { return pte; }
  */
 #ifdef CONFIG_HUGETLB_PAGE
 #define pte_huge(pte)           (pte_val(pte) & _PAGE_HUGE)
-#define pte_mkhuge(pte)         (__pte(pte_val(pte) | _PAGE_HUGE))
+#define pte_mkhuge(pte)         (__pte(pte_val(pte) | \
+                                (parisc_requires_coherency() ? 0 : _PAGE_HUGE)))
 #else
 #define pte_huge(pte)           (0)
 #define pte_mkhuge(pte)         (pte)
index 33170384d3ac1a7fdd835c7b8f04484aaf1f244c..35bdccbb203622e116f288741ac4a9bc173034b0 100644 (file)
 #define __NR_execveat          (__NR_Linux + 342)
 #define __NR_membarrier                (__NR_Linux + 343)
 #define __NR_userfaultfd       (__NR_Linux + 344)
+#define __NR_mlock2            (__NR_Linux + 345)
 
-#define __NR_Linux_syscalls    (__NR_userfaultfd + 1)
+#define __NR_Linux_syscalls    (__NR_mlock2 + 1)
 
 
 #define __IGNORE_select                /* newselect */
index 64f2764a8cef8778a0602262a5c5b10e4d68975d..c99f3dde455ce5979ee4e17830704710ba4683af 100644 (file)
@@ -171,24 +171,6 @@ void pcibios_set_master(struct pci_dev *dev)
 }
 
 
-void __init pcibios_init_bus(struct pci_bus *bus)
-{
-       struct pci_dev *dev = bus->self;
-       unsigned short bridge_ctl;
-
-       /* We deal only with pci controllers and pci-pci bridges. */
-       if (!dev || (dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
-               return;
-
-       /* PCI-PCI bridge - set the cache line and default latency
-          (32) for primary and secondary buses. */
-       pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 32);
-
-       pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bridge_ctl);
-       bridge_ctl |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR;
-       pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bridge_ctl);
-}
-
 /*
  * pcibios align resources() is called every time generic PCI code
  * wants to generate a new address. The process of looking for
index dc1ea796fd605c257c7ce1196a63773a3e3e7987..2264f68f3c2f9716030cb8fab53487f6db22e667 100644 (file)
@@ -435,6 +435,55 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs, int in_syscall)
                regs->gr[28]);
 }
 
+/*
+ * Check how the syscall number gets loaded into %r20 within
+ * the delay branch in userspace and adjust as needed.
+ */
+
+static void check_syscallno_in_delay_branch(struct pt_regs *regs)
+{
+       u32 opcode, source_reg;
+       u32 __user *uaddr;
+       int err;
+
+       /* Usually we don't have to restore %r20 (the system call number)
+        * because it gets loaded in the delay slot of the branch external
+        * instruction via the ldi instruction.
+        * In some cases a register-to-register copy instruction might have
+        * been used instead, in which case we need to copy the syscall
+        * number into the source register before returning to userspace.
+        */
+
+       /* A syscall is just a branch, so all we have to do is fiddle the
+        * return pointer so that the ble instruction gets executed again.
+        */
+       regs->gr[31] -= 8; /* delayed branching */
+
+       /* Get assembler opcode of code in delay branch */
+       uaddr = (unsigned int *) ((regs->gr[31] & ~3) + 4);
+       err = get_user(opcode, uaddr);
+       if (err)
+               return;
+
+       /* Check if delay branch uses "ldi int,%r20" */
+       if ((opcode & 0xffff0000) == 0x34140000)
+               return; /* everything ok, just return */
+
+       /* Check if delay branch uses "nop" */
+       if (opcode == INSN_NOP)
+               return;
+
+       /* Check if delay branch uses "copy %rX,%r20" */
+       if ((opcode & 0xffe0ffff) == 0x08000254) {
+               source_reg = (opcode >> 16) & 31;
+               regs->gr[source_reg] = regs->gr[20];
+               return;
+       }
+
+       pr_warn("syscall restart: %s (pid %d): unexpected opcode 0x%08x\n",
+               current->comm, task_pid_nr(current), opcode);
+}
+
 static inline void
 syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
 {
@@ -457,10 +506,7 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
                }
                /* fallthrough */
        case -ERESTARTNOINTR:
-               /* A syscall is just a branch, so all
-                * we have to do is fiddle the return pointer.
-                */
-               regs->gr[31] -= 8; /* delayed branching */
+               check_syscallno_in_delay_branch(regs);
                break;
        }
 }
@@ -510,15 +556,9 @@ insert_restart_trampoline(struct pt_regs *regs)
        }
        case -ERESTARTNOHAND:
        case -ERESTARTSYS:
-       case -ERESTARTNOINTR: {
-               /* Hooray for delayed branching.  We don't
-                * have to restore %r20 (the system call
-                * number) because it gets loaded in the delay
-                * slot of the branch external instruction.
-                */
-               regs->gr[31] -= 8;
+       case -ERESTARTNOINTR:
+               check_syscallno_in_delay_branch(regs);
                return;
-       }
        default:
                break;
        }
index 78c3ef8c348d5cfdef2b50670a1da348ee49566e..d4ffcfbc98851e7c3f0707ec9d82470d918bed2e 100644 (file)
        ENTRY_COMP(execveat)
        ENTRY_SAME(membarrier)
        ENTRY_SAME(userfaultfd)
+       ENTRY_SAME(mlock2)              /* 345 */
 
 
 .ifne (. - 90b) - (__NR_Linux_syscalls * (91b - 90b))
index 631ede72e226c31c8d9f610bc583fc9f93802191..68f0ed7626bd96252f768c7dcca12e8e0294ef69 100644 (file)
                                reg = <0x520 0x20>;
 
                                phy0: ethernet-phy@1f {
-                                       interrupt-parent = <&mpic>;
-                                       interrupts = <10 1>;
                                        reg = <0x1f>;
                                };
                                phy1: ethernet-phy@0 {
-                                       interrupt-parent = <&mpic>;
-                                       interrupts = <10 1>;
                                        reg = <0>;
                                };
                                phy2: ethernet-phy@1 {
-                                       interrupt-parent = <&mpic>;
-                                       interrupts = <10 1>;
                                        reg = <1>;
                                };
                                phy3: ethernet-phy@2 {
-                                       interrupt-parent = <&mpic>;
-                                       interrupts = <10 1>;
                                        reg = <2>;
                                };
                                tbi0: tbi-phy@11 {
index f2b0b1b0c72acf49373310288fcb330d726740e7..5654ece02c0db5ee41da441c30d8a2c5f1cdcbc4 100644 (file)
@@ -370,16 +370,16 @@ COMPAT_SYS(execveat)
 PPC64ONLY(switch_endian)
 SYSCALL_SPU(userfaultfd)
 SYSCALL_SPU(membarrier)
-SYSCALL(semop)
-SYSCALL(semget)
-COMPAT_SYS(semctl)
-COMPAT_SYS(semtimedop)
-COMPAT_SYS(msgsnd)
-COMPAT_SYS(msgrcv)
-SYSCALL(msgget)
-COMPAT_SYS(msgctl)
-COMPAT_SYS(shmat)
-SYSCALL(shmdt)
-SYSCALL(shmget)
-COMPAT_SYS(shmctl)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
+SYSCALL(ni_syscall)
 SYSCALL(mlock2)
index 1effea5193d6861cb0074a5c682965b4e4f6a13e..12a05652377a28799a89ae59e3d38a7ddeaade92 100644 (file)
 #define __NR_switch_endian     363
 #define __NR_userfaultfd       364
 #define __NR_membarrier                365
-#define __NR_semop             366
-#define __NR_semget            367
-#define __NR_semctl            368
-#define __NR_semtimedop                369
-#define __NR_msgsnd            370
-#define __NR_msgrcv            371
-#define __NR_msgget            372
-#define __NR_msgctl            373
-#define __NR_shmat             374
-#define __NR_shmdt             375
-#define __NR_shmget            376
-#define __NR_shmctl            377
 #define __NR_mlock2            378
 
 #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
index 80dfe8965df9f7d49fc57a1f1d6773f0c5ffd736..8d14feb40f121129854a7760818e926f7b5b742c 100644 (file)
@@ -590,16 +590,10 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
        eeh_ops->configure_bridge(pe);
        eeh_pe_restore_bars(pe);
 
-       /*
-        * If it's PHB PE, the frozen state on all available PEs should have
-        * been cleared by the PHB reset. Otherwise, we unfreeze the PE and its
-        * child PEs because they might be in frozen state.
-        */
-       if (!(pe->type & EEH_PE_PHB)) {
-               rc = eeh_clear_pe_frozen_state(pe, false);
-               if (rc)
-                       return rc;
-       }
+       /* Clear frozen state */
+       rc = eeh_clear_pe_frozen_state(pe, false);
+       if (rc)
+               return rc;
 
        /* Give the system 5 seconds to finish running the user-space
         * hotplug shutdown scripts, e.g. ifdown for ethernet.  Yes,
index 54b45b73195f912688ec4afe8e9fb4c9c3d5723c..a7352b59e6f9b5c74f37556e6858c9ac9c5bb30b 100644 (file)
@@ -224,6 +224,12 @@ static void kvmppc_core_vcpu_put_hv(struct kvm_vcpu *vcpu)
 
 static void kvmppc_set_msr_hv(struct kvm_vcpu *vcpu, u64 msr)
 {
+       /*
+        * Check for illegal transactional state bit combination
+        * and if we find it, force the TS field to a safe state.
+        */
+       if ((msr & MSR_TS_MASK) == MSR_TS_MASK)
+               msr &= ~MSR_TS_MASK;
        vcpu->arch.shregs.msr = msr;
        kvmppc_end_cede(vcpu);
 }
index 04782164ee67d8a570bcb4b4ee166dc6809753de..2d66a8446198dfcf48849c61a561cf7527f79e56 100644 (file)
@@ -78,18 +78,9 @@ static void bpf_jit_build_prologue(struct bpf_prog *fp, u32 *image,
                PPC_LI(r_X, 0);
        }
 
-       switch (filter[0].code) {
-       case BPF_RET | BPF_K:
-       case BPF_LD | BPF_W | BPF_LEN:
-       case BPF_LD | BPF_W | BPF_ABS:
-       case BPF_LD | BPF_H | BPF_ABS:
-       case BPF_LD | BPF_B | BPF_ABS:
-               /* first instruction sets A register (or is RET 'constant') */
-               break;
-       default:
-               /* make sure we dont leak kernel information to user */
+       /* make sure we dont leak kernel information to user */
+       if (bpf_needs_clear_a(&filter[0]))
                PPC_LI(r_A, 0);
-       }
 }
 
 static void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
index 6ccfb6c1c707b40e9fd6ba4cb202d70c1faf57cb..e505223b4ec5ed2d82bcb08b2e718a6b64601f18 100644 (file)
@@ -43,11 +43,34 @@ static unsigned int opal_irq_count;
 static unsigned int *opal_irqs;
 
 static void opal_handle_irq_work(struct irq_work *work);
-static __be64 last_outstanding_events;
+static u64 last_outstanding_events;
 static struct irq_work opal_event_irq_work = {
        .func = opal_handle_irq_work,
 };
 
+void opal_handle_events(uint64_t events)
+{
+       int virq, hwirq = 0;
+       u64 mask = opal_event_irqchip.mask;
+
+       if (!in_irq() && (events & mask)) {
+               last_outstanding_events = events;
+               irq_work_queue(&opal_event_irq_work);
+               return;
+       }
+
+       while (events & mask) {
+               hwirq = fls64(events) - 1;
+               if (BIT_ULL(hwirq) & mask) {
+                       virq = irq_find_mapping(opal_event_irqchip.domain,
+                                               hwirq);
+                       if (virq)
+                               generic_handle_irq(virq);
+               }
+               events &= ~BIT_ULL(hwirq);
+       }
+}
+
 static void opal_event_mask(struct irq_data *d)
 {
        clear_bit(d->hwirq, &opal_event_irqchip.mask);
@@ -55,9 +78,21 @@ static void opal_event_mask(struct irq_data *d)
 
 static void opal_event_unmask(struct irq_data *d)
 {
+       __be64 events;
+
        set_bit(d->hwirq, &opal_event_irqchip.mask);
 
-       opal_poll_events(&last_outstanding_events);
+       opal_poll_events(&events);
+       last_outstanding_events = be64_to_cpu(events);
+
+       /*
+        * We can't just handle the events now with opal_handle_events().
+        * If we did we would deadlock when opal_event_unmask() is called from
+        * handle_level_irq() with the irq descriptor lock held, because
+        * calling opal_handle_events() would call generic_handle_irq() and
+        * then handle_level_irq() which would try to take the descriptor lock
+        * again. Instead queue the events for later.
+        */
        if (last_outstanding_events & opal_event_irqchip.mask)
                /* Need to retrigger the interrupt */
                irq_work_queue(&opal_event_irq_work);
@@ -96,29 +131,6 @@ static int opal_event_map(struct irq_domain *d, unsigned int irq,
        return 0;
 }
 
-void opal_handle_events(uint64_t events)
-{
-       int virq, hwirq = 0;
-       u64 mask = opal_event_irqchip.mask;
-
-       if (!in_irq() && (events & mask)) {
-               last_outstanding_events = events;
-               irq_work_queue(&opal_event_irq_work);
-               return;
-       }
-
-       while (events & mask) {
-               hwirq = fls64(events) - 1;
-               if (BIT_ULL(hwirq) & mask) {
-                       virq = irq_find_mapping(opal_event_irqchip.domain,
-                                               hwirq);
-                       if (virq)
-                               generic_handle_irq(virq);
-               }
-               events &= ~BIT_ULL(hwirq);
-       }
-}
-
 static irqreturn_t opal_interrupt(int irq, void *data)
 {
        __be64 events;
@@ -131,7 +143,7 @@ static irqreturn_t opal_interrupt(int irq, void *data)
 
 static void opal_handle_irq_work(struct irq_work *work)
 {
-       opal_handle_events(be64_to_cpu(last_outstanding_events));
+       opal_handle_events(last_outstanding_events);
 }
 
 static int opal_event_match(struct irq_domain *h, struct device_node *node,
index 4296d55e88f30afa7cb91fd54d06e6b2a532d577..57cffb80bc36a85d975dc993235c02efda1d7be8 100644 (file)
@@ -278,7 +278,7 @@ static void opal_handle_message(void)
 
        /* Sanity check */
        if (type >= OPAL_MSG_TYPE_MAX) {
-               pr_warning("%s: Unknown message type: %u\n", __func__, type);
+               pr_warn_once("%s: Unknown message type: %u\n", __func__, type);
                return;
        }
        opal_message_do_notify(type, (void *)&msg);
index 8140d10c67850902d9f60c967000dff7bdcd26a7..6e72961608f0d42f800a4f57b15d08c8456a38ab 100644 (file)
@@ -1920,16 +1920,23 @@ static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
                        }
                        if (separator)
                                ptr += sprintf(ptr, "%c", separator);
+                       /*
+                        * Use four '%' characters below because of the
+                        * following two conversions:
+                        *
+                        *  1) sprintf: %%%%r -> %%r
+                        *  2) printk : %%r   -> %r
+                        */
                        if (operand->flags & OPERAND_GPR)
-                               ptr += sprintf(ptr, "%%r%i", value);
+                               ptr += sprintf(ptr, "%%%%r%i", value);
                        else if (operand->flags & OPERAND_FPR)
-                               ptr += sprintf(ptr, "%%f%i", value);
+                               ptr += sprintf(ptr, "%%%%f%i", value);
                        else if (operand->flags & OPERAND_AR)
-                               ptr += sprintf(ptr, "%%a%i", value);
+                               ptr += sprintf(ptr, "%%%%a%i", value);
                        else if (operand->flags & OPERAND_CR)
-                               ptr += sprintf(ptr, "%%c%i", value);
+                               ptr += sprintf(ptr, "%%%%c%i", value);
                        else if (operand->flags & OPERAND_VR)
-                               ptr += sprintf(ptr, "%%v%i", value);
+                               ptr += sprintf(ptr, "%%%%v%i", value);
                        else if (operand->flags & OPERAND_PCREL)
                                ptr += sprintf(ptr, "%lx", (signed int) value
                                                                      + addr);
index e6820c86e8c7bc1c0daf34cd9a891c45b3a5775f..47ebd5b5ed55e018343e0c577eb2ca21e885bc17 100644 (file)
 #define __NR_fsetxattr         256
 #define __NR_getxattr          257
 #define __NR_lgetxattr         258
-#define __NR_fgetxattr         269
+#define __NR_fgetxattr         259
 #define __NR_listxattr         260
 #define __NR_llistxattr                261
 #define __NR_flistxattr                262
index 7cfd7f153966719c9201a66ff6043c3e48a47a93..4dca18347ee9a40949d55af11ae6adf07d05ca4b 100644 (file)
@@ -10,7 +10,7 @@
  *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
  *  Copyright (C) 2009 Jaswinder Singh Rajput
  *  Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
- *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra
  *  Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
  *
  * ppc:
index 370ca1e71ffbc8dc2fb4cd9567b44f95cf61eee6..93310837c2dfaa27ce384a32d2e7cec3c75c15fa 100644 (file)
@@ -95,6 +95,7 @@
  * really available.  So we simply advertise only "crypto" support.
  */
 #define HWCAP_SPARC_CRYPTO     0x04000000 /* CRYPTO insns available */
+#define HWCAP_SPARC_ADI                0x08000000 /* ADI available */
 
 #define CORE_DUMP_USE_REGSET
 
index efe9479f837bb50d289106cd22128292dd19ef5f..1c26d440d288dfb8d28579fda55e2a76ccf4c139 100644 (file)
 #define __NR_bpf               349
 #define __NR_execveat          350
 #define __NR_membarrier                351
+#define __NR_userfaultfd       352
+#define __NR_bind              353
+#define __NR_listen            354
+#define __NR_setsockopt                355
+#define __NR_mlock2            356
 
-#define NR_syscalls            352
+#define NR_syscalls            357
 
 /* Bitmask values returned from kern_features system call.  */
 #define KERN_FEATURE_MIXED_MODE_STACK  0x00000001
index 3d61fcae7ee38beaabe1b6f66bbdd781c43f1353..f2d30cab5b3f388fa9b446cf5b12afda92fa0a9d 100644 (file)
@@ -946,6 +946,12 @@ ENTRY(__retl_one)
         mov    1, %o0
 ENDPROC(__retl_one)
 
+ENTRY(__retl_one_fp)
+       VISExitHalf
+       retl
+        mov    1, %o0
+ENDPROC(__retl_one_fp)
+
 ENTRY(__ret_one_asi)
        wr      %g0, ASI_AIUS, %asi
        ret
@@ -958,6 +964,13 @@ ENTRY(__retl_one_asi)
         mov    1, %o0
 ENDPROC(__retl_one_asi)
 
+ENTRY(__retl_one_asi_fp)
+       wr      %g0, ASI_AIUS, %asi
+       VISExitHalf
+       retl
+        mov    1, %o0
+ENDPROC(__retl_one_asi_fp)
+
 ENTRY(__retl_o1)
        retl
         mov    %o1, %o0
index b0da5aedb336c643baf9163c010c6c679ce6bbdc..6596f66ce1126fa487b7ce8eec19ef17dc4912e7 100644 (file)
@@ -9,7 +9,7 @@
  *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
  *  Copyright (C) 2009 Jaswinder Singh Rajput
  *  Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
- *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra
  */
 
 #include <linux/perf_event.h>
@@ -1828,11 +1828,18 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry,
 void
 perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
+       u64 saved_fault_address = current_thread_info()->fault_address;
+       u8 saved_fault_code = get_thread_fault_code();
+       mm_segment_t old_fs;
+
        perf_callchain_store(entry, regs->tpc);
 
        if (!current->mm)
                return;
 
+       old_fs = get_fs();
+       set_fs(USER_DS);
+
        flushw_user();
 
        pagefault_disable();
@@ -1843,4 +1850,8 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
                perf_callchain_user_64(entry, regs);
 
        pagefault_enable();
+
+       set_fs(old_fs);
+       set_thread_fault_code(saved_fault_code);
+       current_thread_info()->fault_address = saved_fault_address;
 }
index 39f0c662f4c81dcdf3050926a5a9525d352933a3..d08bdaffdbfccbafc9b3d67c30267fe397eb917f 100644 (file)
@@ -73,7 +73,13 @@ rtrap_nmi:   ldx                     [%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
                andn                    %l1, %l4, %l1
                srl                     %l4, 20, %l4
                ba,pt                   %xcc, rtrap_no_irq_enable
-                wrpr                   %l4, %pil
+               nop
+               /* Do not actually set the %pil here.  We will do that
+                * below after we clear PSTATE_IE in the %pstate register.
+                * If we re-enable interrupts here, we can recurse down
+                * the hardirq stack potentially endlessly, causing a
+                * stack overflow.
+                */
 
                .align                  64
                .globl                  rtrap_irq, rtrap, irqsz_patchme, rtrap_xcall
index f7b261749383b4992300ba4418b1d16ef7251360..f3185e2b028b86886a2a185faee9d99fa5c5c47f 100644 (file)
@@ -380,7 +380,8 @@ static const char *hwcaps[] = {
         */
        "mul32", "div32", "fsmuld", "v8plus", "popc", "vis", "vis2",
        "ASIBlkInit", "fmaf", "vis3", "hpc", "random", "trans", "fjfmau",
-       "ima", "cspare", "pause", "cbcond",
+       "ima", "cspare", "pause", "cbcond", NULL /*reserved for crypto */,
+       "adp",
 };
 
 static const char *crypto_hwcaps[] = {
@@ -396,7 +397,7 @@ void cpucap_info(struct seq_file *m)
        seq_puts(m, "cpucaps\t\t: ");
        for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
                unsigned long bit = 1UL << i;
-               if (caps & bit) {
+               if (hwcaps[i] && (caps & bit)) {
                        seq_printf(m, "%s%s",
                                   printed ? "," : "", hwcaps[i]);
                        printed++;
@@ -450,7 +451,7 @@ static void __init report_hwcaps(unsigned long caps)
 
        for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
                unsigned long bit = 1UL << i;
-               if (caps & bit)
+               if (hwcaps[i] && (caps & bit))
                        report_one_hwcap(&printed, hwcaps[i]);
        }
        if (caps & HWCAP_SPARC_CRYPTO)
@@ -485,7 +486,7 @@ static unsigned long __init mdesc_cpu_hwcap_list(void)
                for (i = 0; i < ARRAY_SIZE(hwcaps); i++) {
                        unsigned long bit = 1UL << i;
 
-                       if (!strcmp(prop, hwcaps[i])) {
+                       if (hwcaps[i] && !strcmp(prop, hwcaps[i])) {
                                caps |= bit;
                                break;
                        }
index cc23b62b6e38a858c7e077c6b2c0757a63803b3d..e663b6c78de2e6498a5a458f1129504cae3ab2a8 100644 (file)
@@ -35,18 +35,18 @@ sys_call_table:
 /*80*/ .long sys_setgroups16, sys_getpgrp, sys_setgroups, sys_setitimer, sys_ftruncate64
 /*85*/ .long sys_swapon, sys_getitimer, sys_setuid, sys_sethostname, sys_setgid
 /*90*/ .long sys_dup2, sys_setfsuid, sys_fcntl, sys_select, sys_setfsgid
-/*95*/ .long sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+/*95*/ .long sys_fsync, sys_setpriority, sys_socket, sys_connect, sys_accept
 /*100*/        .long sys_getpriority, sys_rt_sigreturn, sys_rt_sigaction, sys_rt_sigprocmask, sys_rt_sigpending
 /*105*/        .long sys_rt_sigtimedwait, sys_rt_sigqueueinfo, sys_rt_sigsuspend, sys_setresuid, sys_getresuid
-/*110*/        .long sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall
-/*115*/        .long sys_getgroups, sys_gettimeofday, sys_getrusage, sys_nis_syscall, sys_getcwd
+/*110*/        .long sys_setresgid, sys_getresgid, sys_setregid, sys_recvmsg, sys_sendmsg
+/*115*/        .long sys_getgroups, sys_gettimeofday, sys_getrusage, sys_getsockopt, sys_getcwd
 /*120*/        .long sys_readv, sys_writev, sys_settimeofday, sys_fchown16, sys_fchmod
-/*125*/        .long sys_nis_syscall, sys_setreuid16, sys_setregid16, sys_rename, sys_truncate
-/*130*/        .long sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall
-/*135*/        .long sys_nis_syscall, sys_mkdir, sys_rmdir, sys_utimes, sys_stat64
-/*140*/        .long sys_sendfile64, sys_nis_syscall, sys_futex, sys_gettid, sys_getrlimit
+/*125*/        .long sys_recvfrom, sys_setreuid16, sys_setregid16, sys_rename, sys_truncate
+/*130*/        .long sys_ftruncate, sys_flock, sys_lstat64, sys_sendto, sys_shutdown
+/*135*/        .long sys_socketpair, sys_mkdir, sys_rmdir, sys_utimes, sys_stat64
+/*140*/        .long sys_sendfile64, sys_getpeername, sys_futex, sys_gettid, sys_getrlimit
 /*145*/        .long sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
-/*150*/        .long sys_nis_syscall, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64
+/*150*/        .long sys_getsockname, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64
 /*155*/        .long sys_fcntl64, sys_inotify_rm_watch, sys_statfs, sys_fstatfs, sys_oldumount
 /*160*/        .long sys_sched_setaffinity, sys_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall
 /*165*/        .long sys_quotactl, sys_set_tid_address, sys_mount, sys_ustat, sys_setxattr
@@ -87,4 +87,5 @@ sys_call_table:
 /*335*/        .long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
 /*340*/        .long sys_ni_syscall, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
 /*345*/        .long sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf
-/*350*/        .long sys_execveat, sys_membarrier
+/*350*/        .long sys_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen
+/*355*/        .long sys_setsockopt, sys_mlock2
index f229468a747975ea7eb0dac89886747efb52f773..1557121f4cdce8a6ae21c31fb33e9aa2d7cbc443 100644 (file)
@@ -37,15 +37,15 @@ sys_call_table32:
 /*80*/ .word sys_setgroups16, sys_getpgrp, sys_setgroups, compat_sys_setitimer, sys32_ftruncate64
        .word sys_swapon, compat_sys_getitimer, sys_setuid, sys_sethostname, sys_setgid
 /*90*/ .word sys_dup2, sys_setfsuid, compat_sys_fcntl, sys32_select, sys_setfsgid
-       .word sys_fsync, sys_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+       .word sys_fsync, sys_setpriority, sys_socket, sys_connect, sys_accept
 /*100*/ .word sys_getpriority, sys32_rt_sigreturn, compat_sys_rt_sigaction, compat_sys_rt_sigprocmask, compat_sys_rt_sigpending
        .word compat_sys_rt_sigtimedwait, compat_sys_rt_sigqueueinfo, compat_sys_rt_sigsuspend, sys_setresuid, sys_getresuid
-/*110*/        .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall
-       .word sys_getgroups, compat_sys_gettimeofday, compat_sys_getrusage, sys_nis_syscall, sys_getcwd
+/*110*/        .word sys_setresgid, sys_getresgid, sys_setregid, compat_sys_recvmsg, compat_sys_sendmsg
+       .word sys_getgroups, compat_sys_gettimeofday, compat_sys_getrusage, compat_sys_getsockopt, sys_getcwd
 /*120*/        .word compat_sys_readv, compat_sys_writev, compat_sys_settimeofday, sys_fchown16, sys_fchmod
-       .word sys_nis_syscall, sys_setreuid16, sys_setregid16, sys_rename, compat_sys_truncate
-/*130*/        .word compat_sys_ftruncate, sys_flock, compat_sys_lstat64, sys_nis_syscall, sys_nis_syscall
-       .word sys_nis_syscall, sys_mkdir, sys_rmdir, compat_sys_utimes, compat_sys_stat64
+       .word sys_recvfrom, sys_setreuid16, sys_setregid16, sys_rename, compat_sys_truncate
+/*130*/        .word compat_sys_ftruncate, sys_flock, compat_sys_lstat64, sys_sendto, sys_shutdown
+       .word sys_socketpair, sys_mkdir, sys_rmdir, compat_sys_utimes, compat_sys_stat64
 /*140*/        .word sys_sendfile64, sys_nis_syscall, sys32_futex, sys_gettid, compat_sys_getrlimit
        .word compat_sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
 /*150*/        .word sys_nis_syscall, sys_inotify_init, sys_inotify_add_watch, sys_poll, sys_getdents64
@@ -88,7 +88,8 @@ sys_call_table32:
        .word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev
 /*340*/        .word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
        .word sys32_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf
-/*350*/        .word sys32_execveat, sys_membarrier
+/*350*/        .word sys32_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen
+       .word compat_sys_setsockopt, sys_mlock2
 
 #endif /* CONFIG_COMPAT */
 
@@ -168,4 +169,5 @@ sys_call_table:
        .word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
 /*340*/        .word sys_kern_features, sys_kcmp, sys_finit_module, sys_sched_setattr, sys_sched_getattr
        .word sys_renameat2, sys_seccomp, sys_getrandom, sys_memfd_create, sys_bpf
-/*350*/        .word sys64_execveat, sys_membarrier
+/*350*/        .word sys64_execveat, sys_membarrier, sys_userfaultfd, sys_bind, sys_listen
+       .word sys_setsockopt, sys_mlock2
index 119ccb9a54f49e2ac2724650060eb7a1d70e8d9e..d5242b8c4f9495fe4241ee39de01255364e877af 100644 (file)
        .text;                  \
        .align 4;
 
+#define EX_LD_FP(x)            \
+98:    x;                      \
+       .section __ex_table,"a";\
+       .align 4;               \
+       .word 98b, __retl_one_asi_fp;\
+       .text;                  \
+       .align 4;
+
 #ifndef ASI_AIUS
 #define ASI_AIUS       0x11
 #endif
index 7fe1ccefd9d056a104407c8d1595095c7fc5add8..4e962d993b10cdff7677f8d51e61ad877901facc 100644 (file)
        .text;                  \
        .align 4;
 
+#define EX_ST_FP(x)            \
+98:    x;                      \
+       .section __ex_table,"a";\
+       .align 4;               \
+       .word 98b, __retl_one_asi_fp;\
+       .text;                  \
+       .align 4;
+
 #ifndef ASI_AIUS
 #define ASI_AIUS       0x11
 #endif
index 30eee6e8a81b2d45797aab304914b10571573b1a..d5f585df2f3fc345c87f04fb1a420fa766816cb5 100644 (file)
 #ifndef EX_LD
 #define EX_LD(x)       x
 #endif
+#ifndef EX_LD_FP
+#define EX_LD_FP(x)    x
+#endif
 
 #ifndef EX_ST
 #define EX_ST(x)       x
 #endif
+#ifndef EX_ST_FP
+#define EX_ST_FP(x)    x
+#endif
 
 #ifndef EX_RETVAL
 #define EX_RETVAL(x)   x
        fsrc2           %x6, %f12; \
        fsrc2           %x7, %f14;
 #define FREG_LOAD_1(base, x0) \
-       EX_LD(LOAD(ldd, base + 0x00, %x0))
+       EX_LD_FP(LOAD(ldd, base + 0x00, %x0))
 #define FREG_LOAD_2(base, x0, x1) \
-       EX_LD(LOAD(ldd, base + 0x00, %x0)); \
-       EX_LD(LOAD(ldd, base + 0x08, %x1));
+       EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
+       EX_LD_FP(LOAD(ldd, base + 0x08, %x1));
 #define FREG_LOAD_3(base, x0, x1, x2) \
-       EX_LD(LOAD(ldd, base + 0x00, %x0)); \
-       EX_LD(LOAD(ldd, base + 0x08, %x1)); \
-       EX_LD(LOAD(ldd, base + 0x10, %x2));
+       EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
+       EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
+       EX_LD_FP(LOAD(ldd, base + 0x10, %x2));
 #define FREG_LOAD_4(base, x0, x1, x2, x3) \
-       EX_LD(LOAD(ldd, base + 0x00, %x0)); \
-       EX_LD(LOAD(ldd, base + 0x08, %x1)); \
-       EX_LD(LOAD(ldd, base + 0x10, %x2)); \
-       EX_LD(LOAD(ldd, base + 0x18, %x3));
+       EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
+       EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
+       EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \
+       EX_LD_FP(LOAD(ldd, base + 0x18, %x3));
 #define FREG_LOAD_5(base, x0, x1, x2, x3, x4) \
-       EX_LD(LOAD(ldd, base + 0x00, %x0)); \
-       EX_LD(LOAD(ldd, base + 0x08, %x1)); \
-       EX_LD(LOAD(ldd, base + 0x10, %x2)); \
-       EX_LD(LOAD(ldd, base + 0x18, %x3)); \
-       EX_LD(LOAD(ldd, base + 0x20, %x4));
+       EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
+       EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
+       EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \
+       EX_LD_FP(LOAD(ldd, base + 0x18, %x3)); \
+       EX_LD_FP(LOAD(ldd, base + 0x20, %x4));
 #define FREG_LOAD_6(base, x0, x1, x2, x3, x4, x5) \
-       EX_LD(LOAD(ldd, base + 0x00, %x0)); \
-       EX_LD(LOAD(ldd, base + 0x08, %x1)); \
-       EX_LD(LOAD(ldd, base + 0x10, %x2)); \
-       EX_LD(LOAD(ldd, base + 0x18, %x3)); \
-       EX_LD(LOAD(ldd, base + 0x20, %x4)); \
-       EX_LD(LOAD(ldd, base + 0x28, %x5));
+       EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
+       EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
+       EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \
+       EX_LD_FP(LOAD(ldd, base + 0x18, %x3)); \
+       EX_LD_FP(LOAD(ldd, base + 0x20, %x4)); \
+       EX_LD_FP(LOAD(ldd, base + 0x28, %x5));
 #define FREG_LOAD_7(base, x0, x1, x2, x3, x4, x5, x6) \
-       EX_LD(LOAD(ldd, base + 0x00, %x0)); \
-       EX_LD(LOAD(ldd, base + 0x08, %x1)); \
-       EX_LD(LOAD(ldd, base + 0x10, %x2)); \
-       EX_LD(LOAD(ldd, base + 0x18, %x3)); \
-       EX_LD(LOAD(ldd, base + 0x20, %x4)); \
-       EX_LD(LOAD(ldd, base + 0x28, %x5)); \
-       EX_LD(LOAD(ldd, base + 0x30, %x6));
+       EX_LD_FP(LOAD(ldd, base + 0x00, %x0)); \
+       EX_LD_FP(LOAD(ldd, base + 0x08, %x1)); \
+       EX_LD_FP(LOAD(ldd, base + 0x10, %x2)); \
+       EX_LD_FP(LOAD(ldd, base + 0x18, %x3)); \
+       EX_LD_FP(LOAD(ldd, base + 0x20, %x4)); \
+       EX_LD_FP(LOAD(ldd, base + 0x28, %x5)); \
+       EX_LD_FP(LOAD(ldd, base + 0x30, %x6));
 
        .register       %g2,#scratch
        .register       %g3,#scratch
@@ -275,11 +281,11 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
         nop
        /* fall through for 0 < low bits < 8 */
 110:   sub             %o4, 64, %g2
-       EX_LD(LOAD_BLK(%g2, %f0))
-1:     EX_ST(STORE_INIT(%g0, %o4 + %g3))
-       EX_LD(LOAD_BLK(%o4, %f16))
+       EX_LD_FP(LOAD_BLK(%g2, %f0))
+1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
+       EX_LD_FP(LOAD_BLK(%o4, %f16))
        FREG_FROB(f0, f2, f4, f6, f8, f10, f12, f14, f16)
-       EX_ST(STORE_BLK(%f0, %o4 + %g3))
+       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
        FREG_MOVE_8(f16, f18, f20, f22, f24, f26, f28, f30)
        subcc           %g1, 64, %g1
        add             %o4, 64, %o4
@@ -290,10 +296,10 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
 120:   sub             %o4, 56, %g2
        FREG_LOAD_7(%g2, f0, f2, f4, f6, f8, f10, f12)
-1:     EX_ST(STORE_INIT(%g0, %o4 + %g3))
-       EX_LD(LOAD_BLK(%o4, %f16))
+1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
+       EX_LD_FP(LOAD_BLK(%o4, %f16))
        FREG_FROB(f0, f2, f4, f6, f8, f10, f12, f16, f18)
-       EX_ST(STORE_BLK(%f0, %o4 + %g3))
+       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
        FREG_MOVE_7(f18, f20, f22, f24, f26, f28, f30)
        subcc           %g1, 64, %g1
        add             %o4, 64, %o4
@@ -304,10 +310,10 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
 130:   sub             %o4, 48, %g2
        FREG_LOAD_6(%g2, f0, f2, f4, f6, f8, f10)
-1:     EX_ST(STORE_INIT(%g0, %o4 + %g3))
-       EX_LD(LOAD_BLK(%o4, %f16))
+1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
+       EX_LD_FP(LOAD_BLK(%o4, %f16))
        FREG_FROB(f0, f2, f4, f6, f8, f10, f16, f18, f20)
-       EX_ST(STORE_BLK(%f0, %o4 + %g3))
+       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
        FREG_MOVE_6(f20, f22, f24, f26, f28, f30)
        subcc           %g1, 64, %g1
        add             %o4, 64, %o4
@@ -318,10 +324,10 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
 140:   sub             %o4, 40, %g2
        FREG_LOAD_5(%g2, f0, f2, f4, f6, f8)
-1:     EX_ST(STORE_INIT(%g0, %o4 + %g3))
-       EX_LD(LOAD_BLK(%o4, %f16))
+1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
+       EX_LD_FP(LOAD_BLK(%o4, %f16))
        FREG_FROB(f0, f2, f4, f6, f8, f16, f18, f20, f22)
-       EX_ST(STORE_BLK(%f0, %o4 + %g3))
+       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
        FREG_MOVE_5(f22, f24, f26, f28, f30)
        subcc           %g1, 64, %g1
        add             %o4, 64, %o4
@@ -332,10 +338,10 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
 150:   sub             %o4, 32, %g2
        FREG_LOAD_4(%g2, f0, f2, f4, f6)
-1:     EX_ST(STORE_INIT(%g0, %o4 + %g3))
-       EX_LD(LOAD_BLK(%o4, %f16))
+1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
+       EX_LD_FP(LOAD_BLK(%o4, %f16))
        FREG_FROB(f0, f2, f4, f6, f16, f18, f20, f22, f24)
-       EX_ST(STORE_BLK(%f0, %o4 + %g3))
+       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
        FREG_MOVE_4(f24, f26, f28, f30)
        subcc           %g1, 64, %g1
        add             %o4, 64, %o4
@@ -346,10 +352,10 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
 160:   sub             %o4, 24, %g2
        FREG_LOAD_3(%g2, f0, f2, f4)
-1:     EX_ST(STORE_INIT(%g0, %o4 + %g3))
-       EX_LD(LOAD_BLK(%o4, %f16))
+1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
+       EX_LD_FP(LOAD_BLK(%o4, %f16))
        FREG_FROB(f0, f2, f4, f16, f18, f20, f22, f24, f26)
-       EX_ST(STORE_BLK(%f0, %o4 + %g3))
+       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
        FREG_MOVE_3(f26, f28, f30)
        subcc           %g1, 64, %g1
        add             %o4, 64, %o4
@@ -360,10 +366,10 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
 170:   sub             %o4, 16, %g2
        FREG_LOAD_2(%g2, f0, f2)
-1:     EX_ST(STORE_INIT(%g0, %o4 + %g3))
-       EX_LD(LOAD_BLK(%o4, %f16))
+1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
+       EX_LD_FP(LOAD_BLK(%o4, %f16))
        FREG_FROB(f0, f2, f16, f18, f20, f22, f24, f26, f28)
-       EX_ST(STORE_BLK(%f0, %o4 + %g3))
+       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
        FREG_MOVE_2(f28, f30)
        subcc           %g1, 64, %g1
        add             %o4, 64, %o4
@@ -374,10 +380,10 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
 180:   sub             %o4, 8, %g2
        FREG_LOAD_1(%g2, f0)
-1:     EX_ST(STORE_INIT(%g0, %o4 + %g3))
-       EX_LD(LOAD_BLK(%o4, %f16))
+1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
+       EX_LD_FP(LOAD_BLK(%o4, %f16))
        FREG_FROB(f0, f16, f18, f20, f22, f24, f26, f28, f30)
-       EX_ST(STORE_BLK(%f0, %o4 + %g3))
+       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
        FREG_MOVE_1(f30)
        subcc           %g1, 64, %g1
        add             %o4, 64, %o4
@@ -387,10 +393,10 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
         nop
 
 190:
-1:     EX_ST(STORE_INIT(%g0, %o4 + %g3))
+1:     EX_ST_FP(STORE_INIT(%g0, %o4 + %g3))
        subcc           %g1, 64, %g1
-       EX_LD(LOAD_BLK(%o4, %f0))
-       EX_ST(STORE_BLK(%f0, %o4 + %g3))
+       EX_LD_FP(LOAD_BLK(%o4, %f0))
+       EX_ST_FP(STORE_BLK(%f0, %o4 + %g3))
        add             %o4, 64, %o4
        bne,pt          %xcc, 1b
         LOAD(prefetch, %o4 + 64, #one_read)
index fd9f903ffa3269713dcec781a0ed93a77ae70c1b..2e8ee7ad07a9ce06129cd63c4129ccade674ab77 100644 (file)
        .text;                  \
        .align 4;
 
+#define EX_LD_FP(x)            \
+98:    x;                      \
+       .section __ex_table,"a";\
+       .align 4;               \
+       .word 98b, __retl_one_asi_fp;\
+       .text;                  \
+       .align 4;
+
 #ifndef ASI_AIUS
 #define ASI_AIUS       0x11
 #endif
index 9744c4540a8d99f6010a859aa1ef1510f7b70827..be0bf4590df8971ddf29a81153f05de7c0ef30da 100644 (file)
        .text;                  \
        .align 4;
 
+#define EX_ST_FP(x)            \
+98:    x;                      \
+       .section __ex_table,"a";\
+       .align 4;               \
+       .word 98b, __retl_one_asi_fp;\
+       .text;                  \
+       .align 4;
+
 #ifndef ASI_AIUS
 #define ASI_AIUS       0x11
 #endif
index 83aeeb1dffdb3b4c29293d5924cd5259e2269ce5..8e13ee1f4454ea2b6478d302a9a1048bfeb60aff 100644 (file)
 #ifndef EX_LD
 #define EX_LD(x)       x
 #endif
+#ifndef EX_LD_FP
+#define EX_LD_FP(x)    x
+#endif
 
 #ifndef EX_ST
 #define EX_ST(x)       x
 #endif
+#ifndef EX_ST_FP
+#define EX_ST_FP(x)    x
+#endif
 
 #ifndef EX_RETVAL
 #define EX_RETVAL(x)   x
@@ -210,17 +216,17 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
        sub             %o2, %o4, %o2
        alignaddr       %o1, %g0, %g1
        add             %o1, %o4, %o1
-       EX_LD(LOAD(ldd, %g1 + 0x00, %f0))
-1:     EX_LD(LOAD(ldd, %g1 + 0x08, %f2))
+       EX_LD_FP(LOAD(ldd, %g1 + 0x00, %f0))
+1:     EX_LD_FP(LOAD(ldd, %g1 + 0x08, %f2))
        subcc           %o4, 0x40, %o4
-       EX_LD(LOAD(ldd, %g1 + 0x10, %f4))
-       EX_LD(LOAD(ldd, %g1 + 0x18, %f6))
-       EX_LD(LOAD(ldd, %g1 + 0x20, %f8))
-       EX_LD(LOAD(ldd, %g1 + 0x28, %f10))
-       EX_LD(LOAD(ldd, %g1 + 0x30, %f12))
-       EX_LD(LOAD(ldd, %g1 + 0x38, %f14))
+       EX_LD_FP(LOAD(ldd, %g1 + 0x10, %f4))
+       EX_LD_FP(LOAD(ldd, %g1 + 0x18, %f6))
+       EX_LD_FP(LOAD(ldd, %g1 + 0x20, %f8))
+       EX_LD_FP(LOAD(ldd, %g1 + 0x28, %f10))
+       EX_LD_FP(LOAD(ldd, %g1 + 0x30, %f12))
+       EX_LD_FP(LOAD(ldd, %g1 + 0x38, %f14))
        faligndata      %f0, %f2, %f16
-       EX_LD(LOAD(ldd, %g1 + 0x40, %f0))
+       EX_LD_FP(LOAD(ldd, %g1 + 0x40, %f0))
        faligndata      %f2, %f4, %f18
        add             %g1, 0x40, %g1
        faligndata      %f4, %f6, %f20
@@ -229,14 +235,14 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
        faligndata      %f10, %f12, %f26
        faligndata      %f12, %f14, %f28
        faligndata      %f14, %f0, %f30
-       EX_ST(STORE(std, %f16, %o0 + 0x00))
-       EX_ST(STORE(std, %f18, %o0 + 0x08))
-       EX_ST(STORE(std, %f20, %o0 + 0x10))
-       EX_ST(STORE(std, %f22, %o0 + 0x18))
-       EX_ST(STORE(std, %f24, %o0 + 0x20))
-       EX_ST(STORE(std, %f26, %o0 + 0x28))
-       EX_ST(STORE(std, %f28, %o0 + 0x30))
-       EX_ST(STORE(std, %f30, %o0 + 0x38))
+       EX_ST_FP(STORE(std, %f16, %o0 + 0x00))
+       EX_ST_FP(STORE(std, %f18, %o0 + 0x08))
+       EX_ST_FP(STORE(std, %f20, %o0 + 0x10))
+       EX_ST_FP(STORE(std, %f22, %o0 + 0x18))
+       EX_ST_FP(STORE(std, %f24, %o0 + 0x20))
+       EX_ST_FP(STORE(std, %f26, %o0 + 0x28))
+       EX_ST_FP(STORE(std, %f28, %o0 + 0x30))
+       EX_ST_FP(STORE(std, %f30, %o0 + 0x38))
        add             %o0, 0x40, %o0
        bne,pt          %icc, 1b
         LOAD(prefetch, %g1 + 0x200, #n_reads_strong)
index a6ae2ea04bf5dfbffda2884a6a46b051ae2ac2a8..ecc5692fa2b49a3acfc6a6592c6c247835417b4c 100644 (file)
        .text;                  \
        .align 4;
 
+#define EX_LD_FP(x)            \
+98:    x;                      \
+       .section __ex_table,"a";\
+       .align 4;               \
+       .word 98b, __retl_one_fp;\
+       .text;                  \
+       .align 4;
+
 #define FUNC_NAME              ___copy_from_user
 #define LOAD(type,addr,dest)   type##a [addr] %asi, dest
 #define LOAD_BLK(addr,dest)    ldda [addr] ASI_BLK_AIUS, dest
index f4b970eeb485f838ce23dc5507a5bccd6defd348..9eea392e44d471679ba85c22867a9767b34912a5 100644 (file)
        .text;                  \
        .align 4;
 
+#define EX_ST_FP(x)            \
+98:    x;                      \
+       .section __ex_table,"a";\
+       .align 4;               \
+       .word 98b, __retl_one_fp;\
+       .text;                  \
+       .align 4;
+
 #define FUNC_NAME              ___copy_to_user
 #define STORE(type,src,addr)   type##a src, [addr] ASI_AIUS
 #define STORE_BLK(src,addr)    stda src, [addr] ASI_BLK_AIUS
index b67142b7768e50e20fb28d5c4ed562435ab145f5..3e6209ebb7d7865fd62bb21df56dabda07fe4f5f 100644 (file)
 #ifndef EX_LD
 #define EX_LD(x)       x
 #endif
+#ifndef EX_LD_FP
+#define EX_LD_FP(x)    x
+#endif
 
 #ifndef EX_ST
 #define EX_ST(x)       x
 #endif
+#ifndef EX_ST_FP
+#define EX_ST_FP(x)    x
+#endif
 
 #ifndef EX_RETVAL
 #define EX_RETVAL(x)   x
@@ -73,8 +79,8 @@
        faligndata              %f8, %f9, %f62;
 
 #define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, len, jmptgt)   \
-       EX_LD(LOAD_BLK(%src, %fdest));                          \
-       EX_ST(STORE_BLK(%fsrc, %dest));                         \
+       EX_LD_FP(LOAD_BLK(%src, %fdest));                               \
+       EX_ST_FP(STORE_BLK(%fsrc, %dest));                              \
        add                     %src, 0x40, %src;               \
        subcc                   %len, 0x40, %len;               \
        be,pn                   %xcc, jmptgt;                   \
 
 #define DO_SYNC                        membar  #Sync;
 #define STORE_SYNC(dest, fsrc)                         \
-       EX_ST(STORE_BLK(%fsrc, %dest));                 \
+       EX_ST_FP(STORE_BLK(%fsrc, %dest));                      \
        add                     %dest, 0x40, %dest;     \
        DO_SYNC
 
 #define STORE_JUMP(dest, fsrc, target)                 \
-       EX_ST(STORE_BLK(%fsrc, %dest));                 \
+       EX_ST_FP(STORE_BLK(%fsrc, %dest));                      \
        add                     %dest, 0x40, %dest;     \
        ba,pt                   %xcc, target;           \
         nop;
        subcc                   %left, 8, %left;\
        bl,pn                   %xcc, 95f;      \
         faligndata             %f0, %f1, %f48; \
-       EX_ST(STORE(std, %f48, %dest));         \
+       EX_ST_FP(STORE(std, %f48, %dest));              \
        add                     %dest, 8, %dest;
 
 #define UNEVEN_VISCHUNK_LAST(dest, f0, f1, left)       \
@@ -160,8 +166,8 @@ FUNC_NAME:          /* %o0=dst, %o1=src, %o2=len */
         and            %g2, 0x38, %g2
 
 1:     subcc           %g1, 0x1, %g1
-       EX_LD(LOAD(ldub, %o1 + 0x00, %o3))
-       EX_ST(STORE(stb, %o3, %o1 + %GLOBAL_SPARE))
+       EX_LD_FP(LOAD(ldub, %o1 + 0x00, %o3))
+       EX_ST_FP(STORE(stb, %o3, %o1 + %GLOBAL_SPARE))
        bgu,pt          %XCC, 1b
         add            %o1, 0x1, %o1
 
@@ -172,20 +178,20 @@ FUNC_NAME:                /* %o0=dst, %o1=src, %o2=len */
        be,pt           %icc, 3f
         alignaddr      %o1, %g0, %o1
 
-       EX_LD(LOAD(ldd, %o1, %f4))
-1:     EX_LD(LOAD(ldd, %o1 + 0x8, %f6))
+       EX_LD_FP(LOAD(ldd, %o1, %f4))
+1:     EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f6))
        add             %o1, 0x8, %o1
        subcc           %g2, 0x8, %g2
        faligndata      %f4, %f6, %f0
-       EX_ST(STORE(std, %f0, %o0))
+       EX_ST_FP(STORE(std, %f0, %o0))
        be,pn           %icc, 3f
         add            %o0, 0x8, %o0
 
-       EX_LD(LOAD(ldd, %o1 + 0x8, %f4))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f4))
        add             %o1, 0x8, %o1
        subcc           %g2, 0x8, %g2
        faligndata      %f6, %f4, %f0
-       EX_ST(STORE(std, %f0, %o0))
+       EX_ST_FP(STORE(std, %f0, %o0))
        bne,pt          %icc, 1b
         add            %o0, 0x8, %o0
 
@@ -208,13 +214,13 @@ FUNC_NAME:                /* %o0=dst, %o1=src, %o2=len */
        add             %g1, %GLOBAL_SPARE, %g1
        subcc           %o2, %g3, %o2
 
-       EX_LD(LOAD_BLK(%o1, %f0))
+       EX_LD_FP(LOAD_BLK(%o1, %f0))
        add             %o1, 0x40, %o1
        add             %g1, %g3, %g1
-       EX_LD(LOAD_BLK(%o1, %f16))
+       EX_LD_FP(LOAD_BLK(%o1, %f16))
        add             %o1, 0x40, %o1
        sub             %GLOBAL_SPARE, 0x80, %GLOBAL_SPARE
-       EX_LD(LOAD_BLK(%o1, %f32))
+       EX_LD_FP(LOAD_BLK(%o1, %f32))
        add             %o1, 0x40, %o1
 
        /* There are 8 instances of the unrolled loop,
@@ -426,28 +432,28 @@ FUNC_NAME:                /* %o0=dst, %o1=src, %o2=len */
 62:    FINISH_VISCHUNK(o0, f44, f46, g3)
 63:    UNEVEN_VISCHUNK_LAST(o0, f46, f0,  g3)
 
-93:    EX_LD(LOAD(ldd, %o1, %f2))
+93:    EX_LD_FP(LOAD(ldd, %o1, %f2))
        add             %o1, 8, %o1
        subcc           %g3, 8, %g3
        faligndata      %f0, %f2, %f8
-       EX_ST(STORE(std, %f8, %o0))
+       EX_ST_FP(STORE(std, %f8, %o0))
        bl,pn           %xcc, 95f
         add            %o0, 8, %o0
-       EX_LD(LOAD(ldd, %o1, %f0))
+       EX_LD_FP(LOAD(ldd, %o1, %f0))
        add             %o1, 8, %o1
        subcc           %g3, 8, %g3
        faligndata      %f2, %f0, %f8
-       EX_ST(STORE(std, %f8, %o0))
+       EX_ST_FP(STORE(std, %f8, %o0))
        bge,pt          %xcc, 93b
         add            %o0, 8, %o0
 
 95:    brz,pt          %o2, 2f
         mov            %g1, %o1
 
-1:     EX_LD(LOAD(ldub, %o1, %o3))
+1:     EX_LD_FP(LOAD(ldub, %o1, %o3))
        add             %o1, 1, %o1
        subcc           %o2, 1, %o2
-       EX_ST(STORE(stb, %o3, %o0))
+       EX_ST_FP(STORE(stb, %o3, %o0))
        bne,pt          %xcc, 1b
         add            %o0, 1, %o0
 
index b1acd1331c338fce1a70e6a13f597509b28501a7..88ad73d86fe44b64c2313483e7490cc8ae0ee438 100644 (file)
        .text;                  \
        .align 4;
 
+#define EX_LD_FP(x)            \
+98:    x;                      \
+       .section __ex_table,"a";\
+       .align 4;               \
+       .word 98b, __retl_one_fp;\
+       .text;                  \
+       .align 4;
+
 #define FUNC_NAME              U3copy_from_user
 #define LOAD(type,addr,dest)   type##a [addr] %asi, dest
 #define EX_RETVAL(x)           0
index ef1e493afdfa900a1b32863c2bf2995560cbe0cd..845139d7553720ce5fe98d6e30bcb11215f71e2f 100644 (file)
        .text;                  \
        .align 4;
 
+#define EX_ST_FP(x)            \
+98:    x;                      \
+       .section __ex_table,"a";\
+       .align 4;               \
+       .word 98b, __retl_one_fp;\
+       .text;                  \
+       .align 4;
+
 #define FUNC_NAME              U3copy_to_user
 #define STORE(type,src,addr)   type##a src, [addr] ASI_AIUS
 #define STORE_BLK(src,addr)    stda src, [addr] ASI_BLK_AIUS
index 7cae9cc6a204a46e535c8c651176ccc873778700..491ee69e49951fc2040640e77b896552872c8a0a 100644 (file)
 #ifndef EX_LD
 #define EX_LD(x)       x
 #endif
+#ifndef EX_LD_FP
+#define EX_LD_FP(x)    x
+#endif
 
 #ifndef EX_ST
 #define EX_ST(x)       x
 #endif
+#ifndef EX_ST_FP
+#define EX_ST_FP(x)    x
+#endif
 
 #ifndef EX_RETVAL
 #define EX_RETVAL(x)   x
@@ -120,8 +126,8 @@ FUNC_NAME:  /* %o0=dst, %o1=src, %o2=len */
         and            %g2, 0x38, %g2
 
 1:     subcc           %g1, 0x1, %g1
-       EX_LD(LOAD(ldub, %o1 + 0x00, %o3))
-       EX_ST(STORE(stb, %o3, %o1 + GLOBAL_SPARE))
+       EX_LD_FP(LOAD(ldub, %o1 + 0x00, %o3))
+       EX_ST_FP(STORE(stb, %o3, %o1 + GLOBAL_SPARE))
        bgu,pt          %XCC, 1b
         add            %o1, 0x1, %o1
 
@@ -132,20 +138,20 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
        be,pt           %icc, 3f
         alignaddr      %o1, %g0, %o1
 
-       EX_LD(LOAD(ldd, %o1, %f4))
-1:     EX_LD(LOAD(ldd, %o1 + 0x8, %f6))
+       EX_LD_FP(LOAD(ldd, %o1, %f4))
+1:     EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f6))
        add             %o1, 0x8, %o1
        subcc           %g2, 0x8, %g2
        faligndata      %f4, %f6, %f0
-       EX_ST(STORE(std, %f0, %o0))
+       EX_ST_FP(STORE(std, %f0, %o0))
        be,pn           %icc, 3f
         add            %o0, 0x8, %o0
 
-       EX_LD(LOAD(ldd, %o1 + 0x8, %f4))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x8, %f4))
        add             %o1, 0x8, %o1
        subcc           %g2, 0x8, %g2
        faligndata      %f6, %f4, %f2
-       EX_ST(STORE(std, %f2, %o0))
+       EX_ST_FP(STORE(std, %f2, %o0))
        bne,pt          %icc, 1b
         add            %o0, 0x8, %o0
 
@@ -155,25 +161,25 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
        LOAD(prefetch, %o1 + 0x080, #one_read)
        LOAD(prefetch, %o1 + 0x0c0, #one_read)
        LOAD(prefetch, %o1 + 0x100, #one_read)
-       EX_LD(LOAD(ldd, %o1 + 0x000, %f0))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x000, %f0))
        LOAD(prefetch, %o1 + 0x140, #one_read)
-       EX_LD(LOAD(ldd, %o1 + 0x008, %f2))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2))
        LOAD(prefetch, %o1 + 0x180, #one_read)
-       EX_LD(LOAD(ldd, %o1 + 0x010, %f4))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4))
        LOAD(prefetch, %o1 + 0x1c0, #one_read)
        faligndata      %f0, %f2, %f16
-       EX_LD(LOAD(ldd, %o1 + 0x018, %f6))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6))
        faligndata      %f2, %f4, %f18
-       EX_LD(LOAD(ldd, %o1 + 0x020, %f8))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8))
        faligndata      %f4, %f6, %f20
-       EX_LD(LOAD(ldd, %o1 + 0x028, %f10))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10))
        faligndata      %f6, %f8, %f22
 
-       EX_LD(LOAD(ldd, %o1 + 0x030, %f12))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12))
        faligndata      %f8, %f10, %f24
-       EX_LD(LOAD(ldd, %o1 + 0x038, %f14))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14))
        faligndata      %f10, %f12, %f26
-       EX_LD(LOAD(ldd, %o1 + 0x040, %f0))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0))
 
        subcc           GLOBAL_SPARE, 0x80, GLOBAL_SPARE
        add             %o1, 0x40, %o1
@@ -184,26 +190,26 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
        .align          64
 1:
-       EX_LD(LOAD(ldd, %o1 + 0x008, %f2))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2))
        faligndata      %f12, %f14, %f28
-       EX_LD(LOAD(ldd, %o1 + 0x010, %f4))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4))
        faligndata      %f14, %f0, %f30
-       EX_ST(STORE_BLK(%f16, %o0))
-       EX_LD(LOAD(ldd, %o1 + 0x018, %f6))
+       EX_ST_FP(STORE_BLK(%f16, %o0))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6))
        faligndata      %f0, %f2, %f16
        add             %o0, 0x40, %o0
 
-       EX_LD(LOAD(ldd, %o1 + 0x020, %f8))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8))
        faligndata      %f2, %f4, %f18
-       EX_LD(LOAD(ldd, %o1 + 0x028, %f10))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10))
        faligndata      %f4, %f6, %f20
-       EX_LD(LOAD(ldd, %o1 + 0x030, %f12))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12))
        subcc           %o3, 0x01, %o3
        faligndata      %f6, %f8, %f22
-       EX_LD(LOAD(ldd, %o1 + 0x038, %f14))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14))
 
        faligndata      %f8, %f10, %f24
-       EX_LD(LOAD(ldd, %o1 + 0x040, %f0))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0))
        LOAD(prefetch, %o1 + 0x1c0, #one_read)
        faligndata      %f10, %f12, %f26
        bg,pt           %XCC, 1b
@@ -211,29 +217,29 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
        /* Finally we copy the last full 64-byte block. */
 2:
-       EX_LD(LOAD(ldd, %o1 + 0x008, %f2))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x008, %f2))
        faligndata      %f12, %f14, %f28
-       EX_LD(LOAD(ldd, %o1 + 0x010, %f4))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x010, %f4))
        faligndata      %f14, %f0, %f30
-       EX_ST(STORE_BLK(%f16, %o0))
-       EX_LD(LOAD(ldd, %o1 + 0x018, %f6))
+       EX_ST_FP(STORE_BLK(%f16, %o0))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x018, %f6))
        faligndata      %f0, %f2, %f16
-       EX_LD(LOAD(ldd, %o1 + 0x020, %f8))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x020, %f8))
        faligndata      %f2, %f4, %f18
-       EX_LD(LOAD(ldd, %o1 + 0x028, %f10))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x028, %f10))
        faligndata      %f4, %f6, %f20
-       EX_LD(LOAD(ldd, %o1 + 0x030, %f12))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x030, %f12))
        faligndata      %f6, %f8, %f22
-       EX_LD(LOAD(ldd, %o1 + 0x038, %f14))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x038, %f14))
        faligndata      %f8, %f10, %f24
        cmp             %g1, 0
        be,pt           %XCC, 1f
         add            %o0, 0x40, %o0
-       EX_LD(LOAD(ldd, %o1 + 0x040, %f0))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x040, %f0))
 1:     faligndata      %f10, %f12, %f26
        faligndata      %f12, %f14, %f28
        faligndata      %f14, %f0, %f30
-       EX_ST(STORE_BLK(%f16, %o0))
+       EX_ST_FP(STORE_BLK(%f16, %o0))
        add             %o0, 0x40, %o0
        add             %o1, 0x40, %o1
        membar          #Sync
@@ -253,20 +259,20 @@ FUNC_NAME:        /* %o0=dst, %o1=src, %o2=len */
 
        sub             %o2, %g2, %o2
        be,a,pt         %XCC, 1f
-        EX_LD(LOAD(ldd, %o1 + 0x00, %f0))
+        EX_LD_FP(LOAD(ldd, %o1 + 0x00, %f0))
 
-1:     EX_LD(LOAD(ldd, %o1 + 0x08, %f2))
+1:     EX_LD_FP(LOAD(ldd, %o1 + 0x08, %f2))
        add             %o1, 0x8, %o1
        subcc           %g2, 0x8, %g2
        faligndata      %f0, %f2, %f8
-       EX_ST(STORE(std, %f8, %o0))
+       EX_ST_FP(STORE(std, %f8, %o0))
        be,pn           %XCC, 2f
         add            %o0, 0x8, %o0
-       EX_LD(LOAD(ldd, %o1 + 0x08, %f0))
+       EX_LD_FP(LOAD(ldd, %o1 + 0x08, %f0))
        add             %o1, 0x8, %o1
        subcc           %g2, 0x8, %g2
        faligndata      %f2, %f0, %f8
-       EX_ST(STORE(std, %f8, %o0))
+       EX_ST_FP(STORE(std, %f8, %o0))
        bne,pn          %XCC, 1b
         add            %o0, 0x8, %o0
 
index 22564f5f23647a6f54752052091d2c74c194bccf..3e6e05a7c4c22b297861eb82871d92b7217cffee 100644 (file)
@@ -420,22 +420,9 @@ void bpf_jit_compile(struct bpf_prog *fp)
                }
                emit_reg_move(O7, r_saved_O7);
 
-               switch (filter[0].code) {
-               case BPF_RET | BPF_K:
-               case BPF_LD | BPF_W | BPF_LEN:
-               case BPF_LD | BPF_W | BPF_ABS:
-               case BPF_LD | BPF_H | BPF_ABS:
-               case BPF_LD | BPF_B | BPF_ABS:
-                       /* The first instruction sets the A register (or is
-                        * a "RET 'constant'")
-                        */
-                       break;
-               default:
-                       /* Make sure we dont leak kernel information to the
-                        * user.
-                        */
+               /* Make sure we dont leak kernel information to the user. */
+               if (bpf_needs_clear_a(&filter[0]))
                        emit_clear(r_A); /* A = 0 */
-               }
 
                for (i = 0; i < flen; i++) {
                        unsigned int K = filter[i].k;
index 106c21bd7f449d947094db5fdefce8a9a6e1b142..8ec7a4599c085dd0d05f7ad819c11d4659223c51 100644 (file)
@@ -176,8 +176,6 @@ config NR_CPUS
          smaller kernel memory footprint results from using a smaller
          value on chips with fewer tiles.
 
-if TILEGX
-
 choice
        prompt "Kernel page size"
        default PAGE_SIZE_64KB
@@ -188,8 +186,11 @@ choice
          connections, etc., it may be better to select 16KB, which uses
          memory more efficiently at some cost in TLB performance.
 
-         Note that this option is TILE-Gx specific; currently
-         TILEPro page size is set by rebuilding the hypervisor.
+         Note that for TILEPro, you must also rebuild the hypervisor
+         with a matching page size.
+
+config PAGE_SIZE_4KB
+       bool "4KB" if TILEPRO
 
 config PAGE_SIZE_16KB
        bool "16KB"
@@ -199,8 +200,6 @@ config PAGE_SIZE_64KB
 
 endchoice
 
-endif
-
 source "kernel/Kconfig.hz"
 
 config KEXEC
index a213a8d84a95ac48a149de807558290c21dbe2cb..8eca6a0e176200c3604151c4168b0553a0002768 100644 (file)
 #include <arch/chip.h>
 
 /* PAGE_SHIFT and HPAGE_SHIFT determine the page sizes. */
-#if defined(CONFIG_PAGE_SIZE_16KB)
+#if defined(CONFIG_PAGE_SIZE_4KB)  /* tilepro only */
+#define PAGE_SHIFT     12
+#define CTX_PAGE_FLAG  HV_CTX_PG_SM_4K
+#elif defined(CONFIG_PAGE_SIZE_16KB)
 #define PAGE_SHIFT     14
 #define CTX_PAGE_FLAG  HV_CTX_PG_SM_16K
 #elif defined(CONFIG_PAGE_SIZE_64KB)
 #define PAGE_SHIFT     16
 #define CTX_PAGE_FLAG  HV_CTX_PG_SM_64K
 #else
-#define PAGE_SHIFT     HV_LOG2_DEFAULT_PAGE_SIZE_SMALL
-#define CTX_PAGE_FLAG  0
+#error Page size not specified in Kconfig
 #endif
 #define HPAGE_SHIFT    HV_LOG2_DEFAULT_PAGE_SIZE_LARGE
 
index bb509cee3b598807eeae1aca6056e7adaed59e19..8767060d70fb32eb2dfc0a7da1010233973d78ea 100644 (file)
@@ -21,7 +21,7 @@
  *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
  *  Copyright (C) 2009 Jaswinder Singh Rajput
  *  Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
- *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra
  *  Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
  *  Copyright (C) 2009 Google, Inc., Stephane Eranian
  */
index 25ed4098640eecf5fc23ae5a8a494b7275badb4a..e3abe6f3156d3fbacca4003c072954619c7e1bb1 100644 (file)
@@ -131,7 +131,7 @@ export LDS_ELF_FORMAT := $(ELF_FORMAT)
 # The wrappers will select whether using "malloc" or the kernel allocator.
 LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
 
-LD_FLAGS_CMDLINE = $(foreach opt,$(LDFLAGS),-Wl,$(opt)) -lrt
+LD_FLAGS_CMDLINE = $(foreach opt,$(LDFLAGS),-Wl,$(opt))
 
 # Used by link-vmlinux.sh which has special support for um link
 export CFLAGS_vmlinux := $(LINK-y) $(LINK_WRAPS) $(LD_FLAGS_CMDLINE)
index e697a4136707e13c609a5e51529f87631896b0c6..e9f8445861dc73639bb32742bb5f6fae327a8b4c 100644 (file)
@@ -249,21 +249,23 @@ void close_addr(unsigned char *addr, unsigned char *netmask, void *arg)
 
 char *split_if_spec(char *str, ...)
 {
-       char **arg, *end;
+       char **arg, *end, *ret = NULL;
        va_list ap;
 
        va_start(ap, str);
        while ((arg = va_arg(ap, char **)) != NULL) {
                if (*str == '\0')
-                       return NULL;
+                       goto out;
                end = strchr(str, ',');
                if (end != str)
                        *arg = str;
                if (end == NULL)
-                       return NULL;
+                       goto out;
                *end++ = '\0';
                str = end;
        }
+       ret = str;
+out:
        va_end(ap);
-       return str;
+       return ret;
 }
index 57acbd67d85dbd4051cd3c534ceff2a300ce9906..fc8be0e3a4ff879a2cf9fddc8e017dfa974ffc95 100644 (file)
@@ -69,7 +69,7 @@ void do_signal(struct pt_regs *regs)
        struct ksignal ksig;
        int handled_sig = 0;
 
-       while (get_signal(&ksig)) {
+       if (get_signal(&ksig)) {
                handled_sig = 1;
                /* Whee!  Actually deliver the signal.  */
                handle_signal(&ksig, regs);
index a89fdbc1f0beb7e7198c7a625767a2cfe32ca9e3..03663740c86655cabf21504578e97d73d98595be 100644 (file)
@@ -421,7 +421,7 @@ __visible long do_fast_syscall_32(struct pt_regs *regs)
        regs->ip = landing_pad;
 
        /*
-        * Fetch ECX from where the vDSO stashed it.
+        * Fetch EBP from where the vDSO stashed it.
         *
         * WARNING: We are in CONTEXT_USER and RCU isn't paying attention!
         */
@@ -432,10 +432,10 @@ __visible long do_fast_syscall_32(struct pt_regs *regs)
                 * Micro-optimization: the pointer we're following is explicitly
                 * 32 bits, so it can't be out of range.
                 */
-               __get_user(*(u32 *)&regs->cx,
+               __get_user(*(u32 *)&regs->bp,
                            (u32 __user __force *)(unsigned long)(u32)regs->sp)
 #else
-               get_user(*(u32 *)&regs->cx,
+               get_user(*(u32 *)&regs->bp,
                         (u32 __user __force *)(unsigned long)(u32)regs->sp)
 #endif
                ) {
index 3eb572ed3d7ad438d8dfd1627b5b4121314c9f67..f3b6d54e0042b7f08c25a82283f88e8193c70c4a 100644 (file)
@@ -292,7 +292,7 @@ ENTRY(entry_SYSENTER_32)
        movl    TSS_sysenter_sp0(%esp), %esp
 sysenter_past_esp:
        pushl   $__USER_DS              /* pt_regs->ss */
-       pushl   %ecx                    /* pt_regs->cx */
+       pushl   %ebp                    /* pt_regs->sp (stashed in bp) */
        pushfl                          /* pt_regs->flags (except IF = 0) */
        orl     $X86_EFLAGS_IF, (%esp)  /* Fix IF */
        pushl   $__USER_CS              /* pt_regs->cs */
@@ -308,8 +308,9 @@ sysenter_past_esp:
 
        movl    %esp, %eax
        call    do_fast_syscall_32
-       testl   %eax, %eax
-       jz      .Lsyscall_32_done
+       /* XEN PV guests always use IRET path */
+       ALTERNATIVE "testl %eax, %eax; jz .Lsyscall_32_done", \
+                   "jmp .Lsyscall_32_done", X86_FEATURE_XENPV
 
 /* Opportunistic SYSEXIT */
        TRACE_IRQS_ON                   /* User mode traces as IRQs on. */
index c3201830a85ee8dcddabb0cab864545d99d47fd3..6a1ae3751e824d9917e65c136e9f7de3cc5f4f47 100644 (file)
@@ -63,7 +63,7 @@ ENTRY(entry_SYSENTER_compat)
 
        /* Construct struct pt_regs on stack */
        pushq   $__USER32_DS            /* pt_regs->ss */
-       pushq   %rcx                    /* pt_regs->sp */
+       pushq   %rbp                    /* pt_regs->sp (stashed in bp) */
 
        /*
         * Push flags.  This is nasty.  First, interrupts are currently
@@ -82,14 +82,14 @@ ENTRY(entry_SYSENTER_compat)
        pushq   %rdi                    /* pt_regs->di */
        pushq   %rsi                    /* pt_regs->si */
        pushq   %rdx                    /* pt_regs->dx */
-       pushq   %rcx                    /* pt_regs->cx (will be overwritten) */
+       pushq   %rcx                    /* pt_regs->cx */
        pushq   $-ENOSYS                /* pt_regs->ax */
        pushq   %r8                     /* pt_regs->r8  = 0 */
        pushq   %r8                     /* pt_regs->r9  = 0 */
        pushq   %r8                     /* pt_regs->r10 = 0 */
        pushq   %r8                     /* pt_regs->r11 = 0 */
        pushq   %rbx                    /* pt_regs->rbx */
-       pushq   %rbp                    /* pt_regs->rbp */
+       pushq   %rbp                    /* pt_regs->rbp (will be overwritten) */
        pushq   %r8                     /* pt_regs->r12 = 0 */
        pushq   %r8                     /* pt_regs->r13 = 0 */
        pushq   %r8                     /* pt_regs->r14 = 0 */
@@ -121,8 +121,9 @@ sysenter_flags_fixed:
 
        movq    %rsp, %rdi
        call    do_fast_syscall_32
-       testl   %eax, %eax
-       jz      .Lsyscall_32_done
+       /* XEN PV guests always use IRET path */
+       ALTERNATIVE "testl %eax, %eax; jz .Lsyscall_32_done", \
+                   "jmp .Lsyscall_32_done", X86_FEATURE_XENPV
        jmp     sysret32_from_system_call
 
 sysenter_fix_flags:
@@ -178,7 +179,7 @@ ENTRY(entry_SYSCALL_compat)
        pushq   %rdi                    /* pt_regs->di */
        pushq   %rsi                    /* pt_regs->si */
        pushq   %rdx                    /* pt_regs->dx */
-       pushq   %rcx                    /* pt_regs->cx (will be overwritten) */
+       pushq   %rbp                    /* pt_regs->cx (stashed in bp) */
        pushq   $-ENOSYS                /* pt_regs->ax */
        xorq    %r8,%r8
        pushq   %r8                     /* pt_regs->r8  = 0 */
@@ -186,7 +187,7 @@ ENTRY(entry_SYSCALL_compat)
        pushq   %r8                     /* pt_regs->r10 = 0 */
        pushq   %r8                     /* pt_regs->r11 = 0 */
        pushq   %rbx                    /* pt_regs->rbx */
-       pushq   %rbp                    /* pt_regs->rbp */
+       pushq   %rbp                    /* pt_regs->rbp (will be overwritten) */
        pushq   %r8                     /* pt_regs->r12 = 0 */
        pushq   %r8                     /* pt_regs->r13 = 0 */
        pushq   %r8                     /* pt_regs->r14 = 0 */
@@ -200,8 +201,9 @@ ENTRY(entry_SYSCALL_compat)
 
        movq    %rsp, %rdi
        call    do_fast_syscall_32
-       testl   %eax, %eax
-       jz      .Lsyscall_32_done
+       /* XEN PV guests always use IRET path */
+       ALTERNATIVE "testl %eax, %eax; jz .Lsyscall_32_done", \
+                   "jmp .Lsyscall_32_done", X86_FEATURE_XENPV
 
        /* Opportunistic SYSRET */
 sysret32_from_system_call:
index 93bd8452383f8e355fcc5743a54947f46ef1a32e..3a1d9297074bc5e1d2e559735bb5247acffa6164 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Code for the vDSO.  This version uses the old int $0x80 method.
+ * AT_SYSINFO entry point
 */
 
 #include <asm/dwarf2.h>
@@ -21,35 +21,67 @@ __kernel_vsyscall:
        /*
         * Reshuffle regs so that all of any of the entry instructions
         * will preserve enough state.
+        *
+        * A really nice entry sequence would be:
+        *  pushl %edx
+        *  pushl %ecx
+        *  movl  %esp, %ecx
+        *
+        * Unfortunately, naughty Android versions between July and December
+        * 2015 actually hardcode the traditional Linux SYSENTER entry
+        * sequence.  That is severely broken for a number of reasons (ask
+        * anyone with an AMD CPU, for example).  Nonetheless, we try to keep
+        * it working approximately as well as it ever worked.
+        *
+        * This link may eludicate some of the history:
+        *   https://android-review.googlesource.com/#/q/Iac3295376d61ef83e713ac9b528f3b50aa780cd7
+        * personally, I find it hard to understand what's going on there.
+        *
+        * Note to future user developers: DO NOT USE SYSENTER IN YOUR CODE.
+        * Execute an indirect call to the address in the AT_SYSINFO auxv
+        * entry.  That is the ONLY correct way to make a fast 32-bit system
+        * call on Linux.  (Open-coding int $0x80 is also fine, but it's
+        * slow.)
         */
+       pushl   %ecx
+       CFI_ADJUST_CFA_OFFSET   4
+       CFI_REL_OFFSET          ecx, 0
        pushl   %edx
        CFI_ADJUST_CFA_OFFSET   4
        CFI_REL_OFFSET          edx, 0
-       pushl   %ecx
+       pushl   %ebp
        CFI_ADJUST_CFA_OFFSET   4
-       CFI_REL_OFFSET          ecx, 0
-       movl    %esp, %ecx
+       CFI_REL_OFFSET          ebp, 0
+
+       #define SYSENTER_SEQUENCE       "movl %esp, %ebp; sysenter"
+       #define SYSCALL_SEQUENCE        "movl %ecx, %ebp; syscall"
 
 #ifdef CONFIG_X86_64
        /* If SYSENTER (Intel) or SYSCALL32 (AMD) is available, use it. */
-       ALTERNATIVE_2 "", "sysenter", X86_FEATURE_SYSENTER32, \
-                         "syscall",  X86_FEATURE_SYSCALL32
+       ALTERNATIVE_2 "", SYSENTER_SEQUENCE, X86_FEATURE_SYSENTER32, \
+                         SYSCALL_SEQUENCE,  X86_FEATURE_SYSCALL32
 #else
-       ALTERNATIVE "", "sysenter", X86_FEATURE_SEP
+       ALTERNATIVE "", SYSENTER_SEQUENCE, X86_FEATURE_SEP
 #endif
 
        /* Enter using int $0x80 */
-       movl    (%esp), %ecx
        int     $0x80
 GLOBAL(int80_landing_pad)
 
-       /* Restore ECX and EDX in case they were clobbered. */
-       popl    %ecx
-       CFI_RESTORE             ecx
+       /*
+        * Restore EDX and ECX in case they were clobbered.  EBP is not
+        * clobbered (the kernel restores it), but it's cleaner and
+        * probably faster to pop it than to adjust ESP using addl.
+        */
+       popl    %ebp
+       CFI_RESTORE             ebp
        CFI_ADJUST_CFA_OFFSET   -4
        popl    %edx
        CFI_RESTORE             edx
        CFI_ADJUST_CFA_OFFSET   -4
+       popl    %ecx
+       CFI_RESTORE             ecx
+       CFI_ADJUST_CFA_OFFSET   -4
        ret
        CFI_ENDPROC
 
index e4f8010f22e04d2f261bb73bc7745f68f36a392f..f7ba9fbf12eeb8770280823b6030d09d044deb66 100644 (file)
 #define X86_FEATURE_PAUSEFILTER ( 8*32+13) /* AMD filtered pause intercept */
 #define X86_FEATURE_PFTHRESHOLD ( 8*32+14) /* AMD pause filter threshold */
 #define X86_FEATURE_VMMCALL     ( 8*32+15) /* Prefer vmmcall to vmcall */
+#define X86_FEATURE_XENPV       ( 8*32+16) /* "" Xen paravirtual guest */
 
 
 /* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */
index 10d0596433f89b849f91c164d7252a29bcac921b..c759b3cca66343bda8096f41a462e0b13fc45cd8 100644 (file)
@@ -19,6 +19,12 @@ static inline int paravirt_enabled(void)
        return pv_info.paravirt_enabled;
 }
 
+static inline int paravirt_has_feature(unsigned int feature)
+{
+       WARN_ON_ONCE(!pv_info.paravirt_enabled);
+       return (pv_info.features & feature);
+}
+
 static inline void load_sp0(struct tss_struct *tss,
                             struct thread_struct *thread)
 {
index 31247b5bff7c8ff86d893851dc9073b72a647cc2..3d44191185f8ca345d4ad3e928101172621d573d 100644 (file)
@@ -70,9 +70,14 @@ struct pv_info {
 #endif
 
        int paravirt_enabled;
+       unsigned int features;    /* valid only if paravirt_enabled is set */
        const char *name;
 };
 
+#define paravirt_has(x) paravirt_has_feature(PV_SUPPORTED_##x)
+/* Supported features */
+#define PV_SUPPORTED_RTC        (1<<0)
+
 struct pv_init_ops {
        /*
         * Patch may replace one of the defined code sequences with
index 67522256c7ffaf610aa70ef885bd8df584d1bbbd..2d5a50cb61a2d6ad5c68d5563636edcc112ff4f9 100644 (file)
@@ -472,6 +472,7 @@ static inline unsigned long current_top_of_stack(void)
 #else
 #define __cpuid                        native_cpuid
 #define paravirt_enabled()     0
+#define paravirt_has(x)        0
 
 static inline void load_sp0(struct tss_struct *tss,
                            struct thread_struct *thread)
index 38dd5efdd04c33aa58b2b20b19596bcd12e3e4af..2bd2292a316d474ea917b6a8b247b7cd5726a16a 100644 (file)
@@ -193,20 +193,17 @@ static int __init numachip_system_init(void)
        case 1:
                init_extra_mapping_uc(NUMACHIP_LCSR_BASE, NUMACHIP_LCSR_SIZE);
                numachip_apic_icr_write = numachip1_apic_icr_write;
-               x86_init.pci.arch_init = pci_numachip_init;
                break;
        case 2:
                init_extra_mapping_uc(NUMACHIP2_LCSR_BASE, NUMACHIP2_LCSR_SIZE);
                numachip_apic_icr_write = numachip2_apic_icr_write;
-
-               /* Use MCFG config cycles rather than locked CF8 cycles */
-               raw_pci_ops = &pci_mmcfg;
                break;
        default:
                return 0;
        }
 
        x86_cpuinit.fixup_cpu_id = fixup_cpu_id;
+       x86_init.pci.arch_init = pci_numachip_init;
 
        return 0;
 }
index c5b0d562dbf55064685c78b5d0fa6280748086d1..7e8a736d09db1df950e37a1746a270299f83685f 100644 (file)
@@ -999,6 +999,17 @@ void do_machine_check(struct pt_regs *regs, long error_code)
        int flags = MF_ACTION_REQUIRED;
        int lmce = 0;
 
+       /* If this CPU is offline, just bail out. */
+       if (cpu_is_offline(smp_processor_id())) {
+               u64 mcgstatus;
+
+               mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
+               if (mcgstatus & MCG_STATUS_RIPV) {
+                       mce_wrmsrl(MSR_IA32_MCG_STATUS, 0);
+                       return;
+               }
+       }
+
        ist_enter(regs);
 
        this_cpu_inc(mce_exception_count);
index 4562cf070c279d5edeb0e18ae94c8bff94166dd8..2bf79d7c97dfb8848b1e7b060a66ddedb4605a1a 100644 (file)
@@ -5,7 +5,7 @@
  *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
  *  Copyright (C) 2009 Jaswinder Singh Rajput
  *  Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
- *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra
  *  Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
  *  Copyright (C) 2009 Google, Inc., Stephane Eranian
  *
index 499f533dd3ccbd22bb84423649e031f2759080ca..d0e35ebb2adb1d34b526fcb04b2bc192c643fd55 100644 (file)
@@ -5,7 +5,7 @@
  *  Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
  *  Copyright (C) 2009 Jaswinder Singh Rajput
  *  Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
- *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra
  *  Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
  *  Copyright (C) 2009 Google, Inc., Stephane Eranian
  *
@@ -387,7 +387,7 @@ struct cpu_hw_events {
 /* Check flags and event code/umask, and set the HSW N/A flag */
 #define INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(code, n) \
        __EVENT_CONSTRAINT(code, n,                     \
-                         INTEL_ARCH_EVENT_MASK|INTEL_ARCH_EVENT_MASK, \
+                         INTEL_ARCH_EVENT_MASK|X86_ALL_EVENT_FLAGS, \
                          HWEIGHT(n), 0, PERF_X86_EVENT_PEBS_NA_HSW)
 
 
@@ -627,6 +627,7 @@ struct x86_perf_task_context {
        u64 lbr_from[MAX_LBR_ENTRIES];
        u64 lbr_to[MAX_LBR_ENTRIES];
        u64 lbr_info[MAX_LBR_ENTRIES];
+       int tos;
        int lbr_callstack_users;
        int lbr_stack_state;
 };
index f63360be22387d4fb4cb30728f1834ee4cbd6228..e2a430021e46e71eb2904af74ae5a7d50653d048 100644 (file)
@@ -232,7 +232,7 @@ static struct event_constraint intel_hsw_event_constraints[] = {
        FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
        FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
        FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
-       INTEL_EVENT_CONSTRAINT(0x48, 0x4), /* L1D_PEND_MISS.* */
+       INTEL_UEVENT_CONSTRAINT(0x148, 0x4),    /* L1D_PEND_MISS.PENDING */
        INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PREC_DIST */
        INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.LOAD_LATENCY */
        /* CYCLE_ACTIVITY.CYCLES_L1D_PENDING */
index 377e8f8ed39186ad4ef57b33264592ed8459a037..a316ca96f1b639d8a0f58f616c1c62d4da61bfdf 100644 (file)
@@ -298,7 +298,7 @@ static bool __match_event(struct perf_event *a, struct perf_event *b)
 static inline struct perf_cgroup *event_to_cgroup(struct perf_event *event)
 {
        if (event->attach_state & PERF_ATTACH_TASK)
-               return perf_cgroup_from_task(event->hw.target);
+               return perf_cgroup_from_task(event->hw.target, event->ctx);
 
        return event->cgrp;
 }
index bfd0b717e944ce012b7a0abe19c89f5294d284e1..659f01e165d57520f33b09ba68818f72cd206a4d 100644 (file)
@@ -239,7 +239,7 @@ static void __intel_pmu_lbr_restore(struct x86_perf_task_context *task_ctx)
        }
 
        mask = x86_pmu.lbr_nr - 1;
-       tos = intel_pmu_lbr_tos();
+       tos = task_ctx->tos;
        for (i = 0; i < tos; i++) {
                lbr_idx = (tos - i) & mask;
                wrmsrl(x86_pmu.lbr_from + lbr_idx, task_ctx->lbr_from[i]);
@@ -247,6 +247,7 @@ static void __intel_pmu_lbr_restore(struct x86_perf_task_context *task_ctx)
                if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
                        wrmsrl(MSR_LBR_INFO_0 + lbr_idx, task_ctx->lbr_info[i]);
        }
+       wrmsrl(x86_pmu.lbr_tos, tos);
        task_ctx->lbr_stack_state = LBR_NONE;
 }
 
@@ -270,6 +271,7 @@ static void __intel_pmu_lbr_save(struct x86_perf_task_context *task_ctx)
                if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
                        rdmsrl(MSR_LBR_INFO_0 + lbr_idx, task_ctx->lbr_info[i]);
        }
+       task_ctx->tos = tos;
        task_ctx->lbr_stack_state = LBR_VALID;
 }
 
index dc5fa6a1e8d640aa8fc407ee3035feb0a1778451..3512ba607361403e587f417cbce2775cdec428a1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * x86 specific code for irq_work
  *
- * Copyright (C) 2010 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright (C) 2010 Red Hat, Inc., Peter Zijlstra
  */
 
 #include <linux/kernel.h>
index cd9685235df91b69f5e39885e55850964c67e8fc..4af8d063fb362cd2bf92b97a48fa8c1d5d95fd3b 100644 (file)
@@ -200,6 +200,9 @@ static __init int add_rtc_cmos(void)
        }
 #endif
 
+       if (paravirt_enabled() && !paravirt_has(RTC))
+               return -ENODEV;
+
        platform_device_register(&rtc_device);
        dev_info(&rtc_device.dev,
                 "registered platform RTC device (no PNP device found)\n");
index 06332cb7e7d1d79c5af04eba698ad8642c2762b5..3f5c48ddba453064ff6dbe91731d1d0c7776be53 100644 (file)
@@ -38,6 +38,14 @@ static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu)
        return best && (best->ecx & bit(X86_FEATURE_XSAVE));
 }
 
+static inline bool guest_cpuid_has_mtrr(struct kvm_vcpu *vcpu)
+{
+       struct kvm_cpuid_entry2 *best;
+
+       best = kvm_find_cpuid_entry(vcpu, 1, 0);
+       return best && (best->edx & bit(X86_FEATURE_MTRR));
+}
+
 static inline bool guest_cpuid_has_tsc_adjust(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *best;
index 08116ff227cc67acaaf452322b1f95db8e051bfd..b0ea42b78ccdb50879a10c440d5e3a7fe194fbe9 100644 (file)
@@ -420,6 +420,7 @@ void kvm_pit_load_count(struct kvm *kvm, int channel, u32 val, int hpet_legacy_s
        u8 saved_mode;
        if (hpet_legacy_start) {
                /* save existing mode for later reenablement */
+               WARN_ON(channel != 0);
                saved_mode = kvm->arch.vpit->pit_state.channels[0].mode;
                kvm->arch.vpit->pit_state.channels[0].mode = 0xff; /* disable timer */
                pit_load_count(kvm, channel, val);
index 9e8bf13572e6dc3f95d33d24f079d63e256a3a7a..3f8c732117eccf73140fded817e1b155dfa76073 100644 (file)
@@ -120,14 +120,22 @@ static u8 mtrr_default_type(struct kvm_mtrr *mtrr_state)
        return mtrr_state->deftype & IA32_MTRR_DEF_TYPE_TYPE_MASK;
 }
 
-static u8 mtrr_disabled_type(void)
+static u8 mtrr_disabled_type(struct kvm_vcpu *vcpu)
 {
        /*
         * Intel SDM 11.11.2.2: all MTRRs are disabled when
         * IA32_MTRR_DEF_TYPE.E bit is cleared, and the UC
         * memory type is applied to all of physical memory.
+        *
+        * However, virtual machines can be run with CPUID such that
+        * there are no MTRRs.  In that case, the firmware will never
+        * enable MTRRs and it is obviously undesirable to run the
+        * guest entirely with UC memory and we use WB.
         */
-       return MTRR_TYPE_UNCACHABLE;
+       if (guest_cpuid_has_mtrr(vcpu))
+               return MTRR_TYPE_UNCACHABLE;
+       else
+               return MTRR_TYPE_WRBACK;
 }
 
 /*
@@ -267,7 +275,7 @@ static int fixed_mtrr_addr_to_seg(u64 addr)
 
        for (seg = 0; seg < seg_num; seg++) {
                mtrr_seg = &fixed_seg_table[seg];
-               if (mtrr_seg->start >= addr && addr < mtrr_seg->end)
+               if (mtrr_seg->start <= addr && addr < mtrr_seg->end)
                        return seg;
        }
 
@@ -300,7 +308,6 @@ static void var_mtrr_range(struct kvm_mtrr_range *range, u64 *start, u64 *end)
        *start = range->base & PAGE_MASK;
 
        mask = range->mask & PAGE_MASK;
-       mask |= ~0ULL << boot_cpu_data.x86_phys_bits;
 
        /* This cannot overflow because writing to the reserved bits of
         * variable MTRRs causes a #GP.
@@ -356,10 +363,14 @@ static void set_var_mtrr_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
        if (var_mtrr_range_is_valid(cur))
                list_del(&mtrr_state->var_ranges[index].node);
 
+       /* Extend the mask with all 1 bits to the left, since those
+        * bits must implicitly be 0.  The bits are then cleared
+        * when reading them.
+        */
        if (!is_mtrr_mask)
                cur->base = data;
        else
-               cur->mask = data;
+               cur->mask = data | (-1LL << cpuid_maxphyaddr(vcpu));
 
        /* add it to the list if it's enabled. */
        if (var_mtrr_range_is_valid(cur)) {
@@ -426,6 +437,8 @@ int kvm_mtrr_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
                        *pdata = vcpu->arch.mtrr_state.var_ranges[index].base;
                else
                        *pdata = vcpu->arch.mtrr_state.var_ranges[index].mask;
+
+               *pdata &= (1ULL << cpuid_maxphyaddr(vcpu)) - 1;
        }
 
        return 0;
@@ -670,7 +683,7 @@ u8 kvm_mtrr_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn)
        }
 
        if (iter.mtrr_disabled)
-               return mtrr_disabled_type();
+               return mtrr_disabled_type(vcpu);
 
        /* not contained in any MTRRs. */
        if (type == -1)
index 83a1c643f9a50fd3fa0ffc041c40d9f4d25aa5b5..899c40f826dd9a5f10c57e0758153cdbb1d9f1a6 100644 (file)
@@ -3422,6 +3422,8 @@ static int handle_exit(struct kvm_vcpu *vcpu)
        struct kvm_run *kvm_run = vcpu->run;
        u32 exit_code = svm->vmcb->control.exit_code;
 
+       trace_kvm_exit(exit_code, vcpu, KVM_ISA_SVM);
+
        if (!is_cr_intercept(svm, INTERCEPT_CR0_WRITE))
                vcpu->arch.cr0 = svm->vmcb->save.cr0;
        if (npt_enabled)
@@ -3892,8 +3894,6 @@ static void svm_vcpu_run(struct kvm_vcpu *vcpu)
        vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
        vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
 
-       trace_kvm_exit(svm->vmcb->control.exit_code, vcpu, KVM_ISA_SVM);
-
        if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
                kvm_before_handle_nmi(&svm->vcpu);
 
index af823a388c1994ba244e3ef0098f1a578408101e..44976a596fa65d2ca90421a7f7f06cfb2d0b17be 100644 (file)
@@ -2803,7 +2803,7 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                msr_info->data = vcpu->arch.ia32_xss;
                break;
        case MSR_TSC_AUX:
-               if (!guest_cpuid_has_rdtscp(vcpu))
+               if (!guest_cpuid_has_rdtscp(vcpu) && !msr_info->host_initiated)
                        return 1;
                /* Otherwise falls through */
        default:
@@ -2909,7 +2909,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                        clear_atomic_switch_msr(vmx, MSR_IA32_XSS);
                break;
        case MSR_TSC_AUX:
-               if (!guest_cpuid_has_rdtscp(vcpu))
+               if (!guest_cpuid_has_rdtscp(vcpu) && !msr_info->host_initiated)
                        return 1;
                /* Check reserved bit, higher 32 bits should be zero */
                if ((data >> 32) != 0)
@@ -8042,6 +8042,8 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu)
        u32 exit_reason = vmx->exit_reason;
        u32 vectoring_info = vmx->idt_vectoring_info;
 
+       trace_kvm_exit(exit_reason, vcpu, KVM_ISA_VMX);
+
        /*
         * Flush logged GPAs PML buffer, this will make dirty_bitmap more
         * updated. Another good is, in kvm_vm_ioctl_get_dirty_log, before
@@ -8668,7 +8670,6 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
        vmx->loaded_vmcs->launched = 1;
 
        vmx->exit_reason = vmcs_read32(VM_EXIT_REASON);
-       trace_kvm_exit(vmx->exit_reason, vcpu, KVM_ISA_VMX);
 
        /*
         * the KVM_REQ_EVENT optimization bit is only on for one entry, and if
index eed32283d22cc0cafbff75e8f2a246887d4cbb5f..97592e190413fd741fdd802646d62f1c3cde1e62 100644 (file)
@@ -3572,9 +3572,11 @@ static int kvm_vm_ioctl_get_pit(struct kvm *kvm, struct kvm_pit_state *ps)
 
 static int kvm_vm_ioctl_set_pit(struct kvm *kvm, struct kvm_pit_state *ps)
 {
+       int i;
        mutex_lock(&kvm->arch.vpit->pit_state.lock);
        memcpy(&kvm->arch.vpit->pit_state, ps, sizeof(struct kvm_pit_state));
-       kvm_pit_load_count(kvm, 0, ps->channels[0].count, 0);
+       for (i = 0; i < 3; i++)
+               kvm_pit_load_count(kvm, i, ps->channels[i].count, 0);
        mutex_unlock(&kvm->arch.vpit->pit_state.lock);
        return 0;
 }
@@ -3593,6 +3595,7 @@ static int kvm_vm_ioctl_get_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps)
 static int kvm_vm_ioctl_set_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps)
 {
        int start = 0;
+       int i;
        u32 prev_legacy, cur_legacy;
        mutex_lock(&kvm->arch.vpit->pit_state.lock);
        prev_legacy = kvm->arch.vpit->pit_state.flags & KVM_PIT_FLAGS_HPET_LEGACY;
@@ -3602,7 +3605,9 @@ static int kvm_vm_ioctl_set_pit2(struct kvm *kvm, struct kvm_pit_state2 *ps)
        memcpy(&kvm->arch.vpit->pit_state.channels, &ps->channels,
               sizeof(kvm->arch.vpit->pit_state.channels));
        kvm->arch.vpit->pit_state.flags = ps->flags;
-       kvm_pit_load_count(kvm, 0, kvm->arch.vpit->pit_state.channels[0].count, start);
+       for (i = 0; i < 3; i++)
+               kvm_pit_load_count(kvm, i, kvm->arch.vpit->pit_state.channels[i].count,
+                                  start && i == 0);
        mutex_unlock(&kvm->arch.vpit->pit_state.lock);
        return 0;
 }
@@ -6515,6 +6520,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
        if (req_immediate_exit)
                smp_send_reschedule(vcpu->cpu);
 
+       trace_kvm_entry(vcpu->vcpu_id);
+       wait_lapic_expire(vcpu);
        __kvm_guest_enter();
 
        if (unlikely(vcpu->arch.switch_db_regs)) {
@@ -6527,8 +6534,6 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
                vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_RELOAD;
        }
 
-       trace_kvm_entry(vcpu->vcpu_id);
-       wait_lapic_expire(vcpu);
        kvm_x86_ops->run(vcpu);
 
        /*
index a0d09f6c65337fc381353783639f45251bf28d78..a43b2eafc466f5c552d6f1b805d6b727ad8371f1 100644 (file)
@@ -1414,6 +1414,7 @@ __init void lguest_init(void)
        pv_info.kernel_rpl = 1;
        /* Everyone except Xen runs with this set. */
        pv_info.shared_kernel_pmd = 1;
+       pv_info.features = 0;
 
        /*
         * We set up all the lguest overrides for sensitive operations.  These
index a035c2aa780190c8c198e1bd8c2bec20a18d8ecb..0f1c6fc3ddd88948646963772ac0fa12c492c212 100644 (file)
@@ -89,7 +89,7 @@ static struct addr_marker address_markers[] = {
        { 0/* VMALLOC_START */, "vmalloc() Area" },
        { 0/*VMALLOC_END*/,     "vmalloc() End" },
 # ifdef CONFIG_HIGHMEM
-       { 0/*PKMAP_BASE*/,      "Persisent kmap() Area" },
+       { 0/*PKMAP_BASE*/,      "Persistent kmap() Area" },
 # endif
        { 0/*FIXADDR_START*/,   "Fixmap Area" },
 #endif
index 06934a8a48724dc5fc6600b49178e9573e7558c5..14fcd01ed99293c162582438b4755a47fff59f43 100644 (file)
@@ -211,7 +211,7 @@ static int copy_sc_from_user(struct pt_regs *regs,
                if (err)
                        return 1;
 
-               err = convert_fxsr_from_user(&fpx, sc.fpstate);
+               err = convert_fxsr_from_user(&fpx, (void *)sc.fpstate);
                if (err)
                        return 1;
 
@@ -227,7 +227,7 @@ static int copy_sc_from_user(struct pt_regs *regs,
        {
                struct user_i387_struct fp;
 
-               err = copy_from_user(&fp, sc.fpstate,
+               err = copy_from_user(&fp, (void *)sc.fpstate,
                                     sizeof(struct user_i387_struct));
                if (err)
                        return 1;
@@ -291,7 +291,7 @@ static int copy_sc_to_user(struct sigcontext __user *to,
 #endif
 #undef PUTREG
        sc.oldmask = mask;
-       sc.fpstate = to_fp;
+       sc.fpstate = (unsigned long)to_fp;
 
        err = copy_to_user(to, &sc, sizeof(struct sigcontext));
        if (err)
@@ -468,12 +468,10 @@ long sys_sigreturn(void)
        struct sigframe __user *frame = (struct sigframe __user *)(sp - 8);
        sigset_t set;
        struct sigcontext __user *sc = &frame->sc;
-       unsigned long __user *oldmask = &sc->oldmask;
-       unsigned long __user *extramask = frame->extramask;
        int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
 
-       if (copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) ||
-           copy_from_user(&set.sig[1], extramask, sig_size))
+       if (copy_from_user(&set.sig[0], &sc->oldmask, sizeof(set.sig[0])) ||
+           copy_from_user(&set.sig[1], frame->extramask, sig_size))
                goto segfault;
 
        set_current_blocked(&set);
@@ -505,6 +503,7 @@ int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
 {
        struct rt_sigframe __user *frame;
        int err = 0, sig = ksig->sig;
+       unsigned long fp_to;
 
        frame = (struct rt_sigframe __user *)
                round_down(stack_top - sizeof(struct rt_sigframe), 16);
@@ -526,7 +525,10 @@ int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
        err |= __save_altstack(&frame->uc.uc_stack, PT_REGS_SP(regs));
        err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs,
                               set->sig[0]);
-       err |= __put_user(&frame->fpstate, &frame->uc.uc_mcontext.fpstate);
+
+       fp_to = (unsigned long)&frame->fpstate;
+
+       err |= __put_user(fp_to, &frame->uc.uc_mcontext.fpstate);
        if (sizeof(*set) == 16) {
                err |= __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
                err |= __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
index 5774800ff583ca33916e365e408b057d982a8384..b7de78bdc09c12b3e6cea070e4d35b346d24c8be 100644 (file)
@@ -1192,7 +1192,7 @@ static const struct pv_info xen_info __initconst = {
 #ifdef CONFIG_X86_64
        .extra_user_64bit_cs = FLAT_USER_CS64,
 #endif
-
+       .features = 0,
        .name = "Xen",
 };
 
@@ -1535,6 +1535,8 @@ asmlinkage __visible void __init xen_start_kernel(void)
 
        /* Install Xen paravirt ops */
        pv_info = xen_info;
+       if (xen_initial_domain())
+               pv_info.features |= PV_SUPPORTED_RTC;
        pv_init_ops = xen_init_ops;
        pv_apic_ops = xen_apic_ops;
        if (!xen_pvh_domain()) {
@@ -1886,8 +1888,10 @@ EXPORT_SYMBOL_GPL(xen_hvm_need_lapic);
 
 static void xen_set_cpu_features(struct cpuinfo_x86 *c)
 {
-       if (xen_pv_domain())
+       if (xen_pv_domain()) {
                clear_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
+               set_cpu_cap(c, X86_FEATURE_XENPV);
+       }
 }
 
 const struct hypervisor_x86 x86_hyper_xen = {
index ac161db633885872fdebdce976d05b978e1235da..cb5e266a8bf752297eaf6fc0d822c9398239fadf 100644 (file)
@@ -2495,14 +2495,9 @@ void __init xen_init_mmu_ops(void)
 {
        x86_init.paging.pagetable_init = xen_pagetable_init;
 
-       /* Optimization - we can use the HVM one but it has no idea which
-        * VCPUs are descheduled - which means that it will needlessly IPI
-        * them. Xen knows so let it do the job.
-        */
-       if (xen_feature(XENFEAT_auto_translated_physmap)) {
-               pv_mmu_ops.flush_tlb_others = xen_flush_tlb_others;
+       if (xen_feature(XENFEAT_auto_translated_physmap))
                return;
-       }
+
        pv_mmu_ops = xen_mmu_ops;
 
        memset(dummy_mapping, 0xff, PAGE_SIZE);
index feddabdab4488c54784aa5a64067d09b50b3cb22..df0c4055958379753aac957dd2c9e4c68fbaf765 100644 (file)
@@ -1,6 +1,7 @@
 #include <linux/types.h>
 #include <linux/tick.h>
 
+#include <xen/xen.h>
 #include <xen/interface/xen.h>
 #include <xen/grant_table.h>
 #include <xen/events.h>
@@ -68,26 +69,16 @@ static void xen_pv_post_suspend(int suspend_cancelled)
 
 void xen_arch_pre_suspend(void)
 {
-       int cpu;
-
-       for_each_online_cpu(cpu)
-               xen_pmu_finish(cpu);
-
        if (xen_pv_domain())
                xen_pv_pre_suspend();
 }
 
 void xen_arch_post_suspend(int cancelled)
 {
-       int cpu;
-
        if (xen_pv_domain())
                xen_pv_post_suspend(cancelled);
        else
                xen_hvm_post_suspend(cancelled);
-
-       for_each_online_cpu(cpu)
-               xen_pmu_init(cpu);
 }
 
 static void xen_vcpu_notify_restore(void *data)
@@ -106,10 +97,20 @@ static void xen_vcpu_notify_suspend(void *data)
 
 void xen_arch_resume(void)
 {
+       int cpu;
+
        on_each_cpu(xen_vcpu_notify_restore, NULL, 1);
+
+       for_each_online_cpu(cpu)
+               xen_pmu_init(cpu);
 }
 
 void xen_arch_suspend(void)
 {
+       int cpu;
+
+       for_each_online_cpu(cpu)
+               xen_pmu_finish(cpu);
+
        on_each_cpu(xen_vcpu_notify_suspend, NULL, 1);
 }
index 5bcdfc10c23a6340367c4b9781496a49b5c81efe..5a37188b559fba8feb1da48b00d5290c3a6a09b6 100644 (file)
@@ -1127,15 +1127,15 @@ void blkcg_exit_queue(struct request_queue *q)
  * of the main cic data structures.  For now we allow a task to change
  * its cgroup only if it's the only owner of its ioc.
  */
-static int blkcg_can_attach(struct cgroup_subsys_state *css,
-                           struct cgroup_taskset *tset)
+static int blkcg_can_attach(struct cgroup_taskset *tset)
 {
        struct task_struct *task;
+       struct cgroup_subsys_state *dst_css;
        struct io_context *ioc;
        int ret = 0;
 
        /* task_lock() is needed to avoid races with exit_io_context() */
-       cgroup_taskset_for_each(task, tset) {
+       cgroup_taskset_for_each(task, dst_css, tset) {
                task_lock(task);
                ioc = task->io_context;
                if (ioc && atomic_read(&ioc->nr_tasks) > 1)
index a0af4043dda2bbe953b3550c07ac40f88148958b..33e2f62d50622ea8b40153175d0f44d96df399a6 100644 (file)
@@ -206,6 +206,22 @@ void blk_delay_queue(struct request_queue *q, unsigned long msecs)
 }
 EXPORT_SYMBOL(blk_delay_queue);
 
+/**
+ * blk_start_queue_async - asynchronously restart a previously stopped queue
+ * @q:    The &struct request_queue in question
+ *
+ * Description:
+ *   blk_start_queue_async() will clear the stop flag on the queue, and
+ *   ensure that the request_fn for the queue is run from an async
+ *   context.
+ **/
+void blk_start_queue_async(struct request_queue *q)
+{
+       queue_flag_clear(QUEUE_FLAG_STOPPED, q);
+       blk_run_queue_async(q);
+}
+EXPORT_SYMBOL(blk_start_queue_async);
+
 /**
  * blk_start_queue - restart a previously stopped queue
  * @q:    The &struct request_queue in question
@@ -1689,8 +1705,6 @@ static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio)
        struct request *req;
        unsigned int request_count = 0;
 
-       blk_queue_split(q, &bio, q->bio_split);
-
        /*
         * low level driver can indicate that it wants pages above a
         * certain limit bounced to low memory (ie for highmem, or even
@@ -1698,6 +1712,8 @@ static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio)
         */
        blk_queue_bounce(q, &bio);
 
+       blk_queue_split(q, &bio, q->bio_split);
+
        if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) {
                bio->bi_error = -EIO;
                bio_endio(bio);
@@ -3405,6 +3421,9 @@ int blk_pre_runtime_suspend(struct request_queue *q)
 {
        int ret = 0;
 
+       if (!q->dev)
+               return ret;
+
        spin_lock_irq(q->queue_lock);
        if (q->nr_pending) {
                ret = -EBUSY;
@@ -3432,6 +3451,9 @@ EXPORT_SYMBOL(blk_pre_runtime_suspend);
  */
 void blk_post_runtime_suspend(struct request_queue *q, int err)
 {
+       if (!q->dev)
+               return;
+
        spin_lock_irq(q->queue_lock);
        if (!err) {
                q->rpm_status = RPM_SUSPENDED;
@@ -3456,6 +3478,9 @@ EXPORT_SYMBOL(blk_post_runtime_suspend);
  */
 void blk_pre_runtime_resume(struct request_queue *q)
 {
+       if (!q->dev)
+               return;
+
        spin_lock_irq(q->queue_lock);
        q->rpm_status = RPM_RESUMING;
        spin_unlock_irq(q->queue_lock);
@@ -3478,6 +3503,9 @@ EXPORT_SYMBOL(blk_pre_runtime_resume);
  */
 void blk_post_runtime_resume(struct request_queue *q, int err)
 {
+       if (!q->dev)
+               return;
+
        spin_lock_irq(q->queue_lock);
        if (!err) {
                q->rpm_status = RPM_ACTIVE;
index b4ffc5be1a93c1ff0bceb6b9a5cc3dc1b5101d97..e5b5721809e21d5d379e6e711e23ef709252e0ed 100644 (file)
@@ -277,12 +277,12 @@ static int ablkcipher_walk_first(struct ablkcipher_request *req,
        if (WARN_ON_ONCE(in_irq()))
                return -EDEADLK;
 
+       walk->iv = req->info;
        walk->nbytes = walk->total;
        if (unlikely(!walk->total))
                return 0;
 
        walk->iv_buffer = NULL;
-       walk->iv = req->info;
        if (unlikely(((unsigned long)walk->iv & alignmask))) {
                int err = ablkcipher_copy_iv(walk, tfm, alignmask);
 
index ca9efe17db1ac4e9e2806528ea28d2d87a954b8f..634b4d1ab6817d56343d5b8b24b29cd34de422d1 100644 (file)
@@ -47,7 +47,7 @@ struct skcipher_ctx {
        bool merge;
        bool enc;
 
-       struct ablkcipher_request req;
+       struct skcipher_request req;
 };
 
 struct skcipher_async_rsgl {
@@ -64,13 +64,13 @@ struct skcipher_async_req {
 };
 
 #define GET_SREQ(areq, ctx) (struct skcipher_async_req *)((char *)areq + \
-       crypto_ablkcipher_reqsize(crypto_ablkcipher_reqtfm(&ctx->req)))
+       crypto_skcipher_reqsize(crypto_skcipher_reqtfm(&ctx->req)))
 
 #define GET_REQ_SIZE(ctx) \
-       crypto_ablkcipher_reqsize(crypto_ablkcipher_reqtfm(&ctx->req))
+       crypto_skcipher_reqsize(crypto_skcipher_reqtfm(&ctx->req))
 
 #define GET_IV_SIZE(ctx) \
-       crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(&ctx->req))
+       crypto_skcipher_ivsize(crypto_skcipher_reqtfm(&ctx->req))
 
 #define MAX_SGL_ENTS ((4096 - sizeof(struct skcipher_sg_list)) / \
                      sizeof(struct scatterlist) - 1)
@@ -302,8 +302,8 @@ static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg,
        struct sock *sk = sock->sk;
        struct alg_sock *ask = alg_sk(sk);
        struct skcipher_ctx *ctx = ask->private;
-       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(&ctx->req);
-       unsigned ivsize = crypto_ablkcipher_ivsize(tfm);
+       struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(&ctx->req);
+       unsigned ivsize = crypto_skcipher_ivsize(tfm);
        struct skcipher_sg_list *sgl;
        struct af_alg_control con = {};
        long copied = 0;
@@ -507,7 +507,7 @@ static int skcipher_recvmsg_async(struct socket *sock, struct msghdr *msg,
        struct skcipher_sg_list *sgl;
        struct scatterlist *sg;
        struct skcipher_async_req *sreq;
-       struct ablkcipher_request *req;
+       struct skcipher_request *req;
        struct skcipher_async_rsgl *last_rsgl = NULL;
        unsigned int txbufs = 0, len = 0, tx_nents = skcipher_all_sg_nents(ctx);
        unsigned int reqlen = sizeof(struct skcipher_async_req) +
@@ -531,9 +531,9 @@ static int skcipher_recvmsg_async(struct socket *sock, struct msghdr *msg,
        }
        sg_init_table(sreq->tsg, tx_nents);
        memcpy(sreq->iv, ctx->iv, GET_IV_SIZE(ctx));
-       ablkcipher_request_set_tfm(req, crypto_ablkcipher_reqtfm(&ctx->req));
-       ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-                                       skcipher_async_cb, sk);
+       skcipher_request_set_tfm(req, crypto_skcipher_reqtfm(&ctx->req));
+       skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+                                     skcipher_async_cb, sk);
 
        while (iov_iter_count(&msg->msg_iter)) {
                struct skcipher_async_rsgl *rsgl;
@@ -608,10 +608,10 @@ static int skcipher_recvmsg_async(struct socket *sock, struct msghdr *msg,
        if (mark)
                sg_mark_end(sreq->tsg + txbufs - 1);
 
-       ablkcipher_request_set_crypt(req, sreq->tsg, sreq->first_sgl.sgl.sg,
-                                    len, sreq->iv);
-       err = ctx->enc ? crypto_ablkcipher_encrypt(req) :
-                        crypto_ablkcipher_decrypt(req);
+       skcipher_request_set_crypt(req, sreq->tsg, sreq->first_sgl.sgl.sg,
+                                  len, sreq->iv);
+       err = ctx->enc ? crypto_skcipher_encrypt(req) :
+                        crypto_skcipher_decrypt(req);
        if (err == -EINPROGRESS) {
                atomic_inc(&ctx->inflight);
                err = -EIOCBQUEUED;
@@ -632,7 +632,7 @@ static int skcipher_recvmsg_sync(struct socket *sock, struct msghdr *msg,
        struct sock *sk = sock->sk;
        struct alg_sock *ask = alg_sk(sk);
        struct skcipher_ctx *ctx = ask->private;
-       unsigned bs = crypto_ablkcipher_blocksize(crypto_ablkcipher_reqtfm(
+       unsigned bs = crypto_skcipher_blocksize(crypto_skcipher_reqtfm(
                &ctx->req));
        struct skcipher_sg_list *sgl;
        struct scatterlist *sg;
@@ -669,14 +669,13 @@ static int skcipher_recvmsg_sync(struct socket *sock, struct msghdr *msg,
                if (!used)
                        goto free;
 
-               ablkcipher_request_set_crypt(&ctx->req, sg,
-                                            ctx->rsgl.sg, used,
-                                            ctx->iv);
+               skcipher_request_set_crypt(&ctx->req, sg, ctx->rsgl.sg, used,
+                                          ctx->iv);
 
                err = af_alg_wait_for_completion(
                                ctx->enc ?
-                                       crypto_ablkcipher_encrypt(&ctx->req) :
-                                       crypto_ablkcipher_decrypt(&ctx->req),
+                                       crypto_skcipher_encrypt(&ctx->req) :
+                                       crypto_skcipher_decrypt(&ctx->req),
                                &ctx->completion);
 
 free:
@@ -751,17 +750,17 @@ static struct proto_ops algif_skcipher_ops = {
 
 static void *skcipher_bind(const char *name, u32 type, u32 mask)
 {
-       return crypto_alloc_ablkcipher(name, type, mask);
+       return crypto_alloc_skcipher(name, type, mask);
 }
 
 static void skcipher_release(void *private)
 {
-       crypto_free_ablkcipher(private);
+       crypto_free_skcipher(private);
 }
 
 static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
 {
-       return crypto_ablkcipher_setkey(private, key, keylen);
+       return crypto_skcipher_setkey(private, key, keylen);
 }
 
 static void skcipher_wait(struct sock *sk)
@@ -778,13 +777,13 @@ static void skcipher_sock_destruct(struct sock *sk)
 {
        struct alg_sock *ask = alg_sk(sk);
        struct skcipher_ctx *ctx = ask->private;
-       struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(&ctx->req);
+       struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(&ctx->req);
 
        if (atomic_read(&ctx->inflight))
                skcipher_wait(sk);
 
        skcipher_free_sgl(sk);
-       sock_kzfree_s(sk, ctx->iv, crypto_ablkcipher_ivsize(tfm));
+       sock_kzfree_s(sk, ctx->iv, crypto_skcipher_ivsize(tfm));
        sock_kfree_s(sk, ctx, ctx->len);
        af_alg_release_parent(sk);
 }
@@ -793,20 +792,20 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
 {
        struct skcipher_ctx *ctx;
        struct alg_sock *ask = alg_sk(sk);
-       unsigned int len = sizeof(*ctx) + crypto_ablkcipher_reqsize(private);
+       unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(private);
 
        ctx = sock_kmalloc(sk, len, GFP_KERNEL);
        if (!ctx)
                return -ENOMEM;
 
-       ctx->iv = sock_kmalloc(sk, crypto_ablkcipher_ivsize(private),
+       ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(private),
                               GFP_KERNEL);
        if (!ctx->iv) {
                sock_kfree_s(sk, ctx, len);
                return -ENOMEM;
        }
 
-       memset(ctx->iv, 0, crypto_ablkcipher_ivsize(private));
+       memset(ctx->iv, 0, crypto_skcipher_ivsize(private));
 
        INIT_LIST_HEAD(&ctx->tsgl);
        ctx->len = len;
@@ -819,9 +818,9 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
 
        ask->private = ctx;
 
-       ablkcipher_request_set_tfm(&ctx->req, private);
-       ablkcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
-                                       af_alg_complete, &ctx->completion);
+       skcipher_request_set_tfm(&ctx->req, private);
+       skcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+                                     af_alg_complete, &ctx->completion);
 
        sk->sk_destruct = skcipher_sock_destruct;
 
index f8c0b8dbeb7582beca1ee7fd5c7aaac58aba23cd..88bc8e6b2a545b9667f3d5fb390854a19f0be778 100644 (file)
@@ -53,7 +53,7 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
        struct dmaengine_unmap_data *unmap = NULL;
 
        if (device)
-               unmap = dmaengine_get_unmap_data(device->dev, 2, GFP_NOIO);
+               unmap = dmaengine_get_unmap_data(device->dev, 2, GFP_NOWAIT);
 
        if (unmap && is_dma_copy_aligned(device, src_offset, dest_offset, len)) {
                unsigned long dma_prep_flags = 0;
index 5d355e0c263339b5bd179ad61aad63c9b7efb3a3..c0748bbd4c083b47f78c662cdd7cb490590a2587 100644 (file)
@@ -188,7 +188,7 @@ async_gen_syndrome(struct page **blocks, unsigned int offset, int disks,
        BUG_ON(disks > 255 || !(P(blocks, disks) || Q(blocks, disks)));
 
        if (device)
-               unmap = dmaengine_get_unmap_data(device->dev, disks, GFP_NOIO);
+               unmap = dmaengine_get_unmap_data(device->dev, disks, GFP_NOWAIT);
 
        /* XORing P/Q is only implemented in software */
        if (unmap && !(submit->flags & ASYNC_TX_PQ_XOR_DST) &&
@@ -307,7 +307,7 @@ async_syndrome_val(struct page **blocks, unsigned int offset, int disks,
        BUG_ON(disks < 4);
 
        if (device)
-               unmap = dmaengine_get_unmap_data(device->dev, disks, GFP_NOIO);
+               unmap = dmaengine_get_unmap_data(device->dev, disks, GFP_NOWAIT);
 
        if (unmap && disks <= dma_maxpq(device, 0) &&
            is_dma_pq_aligned(device, offset, 0, len)) {
index 934a849814958e6ea37b9dbdb96abc820c4fe9e1..8fab6275ea1facaae8730a8f676f2578c792e7c3 100644 (file)
@@ -41,7 +41,7 @@ async_sum_product(struct page *dest, struct page **srcs, unsigned char *coef,
        u8 *a, *b, *c;
 
        if (dma)
-               unmap = dmaengine_get_unmap_data(dma->dev, 3, GFP_NOIO);
+               unmap = dmaengine_get_unmap_data(dma->dev, 3, GFP_NOWAIT);
 
        if (unmap) {
                struct device *dev = dma->dev;
@@ -105,7 +105,7 @@ async_mult(struct page *dest, struct page *src, u8 coef, size_t len,
        u8 *d, *s;
 
        if (dma)
-               unmap = dmaengine_get_unmap_data(dma->dev, 3, GFP_NOIO);
+               unmap = dmaengine_get_unmap_data(dma->dev, 3, GFP_NOWAIT);
 
        if (unmap) {
                dma_addr_t dma_dest[2];
index e1bce26cd4f9098f2765ffbf0f8e2f00017a9219..da75777f2b3f04f09a3fc025da9e38102b2211e8 100644 (file)
@@ -182,7 +182,7 @@ async_xor(struct page *dest, struct page **src_list, unsigned int offset,
        BUG_ON(src_cnt <= 1);
 
        if (device)
-               unmap = dmaengine_get_unmap_data(device->dev, src_cnt+1, GFP_NOIO);
+               unmap = dmaengine_get_unmap_data(device->dev, src_cnt+1, GFP_NOWAIT);
 
        if (unmap && is_dma_xor_aligned(device, offset, 0, len)) {
                struct dma_async_tx_descriptor *tx;
@@ -278,7 +278,7 @@ async_xor_val(struct page *dest, struct page **src_list, unsigned int offset,
        BUG_ON(src_cnt <= 1);
 
        if (device)
-               unmap = dmaengine_get_unmap_data(device->dev, src_cnt, GFP_NOIO);
+               unmap = dmaengine_get_unmap_data(device->dev, src_cnt, GFP_NOWAIT);
 
        if (unmap && src_cnt <= device->max_xor &&
            is_dma_xor_aligned(device, offset, 0, len)) {
index 11b981492031361f7cdf336b58ecbb98b8951196..8cc1622b2ee008ef7f5ff31a3ea7d8777f3f5f1b 100644 (file)
@@ -326,12 +326,12 @@ static int blkcipher_walk_first(struct blkcipher_desc *desc,
        if (WARN_ON_ONCE(in_irq()))
                return -EDEADLK;
 
+       walk->iv = desc->info;
        walk->nbytes = walk->total;
        if (unlikely(!walk->total))
                return 0;
 
        walk->buffer = NULL;
-       walk->iv = desc->info;
        if (unlikely(((unsigned long)walk->iv & walk->alignmask))) {
                int err = blkcipher_copy_iv(walk);
                if (err)
index 707cf6213bc2888b4cc1e09a0f851d232b9521c0..b9afb47db7ed98f23f140cd24433682b82d2274f 100644 (file)
@@ -104,7 +104,7 @@ static void acpi_expose_nondev_subnodes(struct kobject *kobj,
 
                init_completion(&dn->kobj_done);
                ret = kobject_init_and_add(&dn->kobj, &acpi_data_node_ktype,
-                                          kobj, dn->name);
+                                          kobj, "%s", dn->name);
                if (ret)
                        acpi_handle_err(dn->handle, "Failed to expose (%d)\n", ret);
                else
index e7ed39bab97d5d0a97d03919bd615eb5fba4105e..aa45d480270721280a9e8085574a14d086a079fc 100644 (file)
@@ -1810,7 +1810,7 @@ static void acpi_nfit_notify(struct acpi_device *adev, u32 event)
        if (!dev->driver) {
                /* dev->driver may be null if we're being removed */
                dev_dbg(dev, "%s: no driver found for dev\n", __func__);
-               return;
+               goto out_unlock;
        }
 
        if (!acpi_desc) {
index f4e02ae93f585fbb8de42c09d4d0fb32d2751887..11154a330f075dc04c0fec99299d6f5000e901be 100644 (file)
@@ -200,7 +200,8 @@ static int acpi_pss_perf_init(struct acpi_processor *pr,
                goto err_remove_sysfs_thermal;
        }
 
-       sysfs_remove_link(&pr->cdev->device.kobj, "device");
+       return 0;
+
  err_remove_sysfs_thermal:
        sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
  err_thermal_unregister:
index ff02bb4218fcaae3bbf60821e6d41f81b5a0e40d..cdfbcc54821fd6ea3a5dd6a11c969f12055c7e24 100644 (file)
@@ -314,16 +314,6 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */
        { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */
        { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */
-       { PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/
-       { PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/
-       { PCI_VDEVICE(INTEL, 0xa184), board_ahci }, /* Lewisburg RAID*/
-       { PCI_VDEVICE(INTEL, 0xa204), board_ahci }, /* Lewisburg RAID*/
-       { PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/
-       { PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
-       { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/
-       { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/
-       { PCI_VDEVICE(INTEL, 0xa18e), board_ahci }, /* Lewisburg RAID*/
-       { PCI_VDEVICE(INTEL, 0xa20e), board_ahci }, /* Lewisburg RAID*/
        { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */
        { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */
        { PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
@@ -350,10 +340,22 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x9d03), board_ahci }, /* Sunrise Point-LP AHCI */
        { PCI_VDEVICE(INTEL, 0x9d05), board_ahci }, /* Sunrise Point-LP RAID */
        { PCI_VDEVICE(INTEL, 0x9d07), board_ahci }, /* Sunrise Point-LP RAID */
+       { PCI_VDEVICE(INTEL, 0xa102), board_ahci }, /* Sunrise Point-H AHCI */
        { PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */
        { PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */
+       { PCI_VDEVICE(INTEL, 0xa106), board_ahci }, /* Sunrise Point-H RAID */
        { PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */
        { PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
+       { PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/
+       { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* Lewisburg RAID*/
+       { PCI_VDEVICE(INTEL, 0xa182), board_ahci }, /* Lewisburg AHCI*/
+       { PCI_VDEVICE(INTEL, 0xa184), board_ahci }, /* Lewisburg RAID*/
+       { PCI_VDEVICE(INTEL, 0xa186), board_ahci }, /* Lewisburg RAID*/
+       { PCI_VDEVICE(INTEL, 0xa18e), board_ahci }, /* Lewisburg RAID*/
+       { PCI_VDEVICE(INTEL, 0xa202), board_ahci }, /* Lewisburg AHCI*/
+       { PCI_VDEVICE(INTEL, 0xa204), board_ahci }, /* Lewisburg RAID*/
+       { PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
+       { PCI_VDEVICE(INTEL, 0xa20e), board_ahci }, /* Lewisburg 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,
index 8490d37aee2a466809c2634e51e8b96386e2eecb..f7a7fa81740e8f7e7f1daa0c6d6e48d344496ceb 100644 (file)
@@ -62,6 +62,7 @@ static void ahci_mvebu_regret_option(struct ahci_host_priv *hpriv)
        writel(0x80, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA);
 }
 
+#ifdef CONFIG_PM_SLEEP
 static int ahci_mvebu_suspend(struct platform_device *pdev, pm_message_t state)
 {
        return ahci_platform_suspend_host(&pdev->dev);
@@ -81,6 +82,10 @@ static int ahci_mvebu_resume(struct platform_device *pdev)
 
        return ahci_platform_resume_host(&pdev->dev);
 }
+#else
+#define ahci_mvebu_suspend NULL
+#define ahci_mvebu_resume NULL
+#endif
 
 static const struct ata_port_info ahci_mvebu_port_info = {
        .flags     = AHCI_FLAG_COMMON,
index 096064cd6c52b1b0f72bf710d1a56893bd6bff9c..4665512dae44d99e9a5af194812094498d5888cf 100644 (file)
@@ -1273,6 +1273,15 @@ static int ahci_exec_polled_cmd(struct ata_port *ap, int pmp,
        ata_tf_to_fis(tf, pmp, is_cmd, fis);
        ahci_fill_cmd_slot(pp, 0, cmd_fis_len | flags | (pmp << 12));
 
+       /* set port value for softreset of Port Multiplier */
+       if (pp->fbs_enabled && pp->fbs_last_dev != pmp) {
+               tmp = readl(port_mmio + PORT_FBS);
+               tmp &= ~(PORT_FBS_DEV_MASK | PORT_FBS_DEC);
+               tmp |= pmp << PORT_FBS_DEV_OFFSET;
+               writel(tmp, port_mmio + PORT_FBS);
+               pp->fbs_last_dev = pmp;
+       }
+
        /* issue & wait */
        writel(1, port_mmio + PORT_CMD_ISSUE);
 
index cb0508af1459ac43f4aa26f1a16d94134bd9d0bc..961acc788f4490cea48abb4e215cb144d8fc5e93 100644 (file)
@@ -1505,12 +1505,20 @@ static const char *ata_err_string(unsigned int err_mask)
 unsigned int ata_read_log_page(struct ata_device *dev, u8 log,
                               u8 page, void *buf, unsigned int sectors)
 {
+       unsigned long ap_flags = dev->link->ap->flags;
        struct ata_taskfile tf;
        unsigned int err_mask;
        bool dma = false;
 
        DPRINTK("read log page - log 0x%x, page 0x%x\n", log, page);
 
+       /*
+        * Return error without actually issuing the command on controllers
+        * which e.g. lockup on a read log page.
+        */
+       if (ap_flags & ATA_FLAG_NO_LOG_PAGE)
+               return AC_ERR_DEV;
+
 retry:
        ata_tf_init(dev, &tf);
        if (dev->dma_mode && ata_id_has_read_log_dma_ext(dev->id) &&
index 5389579c51204cf336f2689052ccf29c48b8af98..a723ae92978310f64e65eeef44509337a027c8a5 100644 (file)
@@ -45,7 +45,8 @@ enum {
        SATA_FSL_MAX_PRD_DIRECT = 16,   /* Direct PRDT entries */
 
        SATA_FSL_HOST_FLAGS     = (ATA_FLAG_SATA | ATA_FLAG_PIO_DMA |
-                               ATA_FLAG_PMP | ATA_FLAG_NCQ | ATA_FLAG_AN),
+                                  ATA_FLAG_PMP | ATA_FLAG_NCQ |
+                                  ATA_FLAG_AN | ATA_FLAG_NO_LOG_PAGE),
 
        SATA_FSL_MAX_CMDS       = SATA_FSL_QUEUE_DEPTH,
        SATA_FSL_CMD_HDR_SIZE   = 16,   /* 4 DWORDS */
index dea6edcbf145c3d1eaf45d8265ae7f971d6c808c..29bcff086bcedd548f90a15fd67829c7b21a4de9 100644 (file)
@@ -630,6 +630,9 @@ static void sil_dev_config(struct ata_device *dev)
        unsigned int n, quirks = 0;
        unsigned char model_num[ATA_ID_PROD_LEN + 1];
 
+       /* This controller doesn't support trim */
+       dev->horkage |= ATA_HORKAGE_NOTRIM;
+
        ata_id_c_string(dev->id, model_num, ATA_ID_PROD, sizeof(model_num));
 
        for (n = 0; sil_blacklist[n].product; n++)
index 2804aed3f416aea878efde04937937e238ff4e5e..25425d3f257536b291f27aa975bb8f164c0c437c 100644 (file)
@@ -303,6 +303,10 @@ static int memory_subsys_offline(struct device *dev)
        if (mem->state == MEM_OFFLINE)
                return 0;
 
+       /* Can't offline block with non-present sections */
+       if (mem->section_count != sections_per_block)
+               return -EINVAL;
+
        return memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
 }
 
index 167418e73445a4f69b372f9205f65ca43f525c9d..65f50eccd49b0aa4b6801912fd8d21a73f79a7b9 100644 (file)
@@ -390,6 +390,7 @@ static int pm_genpd_runtime_suspend(struct device *dev)
        struct generic_pm_domain *genpd;
        bool (*stop_ok)(struct device *__dev);
        struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
+       bool runtime_pm = pm_runtime_enabled(dev);
        ktime_t time_start;
        s64 elapsed_ns;
        int ret;
@@ -400,12 +401,19 @@ static int pm_genpd_runtime_suspend(struct device *dev)
        if (IS_ERR(genpd))
                return -EINVAL;
 
+       /*
+        * A runtime PM centric subsystem/driver may re-use the runtime PM
+        * callbacks for other purposes than runtime PM. In those scenarios
+        * runtime PM is disabled. Under these circumstances, we shall skip
+        * validating/measuring the PM QoS latency.
+        */
        stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL;
-       if (stop_ok && !stop_ok(dev))
+       if (runtime_pm && stop_ok && !stop_ok(dev))
                return -EBUSY;
 
        /* Measure suspend latency. */
-       time_start = ktime_get();
+       if (runtime_pm)
+               time_start = ktime_get();
 
        ret = genpd_save_dev(genpd, dev);
        if (ret)
@@ -418,13 +426,15 @@ static int pm_genpd_runtime_suspend(struct device *dev)
        }
 
        /* Update suspend latency value if the measured time exceeds it. */
-       elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
-       if (elapsed_ns > td->suspend_latency_ns) {
-               td->suspend_latency_ns = elapsed_ns;
-               dev_dbg(dev, "suspend latency exceeded, %lld ns\n",
-                       elapsed_ns);
-               genpd->max_off_time_changed = true;
-               td->constraint_changed = true;
+       if (runtime_pm) {
+               elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
+               if (elapsed_ns > td->suspend_latency_ns) {
+                       td->suspend_latency_ns = elapsed_ns;
+                       dev_dbg(dev, "suspend latency exceeded, %lld ns\n",
+                               elapsed_ns);
+                       genpd->max_off_time_changed = true;
+                       td->constraint_changed = true;
+               }
        }
 
        /*
@@ -453,6 +463,7 @@ static int pm_genpd_runtime_resume(struct device *dev)
 {
        struct generic_pm_domain *genpd;
        struct gpd_timing_data *td = &dev_gpd_data(dev)->td;
+       bool runtime_pm = pm_runtime_enabled(dev);
        ktime_t time_start;
        s64 elapsed_ns;
        int ret;
@@ -479,14 +490,14 @@ static int pm_genpd_runtime_resume(struct device *dev)
 
  out:
        /* Measure resume latency. */
-       if (timed)
+       if (timed && runtime_pm)
                time_start = ktime_get();
 
        genpd_start_dev(genpd, dev);
        genpd_restore_dev(genpd, dev);
 
        /* Update resume latency value if the measured time exceeds it. */
-       if (timed) {
+       if (timed && runtime_pm) {
                elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start));
                if (elapsed_ns > td->resume_latency_ns) {
                        td->resume_latency_ns = elapsed_ns;
index 0c3940ec5e62c070b393a5f187ac22674e262c3b..09e3c0d87eccff2d526666b99d3036f3921662a8 100644 (file)
@@ -219,6 +219,9 @@ static void end_cmd(struct nullb_cmd *cmd)
 {
        struct request_queue *q = NULL;
 
+       if (cmd->rq)
+               q = cmd->rq->q;
+
        switch (queue_mode)  {
        case NULL_Q_MQ:
                blk_mq_end_request(cmd->rq, 0);
@@ -229,23 +232,19 @@ static void end_cmd(struct nullb_cmd *cmd)
                break;
        case NULL_Q_BIO:
                bio_endio(cmd->bio);
-               goto free_cmd;
+               break;
        }
 
-       if (cmd->rq)
-               q = cmd->rq->q;
+       free_cmd(cmd);
 
        /* Restart queue if needed, as we are freeing a tag */
-       if (q && !q->mq_ops && blk_queue_stopped(q)) {
+       if (queue_mode == NULL_Q_RQ && blk_queue_stopped(q)) {
                unsigned long flags;
 
                spin_lock_irqsave(q->queue_lock, flags);
-               if (blk_queue_stopped(q))
-                       blk_start_queue(q);
+               blk_start_queue_async(q);
                spin_unlock_irqrestore(q->queue_lock, flags);
        }
-free_cmd:
-       free_cmd(cmd);
 }
 
 static enum hrtimer_restart null_cmd_timer_expired(struct hrtimer *timer)
@@ -444,8 +443,9 @@ static void null_lnvm_end_io(struct request *rq, int error)
        blk_put_request(rq);
 }
 
-static int null_lnvm_submit_io(struct request_queue *q, struct nvm_rq *rqd)
+static int null_lnvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
 {
+       struct request_queue *q = dev->q;
        struct request *rq;
        struct bio *bio = rqd->bio;
 
@@ -470,7 +470,7 @@ static int null_lnvm_submit_io(struct request_queue *q, struct nvm_rq *rqd)
        return 0;
 }
 
-static int null_lnvm_id(struct request_queue *q, struct nvm_id *id)
+static int null_lnvm_id(struct nvm_dev *dev, struct nvm_id *id)
 {
        sector_t size = gb * 1024 * 1024 * 1024ULL;
        sector_t blksize;
@@ -523,7 +523,7 @@ static int null_lnvm_id(struct request_queue *q, struct nvm_id *id)
        return 0;
 }
 
-static void *null_lnvm_create_dma_pool(struct request_queue *q, char *name)
+static void *null_lnvm_create_dma_pool(struct nvm_dev *dev, char *name)
 {
        mempool_t *virtmem_pool;
 
@@ -541,7 +541,7 @@ static void null_lnvm_destroy_dma_pool(void *pool)
        mempool_destroy(pool);
 }
 
-static void *null_lnvm_dev_dma_alloc(struct request_queue *q, void *pool,
+static void *null_lnvm_dev_dma_alloc(struct nvm_dev *dev, void *pool,
                                gfp_t mem_flags, dma_addr_t *dma_handler)
 {
        return mempool_alloc(pool, mem_flags);
@@ -765,7 +765,9 @@ out:
 
 static int __init null_init(void)
 {
+       int ret = 0;
        unsigned int i;
+       struct nullb *nullb;
 
        if (bs > PAGE_SIZE) {
                pr_warn("null_blk: invalid block size\n");
@@ -807,22 +809,29 @@ static int __init null_init(void)
                                                                0, 0, NULL);
                if (!ppa_cache) {
                        pr_err("null_blk: unable to create ppa cache\n");
-                       return -ENOMEM;
+                       ret = -ENOMEM;
+                       goto err_ppa;
                }
        }
 
        for (i = 0; i < nr_devices; i++) {
-               if (null_add_dev()) {
-                       unregister_blkdev(null_major, "nullb");
-                       goto err_ppa;
-               }
+               ret = null_add_dev();
+               if (ret)
+                       goto err_dev;
        }
 
        pr_info("null: module loaded\n");
        return 0;
-err_ppa:
+
+err_dev:
+       while (!list_empty(&nullb_list)) {
+               nullb = list_entry(nullb_list.next, struct nullb, list);
+               null_del_dev(nullb);
+       }
        kmem_cache_destroy(ppa_cache);
-       return -EINVAL;
+err_ppa:
+       unregister_blkdev(null_major, "nullb");
+       return ret;
 }
 
 static void __exit null_exit(void)
index f9099940c2720f95874e6621b4c7e5e1e798fe2c..41fb1a917b172dc9446495d84357060847c2b569 100644 (file)
@@ -950,6 +950,8 @@ static int xen_blkbk_parse_indirect(struct blkif_request *req,
                goto unmap;
 
        for (n = 0, i = 0; n < nseg; n++) {
+               uint8_t first_sect, last_sect;
+
                if ((n % SEGS_PER_INDIRECT_FRAME) == 0) {
                        /* Map indirect segments */
                        if (segments)
@@ -957,15 +959,18 @@ static int xen_blkbk_parse_indirect(struct blkif_request *req,
                        segments = kmap_atomic(pages[n/SEGS_PER_INDIRECT_FRAME]->page);
                }
                i = n % SEGS_PER_INDIRECT_FRAME;
+
                pending_req->segments[n]->gref = segments[i].gref;
-               seg[n].nsec = segments[i].last_sect -
-                       segments[i].first_sect + 1;
-               seg[n].offset = (segments[i].first_sect << 9);
-               if ((segments[i].last_sect >= (XEN_PAGE_SIZE >> 9)) ||
-                   (segments[i].last_sect < segments[i].first_sect)) {
+
+               first_sect = READ_ONCE(segments[i].first_sect);
+               last_sect = READ_ONCE(segments[i].last_sect);
+               if (last_sect >= (XEN_PAGE_SIZE >> 9) || last_sect < first_sect) {
                        rc = -EINVAL;
                        goto unmap;
                }
+
+               seg[n].nsec = last_sect - first_sect + 1;
+               seg[n].offset = first_sect << 9;
                preq->nr_sects += seg[n].nsec;
        }
 
index 68e87a037b992df8c64d6894719b5b390ef1d10a..c929ae22764c9dd4345195a1542df997c5a8e29b 100644 (file)
@@ -408,8 +408,8 @@ static inline void blkif_get_x86_32_req(struct blkif_request *dst,
                                        struct blkif_x86_32_request *src)
 {
        int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST, j;
-       dst->operation = src->operation;
-       switch (src->operation) {
+       dst->operation = READ_ONCE(src->operation);
+       switch (dst->operation) {
        case BLKIF_OP_READ:
        case BLKIF_OP_WRITE:
        case BLKIF_OP_WRITE_BARRIER:
@@ -456,8 +456,8 @@ static inline void blkif_get_x86_64_req(struct blkif_request *dst,
                                        struct blkif_x86_64_request *src)
 {
        int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST, j;
-       dst->operation = src->operation;
-       switch (src->operation) {
+       dst->operation = READ_ONCE(src->operation);
+       switch (dst->operation) {
        case BLKIF_OP_READ:
        case BLKIF_OP_WRITE:
        case BLKIF_OP_WRITE_BARRIER:
index 846bc29c157dcca1bde81f288a5d323476042295..25996e2561105ac615cf4cc99c468f7a8db0f3df 100644 (file)
@@ -342,13 +342,13 @@ static int sunxi_rsb_read(struct sunxi_rsb *rsb, u8 rtaddr, u8 addr,
 
        ret = _sunxi_rsb_run_xfer(rsb);
        if (ret)
-               goto out;
+               goto unlock;
 
        *buf = readl(rsb->regs + RSB_DATA);
 
+unlock:
        mutex_unlock(&rsb->lock);
 
-out:
        return ret;
 }
 
@@ -527,9 +527,9 @@ static int sunxi_rsb_init_device_mode(struct sunxi_rsb *rsb)
  */
 
 static const struct sunxi_rsb_addr_map sunxi_rsb_addr_maps[] = {
-       { 0x3e3, 0x2d }, /* Primary PMIC: AXP223, AXP809, AXP81X, ... */
+       { 0x3a3, 0x2d }, /* Primary PMIC: AXP223, AXP809, AXP81X, ... */
        { 0x745, 0x3a }, /* Secondary PMIC: AXP806, ... */
-       { 0xe89, 0x45 }, /* Peripheral IC: AC100, ... */
+       { 0xe89, 0x4e }, /* Peripheral IC: AC100, ... */
 };
 
 static u8 sunxi_rsb_get_rtaddr(u16 hwaddr)
index 55fe9020459f2c4bdcec710a90220b2ea32e54db..4cc72fa017c7bbb02c4027e3bf44bc4d102d3849 100644 (file)
@@ -1230,14 +1230,14 @@ static int smi_start_processing(void       *send_info,
 
        new_smi->intf = intf;
 
-       /* Try to claim any interrupts. */
-       if (new_smi->irq_setup)
-               new_smi->irq_setup(new_smi);
-
        /* Set up the timer that drives the interface. */
        setup_timer(&new_smi->si_timer, smi_timeout, (long)new_smi);
        smi_mod_timer(new_smi, jiffies + SI_TIMEOUT_JIFFIES);
 
+       /* Try to claim any interrupts. */
+       if (new_smi->irq_setup)
+               new_smi->irq_setup(new_smi);
+
        /*
         * Check if the user forcefully enabled the daemon.
         */
index 10819e2484145ebae0ef9b1092098d1bbc7848d1..335322dc403f48fcf773028d232e5c772f3cd8b5 100644 (file)
@@ -209,6 +209,8 @@ EXPORT_SYMBOL_GPL(clk_register_gpio_mux);
 
 struct clk_gpio_delayed_register_data {
        const char *gpio_name;
+       int num_parents;
+       const char **parent_names;
        struct device_node *node;
        struct mutex lock;
        struct clk *clk;
@@ -222,8 +224,6 @@ static struct clk *of_clk_gpio_delayed_register_get(
 {
        struct clk_gpio_delayed_register_data *data = _data;
        struct clk *clk;
-       const char **parent_names;
-       int i, num_parents;
        int gpio;
        enum of_gpio_flags of_flags;
 
@@ -248,26 +248,14 @@ static struct clk *of_clk_gpio_delayed_register_get(
                return ERR_PTR(gpio);
        }
 
-       num_parents = of_clk_get_parent_count(data->node);
-
-       parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL);
-       if (!parent_names) {
-               clk = ERR_PTR(-ENOMEM);
-               goto out;
-       }
-
-       for (i = 0; i < num_parents; i++)
-               parent_names[i] = of_clk_get_parent_name(data->node, i);
-
-       clk = data->clk_register_get(data->node->name, parent_names,
-                       num_parents, gpio, of_flags & OF_GPIO_ACTIVE_LOW);
+       clk = data->clk_register_get(data->node->name, data->parent_names,
+                       data->num_parents, gpio, of_flags & OF_GPIO_ACTIVE_LOW);
        if (IS_ERR(clk))
                goto out;
 
        data->clk = clk;
 out:
        mutex_unlock(&data->lock);
-       kfree(parent_names);
 
        return clk;
 }
@@ -296,11 +284,24 @@ static void __init of_gpio_clk_setup(struct device_node *node,
                                unsigned gpio, bool active_low))
 {
        struct clk_gpio_delayed_register_data *data;
+       const char **parent_names;
+       int i, num_parents;
 
        data = kzalloc(sizeof(*data), GFP_KERNEL);
        if (!data)
                return;
 
+       num_parents = of_clk_get_parent_count(node);
+
+       parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL);
+       if (!parent_names)
+               return;
+
+       for (i = 0; i < num_parents; i++)
+               parent_names[i] = of_clk_get_parent_name(node, i);
+
+       data->num_parents = num_parents;
+       data->parent_names = parent_names;
        data->node = node;
        data->gpio_name = gpio_name;
        data->clk_register_get = clk_register_get;
index 1ab0fb81c6a0ef7746d77427c488bdb84235011a..7bc1c4527ae48d0baad2ebb4e141385e695ff8f4 100644 (file)
@@ -778,8 +778,10 @@ static struct clk * __init create_one_cmux(struct clockgen *cg, int idx)
         */
        clksel = (cg_in(cg, hwc->reg) & CLKSEL_MASK) >> CLKSEL_SHIFT;
        div = get_pll_div(cg, hwc, clksel);
-       if (!div)
+       if (!div) {
+               kfree(hwc);
                return NULL;
+       }
 
        pct80_rate = clk_get_rate(div->clk);
        pct80_rate *= 8;
index 0b501a9fef92b96810655b952870c7da58400c2c..cd0f2726f5e0dd0da33b06e4518f02fc231cf1f7 100644 (file)
@@ -292,6 +292,7 @@ static int scpi_clocks_probe(struct platform_device *pdev)
                ret = scpi_clk_add(dev, child, match);
                if (ret) {
                        scpi_clocks_remove(pdev);
+                       of_node_put(child);
                        return ret;
                }
        }
index 8564e4342c7d1fa115c1b5f9043bf6bbb8d6e70d..82fe3662b5f6d43e5bf4d8cc1acb3ea3b29048b9 100644 (file)
@@ -52,7 +52,7 @@ static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw,
                unsigned long parent_rate)
 {
        struct clk_pllv1 *pll = to_clk_pllv1(hw);
-       long long ll;
+       unsigned long long ull;
        int mfn_abs;
        unsigned int mfi, mfn, mfd, pd;
        u32 reg;
@@ -94,16 +94,16 @@ static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw,
        rate = parent_rate * 2;
        rate /= pd + 1;
 
-       ll = (unsigned long long)rate * mfn_abs;
+       ull = (unsigned long long)rate * mfn_abs;
 
-       do_div(ll, mfd + 1);
+       do_div(ull, mfd + 1);
 
        if (mfn_is_negative(pll, mfn))
-               ll = -ll;
+               ull = (rate * mfi) - ull;
+       else
+               ull = (rate * mfi) + ull;
 
-       ll = (rate * mfi) + ll;
-
-       return ll;
+       return ull;
 }
 
 static struct clk_ops clk_pllv1_ops = {
index b18f875eac6acadd7e0ae27644fe8af0df240af6..4aeda56ce37279006a5cb8be93f9146d7e3d56d7 100644 (file)
@@ -79,7 +79,7 @@ static unsigned long __clk_pllv2_recalc_rate(unsigned long parent_rate,
 {
        long mfi, mfn, mfd, pdf, ref_clk;
        unsigned long dbl;
-       s64 temp;
+       u64 temp;
 
        dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;
 
@@ -98,8 +98,9 @@ static unsigned long __clk_pllv2_recalc_rate(unsigned long parent_rate,
        temp = (u64) ref_clk * abs(mfn);
        do_div(temp, mfd + 1);
        if (mfn < 0)
-               temp = -temp;
-       temp = (ref_clk * mfi) + temp;
+               temp = (ref_clk * mfi) - temp;
+       else
+               temp = (ref_clk * mfi) + temp;
 
        return temp;
 }
@@ -126,7 +127,7 @@ static int __clk_pllv2_set_rate(unsigned long rate, unsigned long parent_rate,
 {
        u32 reg;
        long mfi, pdf, mfn, mfd = 999999;
-       s64 temp64;
+       u64 temp64;
        unsigned long quad_parent_rate;
 
        quad_parent_rate = 4 * parent_rate;
index d1b1c95177bbeb577c88bf06c06121db76477f24..0a94d9661d9123551b5b84cd5764cb9b91a6c176 100644 (file)
@@ -335,22 +335,22 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
        clk[VF610_CLK_SAI0_SEL] = imx_clk_mux("sai0_sel", CCM_CSCMR1, 0, 2, sai_sels, 4);
        clk[VF610_CLK_SAI0_EN] = imx_clk_gate("sai0_en", "sai0_sel", CCM_CSCDR1, 16);
        clk[VF610_CLK_SAI0_DIV] = imx_clk_divider("sai0_div", "sai0_en", CCM_CSCDR1, 0, 4);
-       clk[VF610_CLK_SAI0] = imx_clk_gate2("sai0", "sai0_div", CCM_CCGR0, CCM_CCGRx_CGn(15));
+       clk[VF610_CLK_SAI0] = imx_clk_gate2("sai0", "ipg_bus", CCM_CCGR0, CCM_CCGRx_CGn(15));
 
        clk[VF610_CLK_SAI1_SEL] = imx_clk_mux("sai1_sel", CCM_CSCMR1, 2, 2, sai_sels, 4);
        clk[VF610_CLK_SAI1_EN] = imx_clk_gate("sai1_en", "sai1_sel", CCM_CSCDR1, 17);
        clk[VF610_CLK_SAI1_DIV] = imx_clk_divider("sai1_div", "sai1_en", CCM_CSCDR1, 4, 4);
-       clk[VF610_CLK_SAI1] = imx_clk_gate2("sai1", "sai1_div", CCM_CCGR1, CCM_CCGRx_CGn(0));
+       clk[VF610_CLK_SAI1] = imx_clk_gate2("sai1", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(0));
 
        clk[VF610_CLK_SAI2_SEL] = imx_clk_mux("sai2_sel", CCM_CSCMR1, 4, 2, sai_sels, 4);
        clk[VF610_CLK_SAI2_EN] = imx_clk_gate("sai2_en", "sai2_sel", CCM_CSCDR1, 18);
        clk[VF610_CLK_SAI2_DIV] = imx_clk_divider("sai2_div", "sai2_en", CCM_CSCDR1, 8, 4);
-       clk[VF610_CLK_SAI2] = imx_clk_gate2("sai2", "sai2_div", CCM_CCGR1, CCM_CCGRx_CGn(1));
+       clk[VF610_CLK_SAI2] = imx_clk_gate2("sai2", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(1));
 
        clk[VF610_CLK_SAI3_SEL] = imx_clk_mux("sai3_sel", CCM_CSCMR1, 6, 2, sai_sels, 4);
        clk[VF610_CLK_SAI3_EN] = imx_clk_gate("sai3_en", "sai3_sel", CCM_CSCDR1, 19);
        clk[VF610_CLK_SAI3_DIV] = imx_clk_divider("sai3_div", "sai3_en", CCM_CSCDR1, 12, 4);
-       clk[VF610_CLK_SAI3] = imx_clk_gate2("sai3", "sai3_div", CCM_CCGR1, CCM_CCGRx_CGn(2));
+       clk[VF610_CLK_SAI3] = imx_clk_gate2("sai3", "ipg_bus", CCM_CCGR1, CCM_CCGRx_CGn(2));
 
        clk[VF610_CLK_NFC_SEL] = imx_clk_mux("nfc_sel", CCM_CSCMR1, 12, 2, nfc_sels, 4);
        clk[VF610_CLK_NFC_EN] = imx_clk_gate("nfc_en", "nfc_sel", CCM_CSCDR2, 9);
index 09d2832fbd7821a56e53fe8dc22ab16548fa3f1c..71fd29348f28b778faacba038cbcc94a887d08ba 100644 (file)
@@ -9,6 +9,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
index 93e967c0f972f954ef1f7af9bb2f90e0c3241cae..75244915df05f92aad3272887e3f5b55b10ba3be 100644 (file)
@@ -9,6 +9,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
index 993abcdb32cce825fdb1d2ea835cb69f3ecf94fc..37ba04ba13686c4f986b6559e7175eb005509e67 100644 (file)
@@ -9,6 +9,7 @@
  * warranty of any kind, whether express or implied.
  */
 
+#include <linux/clk.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
index 5484c31ec5683c6f92a0c4eeab2ceba1a782e562..0ee1f363e4be154749d4b37a07e215dbd705d76e 100644 (file)
 
 #define SUN4I_PLL2_OUTPUTS             4
 
-struct sun4i_pll2_data {
-       u32     post_div_offset;
-       u32     pre_div_flags;
-};
-
 static DEFINE_SPINLOCK(sun4i_a10_pll2_lock);
 
 static void __init sun4i_pll2_setup(struct device_node *node,
-                                   struct sun4i_pll2_data *data)
+                                   int post_div_offset)
 {
        const char *clk_name = node->name, *parent;
        struct clk **clks, *base_clk, *prediv_clk;
@@ -76,7 +71,7 @@ static void __init sun4i_pll2_setup(struct device_node *node,
                                          parent, 0, reg,
                                          SUN4I_PLL2_PRE_DIV_SHIFT,
                                          SUN4I_PLL2_PRE_DIV_WIDTH,
-                                         data->pre_div_flags,
+                                         CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
                                          &sun4i_a10_pll2_lock);
        if (!prediv_clk) {
                pr_err("Couldn't register the prediv clock\n");
@@ -127,7 +122,7 @@ static void __init sun4i_pll2_setup(struct device_node *node,
         */
        val = readl(reg);
        val &= ~(SUN4I_PLL2_POST_DIV_MASK << SUN4I_PLL2_POST_DIV_SHIFT);
-       val |= (SUN4I_PLL2_POST_DIV_VALUE - data->post_div_offset) << SUN4I_PLL2_POST_DIV_SHIFT;
+       val |= (SUN4I_PLL2_POST_DIV_VALUE - post_div_offset) << SUN4I_PLL2_POST_DIV_SHIFT;
        writel(val, reg);
 
        of_property_read_string_index(node, "clock-output-names",
@@ -191,25 +186,17 @@ err_unmap:
        iounmap(reg);
 }
 
-static struct sun4i_pll2_data sun4i_a10_pll2_data = {
-       .pre_div_flags  = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
-};
-
 static void __init sun4i_a10_pll2_setup(struct device_node *node)
 {
-       sun4i_pll2_setup(node, &sun4i_a10_pll2_data);
+       sun4i_pll2_setup(node, 0);
 }
 
 CLK_OF_DECLARE(sun4i_a10_pll2, "allwinner,sun4i-a10-pll2-clk",
               sun4i_a10_pll2_setup);
 
-static struct sun4i_pll2_data sun5i_a13_pll2_data = {
-       .post_div_offset        = 1,
-};
-
 static void __init sun5i_a13_pll2_setup(struct device_node *node)
 {
-       sun4i_pll2_setup(node, &sun5i_a13_pll2_data);
+       sun4i_pll2_setup(node, 1);
 }
 
 CLK_OF_DECLARE(sun5i_a13_pll2, "allwinner,sun5i-a13-pll2-clk",
index 1dfad0c712cd87c63eb2dabecda3be0e17ba22be..2a5d84fdddc5d56c0f47fe56aa03683569a5e929 100644 (file)
@@ -20,6 +20,8 @@ static struct ti_dt_clk dm816x_clks[] = {
        DT_CLK(NULL, "sys_clkin", "sys_clkin_ck"),
        DT_CLK(NULL, "timer_sys_ck", "sys_clkin_ck"),
        DT_CLK(NULL, "sys_32k_ck", "sys_32k_ck"),
+       DT_CLK(NULL, "timer_32k_ck", "sysclk18_ck"),
+       DT_CLK(NULL, "timer_ext_ck", "tclkin_ck"),
        DT_CLK(NULL, "mpu_ck", "mpu_ck"),
        DT_CLK(NULL, "timer1_fck", "timer1_fck"),
        DT_CLK(NULL, "timer2_fck", "timer2_fck"),
index 9023ca9caf84dde6b02c7ffacdded5244b16795d..b5cc6f66ae5df5e1725dc21ebfd3b18ca5eac1fa 100644 (file)
@@ -240,7 +240,7 @@ u8 omap2_init_dpll_parent(struct clk_hw *hw)
  */
 unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
 {
-       long long dpll_clk;
+       u64 dpll_clk;
        u32 dpll_mult, dpll_div, v;
        struct dpll_data *dd;
 
@@ -262,7 +262,7 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
        dpll_div = v & dd->div1_mask;
        dpll_div >>= __ffs(dd->div1_mask);
 
-       dpll_clk = (long long)clk_get_rate(dd->clk_ref) * dpll_mult;
+       dpll_clk = (u64)clk_get_rate(dd->clk_ref) * dpll_mult;
        do_div(dpll_clk, dpll_div + 1);
 
        return dpll_clk;
index 5b1726829e6df038de9e8502471cbb6b70414fd5..df2558350fc1d6be681d818c361339acd2afaba3 100644 (file)
@@ -214,7 +214,6 @@ static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 {
        struct clk_divider *divider;
        unsigned int div, value;
-       unsigned long flags = 0;
        u32 val;
 
        if (!hw || !rate)
@@ -228,9 +227,6 @@ static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
        if (value > div_mask(divider))
                value = div_mask(divider);
 
-       if (divider->lock)
-               spin_lock_irqsave(divider->lock, flags);
-
        if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
                val = div_mask(divider) << (divider->shift + 16);
        } else {
@@ -240,9 +236,6 @@ static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
        val |= value << divider->shift;
        ti_clk_ll_ops->clk_writel(val, divider->reg);
 
-       if (divider->lock)
-               spin_unlock_irqrestore(divider->lock, flags);
-
        return 0;
 }
 
@@ -256,8 +249,7 @@ static struct clk *_register_divider(struct device *dev, const char *name,
                                     const char *parent_name,
                                     unsigned long flags, void __iomem *reg,
                                     u8 shift, u8 width, u8 clk_divider_flags,
-                                    const struct clk_div_table *table,
-                                    spinlock_t *lock)
+                                    const struct clk_div_table *table)
 {
        struct clk_divider *div;
        struct clk *clk;
@@ -288,7 +280,6 @@ static struct clk *_register_divider(struct device *dev, const char *name,
        div->shift = shift;
        div->width = width;
        div->flags = clk_divider_flags;
-       div->lock = lock;
        div->hw.init = &init;
        div->table = table;
 
@@ -421,7 +412,7 @@ struct clk *ti_clk_register_divider(struct ti_clk *setup)
 
        clk = _register_divider(NULL, setup->name, div->parent,
                                flags, (void __iomem *)reg, div->bit_shift,
-                               width, div_flags, table, NULL);
+                               width, div_flags, table);
 
        if (IS_ERR(clk))
                kfree(table);
@@ -584,8 +575,7 @@ static void __init of_ti_divider_clk_setup(struct device_node *node)
                goto cleanup;
 
        clk = _register_divider(NULL, node->name, parent_name, flags, reg,
-                               shift, width, clk_divider_flags, table,
-                               NULL);
+                               shift, width, clk_divider_flags, table);
 
        if (!IS_ERR(clk)) {
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
index f4b2e9888bdf3c3079b0854b1c04c65a5201c5db..66a0d0ed8b55064ac7a888a1d2e6441d3021ceb1 100644 (file)
@@ -168,7 +168,7 @@ static unsigned long ti_fapll_recalc_rate(struct clk_hw *hw,
 {
        struct fapll_data *fd = to_fapll(hw);
        u32 fapll_n, fapll_p, v;
-       long long rate;
+       u64 rate;
 
        if (ti_fapll_clock_is_bypass(fd))
                return parent_rate;
@@ -314,7 +314,7 @@ static unsigned long ti_fapll_synth_recalc_rate(struct clk_hw *hw,
 {
        struct fapll_synth *synth = to_synth(hw);
        u32 synth_div_m;
-       long long rate;
+       u64 rate;
 
        /* The audio_pll_clk1 is hardwired to produce 32.768KiHz clock */
        if (!synth->div)
index 69f08a1d047d8672a758e441fcd718bbf64bb946..dab9ba88b9d6d2b1b97e2472694bbb588997d8de 100644 (file)
@@ -69,7 +69,6 @@ static int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index)
 {
        struct clk_mux *mux = to_clk_mux(hw);
        u32 val;
-       unsigned long flags = 0;
 
        if (mux->table) {
                index = mux->table[index];
@@ -81,9 +80,6 @@ static int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index)
                        index++;
        }
 
-       if (mux->lock)
-               spin_lock_irqsave(mux->lock, flags);
-
        if (mux->flags & CLK_MUX_HIWORD_MASK) {
                val = mux->mask << (mux->shift + 16);
        } else {
@@ -93,9 +89,6 @@ static int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index)
        val |= index << mux->shift;
        ti_clk_ll_ops->clk_writel(val, mux->reg);
 
-       if (mux->lock)
-               spin_unlock_irqrestore(mux->lock, flags);
-
        return 0;
 }
 
@@ -109,7 +102,7 @@ static struct clk *_register_mux(struct device *dev, const char *name,
                                 const char **parent_names, u8 num_parents,
                                 unsigned long flags, void __iomem *reg,
                                 u8 shift, u32 mask, u8 clk_mux_flags,
-                                u32 *table, spinlock_t *lock)
+                                u32 *table)
 {
        struct clk_mux *mux;
        struct clk *clk;
@@ -133,7 +126,6 @@ static struct clk *_register_mux(struct device *dev, const char *name,
        mux->shift = shift;
        mux->mask = mask;
        mux->flags = clk_mux_flags;
-       mux->lock = lock;
        mux->table = table;
        mux->hw.init = &init;
 
@@ -175,7 +167,7 @@ struct clk *ti_clk_register_mux(struct ti_clk *setup)
 
        return _register_mux(NULL, setup->name, mux->parents, mux->num_parents,
                             flags, (void __iomem *)reg, mux->bit_shift, mask,
-                            mux_flags, NULL, NULL);
+                            mux_flags, NULL);
 }
 
 /**
@@ -227,8 +219,7 @@ static void of_mux_clk_setup(struct device_node *node)
        mask = (1 << fls(mask)) - 1;
 
        clk = _register_mux(NULL, node->name, parent_names, num_parents,
-                           flags, reg, shift, mask, clk_mux_flags, NULL,
-                           NULL);
+                           flags, reg, shift, mask, clk_mux_flags, NULL);
 
        if (!IS_ERR(clk))
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
index 1593ade2a8154da8840236bd9a0debb931ebfa5a..c4f7d7a9b68987e861bb52ea807f919ca785a1c9 100644 (file)
@@ -55,7 +55,7 @@ int __init clocksource_mmio_init(void __iomem *base, const char *name,
 {
        struct clocksource_mmio *cs;
 
-       if (bits > 32 || bits < 16)
+       if (bits > 64 || bits < 16)
                return -EINVAL;
 
        cs = kzalloc(sizeof(struct clocksource_mmio), GFP_KERNEL);
index d7373ca69c9947a83dd8a1d67b77c7fc9e77209e..25693b0453714ca8bb1e610fdda0786a1fc3798e 100644 (file)
@@ -179,26 +179,21 @@ static int cn_call_callback(struct sk_buff *skb)
  *
  * It checks skb, netlink header and msg sizes, and calls callback helper.
  */
-static void cn_rx_skb(struct sk_buff *__skb)
+static void cn_rx_skb(struct sk_buff *skb)
 {
        struct nlmsghdr *nlh;
-       struct sk_buff *skb;
        int len, err;
 
-       skb = skb_get(__skb);
-
        if (skb->len >= NLMSG_HDRLEN) {
                nlh = nlmsg_hdr(skb);
                len = nlmsg_len(nlh);
 
                if (len < (int)sizeof(struct cn_msg) ||
                    skb->len < nlh->nlmsg_len ||
-                   len > CONNECTOR_MAX_MSG_SIZE) {
-                       kfree_skb(skb);
+                   len > CONNECTOR_MAX_MSG_SIZE)
                        return;
-               }
 
-               err = cn_call_callback(skb);
+               err = cn_call_callback(skb_get(skb));
                if (err < 0)
                        kfree_skb(skb);
        }
index 235a1ba73d92d577bbf605f5dab9d737fe246797..b1f8a73e5a943e8fc692dfcba7f28d1e08dba4f2 100644 (file)
@@ -226,7 +226,7 @@ config ARM_TEGRA20_CPUFREQ
 
 config ARM_TEGRA124_CPUFREQ
        tristate "Tegra124 CPUFreq support"
-       depends on ARCH_TEGRA && CPUFREQ_DT
+       depends on ARCH_TEGRA && CPUFREQ_DT && REGULATOR
        default y
        help
          This adds the CPUFreq driver support for Tegra124 SOCs.
index 4d07cbd2b23cfb80ddc40fc0822ce37464991498..98fb8821382d8fc145c6bf9227b62236fdabedb1 100644 (file)
@@ -1123,7 +1123,7 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
                                   limits->max_sysfs_pct);
        limits->max_perf_pct = max(limits->min_policy_pct,
                                   limits->max_perf_pct);
-       limits->max_perf = round_up(limits->max_perf, 8);
+       limits->max_perf = round_up(limits->max_perf, FRAC_BITS);
 
        /* Make sure min_perf_pct <= max_perf_pct */
        limits->min_perf_pct = min(limits->max_perf_pct, limits->min_perf_pct);
index 733aa5153e7451f645a65e3452ed44d6d488054a..68ef8fd9482fd2532762789973b8d4dfa98cfdd5 100644 (file)
@@ -648,7 +648,7 @@ late_initcall(s3c_cpufreq_initcall);
  *
  * Register the given set of PLLs with the system.
  */
-int __init s3c_plltab_register(struct cpufreq_frequency_table *plls,
+int s3c_plltab_register(struct cpufreq_frequency_table *plls,
                               unsigned int plls_no)
 {
        struct cpufreq_frequency_table *vals;
index 2c3b16fd3a01fc1c521f8201bd698dab2d6d1215..de5e89b2eaaa3db13413eec5762620c21623738c 100644 (file)
@@ -31,7 +31,7 @@ static struct scpi_ops *scpi_ops;
 
 static struct scpi_dvfs_info *scpi_get_dvfs_info(struct device *cpu_dev)
 {
-       u8 domain = topology_physical_package_id(cpu_dev->id);
+       int domain = topology_physical_package_id(cpu_dev->id);
 
        if (domain < 0)
                return ERR_PTR(-EINVAL);
index 7f039de143f0d07ba3e59cfcf6469082fdeef831..370c661c7d7b25c237a3376dd18da79fbd44eadd 100644 (file)
 #define                AT_XDMAC_CC_WRIP        (0x1 << 23)     /* Write in Progress (read only) */
 #define                        AT_XDMAC_CC_WRIP_DONE           (0x0 << 23)
 #define                        AT_XDMAC_CC_WRIP_IN_PROGRESS    (0x1 << 23)
-#define                AT_XDMAC_CC_PERID(i)    (0x7f & (h) << 24)      /* Channel Peripheral Identifier */
+#define                AT_XDMAC_CC_PERID(i)    (0x7f & (i) << 24)      /* Channel Peripheral Identifier */
 #define AT_XDMAC_CDS_MSP       0x2C    /* Channel Data Stride Memory Set Pattern */
 #define AT_XDMAC_CSUS          0x30    /* Channel Source Microblock Stride */
 #define AT_XDMAC_CDUS          0x34    /* Channel Destination Microblock Stride */
@@ -965,7 +965,9 @@ at_xdmac_prep_interleaved(struct dma_chan *chan,
                                                        NULL,
                                                        src_addr, dst_addr,
                                                        xt, xt->sgl);
-               for (i = 0; i < xt->numf; i++)
+
+               /* Length of the block is (BLEN+1) microblocks. */
+               for (i = 0; i < xt->numf - 1; i++)
                        at_xdmac_increment_block_count(chan, first);
 
                dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n",
@@ -1086,6 +1088,7 @@ at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
                /* Check remaining length and change data width if needed. */
                dwidth = at_xdmac_align_width(chan,
                                              src_addr | dst_addr | xfer_size);
+               chan_cc &= ~AT_XDMAC_CC_DWIDTH_MASK;
                chan_cc |= AT_XDMAC_CC_DWIDTH(dwidth);
 
                ublen = xfer_size >> dwidth;
@@ -1333,7 +1336,7 @@ at_xdmac_prep_dma_memset_sg(struct dma_chan *chan, struct scatterlist *sgl,
                 * since we don't care about the stride anymore.
                 */
                if ((i == (sg_len - 1)) &&
-                   sg_dma_len(ppsg) == sg_dma_len(psg)) {
+                   sg_dma_len(psg) == sg_dma_len(sg)) {
                        dev_dbg(chan2dev(chan),
                                "%s: desc 0x%p can be merged with desc 0x%p\n",
                                __func__, desc, pdesc);
index c92d6a70ccf303c69cfdb127210a09a1262122bc..996c4b00d323ed5c2dd6455f80eb36ed8e9a8b23 100644 (file)
@@ -31,6 +31,7 @@
  */
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -62,6 +63,11 @@ struct bcm2835_dma_cb {
        uint32_t pad[2];
 };
 
+struct bcm2835_cb_entry {
+       struct bcm2835_dma_cb *cb;
+       dma_addr_t paddr;
+};
+
 struct bcm2835_chan {
        struct virt_dma_chan vc;
        struct list_head node;
@@ -72,18 +78,18 @@ struct bcm2835_chan {
 
        int ch;
        struct bcm2835_desc *desc;
+       struct dma_pool *cb_pool;
 
        void __iomem *chan_base;
        int irq_number;
 };
 
 struct bcm2835_desc {
+       struct bcm2835_chan *c;
        struct virt_dma_desc vd;
        enum dma_transfer_direction dir;
 
-       unsigned int control_block_size;
-       struct bcm2835_dma_cb *control_block_base;
-       dma_addr_t control_block_base_phys;
+       struct bcm2835_cb_entry *cb_list;
 
        unsigned int frames;
        size_t size;
@@ -143,10 +149,13 @@ static inline struct bcm2835_desc *to_bcm2835_dma_desc(
 static void bcm2835_dma_desc_free(struct virt_dma_desc *vd)
 {
        struct bcm2835_desc *desc = container_of(vd, struct bcm2835_desc, vd);
-       dma_free_coherent(desc->vd.tx.chan->device->dev,
-                       desc->control_block_size,
-                       desc->control_block_base,
-                       desc->control_block_base_phys);
+       int i;
+
+       for (i = 0; i < desc->frames; i++)
+               dma_pool_free(desc->c->cb_pool, desc->cb_list[i].cb,
+                             desc->cb_list[i].paddr);
+
+       kfree(desc->cb_list);
        kfree(desc);
 }
 
@@ -199,7 +208,7 @@ static void bcm2835_dma_start_desc(struct bcm2835_chan *c)
 
        c->desc = d = to_bcm2835_dma_desc(&vd->tx);
 
-       writel(d->control_block_base_phys, c->chan_base + BCM2835_DMA_ADDR);
+       writel(d->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR);
        writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS);
 }
 
@@ -232,9 +241,16 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
 static int bcm2835_dma_alloc_chan_resources(struct dma_chan *chan)
 {
        struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
+       struct device *dev = c->vc.chan.device->dev;
+
+       dev_dbg(dev, "Allocating DMA channel %d\n", c->ch);
 
-       dev_dbg(c->vc.chan.device->dev,
-                       "Allocating DMA channel %d\n", c->ch);
+       c->cb_pool = dma_pool_create(dev_name(dev), dev,
+                                    sizeof(struct bcm2835_dma_cb), 0, 0);
+       if (!c->cb_pool) {
+               dev_err(dev, "unable to allocate descriptor pool\n");
+               return -ENOMEM;
+       }
 
        return request_irq(c->irq_number,
                        bcm2835_dma_callback, 0, "DMA IRQ", c);
@@ -246,6 +262,7 @@ static void bcm2835_dma_free_chan_resources(struct dma_chan *chan)
 
        vchan_free_chan_resources(&c->vc);
        free_irq(c->irq_number, c);
+       dma_pool_destroy(c->cb_pool);
 
        dev_dbg(c->vc.chan.device->dev, "Freeing DMA channel %u\n", c->ch);
 }
@@ -261,8 +278,7 @@ static size_t bcm2835_dma_desc_size_pos(struct bcm2835_desc *d, dma_addr_t addr)
        size_t size;
 
        for (size = i = 0; i < d->frames; i++) {
-               struct bcm2835_dma_cb *control_block =
-                       &d->control_block_base[i];
+               struct bcm2835_dma_cb *control_block = d->cb_list[i].cb;
                size_t this_size = control_block->length;
                dma_addr_t dma;
 
@@ -343,6 +359,7 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
        dma_addr_t dev_addr;
        unsigned int es, sync_type;
        unsigned int frame;
+       int i;
 
        /* Grab configuration */
        if (!is_slave_direction(direction)) {
@@ -374,27 +391,31 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
        if (!d)
                return NULL;
 
+       d->c = c;
        d->dir = direction;
        d->frames = buf_len / period_len;
 
-       /* Allocate memory for control blocks */
-       d->control_block_size = d->frames * sizeof(struct bcm2835_dma_cb);
-       d->control_block_base = dma_zalloc_coherent(chan->device->dev,
-                       d->control_block_size, &d->control_block_base_phys,
-                       GFP_NOWAIT);
-
-       if (!d->control_block_base) {
+       d->cb_list = kcalloc(d->frames, sizeof(*d->cb_list), GFP_KERNEL);
+       if (!d->cb_list) {
                kfree(d);
                return NULL;
        }
+       /* Allocate memory for control blocks */
+       for (i = 0; i < d->frames; i++) {
+               struct bcm2835_cb_entry *cb_entry = &d->cb_list[i];
+
+               cb_entry->cb = dma_pool_zalloc(c->cb_pool, GFP_ATOMIC,
+                                              &cb_entry->paddr);
+               if (!cb_entry->cb)
+                       goto error_cb;
+       }
 
        /*
         * Iterate over all frames, create a control block
         * for each frame and link them together.
         */
        for (frame = 0; frame < d->frames; frame++) {
-               struct bcm2835_dma_cb *control_block =
-                       &d->control_block_base[frame];
+               struct bcm2835_dma_cb *control_block = d->cb_list[frame].cb;
 
                /* Setup adresses */
                if (d->dir == DMA_DEV_TO_MEM) {
@@ -428,12 +449,21 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
                 * This DMA engine driver currently only supports cyclic DMA.
                 * Therefore, wrap around at number of frames.
                 */
-               control_block->next = d->control_block_base_phys +
-                       sizeof(struct bcm2835_dma_cb)
-                       * ((frame + 1) % d->frames);
+               control_block->next = d->cb_list[((frame + 1) % d->frames)].paddr;
        }
 
        return vchan_tx_prep(&c->vc, &d->vd, flags);
+error_cb:
+       i--;
+       for (; i >= 0; i--) {
+               struct bcm2835_cb_entry *cb_entry = &d->cb_list[i];
+
+               dma_pool_free(c->cb_pool, cb_entry->cb, cb_entry->paddr);
+       }
+
+       kfree(d->cb_list);
+       kfree(d);
+       return NULL;
 }
 
 static int bcm2835_dma_slave_config(struct dma_chan *chan,
index 0675e268d5777967489bf25b30f5d217290fa441..16fe773fb846b5e9c9cb70b625715a5f5f888237 100644 (file)
@@ -1752,16 +1752,14 @@ static enum dma_status edma_tx_status(struct dma_chan *chan,
        return ret;
 }
 
-static bool edma_is_memcpy_channel(int ch_num, u16 *memcpy_channels)
+static bool edma_is_memcpy_channel(int ch_num, s32 *memcpy_channels)
 {
-       s16 *memcpy_ch = memcpy_channels;
-
        if (!memcpy_channels)
                return false;
-       while (*memcpy_ch != -1) {
-               if (*memcpy_ch == ch_num)
+       while (*memcpy_channels != -1) {
+               if (*memcpy_channels == ch_num)
                        return true;
-               memcpy_ch++;
+               memcpy_channels++;
        }
        return false;
 }
@@ -1775,7 +1773,7 @@ static void edma_dma_init(struct edma_cc *ecc, bool legacy_mode)
 {
        struct dma_device *s_ddev = &ecc->dma_slave;
        struct dma_device *m_ddev = NULL;
-       s16 *memcpy_channels = ecc->info->memcpy_channels;
+       s32 *memcpy_channels = ecc->info->memcpy_channels;
        int i, j;
 
        dma_cap_zero(s_ddev->cap_mask);
@@ -1996,16 +1994,16 @@ static struct edma_soc_info *edma_setup_info_from_dt(struct device *dev,
        prop = of_find_property(dev->of_node, "ti,edma-memcpy-channels", &sz);
        if (prop) {
                const char pname[] = "ti,edma-memcpy-channels";
-               size_t nelm = sz / sizeof(s16);
-               s16 *memcpy_ch;
+               size_t nelm = sz / sizeof(s32);
+               s32 *memcpy_ch;
 
-               memcpy_ch = devm_kcalloc(dev, nelm + 1, sizeof(s16),
+               memcpy_ch = devm_kcalloc(dev, nelm + 1, sizeof(s32),
                                         GFP_KERNEL);
                if (!memcpy_ch)
                        return ERR_PTR(-ENOMEM);
 
-               ret = of_property_read_u16_array(dev->of_node, pname,
-                                                (u16 *)memcpy_ch, nelm);
+               ret = of_property_read_u32_array(dev->of_node, pname,
+                                                (u32 *)memcpy_ch, nelm);
                if (ret)
                        return ERR_PTR(ret);
 
@@ -2017,31 +2015,50 @@ static struct edma_soc_info *edma_setup_info_from_dt(struct device *dev,
                                &sz);
        if (prop) {
                const char pname[] = "ti,edma-reserved-slot-ranges";
+               u32 (*tmp)[2];
                s16 (*rsv_slots)[2];
-               size_t nelm = sz / sizeof(*rsv_slots);
+               size_t nelm = sz / sizeof(*tmp);
                struct edma_rsv_info *rsv_info;
+               int i;
 
                if (!nelm)
                        return info;
 
+               tmp = kcalloc(nelm, sizeof(*tmp), GFP_KERNEL);
+               if (!tmp)
+                       return ERR_PTR(-ENOMEM);
+
                rsv_info = devm_kzalloc(dev, sizeof(*rsv_info), GFP_KERNEL);
-               if (!rsv_info)
+               if (!rsv_info) {
+                       kfree(tmp);
                        return ERR_PTR(-ENOMEM);
+               }
 
                rsv_slots = devm_kcalloc(dev, nelm + 1, sizeof(*rsv_slots),
                                         GFP_KERNEL);
-               if (!rsv_slots)
+               if (!rsv_slots) {
+                       kfree(tmp);
                        return ERR_PTR(-ENOMEM);
+               }
 
-               ret = of_property_read_u16_array(dev->of_node, pname,
-                                                (u16 *)rsv_slots, nelm * 2);
-               if (ret)
+               ret = of_property_read_u32_array(dev->of_node, pname,
+                                                (u32 *)tmp, nelm * 2);
+               if (ret) {
+                       kfree(tmp);
                        return ERR_PTR(ret);
+               }
 
+               for (i = 0; i < nelm; i++) {
+                       rsv_slots[i][0] = tmp[i][0];
+                       rsv_slots[i][1] = tmp[i][1];
+               }
                rsv_slots[nelm][0] = -1;
                rsv_slots[nelm][1] = -1;
+
                info->rsv = rsv_info;
                info->rsv->rsv_slots = (const s16 (*)[2])rsv_slots;
+
+               kfree(tmp);
        }
 
        return info;
index 9dfa2b0fa5daf0e395b69fce370c6ba5889d3715..9cb93c5b655d80f411079aff95e02f612b7f3ec0 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/dmapool.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
 
@@ -1610,6 +1611,7 @@ static int xgene_dma_request_irqs(struct xgene_dma *pdma)
        /* Register DMA channel rx irq */
        for (i = 0; i < XGENE_DMA_MAX_CHANNEL; i++) {
                chan = &pdma->chan[i];
+               irq_set_status_flags(chan->rx_irq, IRQ_DISABLE_UNLAZY);
                ret = devm_request_irq(chan->dev, chan->rx_irq,
                                       xgene_dma_chan_ring_isr,
                                       0, chan->name, chan);
@@ -1620,6 +1622,7 @@ static int xgene_dma_request_irqs(struct xgene_dma *pdma)
 
                        for (j = 0; j < i; j++) {
                                chan = &pdma->chan[i];
+                               irq_clear_status_flags(chan->rx_irq, IRQ_DISABLE_UNLAZY);
                                devm_free_irq(chan->dev, chan->rx_irq, chan);
                        }
 
@@ -1640,6 +1643,7 @@ static void xgene_dma_free_irqs(struct xgene_dma *pdma)
 
        for (i = 0; i < XGENE_DMA_MAX_CHANNEL; i++) {
                chan = &pdma->chan[i];
+               irq_clear_status_flags(chan->rx_irq, IRQ_DISABLE_UNLAZY);
                devm_free_irq(chan->dev, chan->rx_irq, chan);
        }
 }
index ac1ce4a73edfc6160924f3ebcb1b0ddb2baf3792..0e08e665f715fb1de98b3118553f858c5b4c2c64 100644 (file)
@@ -521,6 +521,7 @@ static int __init dmi_present(const u8 *buf)
                        dmi_ver = smbios_ver;
                else
                        dmi_ver = (buf[14] & 0xF0) << 4 | (buf[14] & 0x0F);
+               dmi_ver <<= 8;
                dmi_num = get_unaligned_le16(buf + 12);
                dmi_len = get_unaligned_le16(buf + 6);
                dmi_base = get_unaligned_le32(buf + 8);
@@ -528,15 +529,14 @@ static int __init dmi_present(const u8 *buf)
                if (dmi_walk_early(dmi_decode) == 0) {
                        if (smbios_ver) {
                                pr_info("SMBIOS %d.%d present.\n",
-                                      dmi_ver >> 8, dmi_ver & 0xFF);
+                                       dmi_ver >> 16, (dmi_ver >> 8) & 0xFF);
                        } else {
                                smbios_entry_point_size = 15;
                                memcpy(smbios_entry_point, buf,
                                       smbios_entry_point_size);
                                pr_info("Legacy DMI %d.%d present.\n",
-                                      dmi_ver >> 8, dmi_ver & 0xFF);
+                                       dmi_ver >> 16, (dmi_ver >> 8) & 0xFF);
                        }
-                       dmi_ver <<= 8;
                        dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string));
                        printk(KERN_DEBUG "DMI: %s\n", dmi_ids_string);
                        return 0;
index a24f5cb877e0a2b32fcfccc14b80e01f2028a08d..953dc9195937d39bb1def7c7bfaa3f905f8d4032 100644 (file)
@@ -122,12 +122,10 @@ int fpga_mgr_firmware_load(struct fpga_manager *mgr, u32 flags,
        }
 
        ret = fpga_mgr_buf_load(mgr, flags, fw->data, fw->size);
-       if (ret)
-               return ret;
 
        release_firmware(fw);
 
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL_GPL(fpga_mgr_firmware_load);
 
@@ -256,7 +254,6 @@ int fpga_mgr_register(struct device *dev, const char *name,
                      void *priv)
 {
        struct fpga_manager *mgr;
-       const char *dt_label;
        int id, ret;
 
        if (!mops || !mops->write_init || !mops->write ||
@@ -300,11 +297,9 @@ int fpga_mgr_register(struct device *dev, const char *name,
        mgr->dev.id = id;
        dev_set_drvdata(dev, mgr);
 
-       dt_label = of_get_property(mgr->dev.of_node, "label", NULL);
-       if (dt_label)
-               ret = dev_set_name(&mgr->dev, "%s", dt_label);
-       else
-               ret = dev_set_name(&mgr->dev, "fpga%d", id);
+       ret = dev_set_name(&mgr->dev, "fpga%d", id);
+       if (ret)
+               goto error_device;
 
        ret = device_add(&mgr->dev);
        if (ret)
index e5827a56ff3b5eda451202849c41b2d8b0e54f31..5eaea8b812cf39515c3e7132d90d4f3d7e0fba17 100644 (file)
@@ -113,7 +113,7 @@ static int ar934x_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
                __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_CLEAR);
 
        __raw_writel(
-               __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) & BIT(offset),
+               __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) & ~BIT(offset),
                ctrl->base + AR71XX_GPIO_REG_OE);
 
        spin_unlock_irqrestore(&ctrl->lock, flags);
index bd5193c67a9c272cb0bebf779ce3277d22aac479..88ae70ddb1274b11f31bad5dcb344d3a57f9c6e3 100644 (file)
@@ -141,9 +141,9 @@ static int bgpio_get_set(struct gpio_chip *gc, unsigned int gpio)
        unsigned long pinmask = bgc->pin2mask(bgc, gpio);
 
        if (bgc->dir & pinmask)
-               return bgc->read_reg(bgc->reg_set) & pinmask;
+               return !!(bgc->read_reg(bgc->reg_set) & pinmask);
        else
-               return bgc->read_reg(bgc->reg_dat) & pinmask;
+               return !!(bgc->read_reg(bgc->reg_dat) & pinmask);
 }
 
 static int bgpio_get(struct gpio_chip *gc, unsigned int gpio)
index 2a91f3287e3b7e52f2f6e16d108af07d4343be0b..4e4c3083ae567f02db4ff15444ec173ac53ebe0c 100644 (file)
@@ -1279,7 +1279,13 @@ static int _gpiod_get_raw_value(const struct gpio_desc *desc)
        chip = desc->chip;
        offset = gpio_chip_hwgpio(desc);
        value = chip->get ? chip->get(chip, offset) : -EIO;
-       value = value < 0 ? value : !!value;
+       /*
+        * FIXME: fix all drivers to clamp to [0,1] or return negative,
+        * then change this to:
+        * value = value < 0 ? value : !!value;
+        * so we can properly propagate error codes.
+        */
+       value = !!value;
        trace_gpio_value(desc_to_gpio(desc), 1, value);
        return value;
 }
index 5a5f04d0902d662548ebae9f82525e1363e8457c..048cfe073dae6a1e89112b219c6a130b3d513be9 100644 (file)
@@ -1264,7 +1264,8 @@ struct amdgpu_cs_parser {
        struct ww_acquire_ctx   ticket;
 
        /* user fence */
-       struct amdgpu_user_fence uf;
+       struct amdgpu_user_fence        uf;
+       struct amdgpu_bo_list_entry     uf_entry;
 };
 
 struct amdgpu_job {
index 4f352ec9dec4e2fb7c3bb5bd062e674291fc8d5a..25a3e2485cc2e9572943638d1975f678fbc26e38 100644 (file)
@@ -127,6 +127,37 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type,
        return 0;
 }
 
+static int amdgpu_cs_user_fence_chunk(struct amdgpu_cs_parser *p,
+                                     struct drm_amdgpu_cs_chunk_fence *fence_data)
+{
+       struct drm_gem_object *gobj;
+       uint32_t handle;
+
+       handle = fence_data->handle;
+       gobj = drm_gem_object_lookup(p->adev->ddev, p->filp,
+                                    fence_data->handle);
+       if (gobj == NULL)
+               return -EINVAL;
+
+       p->uf.bo = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj));
+       p->uf.offset = fence_data->offset;
+
+       if (amdgpu_ttm_tt_has_userptr(p->uf.bo->tbo.ttm)) {
+               drm_gem_object_unreference_unlocked(gobj);
+               return -EINVAL;
+       }
+
+       p->uf_entry.robj = amdgpu_bo_ref(p->uf.bo);
+       p->uf_entry.prefered_domains = AMDGPU_GEM_DOMAIN_GTT;
+       p->uf_entry.allowed_domains = AMDGPU_GEM_DOMAIN_GTT;
+       p->uf_entry.priority = 0;
+       p->uf_entry.tv.bo = &p->uf_entry.robj->tbo;
+       p->uf_entry.tv.shared = true;
+
+       drm_gem_object_unreference_unlocked(gobj);
+       return 0;
+}
+
 int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
 {
        union drm_amdgpu_cs *cs = data;
@@ -207,28 +238,15 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data)
 
                case AMDGPU_CHUNK_ID_FENCE:
                        size = sizeof(struct drm_amdgpu_cs_chunk_fence);
-                       if (p->chunks[i].length_dw * sizeof(uint32_t) >= size) {
-                               uint32_t handle;
-                               struct drm_gem_object *gobj;
-                               struct drm_amdgpu_cs_chunk_fence *fence_data;
-
-                               fence_data = (void *)p->chunks[i].kdata;
-                               handle = fence_data->handle;
-                               gobj = drm_gem_object_lookup(p->adev->ddev,
-                                                            p->filp, handle);
-                               if (gobj == NULL) {
-                                       ret = -EINVAL;
-                                       goto free_partial_kdata;
-                               }
-
-                               p->uf.bo = gem_to_amdgpu_bo(gobj);
-                               amdgpu_bo_ref(p->uf.bo);
-                               drm_gem_object_unreference_unlocked(gobj);
-                               p->uf.offset = fence_data->offset;
-                       } else {
+                       if (p->chunks[i].length_dw * sizeof(uint32_t) < size) {
                                ret = -EINVAL;
                                goto free_partial_kdata;
                        }
+
+                       ret = amdgpu_cs_user_fence_chunk(p, (void *)p->chunks[i].kdata);
+                       if (ret)
+                               goto free_partial_kdata;
+
                        break;
 
                case AMDGPU_CHUNK_ID_DEPENDENCIES:
@@ -391,6 +409,9 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p)
        p->vm_bos = amdgpu_vm_get_bos(p->adev, &fpriv->vm,
                                      &p->validated);
 
+       if (p->uf.bo)
+               list_add(&p->uf_entry.tv.head, &p->validated);
+
        if (need_mmap_lock)
                down_read(&current->mm->mmap_sem);
 
@@ -488,8 +509,8 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo
                for (i = 0; i < parser->num_ibs; i++)
                        amdgpu_ib_free(parser->adev, &parser->ibs[i]);
        kfree(parser->ibs);
-       if (parser->uf.bo)
-               amdgpu_bo_unref(&parser->uf.bo);
+       amdgpu_bo_unref(&parser->uf.bo);
+       amdgpu_bo_unref(&parser->uf_entry.robj);
 }
 
 static int amdgpu_bo_vm_update_pte(struct amdgpu_cs_parser *p,
index f6ea4b43a60c59b144bc5ff9916d96af38a59b24..9c253c535d26053ae80244a68617675c9b19fc3c 100644 (file)
@@ -477,6 +477,14 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
                if (domain == AMDGPU_GEM_DOMAIN_CPU)
                        goto error_unreserve;
        }
+       list_for_each_entry(entry, &duplicates, head) {
+               domain = amdgpu_mem_type_to_domain(entry->bo->mem.mem_type);
+               /* if anything is swapped out don't swap it in here,
+                  just abort and wait for the next CS */
+               if (domain == AMDGPU_GEM_DOMAIN_CPU)
+                       goto error_unreserve;
+       }
+
        r = amdgpu_vm_update_page_directory(adev, bo_va->vm);
        if (r)
                goto error_unreserve;
index a18164f2f6d28290c09462dd7a755168873a42d3..f8b5fcfa91a27521d40e52b818b15dc3c6a6bbaf 100644 (file)
@@ -229,7 +229,8 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
                mode_flags |= DRM_MODE_FLAG_3D_MASK;
 
        list_for_each_entry(mode, &connector->modes, head) {
-               mode->status = drm_mode_validate_basic(mode);
+               if (mode->status == MODE_OK)
+                       mode->status = drm_mode_validate_basic(mode);
 
                if (mode->status == MODE_OK)
                        mode->status = drm_mode_validate_size(mode, maxX, maxY);
index b3ba27fd9a6bc880d7e061039e61ca42babc148f..e69357172ffb56d2e5f5e86ff551b599196079ba 100644 (file)
@@ -55,6 +55,9 @@ static int exynos_crtc_atomic_check(struct drm_crtc *crtc,
 {
        struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
 
+       if (!state->enable)
+               return 0;
+
        if (exynos_crtc->ops->atomic_check)
                return exynos_crtc->ops->atomic_check(exynos_crtc, state);
 
index a01e51581c4c466a000e2aa6b22f42e97ec31b85..f4af19a0d5696324c307617adfb0c86a3fdfed38 100644 (file)
@@ -2193,8 +2193,17 @@ struct drm_i915_gem_request {
        struct drm_i915_private *i915;
        struct intel_engine_cs *ring;
 
-       /** GEM sequence number associated with this request. */
-       uint32_t seqno;
+        /** GEM sequence number associated with the previous request,
+         * when the HWS breadcrumb is equal to this the GPU is processing
+         * this request.
+         */
+       u32 previous_seqno;
+
+        /** GEM sequence number associated with this request,
+         * when the HWS breadcrumb is equal or greater than this the GPU
+         * has finished processing this request.
+         */
+       u32 seqno;
 
        /** Position in the ringbuffer of the start of the request */
        u32 head;
@@ -2839,6 +2848,7 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
 
 int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
                  u32 flags);
+void __i915_vma_set_map_and_fenceable(struct i915_vma *vma);
 int __must_check i915_vma_unbind(struct i915_vma *vma);
 /*
  * BEWARE: Do not use the function below unless you can _absolutely_
@@ -2910,15 +2920,17 @@ i915_seqno_passed(uint32_t seq1, uint32_t seq2)
        return (int32_t)(seq1 - seq2) >= 0;
 }
 
+static inline bool i915_gem_request_started(struct drm_i915_gem_request *req,
+                                          bool lazy_coherency)
+{
+       u32 seqno = req->ring->get_seqno(req->ring, lazy_coherency);
+       return i915_seqno_passed(seqno, req->previous_seqno);
+}
+
 static inline bool i915_gem_request_completed(struct drm_i915_gem_request *req,
                                              bool lazy_coherency)
 {
-       u32 seqno;
-
-       BUG_ON(req == NULL);
-
-       seqno = req->ring->get_seqno(req->ring, lazy_coherency);
-
+       u32 seqno = req->ring->get_seqno(req->ring, lazy_coherency);
        return i915_seqno_passed(seqno, req->seqno);
 }
 
index 32e6aade62238be511237c9ffad1933e18e561cb..f56af0aaafde511c1add59ce5f89fe2fa9be5c42 100644 (file)
@@ -1146,23 +1146,74 @@ static bool missed_irq(struct drm_i915_private *dev_priv,
        return test_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings);
 }
 
-static int __i915_spin_request(struct drm_i915_gem_request *req)
+static unsigned long local_clock_us(unsigned *cpu)
+{
+       unsigned long t;
+
+       /* Cheaply and approximately convert from nanoseconds to microseconds.
+        * The result and subsequent calculations are also defined in the same
+        * approximate microseconds units. The principal source of timing
+        * error here is from the simple truncation.
+        *
+        * Note that local_clock() is only defined wrt to the current CPU;
+        * the comparisons are no longer valid if we switch CPUs. Instead of
+        * blocking preemption for the entire busywait, we can detect the CPU
+        * switch and use that as indicator of system load and a reason to
+        * stop busywaiting, see busywait_stop().
+        */
+       *cpu = get_cpu();
+       t = local_clock() >> 10;
+       put_cpu();
+
+       return t;
+}
+
+static bool busywait_stop(unsigned long timeout, unsigned cpu)
+{
+       unsigned this_cpu;
+
+       if (time_after(local_clock_us(&this_cpu), timeout))
+               return true;
+
+       return this_cpu != cpu;
+}
+
+static int __i915_spin_request(struct drm_i915_gem_request *req, int state)
 {
        unsigned long timeout;
+       unsigned cpu;
+
+       /* When waiting for high frequency requests, e.g. during synchronous
+        * rendering split between the CPU and GPU, the finite amount of time
+        * required to set up the irq and wait upon it limits the response
+        * rate. By busywaiting on the request completion for a short while we
+        * can service the high frequency waits as quick as possible. However,
+        * if it is a slow request, we want to sleep as quickly as possible.
+        * The tradeoff between waiting and sleeping is roughly the time it
+        * takes to sleep on a request, on the order of a microsecond.
+        */
 
-       if (i915_gem_request_get_ring(req)->irq_refcount)
+       if (req->ring->irq_refcount)
                return -EBUSY;
 
-       timeout = jiffies + 1;
+       /* Only spin if we know the GPU is processing this request */
+       if (!i915_gem_request_started(req, true))
+               return -EAGAIN;
+
+       timeout = local_clock_us(&cpu) + 5;
        while (!need_resched()) {
                if (i915_gem_request_completed(req, true))
                        return 0;
 
-               if (time_after_eq(jiffies, timeout))
+               if (signal_pending_state(state, current))
+                       break;
+
+               if (busywait_stop(timeout, cpu))
                        break;
 
                cpu_relax_lowlatency();
        }
+
        if (i915_gem_request_completed(req, false))
                return 0;
 
@@ -1197,6 +1248,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
        struct drm_i915_private *dev_priv = dev->dev_private;
        const bool irq_test_in_progress =
                ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring);
+       int state = interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
        DEFINE_WAIT(wait);
        unsigned long timeout_expire;
        s64 before, now;
@@ -1229,7 +1281,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
        before = ktime_get_raw_ns();
 
        /* Optimistic spin for the next jiffie before touching IRQs */
-       ret = __i915_spin_request(req);
+       ret = __i915_spin_request(req, state);
        if (ret == 0)
                goto out;
 
@@ -1241,8 +1293,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
        for (;;) {
                struct timer_list timer;
 
-               prepare_to_wait(&ring->irq_queue, &wait,
-                               interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
+               prepare_to_wait(&ring->irq_queue, &wait, state);
 
                /* We need to check whether any gpu reset happened in between
                 * the caller grabbing the seqno and now ... */
@@ -1260,7 +1311,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
                        break;
                }
 
-               if (interruptible && signal_pending(current)) {
+               if (signal_pending_state(state, current)) {
                        ret = -ERESTARTSYS;
                        break;
                }
@@ -2554,6 +2605,7 @@ void __i915_add_request(struct drm_i915_gem_request *request,
        request->batch_obj = obj;
 
        request->emitted_jiffies = jiffies;
+       request->previous_seqno = ring->last_submitted_seqno;
        ring->last_submitted_seqno = request->seqno;
        list_add_tail(&request->list, &ring->request_list);
 
@@ -4080,6 +4132,29 @@ i915_vma_misplaced(struct i915_vma *vma, uint32_t alignment, uint64_t flags)
        return false;
 }
 
+void __i915_vma_set_map_and_fenceable(struct i915_vma *vma)
+{
+       struct drm_i915_gem_object *obj = vma->obj;
+       bool mappable, fenceable;
+       u32 fence_size, fence_alignment;
+
+       fence_size = i915_gem_get_gtt_size(obj->base.dev,
+                                          obj->base.size,
+                                          obj->tiling_mode);
+       fence_alignment = i915_gem_get_gtt_alignment(obj->base.dev,
+                                                    obj->base.size,
+                                                    obj->tiling_mode,
+                                                    true);
+
+       fenceable = (vma->node.size == fence_size &&
+                    (vma->node.start & (fence_alignment - 1)) == 0);
+
+       mappable = (vma->node.start + fence_size <=
+                   to_i915(obj->base.dev)->gtt.mappable_end);
+
+       obj->map_and_fenceable = mappable && fenceable;
+}
+
 static int
 i915_gem_object_do_pin(struct drm_i915_gem_object *obj,
                       struct i915_address_space *vm,
@@ -4147,25 +4222,7 @@ i915_gem_object_do_pin(struct drm_i915_gem_object *obj,
 
        if (ggtt_view && ggtt_view->type == I915_GGTT_VIEW_NORMAL &&
            (bound ^ vma->bound) & GLOBAL_BIND) {
-               bool mappable, fenceable;
-               u32 fence_size, fence_alignment;
-
-               fence_size = i915_gem_get_gtt_size(obj->base.dev,
-                                                  obj->base.size,
-                                                  obj->tiling_mode);
-               fence_alignment = i915_gem_get_gtt_alignment(obj->base.dev,
-                                                            obj->base.size,
-                                                            obj->tiling_mode,
-                                                            true);
-
-               fenceable = (vma->node.size == fence_size &&
-                            (vma->node.start & (fence_alignment - 1)) == 0);
-
-               mappable = (vma->node.start + fence_size <=
-                           dev_priv->gtt.mappable_end);
-
-               obj->map_and_fenceable = mappable && fenceable;
-
+               __i915_vma_set_map_and_fenceable(vma);
                WARN_ON(flags & PIN_MAPPABLE && !obj->map_and_fenceable);
        }
 
index 8c688a5f1589316b3f303d9a5b90857af7e112f8..02ceb7a4b4815e52a825a290aa8e6d2cd78d25b5 100644 (file)
@@ -141,8 +141,6 @@ static void i915_gem_context_clean(struct intel_context *ctx)
        if (!ppgtt)
                return;
 
-       WARN_ON(!list_empty(&ppgtt->base.active_list));
-
        list_for_each_entry_safe(vma, next, &ppgtt->base.inactive_list,
                                 mm_list) {
                if (WARN_ON(__i915_vma_unbind_no_wait(vma)))
index 43f35d12b677606d43b96cedc3cae476067946ab..86c7500454b4d1b3928dc41f37ab9aa6917fd557 100644 (file)
@@ -2676,6 +2676,7 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
                        return ret;
                }
                vma->bound |= GLOBAL_BIND;
+               __i915_vma_set_map_and_fenceable(vma);
                list_add_tail(&vma->mm_list, &ggtt_vm->inactive_list);
        }
 
index cdacf3f5b77a571086024deae067bf32edc3a988..87e919a06b277fea6cfade79445a165bac925056 100644 (file)
@@ -687,6 +687,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
                }
 
                vma->bound |= GLOBAL_BIND;
+               __i915_vma_set_map_and_fenceable(vma);
                list_add_tail(&vma->mm_list, &ggtt->inactive_list);
        }
 
index 22e86d2e408d9493e6c2ea6a60e689a5c03934a9..32cf973469785cb916eb3c2bdd125a741efb5e4c 100644 (file)
@@ -116,6 +116,7 @@ static void skylake_pfit_enable(struct intel_crtc *crtc);
 static void ironlake_pfit_disable(struct intel_crtc *crtc, bool force);
 static void ironlake_pfit_enable(struct intel_crtc *crtc);
 static void intel_modeset_setup_hw_state(struct drm_device *dev);
+static void intel_pre_disable_primary(struct drm_crtc *crtc);
 
 typedef struct {
        int     min, max;
@@ -2607,6 +2608,8 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
        struct drm_i915_gem_object *obj;
        struct drm_plane *primary = intel_crtc->base.primary;
        struct drm_plane_state *plane_state = primary->state;
+       struct drm_crtc_state *crtc_state = intel_crtc->base.state;
+       struct intel_plane *intel_plane = to_intel_plane(primary);
        struct drm_framebuffer *fb;
 
        if (!plane_config->fb)
@@ -2643,6 +2646,18 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
                }
        }
 
+       /*
+        * We've failed to reconstruct the BIOS FB.  Current display state
+        * indicates that the primary plane is visible, but has a NULL FB,
+        * which will lead to problems later if we don't fix it up.  The
+        * simplest solution is to just disable the primary plane now and
+        * pretend the BIOS never had it enabled.
+        */
+       to_intel_plane_state(plane_state)->visible = false;
+       crtc_state->plane_mask &= ~(1 << drm_plane_index(primary));
+       intel_pre_disable_primary(&intel_crtc->base);
+       intel_plane->disable_plane(primary, &intel_crtc->base);
+
        return;
 
 valid_fb:
@@ -6309,9 +6324,11 @@ static void intel_crtc_disable_noatomic(struct drm_crtc *crtc)
        if (to_intel_plane_state(crtc->primary->state)->visible) {
                intel_crtc_wait_for_pending_flips(crtc);
                intel_pre_disable_primary(crtc);
+
+               intel_crtc_disable_planes(crtc, 1 << drm_plane_index(crtc->primary));
+               to_intel_plane_state(crtc->primary->state)->visible = false;
        }
 
-       intel_crtc_disable_planes(crtc, crtc->state->plane_mask);
        dev_priv->display.crtc_disable(crtc);
        intel_crtc->active = false;
        intel_update_watermarks(crtc);
@@ -9908,14 +9925,14 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc,
        return true;
 }
 
-static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
+static void i845_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        uint32_t cntl = 0, size = 0;
 
-       if (base) {
+       if (on) {
                unsigned int width = intel_crtc->base.cursor->state->crtc_w;
                unsigned int height = intel_crtc->base.cursor->state->crtc_h;
                unsigned int stride = roundup_pow_of_two(width) * 4;
@@ -9970,16 +9987,15 @@ static void i845_update_cursor(struct drm_crtc *crtc, u32 base)
        }
 }
 
-static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base)
+static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, bool on)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        int pipe = intel_crtc->pipe;
-       uint32_t cntl;
+       uint32_t cntl = 0;
 
-       cntl = 0;
-       if (base) {
+       if (on) {
                cntl = MCURSOR_GAMMA_ENABLE;
                switch (intel_crtc->base.cursor->state->crtc_w) {
                        case 64:
@@ -10030,18 +10046,17 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
        int y = cursor_state->crtc_y;
        u32 base = 0, pos = 0;
 
-       if (on)
-               base = intel_crtc->cursor_addr;
+       base = intel_crtc->cursor_addr;
 
        if (x >= intel_crtc->config->pipe_src_w)
-               base = 0;
+               on = false;
 
        if (y >= intel_crtc->config->pipe_src_h)
-               base = 0;
+               on = false;
 
        if (x < 0) {
                if (x + cursor_state->crtc_w <= 0)
-                       base = 0;
+                       on = false;
 
                pos |= CURSOR_POS_SIGN << CURSOR_X_SHIFT;
                x = -x;
@@ -10050,16 +10065,13 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
 
        if (y < 0) {
                if (y + cursor_state->crtc_h <= 0)
-                       base = 0;
+                       on = false;
 
                pos |= CURSOR_POS_SIGN << CURSOR_Y_SHIFT;
                y = -y;
        }
        pos |= y << CURSOR_Y_SHIFT;
 
-       if (base == 0 && intel_crtc->cursor_base == 0)
-               return;
-
        I915_WRITE(CURPOS(pipe), pos);
 
        /* ILK+ do this automagically */
@@ -10070,9 +10082,9 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc,
        }
 
        if (IS_845G(dev) || IS_I865G(dev))
-               i845_update_cursor(crtc, base);
+               i845_update_cursor(crtc, base, on);
        else
-               i9xx_update_cursor(crtc, base);
+               i9xx_update_cursor(crtc, base, on);
 }
 
 static bool cursor_size_ok(struct drm_device *dev,
@@ -12111,18 +12123,22 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc,
 static bool check_digital_port_conflicts(struct drm_atomic_state *state)
 {
        struct drm_device *dev = state->dev;
-       struct intel_encoder *encoder;
        struct drm_connector *connector;
-       struct drm_connector_state *connector_state;
        unsigned int used_ports = 0;
-       int i;
 
        /*
         * Walk the connector list instead of the encoder
         * list to detect the problem on ddi platforms
         * where there's just one encoder per digital port.
         */
-       for_each_connector_in_state(state, connector, connector_state, i) {
+       drm_for_each_connector(connector, dev) {
+               struct drm_connector_state *connector_state;
+               struct intel_encoder *encoder;
+
+               connector_state = drm_atomic_get_existing_connector_state(state, connector);
+               if (!connector_state)
+                       connector_state = connector->state;
+
                if (!connector_state->best_encoder)
                        continue;
 
@@ -13716,6 +13732,7 @@ intel_check_cursor_plane(struct drm_plane *plane,
        struct drm_crtc *crtc = crtc_state->base.crtc;
        struct drm_framebuffer *fb = state->base.fb;
        struct drm_i915_gem_object *obj = intel_fb_obj(fb);
+       enum pipe pipe = to_intel_plane(plane)->pipe;
        unsigned stride;
        int ret;
 
@@ -13749,6 +13766,22 @@ intel_check_cursor_plane(struct drm_plane *plane,
                return -EINVAL;
        }
 
+       /*
+        * There's something wrong with the cursor on CHV pipe C.
+        * If it straddles the left edge of the screen then
+        * moving it away from the edge or disabling it often
+        * results in a pipe underrun, and often that can lead to
+        * dead pipe (constant underrun reported, and it scans
+        * out just a solid color). To recover from that, the
+        * display power well must be turned off and on again.
+        * Refuse the put the cursor into that compromised position.
+        */
+       if (IS_CHERRYVIEW(plane->dev) && pipe == PIPE_C &&
+           state->visible && state->base.crtc_x < 0) {
+               DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n");
+               return -EINVAL;
+       }
+
        return 0;
 }
 
@@ -13772,9 +13805,6 @@ intel_commit_cursor_plane(struct drm_plane *plane,
        crtc = crtc ? crtc : plane->crtc;
        intel_crtc = to_intel_crtc(crtc);
 
-       if (intel_crtc->cursor_bo == obj)
-               goto update;
-
        if (!obj)
                addr = 0;
        else if (!INTEL_INFO(dev)->cursor_needs_physical)
@@ -13783,9 +13813,7 @@ intel_commit_cursor_plane(struct drm_plane *plane,
                addr = obj->phys_handle->busaddr;
 
        intel_crtc->cursor_addr = addr;
-       intel_crtc->cursor_bo = obj;
 
-update:
        if (crtc->state->active)
                intel_crtc_update_cursor(crtc, state->visible);
 }
index f2a1142bff34310a40abd262a59106bffdecba6f..0d00f07b7163c90c10d8e994b037b7b24b508d34 100644 (file)
@@ -550,7 +550,6 @@ struct intel_crtc {
        int adjusted_x;
        int adjusted_y;
 
-       struct drm_i915_gem_object *cursor_bo;
        uint32_t cursor_addr;
        uint32_t cursor_cntl;
        uint32_t cursor_size;
index 81cdd9ff38922397171e91558136ae0765229106..e6c035b0fc1ce2d2e674aec93cb50c0ad7b7db67 100644 (file)
@@ -1374,17 +1374,18 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
        struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
        struct drm_i915_private *dev_priv = to_i915(connector->dev);
        bool live_status = false;
-       unsigned int retry = 3;
+       unsigned int try;
 
        DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
                      connector->base.id, connector->name);
 
        intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS);
 
-       while (!live_status && --retry) {
+       for (try = 0; !live_status && try < 9; try++) {
+               if (try)
+                       msleep(10);
                live_status = intel_digital_port_connected(dev_priv,
                                hdmi_to_dig_port(intel_hdmi));
-               mdelay(10);
        }
 
        if (!live_status)
index 071a76b9ac523355e296836f81969374caaa6d86..f091ad12d694a43ebb0dce69b31089ffd4abe366 100644 (file)
@@ -4782,8 +4782,7 @@ static void gen9_enable_rc6(struct drm_device *dev)
        /* 2b: Program RC6 thresholds.*/
 
        /* WaRsDoubleRc6WrlWithCoarsePowerGating: Doubling WRL only when CPG is enabled */
-       if (IS_SKYLAKE(dev) && !((IS_SKL_GT3(dev) || IS_SKL_GT4(dev)) &&
-                                (INTEL_REVID(dev) <= SKL_REVID_E0)))
+       if (IS_SKYLAKE(dev))
                I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 108 << 16);
        else
                I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16);
@@ -4825,7 +4824,7 @@ static void gen9_enable_rc6(struct drm_device *dev)
         * WaRsDisableCoarsePowerGating:skl,bxt - Render/Media PG need to be disabled with RC6.
         */
        if ((IS_BROXTON(dev) && (INTEL_REVID(dev) < BXT_REVID_B0)) ||
-           ((IS_SKL_GT3(dev) || IS_SKL_GT4(dev)) && (INTEL_REVID(dev) <= SKL_REVID_E0)))
+           ((IS_SKL_GT3(dev) || IS_SKL_GT4(dev)) && (INTEL_REVID(dev) <= SKL_REVID_F0)))
                I915_WRITE(GEN9_PG_ENABLE, 0);
        else
                I915_WRITE(GEN9_PG_ENABLE, (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ?
index 8f760002e4018ba05a6fb18a6ecc0d0cf53605fc..913192c94876febb1bf274213c92244b6af6b92d 100644 (file)
@@ -159,7 +159,6 @@ struct nvkm_device_func {
 struct nvkm_device_quirk {
        u8 tv_pin_mask;
        u8 tv_gpio;
-       bool War00C800_0;
 };
 
 struct nvkm_device_chip {
index caf22b589edc3389247abaa724fdb41d7407c2f9..62ad0300cfa5ab0af8610773ae7d5c4b49e310bb 100644 (file)
@@ -258,12 +258,6 @@ nvkm_device_pci_10de_0df4[] = {
        {}
 };
 
-static const struct nvkm_device_pci_vendor
-nvkm_device_pci_10de_0fcd[] = {
-       { 0x17aa, 0x3801, NULL, { .War00C800_0 = true } }, /* Lenovo Y510P */
-       {}
-};
-
 static const struct nvkm_device_pci_vendor
 nvkm_device_pci_10de_0fd2[] = {
        { 0x1028, 0x0595, "GeForce GT 640M LE" },
@@ -278,12 +272,6 @@ nvkm_device_pci_10de_0fe3[] = {
        {}
 };
 
-static const struct nvkm_device_pci_vendor
-nvkm_device_pci_10de_0fe4[] = {
-       { 0x144d, 0xc740, NULL, { .War00C800_0 = true } },
-       {}
-};
-
 static const struct nvkm_device_pci_vendor
 nvkm_device_pci_10de_104b[] = {
        { 0x1043, 0x844c, "GeForce GT 625" },
@@ -690,13 +678,6 @@ nvkm_device_pci_10de_1189[] = {
 static const struct nvkm_device_pci_vendor
 nvkm_device_pci_10de_1199[] = {
        { 0x1458, 0xd001, "GeForce GTX 760" },
-       { 0x1462, 0x1106, "GeForce GTX 780M", { .War00C800_0 = true } }, /* Medion Erazer X7827 */
-       {}
-};
-
-static const struct nvkm_device_pci_vendor
-nvkm_device_pci_10de_11e0[] = {
-       { 0x1558, 0x5106, NULL, { .War00C800_0 = true } },
        {}
 };
 
@@ -706,14 +687,6 @@ nvkm_device_pci_10de_11e3[] = {
        {}
 };
 
-static const struct nvkm_device_pci_vendor
-nvkm_device_pci_10de_11fc[] = {
-       { 0x1179, 0x0001, NULL, { .War00C800_0 = true } }, /* Toshiba Tecra W50 */
-       { 0x17aa, 0x2211, NULL, { .War00C800_0 = true } }, /* Lenovo W541 */
-       { 0x17aa, 0x221e, NULL, { .War00C800_0 = true } }, /* Lenovo W541 */
-       {}
-};
-
 static const struct nvkm_device_pci_vendor
 nvkm_device_pci_10de_1247[] = {
        { 0x1043, 0x212a, "GeForce GT 635M" },
@@ -1368,7 +1341,7 @@ nvkm_device_pci_10de[] = {
        { 0x0fc6, "GeForce GTX 650" },
        { 0x0fc8, "GeForce GT 740" },
        { 0x0fc9, "GeForce GT 730" },
-       { 0x0fcd, "GeForce GT 755M", nvkm_device_pci_10de_0fcd },
+       { 0x0fcd, "GeForce GT 755M" },
        { 0x0fce, "GeForce GT 640M LE" },
        { 0x0fd1, "GeForce GT 650M" },
        { 0x0fd2, "GeForce GT 640M", nvkm_device_pci_10de_0fd2 },
@@ -1382,7 +1355,7 @@ nvkm_device_pci_10de[] = {
        { 0x0fe1, "GeForce GT 730M" },
        { 0x0fe2, "GeForce GT 745M" },
        { 0x0fe3, "GeForce GT 745M", nvkm_device_pci_10de_0fe3 },
-       { 0x0fe4, "GeForce GT 750M", nvkm_device_pci_10de_0fe4 },
+       { 0x0fe4, "GeForce GT 750M" },
        { 0x0fe9, "GeForce GT 750M" },
        { 0x0fea, "GeForce GT 755M" },
        { 0x0fec, "GeForce 710A" },
@@ -1497,12 +1470,12 @@ nvkm_device_pci_10de[] = {
        { 0x11c6, "GeForce GTX 650 Ti" },
        { 0x11c8, "GeForce GTX 650" },
        { 0x11cb, "GeForce GT 740" },
-       { 0x11e0, "GeForce GTX 770M", nvkm_device_pci_10de_11e0 },
+       { 0x11e0, "GeForce GTX 770M" },
        { 0x11e1, "GeForce GTX 765M" },
        { 0x11e2, "GeForce GTX 765M" },
        { 0x11e3, "GeForce GTX 760M", nvkm_device_pci_10de_11e3 },
        { 0x11fa, "Quadro K4000" },
-       { 0x11fc, "Quadro K2100M", nvkm_device_pci_10de_11fc },
+       { 0x11fc, "Quadro K2100M" },
        { 0x1200, "GeForce GTX 560 Ti" },
        { 0x1201, "GeForce GTX 560" },
        { 0x1203, "GeForce GTX 460 SE v2" },
index ffa902ece87234420d2b25d1603995f5679b5245..05a895496fc66f6f96efd64cbdbe822e4baaf1cc 100644 (file)
@@ -156,6 +156,7 @@ nv40_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
                return -ENOMEM;
        nvkm_object_ctor(&nv40_gr_chan, oclass, &chan->object);
        chan->gr = gr;
+       chan->fifo = fifoch;
        *pobject = &chan->object;
 
        spin_lock_irqsave(&chan->gr->base.engine.lock, flags);
index 43006db6fd58252830842c02543ca1659ae23df2..80fed7e78dcbe0bc1e7df6a864c3efb475c2733a 100644 (file)
@@ -83,6 +83,7 @@ nvbios_fan_parse(struct nvkm_bios *bios, struct nvbios_therm_fan *fan)
                        fan->type = NVBIOS_THERM_FAN_UNK;
                }
 
+               fan->fan_mode = NVBIOS_THERM_FAN_LINEAR;
                fan->min_duty = nvbios_rd08(bios, data + 0x02);
                fan->max_duty = nvbios_rd08(bios, data + 0x03);
 
index d942fa7b9f1871b362809baf0bac9c8c7d6ced2b..86f9f3b13f71f7caead9206f9cfcdab6bf88c728 100644 (file)
@@ -81,9 +81,7 @@ gk104_pmu_pgob(struct nvkm_pmu *pmu, bool enable)
        nvkm_mask(device, 0x000200, 0x00001000, 0x00001000);
        nvkm_rd32(device, 0x000200);
 
-       if ( nvkm_boolopt(device->cfgopt, "War00C800_0",
-           device->quirk ? device->quirk->War00C800_0 : false)) {
-               nvkm_info(&pmu->subdev, "hw bug workaround enabled\n");
+       if (nvkm_boolopt(device->cfgopt, "War00C800_0", true)) {
                switch (device->chipset) {
                case 0xe4:
                        magic(device, 0x04000000);
index b8e4cdec28c363c7e5c10881be4ea61461023ace..24f92bea39c7d731365be1464b5b551f3a278f49 100644 (file)
@@ -112,11 +112,8 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
        dma_addr_t paddr;
        int ret;
 
-       /* only doing ARGB32 since this is what is needed to alpha-blend
-        * with video overlays:
-        */
        sizes->surface_bpp = 32;
-       sizes->surface_depth = 32;
+       sizes->surface_depth = 24;
 
        DBG("create fbdev: %dx%d@%d (%dx%d)", sizes->surface_width,
                        sizes->surface_height, sizes->surface_bpp,
index 0154db43860c7ec6ca9d0aeb828650a88e91a718..f81fb26410976840b02811de9693b875edfa3efa 100644 (file)
@@ -4173,11 +4173,7 @@ void cik_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
        control |= ib->length_dw | (vm_id << 24);
 
        radeon_ring_write(ring, header);
-       radeon_ring_write(ring,
-#ifdef __BIG_ENDIAN
-                         (2 << 0) |
-#endif
-                         (ib->gpu_addr & 0xFFFFFFFC));
+       radeon_ring_write(ring, (ib->gpu_addr & 0xFFFFFFFC));
        radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF);
        radeon_ring_write(ring, control);
 }
index 574f62bbd215bcf58c125861f7718aaabba7c423..7eb1ae758906142b86f5c7fd1c01dcc50ce74946 100644 (file)
@@ -361,31 +361,31 @@ int radeon_vce_get_create_msg(struct radeon_device *rdev, int ring,
 
        /* stitch together an VCE create msg */
        ib.length_dw = 0;
-       ib.ptr[ib.length_dw++] = 0x0000000c; /* len */
-       ib.ptr[ib.length_dw++] = 0x00000001; /* session cmd */
-       ib.ptr[ib.length_dw++] = handle;
-
-       ib.ptr[ib.length_dw++] = 0x00000030; /* len */
-       ib.ptr[ib.length_dw++] = 0x01000001; /* create cmd */
-       ib.ptr[ib.length_dw++] = 0x00000000;
-       ib.ptr[ib.length_dw++] = 0x00000042;
-       ib.ptr[ib.length_dw++] = 0x0000000a;
-       ib.ptr[ib.length_dw++] = 0x00000001;
-       ib.ptr[ib.length_dw++] = 0x00000080;
-       ib.ptr[ib.length_dw++] = 0x00000060;
-       ib.ptr[ib.length_dw++] = 0x00000100;
-       ib.ptr[ib.length_dw++] = 0x00000100;
-       ib.ptr[ib.length_dw++] = 0x0000000c;
-       ib.ptr[ib.length_dw++] = 0x00000000;
-
-       ib.ptr[ib.length_dw++] = 0x00000014; /* len */
-       ib.ptr[ib.length_dw++] = 0x05000005; /* feedback buffer */
-       ib.ptr[ib.length_dw++] = upper_32_bits(dummy);
-       ib.ptr[ib.length_dw++] = dummy;
-       ib.ptr[ib.length_dw++] = 0x00000001;
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x0000000c); /* len */
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000001); /* session cmd */
+       ib.ptr[ib.length_dw++] = cpu_to_le32(handle);
+
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000030); /* len */
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x01000001); /* create cmd */
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000000);
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000042);
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x0000000a);
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000001);
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000080);
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000060);
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000100);
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000100);
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x0000000c);
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000000);
+
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000014); /* len */
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x05000005); /* feedback buffer */
+       ib.ptr[ib.length_dw++] = cpu_to_le32(upper_32_bits(dummy));
+       ib.ptr[ib.length_dw++] = cpu_to_le32(dummy);
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000001);
 
        for (i = ib.length_dw; i < ib_size_dw; ++i)
-               ib.ptr[i] = 0x0;
+               ib.ptr[i] = cpu_to_le32(0x0);
 
        r = radeon_ib_schedule(rdev, &ib, NULL, false);
        if (r) {
@@ -428,21 +428,21 @@ int radeon_vce_get_destroy_msg(struct radeon_device *rdev, int ring,
 
        /* stitch together an VCE destroy msg */
        ib.length_dw = 0;
-       ib.ptr[ib.length_dw++] = 0x0000000c; /* len */
-       ib.ptr[ib.length_dw++] = 0x00000001; /* session cmd */
-       ib.ptr[ib.length_dw++] = handle;
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x0000000c); /* len */
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000001); /* session cmd */
+       ib.ptr[ib.length_dw++] = cpu_to_le32(handle);
 
-       ib.ptr[ib.length_dw++] = 0x00000014; /* len */
-       ib.ptr[ib.length_dw++] = 0x05000005; /* feedback buffer */
-       ib.ptr[ib.length_dw++] = upper_32_bits(dummy);
-       ib.ptr[ib.length_dw++] = dummy;
-       ib.ptr[ib.length_dw++] = 0x00000001;
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000014); /* len */
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x05000005); /* feedback buffer */
+       ib.ptr[ib.length_dw++] = cpu_to_le32(upper_32_bits(dummy));
+       ib.ptr[ib.length_dw++] = cpu_to_le32(dummy);
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000001);
 
-       ib.ptr[ib.length_dw++] = 0x00000008; /* len */
-       ib.ptr[ib.length_dw++] = 0x02000001; /* destroy cmd */
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x00000008); /* len */
+       ib.ptr[ib.length_dw++] = cpu_to_le32(0x02000001); /* destroy cmd */
 
        for (i = ib.length_dw; i < ib_size_dw; ++i)
-               ib.ptr[i] = 0x0;
+               ib.ptr[i] = cpu_to_le32(0x0);
 
        r = radeon_ib_schedule(rdev, &ib, NULL, false);
        if (r) {
@@ -699,12 +699,12 @@ bool radeon_vce_semaphore_emit(struct radeon_device *rdev,
 {
        uint64_t addr = semaphore->gpu_addr;
 
-       radeon_ring_write(ring, VCE_CMD_SEMAPHORE);
-       radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF);
-       radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF);
-       radeon_ring_write(ring, 0x01003000 | (emit_wait ? 1 : 0));
+       radeon_ring_write(ring, cpu_to_le32(VCE_CMD_SEMAPHORE));
+       radeon_ring_write(ring, cpu_to_le32((addr >> 3) & 0x000FFFFF));
+       radeon_ring_write(ring, cpu_to_le32((addr >> 23) & 0x000FFFFF));
+       radeon_ring_write(ring, cpu_to_le32(0x01003000 | (emit_wait ? 1 : 0)));
        if (!emit_wait)
-               radeon_ring_write(ring, VCE_CMD_END);
+               radeon_ring_write(ring, cpu_to_le32(VCE_CMD_END));
 
        return true;
 }
@@ -719,10 +719,10 @@ bool radeon_vce_semaphore_emit(struct radeon_device *rdev,
 void radeon_vce_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
 {
        struct radeon_ring *ring = &rdev->ring[ib->ring];
-       radeon_ring_write(ring, VCE_CMD_IB);
-       radeon_ring_write(ring, ib->gpu_addr);
-       radeon_ring_write(ring, upper_32_bits(ib->gpu_addr));
-       radeon_ring_write(ring, ib->length_dw);
+       radeon_ring_write(ring, cpu_to_le32(VCE_CMD_IB));
+       radeon_ring_write(ring, cpu_to_le32(ib->gpu_addr));
+       radeon_ring_write(ring, cpu_to_le32(upper_32_bits(ib->gpu_addr)));
+       radeon_ring_write(ring, cpu_to_le32(ib->length_dw));
 }
 
 /**
@@ -738,12 +738,12 @@ void radeon_vce_fence_emit(struct radeon_device *rdev,
        struct radeon_ring *ring = &rdev->ring[fence->ring];
        uint64_t addr = rdev->fence_drv[fence->ring].gpu_addr;
 
-       radeon_ring_write(ring, VCE_CMD_FENCE);
-       radeon_ring_write(ring, addr);
-       radeon_ring_write(ring, upper_32_bits(addr));
-       radeon_ring_write(ring, fence->seq);
-       radeon_ring_write(ring, VCE_CMD_TRAP);
-       radeon_ring_write(ring, VCE_CMD_END);
+       radeon_ring_write(ring, cpu_to_le32(VCE_CMD_FENCE));
+       radeon_ring_write(ring, cpu_to_le32(addr));
+       radeon_ring_write(ring, cpu_to_le32(upper_32_bits(addr)));
+       radeon_ring_write(ring, cpu_to_le32(fence->seq));
+       radeon_ring_write(ring, cpu_to_le32(VCE_CMD_TRAP));
+       radeon_ring_write(ring, cpu_to_le32(VCE_CMD_END));
 }
 
 /**
@@ -765,7 +765,7 @@ int radeon_vce_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
                          ring->idx, r);
                return r;
        }
-       radeon_ring_write(ring, VCE_CMD_END);
+       radeon_ring_write(ring, cpu_to_le32(VCE_CMD_END));
        radeon_ring_unlock_commit(rdev, ring, false);
 
        for (i = 0; i < rdev->usec_timeout; i++) {
index 6a954544727f3f13cfa8d9be0b8ff4cbf39d9367..f154fb1929bd18e300e226d8fe89925b9e8b3754 100644 (file)
@@ -180,7 +180,7 @@ int ttm_write_lock(struct ttm_lock *lock, bool interruptible)
                        spin_unlock(&lock->lock);
                }
        } else
-               wait_event(lock->queue, __ttm_read_lock(lock));
+               wait_event(lock->queue, __ttm_write_lock(lock));
 
        return ret;
 }
index a09cf8529b9f6374649e2f943ef84e3cf08eeda1..c49812b80dd0dae82c77096f75fbd4cced19ffb1 100644 (file)
@@ -1233,6 +1233,7 @@ static void vmw_master_drop(struct drm_device *dev,
 
        vmw_fp->locked_master = drm_master_get(file_priv->master);
        ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile);
+       vmw_kms_legacy_hotspot_clear(dev_priv);
        if (unlikely((ret != 0))) {
                DRM_ERROR("Unable to lock TTM at VT switch.\n");
                drm_master_put(&vmw_fp->locked_master);
index a8ae9dfb83b7d4916023d9e8e3835da42f0c3979..469cdd520615d036fdb99b0f7e27ed67ce3abd67 100644 (file)
@@ -925,6 +925,7 @@ int vmw_kms_present(struct vmw_private *dev_priv,
                    uint32_t num_clips);
 int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
                                struct drm_file *file_priv);
+void vmw_kms_legacy_hotspot_clear(struct vmw_private *dev_priv);
 
 int vmw_dumb_create(struct drm_file *file_priv,
                    struct drm_device *dev,
index a8baf5f5e76558679d128de151d2caaea193bc6c..b6a0806b06bffaf6da9178905f9b2f6bb037d384 100644 (file)
@@ -390,7 +390,7 @@ void *vmw_fifo_reserve_dx(struct vmw_private *dev_priv, uint32_t bytes,
        else if (ctx_id == SVGA3D_INVALID_ID)
                ret = vmw_local_fifo_reserve(dev_priv, bytes);
        else {
-               WARN_ON("Command buffer has not been allocated.\n");
+               WARN(1, "Command buffer has not been allocated.\n");
                ret = NULL;
        }
        if (IS_ERR_OR_NULL(ret)) {
index 9fcd7f82995c3e1a517930cb8a89a23351c55c15..9b4bb9e74d7300793f3ecb1c0feef42085780819 100644 (file)
@@ -133,13 +133,19 @@ void vmw_cursor_update_position(struct vmw_private *dev_priv,
        vmw_mmio_write(++count, fifo_mem + SVGA_FIFO_CURSOR_COUNT);
 }
 
-int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
-                          uint32_t handle, uint32_t width, uint32_t height)
+
+/*
+ * vmw_du_crtc_cursor_set2 - Driver cursor_set2 callback.
+ */
+int vmw_du_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
+                           uint32_t handle, uint32_t width, uint32_t height,
+                           int32_t hot_x, int32_t hot_y)
 {
        struct vmw_private *dev_priv = vmw_priv(crtc->dev);
        struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
        struct vmw_surface *surface = NULL;
        struct vmw_dma_buffer *dmabuf = NULL;
+       s32 hotspot_x, hotspot_y;
        int ret;
 
        /*
@@ -151,6 +157,8 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
         */
        drm_modeset_unlock_crtc(crtc);
        drm_modeset_lock_all(dev_priv->dev);
+       hotspot_x = hot_x + du->hotspot_x;
+       hotspot_y = hot_y + du->hotspot_y;
 
        /* A lot of the code assumes this */
        if (handle && (width != 64 || height != 64)) {
@@ -187,31 +195,34 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
                vmw_dmabuf_unreference(&du->cursor_dmabuf);
 
        /* setup new image */
+       ret = 0;
        if (surface) {
                /* vmw_user_surface_lookup takes one reference */
                du->cursor_surface = surface;
 
                du->cursor_surface->snooper.crtc = crtc;
                du->cursor_age = du->cursor_surface->snooper.age;
-               vmw_cursor_update_image(dev_priv, surface->snooper.image,
-                                       64, 64, du->hotspot_x, du->hotspot_y);
+               ret = vmw_cursor_update_image(dev_priv, surface->snooper.image,
+                                             64, 64, hotspot_x, hotspot_y);
        } else if (dmabuf) {
                /* vmw_user_surface_lookup takes one reference */
                du->cursor_dmabuf = dmabuf;
 
                ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, width, height,
-                                              du->hotspot_x, du->hotspot_y);
+                                              hotspot_x, hotspot_y);
        } else {
                vmw_cursor_update_position(dev_priv, false, 0, 0);
-               ret = 0;
                goto out;
        }
 
-       vmw_cursor_update_position(dev_priv, true,
-                                  du->cursor_x + du->hotspot_x,
-                                  du->cursor_y + du->hotspot_y);
+       if (!ret) {
+               vmw_cursor_update_position(dev_priv, true,
+                                          du->cursor_x + hotspot_x,
+                                          du->cursor_y + hotspot_y);
+               du->core_hotspot_x = hot_x;
+               du->core_hotspot_y = hot_y;
+       }
 
-       ret = 0;
 out:
        drm_modeset_unlock_all(dev_priv->dev);
        drm_modeset_lock_crtc(crtc, crtc->cursor);
@@ -239,8 +250,10 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
        drm_modeset_lock_all(dev_priv->dev);
 
        vmw_cursor_update_position(dev_priv, shown,
-                                  du->cursor_x + du->hotspot_x,
-                                  du->cursor_y + du->hotspot_y);
+                                  du->cursor_x + du->hotspot_x +
+                                  du->core_hotspot_x,
+                                  du->cursor_y + du->hotspot_y +
+                                  du->core_hotspot_y);
 
        drm_modeset_unlock_all(dev_priv->dev);
        drm_modeset_lock_crtc(crtc, crtc->cursor);
@@ -334,6 +347,29 @@ err_unreserve:
        ttm_bo_unreserve(bo);
 }
 
+/**
+ * vmw_kms_legacy_hotspot_clear - Clear legacy hotspots
+ *
+ * @dev_priv: Pointer to the device private struct.
+ *
+ * Clears all legacy hotspots.
+ */
+void vmw_kms_legacy_hotspot_clear(struct vmw_private *dev_priv)
+{
+       struct drm_device *dev = dev_priv->dev;
+       struct vmw_display_unit *du;
+       struct drm_crtc *crtc;
+
+       drm_modeset_lock_all(dev);
+       drm_for_each_crtc(crtc, dev) {
+               du = vmw_crtc_to_du(crtc);
+
+               du->hotspot_x = 0;
+               du->hotspot_y = 0;
+       }
+       drm_modeset_unlock_all(dev);
+}
+
 void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)
 {
        struct drm_device *dev = dev_priv->dev;
@@ -351,7 +387,9 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)
                du->cursor_age = du->cursor_surface->snooper.age;
                vmw_cursor_update_image(dev_priv,
                                        du->cursor_surface->snooper.image,
-                                       64, 64, du->hotspot_x, du->hotspot_y);
+                                       64, 64,
+                                       du->hotspot_x + du->core_hotspot_x,
+                                       du->hotspot_y + du->core_hotspot_y);
        }
 
        mutex_unlock(&dev->mode_config.mutex);
index 782df7ca97946220414dd66a2afbe4f94b6d403a..edd81503516dbbda1fab84ecd53ecc0df689f24e 100644 (file)
@@ -159,6 +159,8 @@ struct vmw_display_unit {
 
        int hotspot_x;
        int hotspot_y;
+       s32 core_hotspot_x;
+       s32 core_hotspot_y;
 
        unsigned unit;
 
@@ -193,8 +195,9 @@ void vmw_du_crtc_restore(struct drm_crtc *crtc);
 void vmw_du_crtc_gamma_set(struct drm_crtc *crtc,
                           u16 *r, u16 *g, u16 *b,
                           uint32_t start, uint32_t size);
-int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
-                          uint32_t handle, uint32_t width, uint32_t height);
+int vmw_du_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
+                           uint32_t handle, uint32_t width, uint32_t height,
+                           int32_t hot_x, int32_t hot_y);
 int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
 int vmw_du_connector_dpms(struct drm_connector *connector, int mode);
 void vmw_du_connector_save(struct drm_connector *connector);
index bb63e4d795fae43bc07599babe45bedf26f6e114..52caecb4502ed3086b8ea6e15fac9e45a08d4659 100644 (file)
@@ -297,7 +297,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
 static struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
        .save = vmw_du_crtc_save,
        .restore = vmw_du_crtc_restore,
-       .cursor_set = vmw_du_crtc_cursor_set,
+       .cursor_set2 = vmw_du_crtc_cursor_set2,
        .cursor_move = vmw_du_crtc_cursor_move,
        .gamma_set = vmw_du_crtc_gamma_set,
        .destroy = vmw_ldu_crtc_destroy,
index b96d1ab610c5527fb190ea476cdbbb82a2b2e158..13926ff192e3d6ce55b0e741ef66a04c9377596b 100644 (file)
@@ -533,7 +533,7 @@ out_no_fence:
 static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
        .save = vmw_du_crtc_save,
        .restore = vmw_du_crtc_restore,
-       .cursor_set = vmw_du_crtc_cursor_set,
+       .cursor_set2 = vmw_du_crtc_cursor_set2,
        .cursor_move = vmw_du_crtc_cursor_move,
        .gamma_set = vmw_du_crtc_gamma_set,
        .destroy = vmw_sou_crtc_destroy,
index b1fc1c02792d4c3f89cb76a0dfb0f16f3dce2c47..f823fc3efed72473108acab83d65191a00e40e9a 100644 (file)
@@ -1043,7 +1043,7 @@ out_finish:
 static struct drm_crtc_funcs vmw_stdu_crtc_funcs = {
        .save = vmw_du_crtc_save,
        .restore = vmw_du_crtc_restore,
-       .cursor_set = vmw_du_crtc_cursor_set,
+       .cursor_set2 = vmw_du_crtc_cursor_set2,
        .cursor_move = vmw_du_crtc_cursor_move,
        .gamma_set = vmw_du_crtc_gamma_set,
        .destroy = vmw_stdu_crtc_destroy,
index 3166e4bc4eb6daea9a9fcad4eb5fce4b62b1b418..9abcaa53bd25a4149e850562628bdc17e81161ed 100644 (file)
@@ -395,8 +395,10 @@ int vga_get(struct pci_dev *pdev, unsigned int rsrc, int interruptible)
                set_current_state(interruptible ?
                                  TASK_INTERRUPTIBLE :
                                  TASK_UNINTERRUPTIBLE);
-               if (signal_pending(current)) {
-                       rc = -EINTR;
+               if (interruptible && signal_pending(current)) {
+                       __set_current_state(TASK_RUNNING);
+                       remove_wait_queue(&vga_wait_queue, &wait);
+                       rc = -ERESTARTSYS;
                        break;
                }
                schedule();
index 9024a3de403253ad03955544dec063430523deb0..8b78a7f1f779faa586abd156a0f9ce7082616bc5 100644 (file)
 #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001      0xa001
 
 #define USB_VENDOR_ID_ELAN             0x04f3
-#define USB_DEVICE_ID_ELAN_TOUCHSCREEN 0x0089
-#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B    0x009b
-#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103    0x0103
-#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_010c    0x010c
-#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F    0x016f
 
 #define USB_VENDOR_ID_ELECOM           0x056e
 #define USB_DEVICE_ID_ELECOM_BM084     0x0061
index 2324520b006dc7cf24dd2af11a36780c3f989bfd..7dd0953cd70f222f037c72b7c217b76eff8d2942 100644 (file)
@@ -72,11 +72,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
        { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT },
-       { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN, HID_QUIRK_ALWAYS_POLL },
-       { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B, HID_QUIRK_ALWAYS_POLL },
-       { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103, HID_QUIRK_ALWAYS_POLL },
-       { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_010c, HID_QUIRK_ALWAYS_POLL },
-       { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F, HID_QUIRK_ALWAYS_POLL },
+       { USB_VENDOR_ID_ELAN, HID_ANY_ID, HID_QUIRK_ALWAYS_POLL },
        { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
@@ -340,7 +336,8 @@ static const struct hid_blacklist *usbhid_exists_squirk(const u16 idVendor,
 
        for (; hid_blacklist[n].idVendor; n++)
                if (hid_blacklist[n].idVendor == idVendor &&
-                               hid_blacklist[n].idProduct == idProduct)
+                       (hid_blacklist[n].idProduct == (__u16) HID_ANY_ID ||
+                               hid_blacklist[n].idProduct == idProduct))
                        bl_entry = &hid_blacklist[n];
 
        if (bl_entry != NULL)
index 8f59f057cdf4a336cf29cd32803dff2b50143be2..80a73bfc1a65807db6fc276e3027f11500d2f96b 100644 (file)
@@ -1217,6 +1217,7 @@ config SENSORS_PWM_FAN
 config SENSORS_SHT15
        tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
        depends on GPIOLIB || COMPILE_TEST
+       select BITREVERSE
        help
          If you say yes here you get support for the Sensiron SHT10, SHT11,
          SHT15, SHT71, SHT75 humidity and temperature sensors.
index 65482624ea2c81a2ef2b5487d6a0470cc90fead7..5289aa0980a8fac074822ddb412f35e7a9380bd5 100644 (file)
@@ -58,6 +58,7 @@ struct tmp102 {
        u16 config_orig;
        unsigned long last_update;
        int temp[3];
+       bool first_time;
 };
 
 /* convert left adjusted 13-bit TMP102 register value to milliCelsius */
@@ -93,6 +94,7 @@ static struct tmp102 *tmp102_update_device(struct device *dev)
                                tmp102->temp[i] = tmp102_reg_to_mC(status);
                }
                tmp102->last_update = jiffies;
+               tmp102->first_time = false;
        }
        mutex_unlock(&tmp102->lock);
        return tmp102;
@@ -102,6 +104,12 @@ static int tmp102_read_temp(void *dev, int *temp)
 {
        struct tmp102 *tmp102 = tmp102_update_device(dev);
 
+       /* Is it too early even to return a conversion? */
+       if (tmp102->first_time) {
+               dev_dbg(dev, "%s: Conversion not ready yet..\n", __func__);
+               return -EAGAIN;
+       }
+
        *temp = tmp102->temp[0];
 
        return 0;
@@ -114,6 +122,10 @@ static ssize_t tmp102_show_temp(struct device *dev,
        struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
        struct tmp102 *tmp102 = tmp102_update_device(dev);
 
+       /* Is it too early even to return a read? */
+       if (tmp102->first_time)
+               return -EAGAIN;
+
        return sprintf(buf, "%d\n", tmp102->temp[sda->index]);
 }
 
@@ -207,7 +219,9 @@ static int tmp102_probe(struct i2c_client *client,
                status = -ENODEV;
                goto fail_restore_config;
        }
-       tmp102->last_update = jiffies - HZ;
+       tmp102->last_update = jiffies;
+       /* Mark that we are not ready with data until conversion is complete */
+       tmp102->first_time = true;
        mutex_init(&tmp102->lock);
 
        hwmon_dev = hwmon_device_register_with_groups(dev, client->name,
index c5628a42170acf83d0a2c5d2dffa6a50e6572c59..a8bdcb5292f5b30a925c40f28c8d193395b443c6 100644 (file)
@@ -202,8 +202,15 @@ static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev)
         * d is always 6 on Keystone I2C controller
         */
 
-       /* get minimum of 7 MHz clock, but max of 12 MHz */
-       psc = (input_clock / 7000000) - 1;
+       /*
+        * Both Davinci and current Keystone User Guides recommend a value
+        * between 7MHz and 12MHz. In reality 7MHz module clock doesn't
+        * always produce enough margin between SDA and SCL transitions.
+        * Measurements show that the higher the module clock is, the
+        * bigger is the margin, providing more reliable communication.
+        * So we better target for 12MHz.
+        */
+       psc = (input_clock / 12000000) - 1;
        if ((input_clock / (psc + 1)) > 12000000)
                psc++;  /* better to run under spec than over */
        d = (psc >= 2) ? 5 : 7 - psc;
index 8c48b27ba05975e51a40ddaab979e7b23302e3e0..de7fbbb374cd34fce1cc8fffb11c45b21755bead 100644 (file)
@@ -813,6 +813,12 @@ static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
 tx_aborted:
        if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err)
                complete(&dev->cmd_complete);
+       else if (unlikely(dev->accessor_flags & ACCESS_INTR_MASK)) {
+               /* workaround to trigger pending interrupt */
+               stat = dw_readl(dev, DW_IC_INTR_MASK);
+               i2c_dw_disable_int(dev);
+               dw_writel(dev, stat, DW_IC_INTR_MASK);
+       }
 
        return IRQ_HANDLED;
 }
index 1d50898e7b2403868c239f2ebc236a240a755bc7..9ffb63a60f95454ebbaf43f6a12bbe922de66179 100644 (file)
@@ -111,6 +111,7 @@ struct dw_i2c_dev {
 
 #define ACCESS_SWAP            0x00000001
 #define ACCESS_16BIT           0x00000002
+#define ACCESS_INTR_MASK       0x00000004
 
 extern int i2c_dw_init(struct dw_i2c_dev *dev);
 extern void i2c_dw_disable(struct dw_i2c_dev *dev);
index 809579ecb5a44fed6745af1274ed46864763651c..6b00061c37469b98613880ffe71d26118c76d92a 100644 (file)
@@ -93,6 +93,7 @@ static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
 static int dw_i2c_acpi_configure(struct platform_device *pdev)
 {
        struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+       const struct acpi_device_id *id;
 
        dev->adapter.nr = -1;
        dev->tx_fifo_depth = 32;
@@ -106,6 +107,10 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev)
        dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
                           &dev->sda_hold_time);
 
+       id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
+       if (id && id->driver_data)
+               dev->accessor_flags |= (u32)id->driver_data;
+
        return 0;
 }
 
@@ -116,7 +121,7 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = {
        { "INT3433", 0 },
        { "80860F41", 0 },
        { "808622C1", 0 },
-       { "AMD0010", 0 },
+       { "AMD0010", ACCESS_INTR_MASK },
        { }
 };
 MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
@@ -240,12 +245,10 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
        }
 
        r = i2c_dw_probe(dev);
-       if (r) {
+       if (r && !dev->pm_runtime_disabled)
                pm_runtime_disable(&pdev->dev);
-               return r;
-       }
 
-       return 0;
+       return r;
 }
 
 static int dw_i2c_plat_remove(struct platform_device *pdev)
@@ -260,7 +263,8 @@ static int dw_i2c_plat_remove(struct platform_device *pdev)
 
        pm_runtime_dont_use_autosuspend(&pdev->dev);
        pm_runtime_put_sync(&pdev->dev);
-       pm_runtime_disable(&pdev->dev);
+       if (!dev->pm_runtime_disabled)
+               pm_runtime_disable(&pdev->dev);
 
        return 0;
 }
index 9bb0b056b25f235085df0e994c7c6584581a5a6d..d4d853680ae47881151effb56269e4e660d522e1 100644 (file)
@@ -1119,6 +1119,8 @@ static int i2c_imx_probe(struct platform_device *pdev)
                        i2c_imx, IMX_I2C_I2CR);
        imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, IMX_I2C_I2SR);
 
+       i2c_imx_init_recovery_info(i2c_imx, pdev);
+
        /* Add I2C adapter */
        ret = i2c_add_numbered_adapter(&i2c_imx->adapter);
        if (ret < 0) {
@@ -1126,8 +1128,6 @@ static int i2c_imx_probe(struct platform_device *pdev)
                goto clk_disable;
        }
 
-       i2c_imx_init_recovery_info(i2c_imx, pdev);
-
        /* Set up platform driver data */
        platform_set_drvdata(pdev, i2c_imx);
        clk_disable_unprepare(i2c_imx->clk);
index 5801227b97ab089022f90608f6fc425ebd13cd87..43207f52e5a3733f5d405da921fb5d32b331321f 100644 (file)
@@ -146,6 +146,8 @@ struct mv64xxx_i2c_data {
        bool                    errata_delay;
        struct reset_control    *rstc;
        bool                    irq_clear_inverted;
+       /* Clk div is 2 to the power n, not 2 to the power n + 1 */
+       bool                    clk_n_base_0;
 };
 
 static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = {
@@ -757,25 +759,29 @@ MODULE_DEVICE_TABLE(of, mv64xxx_i2c_of_match_table);
 #ifdef CONFIG_OF
 #ifdef CONFIG_HAVE_CLK
 static int
-mv64xxx_calc_freq(const int tclk, const int n, const int m)
+mv64xxx_calc_freq(struct mv64xxx_i2c_data *drv_data,
+                 const int tclk, const int n, const int m)
 {
-       return tclk / (10 * (m + 1) * (2 << n));
+       if (drv_data->clk_n_base_0)
+               return tclk / (10 * (m + 1) * (1 << n));
+       else
+               return tclk / (10 * (m + 1) * (2 << n));
 }
 
 static bool
-mv64xxx_find_baud_factors(const u32 req_freq, const u32 tclk, u32 *best_n,
-                         u32 *best_m)
+mv64xxx_find_baud_factors(struct mv64xxx_i2c_data *drv_data,
+                         const u32 req_freq, const u32 tclk)
 {
        int freq, delta, best_delta = INT_MAX;
        int m, n;
 
        for (n = 0; n <= 7; n++)
                for (m = 0; m <= 15; m++) {
-                       freq = mv64xxx_calc_freq(tclk, n, m);
+                       freq = mv64xxx_calc_freq(drv_data, tclk, n, m);
                        delta = req_freq - freq;
                        if (delta >= 0 && delta < best_delta) {
-                               *best_m = m;
-                               *best_n = n;
+                               drv_data->freq_m = m;
+                               drv_data->freq_n = n;
                                best_delta = delta;
                        }
                        if (best_delta == 0)
@@ -813,8 +819,11 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
        if (of_property_read_u32(np, "clock-frequency", &bus_freq))
                bus_freq = 100000; /* 100kHz by default */
 
-       if (!mv64xxx_find_baud_factors(bus_freq, tclk,
-                                      &drv_data->freq_n, &drv_data->freq_m)) {
+       if (of_device_is_compatible(np, "allwinner,sun4i-a10-i2c") ||
+           of_device_is_compatible(np, "allwinner,sun6i-a31-i2c"))
+               drv_data->clk_n_base_0 = true;
+
+       if (!mv64xxx_find_baud_factors(drv_data, bus_freq, tclk)) {
                rc = -EINVAL;
                goto out;
        }
index b0ae560b38c308335229f0f9b2317f0361b6b8a3..599c0d7bd906d19afc89417afc74d939e6985252 100644 (file)
@@ -576,7 +576,7 @@ static int rcar_reg_slave(struct i2c_client *slave)
        if (slave->flags & I2C_CLIENT_TEN)
                return -EAFNOSUPPORT;
 
-       pm_runtime_forbid(rcar_i2c_priv_to_dev(priv));
+       pm_runtime_get_sync(rcar_i2c_priv_to_dev(priv));
 
        priv->slave = slave;
        rcar_i2c_write(priv, ICSAR, slave->addr);
@@ -598,7 +598,7 @@ static int rcar_unreg_slave(struct i2c_client *slave)
 
        priv->slave = NULL;
 
-       pm_runtime_allow(rcar_i2c_priv_to_dev(priv));
+       pm_runtime_put(rcar_i2c_priv_to_dev(priv));
 
        return 0;
 }
index c1935ebd6a9c38971b6539cc1d1ae03dfc276d17..9096d17beb5bb002d914010a77f156a3f3f97f32 100644 (file)
@@ -908,7 +908,7 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
                                 &i2c->scl_fall_ns))
                i2c->scl_fall_ns = 300;
        if (of_property_read_u32(pdev->dev.of_node, "i2c-sda-falling-time-ns",
-                                &i2c->scl_fall_ns))
+                                &i2c->sda_fall_ns))
                i2c->sda_fall_ns = i2c->scl_fall_ns;
 
        strlcpy(i2c->adap.name, "rk3x-i2c", sizeof(i2c->adap.name));
index ea72dca32fdfde83cfdd223525a915a5721d6816..25020ec777c9783bf5c62853051707bace5c4483 100644 (file)
@@ -822,7 +822,7 @@ static int st_i2c_probe(struct platform_device *pdev)
 
        adap = &i2c_dev->adap;
        i2c_set_adapdata(adap, i2c_dev);
-       snprintf(adap->name, sizeof(adap->name), "ST I2C(0x%pa)", &res->start);
+       snprintf(adap->name, sizeof(adap->name), "ST I2C(%pa)", &res->start);
        adap->owner = THIS_MODULE;
        adap->timeout = 2 * HZ;
        adap->retries = 0;
index 0c4618b4d51549cb7bfe8fead1e3ce61c1882366..c2babe50a0d8f59464f8b77837132192e70e3726 100644 (file)
@@ -839,8 +839,10 @@ static int vadc_get_dt_data(struct vadc_priv *vadc, struct device_node *node)
 
        for_each_available_child_of_node(node, child) {
                ret = vadc_get_dt_channel_data(vadc->dev, &prop, child);
-               if (ret)
+               if (ret) {
+                       of_node_put(child);
                        return ret;
+               }
 
                vadc->chan_props[index] = prop;
 
index d7e908acb48020b3f5390030e5a3687b03ba9878..0f6f63b2026379ffd968a764e3309f8fb792eda5 100644 (file)
@@ -302,7 +302,7 @@ static int iio_scan_mask_set(struct iio_dev *indio_dev,
        if (trialmask == NULL)
                return -ENOMEM;
        if (!indio_dev->masklength) {
-               WARN_ON("Trying to set scanmask prior to registering buffer\n");
+               WARN(1, "Trying to set scanmask prior to registering buffer\n");
                goto err_invalid_mask;
        }
        bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength);
index 208358f9e7e36582152cad8c4f4924d9667a58cc..159ede61f79318d4ee8e581a8a61df2028680aba 100644 (file)
@@ -655,7 +655,7 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
                        break;
                case IIO_SEPARATE:
                        if (!chan->indexed) {
-                               WARN_ON("Differential channels must be indexed\n");
+                               WARN(1, "Differential channels must be indexed\n");
                                ret = -EINVAL;
                                goto error_free_full_postfix;
                        }
index 7d269ef9e0625a81cdf1832c53667e9ed1039f18..f6a07dc32ae486a045b97cfb4406783a9aa05ab8 100644 (file)
@@ -453,6 +453,7 @@ static int apds9960_set_power_state(struct apds9960_data *data, bool on)
                        usleep_range(data->als_adc_int_us,
                                     APDS9960_MAX_INT_TIME_IN_US);
        } else {
+               pm_runtime_mark_last_busy(dev);
                ret = pm_runtime_put_autosuspend(dev);
        }
 
index 961f9f990faffa67fccf54dfa01118ce4339f3b9..e544fcfd5cedf4f3a1d806204b7bcdfbe0d0deb3 100644 (file)
@@ -130,10 +130,10 @@ static int lidar_get_measurement(struct lidar_data *data, u16 *reg)
                if (ret < 0)
                        break;
 
-               /* return 0 since laser is likely pointed out of range */
+               /* return -EINVAL since laser is likely pointed out of range */
                if (ret & LIDAR_REG_STATUS_INVALID) {
                        *reg = 0;
-                       ret = 0;
+                       ret = -EINVAL;
                        break;
                }
 
@@ -197,7 +197,7 @@ static irqreturn_t lidar_trigger_handler(int irq, void *private)
        if (!ret) {
                iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
                                                   iio_get_time_ns());
-       } else {
+       } else if (ret != -EINVAL) {
                dev_err(&data->client->dev, "cannot read LIDAR measurement");
        }
 
index 944cd90417bcc9b2a51d27f903feffad6f2307ea..2d762a2ecd81252cde34cbc2dbc1083c1d8832dc 100644 (file)
@@ -1126,10 +1126,7 @@ static bool validate_ipv4_net_dev(struct net_device *net_dev,
 
        rcu_read_lock();
        err = fib_lookup(dev_net(net_dev), &fl4, &res, 0);
-       if (err)
-               return false;
-
-       ret = FIB_RES_DEV(res) == net_dev;
+       ret = err == 0 && FIB_RES_DEV(res) == net_dev;
        rcu_read_unlock();
 
        return ret;
@@ -1268,15 +1265,17 @@ static bool cma_protocol_roce(const struct rdma_cm_id *id)
        return cma_protocol_roce_dev_port(device, port_num);
 }
 
-static bool cma_match_net_dev(const struct rdma_id_private *id_priv,
-                             const struct net_device *net_dev)
+static bool cma_match_net_dev(const struct rdma_cm_id *id,
+                             const struct net_device *net_dev,
+                             u8 port_num)
 {
-       const struct rdma_addr *addr = &id_priv->id.route.addr;
+       const struct rdma_addr *addr = &id->route.addr;
 
        if (!net_dev)
                /* This request is an AF_IB request or a RoCE request */
-               return addr->src_addr.ss_family == AF_IB ||
-                      cma_protocol_roce(&id_priv->id);
+               return (!id->port_num || id->port_num == port_num) &&
+                      (addr->src_addr.ss_family == AF_IB ||
+                       cma_protocol_roce_dev_port(id->device, port_num));
 
        return !addr->dev_addr.bound_dev_if ||
               (net_eq(dev_net(net_dev), addr->dev_addr.net) &&
@@ -1298,13 +1297,13 @@ static struct rdma_id_private *cma_find_listener(
        hlist_for_each_entry(id_priv, &bind_list->owners, node) {
                if (cma_match_private_data(id_priv, ib_event->private_data)) {
                        if (id_priv->id.device == cm_id->device &&
-                           cma_match_net_dev(id_priv, net_dev))
+                           cma_match_net_dev(&id_priv->id, net_dev, req->port))
                                return id_priv;
                        list_for_each_entry(id_priv_dev,
                                            &id_priv->listen_list,
                                            listen_list) {
                                if (id_priv_dev->id.device == cm_id->device &&
-                                   cma_match_net_dev(id_priv_dev, net_dev))
+                                   cma_match_net_dev(&id_priv_dev->id, net_dev, req->port))
                                        return id_priv_dev;
                        }
                }
index 8d8af7a41a30fae4ceb520ce0d11b6f541905c96..2281de122038e45a5c375f7d7669111ab2aee2de 100644 (file)
@@ -1811,6 +1811,11 @@ static int validate_mad(const struct ib_mad_hdr *mad_hdr,
                if (qp_num == 0)
                        valid = 1;
        } else {
+               /* CM attributes other than ClassPortInfo only use Send method */
+               if ((mad_hdr->mgmt_class == IB_MGMT_CLASS_CM) &&
+                   (mad_hdr->attr_id != IB_MGMT_CLASSPORTINFO_ATTR_ID) &&
+                   (mad_hdr->method != IB_MGMT_METHOD_SEND))
+                       goto out;
                /* Filter GSI packets sent to QP0 */
                if (qp_num != 0)
                        valid = 1;
index 2aba774f835b9caca8e9e1645d1efd6cf6f08bf9..a95a32ba596edc03728cf7790a6752c951cde951 100644 (file)
@@ -512,7 +512,7 @@ static int ib_nl_get_path_rec_attrs_len(ib_sa_comp_mask comp_mask)
        return len;
 }
 
-static int ib_nl_send_msg(struct ib_sa_query *query)
+static int ib_nl_send_msg(struct ib_sa_query *query, gfp_t gfp_mask)
 {
        struct sk_buff *skb = NULL;
        struct nlmsghdr *nlh;
@@ -526,7 +526,7 @@ static int ib_nl_send_msg(struct ib_sa_query *query)
        if (len <= 0)
                return -EMSGSIZE;
 
-       skb = nlmsg_new(len, GFP_KERNEL);
+       skb = nlmsg_new(len, gfp_mask);
        if (!skb)
                return -ENOMEM;
 
@@ -544,7 +544,7 @@ static int ib_nl_send_msg(struct ib_sa_query *query)
        /* Repair the nlmsg header length */
        nlmsg_end(skb, nlh);
 
-       ret = ibnl_multicast(skb, nlh, RDMA_NL_GROUP_LS, GFP_KERNEL);
+       ret = ibnl_multicast(skb, nlh, RDMA_NL_GROUP_LS, gfp_mask);
        if (!ret)
                ret = len;
        else
@@ -553,7 +553,7 @@ static int ib_nl_send_msg(struct ib_sa_query *query)
        return ret;
 }
 
-static int ib_nl_make_request(struct ib_sa_query *query)
+static int ib_nl_make_request(struct ib_sa_query *query, gfp_t gfp_mask)
 {
        unsigned long flags;
        unsigned long delay;
@@ -562,25 +562,27 @@ static int ib_nl_make_request(struct ib_sa_query *query)
        INIT_LIST_HEAD(&query->list);
        query->seq = (u32)atomic_inc_return(&ib_nl_sa_request_seq);
 
+       /* Put the request on the list first.*/
        spin_lock_irqsave(&ib_nl_request_lock, flags);
-       ret = ib_nl_send_msg(query);
-       if (ret <= 0) {
-               ret = -EIO;
-               goto request_out;
-       } else {
-               ret = 0;
-       }
-
        delay = msecs_to_jiffies(sa_local_svc_timeout_ms);
        query->timeout = delay + jiffies;
        list_add_tail(&query->list, &ib_nl_request_list);
        /* Start the timeout if this is the only request */
        if (ib_nl_request_list.next == &query->list)
                queue_delayed_work(ib_nl_wq, &ib_nl_timed_work, delay);
-
-request_out:
        spin_unlock_irqrestore(&ib_nl_request_lock, flags);
 
+       ret = ib_nl_send_msg(query, gfp_mask);
+       if (ret <= 0) {
+               ret = -EIO;
+               /* Remove the request */
+               spin_lock_irqsave(&ib_nl_request_lock, flags);
+               list_del(&query->list);
+               spin_unlock_irqrestore(&ib_nl_request_lock, flags);
+       } else {
+               ret = 0;
+       }
+
        return ret;
 }
 
@@ -1108,7 +1110,7 @@ static int send_mad(struct ib_sa_query *query, int timeout_ms, gfp_t gfp_mask)
 
        if (query->flags & IB_SA_ENABLE_LOCAL_SERVICE) {
                if (!ibnl_chk_listeners(RDMA_NL_GROUP_LS)) {
-                       if (!ib_nl_make_request(query))
+                       if (!ib_nl_make_request(query, gfp_mask))
                                return id;
                }
                ib_sa_disable_local_svc(query);
index 94816aeb95a0a186760fbe98de55edc69266a54c..1c02deab068fbf1031d5b21db960feb9b06865c5 100644 (file)
@@ -62,9 +62,11 @@ static struct uverbs_lock_class rule_lock_class = { .name = "RULE-uobj" };
  * The ib_uobject locking scheme is as follows:
  *
  * - ib_uverbs_idr_lock protects the uverbs idrs themselves, so it
- *   needs to be held during all idr operations.  When an object is
+ *   needs to be held during all idr write operations.  When an object is
  *   looked up, a reference must be taken on the object's kref before
- *   dropping this lock.
+ *   dropping this lock.  For read operations, the rcu_read_lock()
+ *   and rcu_write_lock() but similarly the kref reference is grabbed
+ *   before the rcu_read_unlock().
  *
  * - Each object also has an rwsem.  This rwsem must be held for
  *   reading while an operation that uses the object is performed.
@@ -96,7 +98,7 @@ static void init_uobj(struct ib_uobject *uobj, u64 user_handle,
 
 static void release_uobj(struct kref *kref)
 {
-       kfree(container_of(kref, struct ib_uobject, ref));
+       kfree_rcu(container_of(kref, struct ib_uobject, ref), rcu);
 }
 
 static void put_uobj(struct ib_uobject *uobj)
@@ -145,7 +147,7 @@ static struct ib_uobject *__idr_get_uobj(struct idr *idr, int id,
 {
        struct ib_uobject *uobj;
 
-       spin_lock(&ib_uverbs_idr_lock);
+       rcu_read_lock();
        uobj = idr_find(idr, id);
        if (uobj) {
                if (uobj->context == context)
@@ -153,7 +155,7 @@ static struct ib_uobject *__idr_get_uobj(struct idr *idr, int id,
                else
                        uobj = NULL;
        }
-       spin_unlock(&ib_uverbs_idr_lock);
+       rcu_read_unlock();
 
        return uobj;
 }
@@ -2446,6 +2448,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
        int                             i, sg_ind;
        int                             is_ud;
        ssize_t                         ret = -EINVAL;
+       size_t                          next_size;
 
        if (copy_from_user(&cmd, buf, sizeof cmd))
                return -EFAULT;
@@ -2490,7 +2493,8 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
                                goto out_put;
                        }
 
-                       ud = alloc_wr(sizeof(*ud), user_wr->num_sge);
+                       next_size = sizeof(*ud);
+                       ud = alloc_wr(next_size, user_wr->num_sge);
                        if (!ud) {
                                ret = -ENOMEM;
                                goto out_put;
@@ -2511,7 +2515,8 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
                           user_wr->opcode == IB_WR_RDMA_READ) {
                        struct ib_rdma_wr *rdma;
 
-                       rdma = alloc_wr(sizeof(*rdma), user_wr->num_sge);
+                       next_size = sizeof(*rdma);
+                       rdma = alloc_wr(next_size, user_wr->num_sge);
                        if (!rdma) {
                                ret = -ENOMEM;
                                goto out_put;
@@ -2525,7 +2530,8 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
                           user_wr->opcode == IB_WR_ATOMIC_FETCH_AND_ADD) {
                        struct ib_atomic_wr *atomic;
 
-                       atomic = alloc_wr(sizeof(*atomic), user_wr->num_sge);
+                       next_size = sizeof(*atomic);
+                       atomic = alloc_wr(next_size, user_wr->num_sge);
                        if (!atomic) {
                                ret = -ENOMEM;
                                goto out_put;
@@ -2540,7 +2546,8 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
                } else if (user_wr->opcode == IB_WR_SEND ||
                           user_wr->opcode == IB_WR_SEND_WITH_IMM ||
                           user_wr->opcode == IB_WR_SEND_WITH_INV) {
-                       next = alloc_wr(sizeof(*next), user_wr->num_sge);
+                       next_size = sizeof(*next);
+                       next = alloc_wr(next_size, user_wr->num_sge);
                        if (!next) {
                                ret = -ENOMEM;
                                goto out_put;
@@ -2572,7 +2579,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
 
                if (next->num_sge) {
                        next->sg_list = (void *) next +
-                               ALIGN(sizeof *next, sizeof (struct ib_sge));
+                               ALIGN(next_size, sizeof(struct ib_sge));
                        if (copy_from_user(next->sg_list,
                                           buf + sizeof cmd +
                                           cmd.wr_count * cmd.wqe_size +
index 043a60ee6836db72e498410ebd80e004ed220c7d..545906dec26dc5e936df37c635c68b94bb27e226 100644 (file)
@@ -1516,7 +1516,7 @@ EXPORT_SYMBOL(ib_map_mr_sg);
  * @sg_nents:      number of entries in sg
  * @set_page:      driver page assignment function pointer
  *
- * Core service helper for drivers to covert the largest
+ * Core service helper for drivers to convert the largest
  * prefix of given sg list to a page vector. The sg list
  * prefix converted is the prefix that meet the requirements
  * of ib_map_mr_sg.
@@ -1533,7 +1533,7 @@ int ib_sg_to_pages(struct ib_mr *mr,
        u64 last_end_dma_addr = 0, last_page_addr = 0;
        unsigned int last_page_off = 0;
        u64 page_mask = ~((u64)mr->page_size - 1);
-       int i;
+       int i, ret;
 
        mr->iova = sg_dma_address(&sgl[0]);
        mr->length = 0;
@@ -1544,27 +1544,29 @@ int ib_sg_to_pages(struct ib_mr *mr,
                u64 end_dma_addr = dma_addr + dma_len;
                u64 page_addr = dma_addr & page_mask;
 
-               if (i && page_addr != dma_addr) {
-                       if (last_end_dma_addr != dma_addr) {
-                               /* gap */
-                               goto done;
-
-                       } else if (last_page_off + dma_len <= mr->page_size) {
-                               /* chunk this fragment with the last */
-                               mr->length += dma_len;
-                               last_end_dma_addr += dma_len;
-                               last_page_off += dma_len;
-                               continue;
-                       } else {
-                               /* map starting from the next page */
-                               page_addr = last_page_addr + mr->page_size;
-                               dma_len -= mr->page_size - last_page_off;
-                       }
+               /*
+                * For the second and later elements, check whether either the
+                * end of element i-1 or the start of element i is not aligned
+                * on a page boundary.
+                */
+               if (i && (last_page_off != 0 || page_addr != dma_addr)) {
+                       /* Stop mapping if there is a gap. */
+                       if (last_end_dma_addr != dma_addr)
+                               break;
+
+                       /*
+                        * Coalesce this element with the last. If it is small
+                        * enough just update mr->length. Otherwise start
+                        * mapping from the next page.
+                        */
+                       goto next_page;
                }
 
                do {
-                       if (unlikely(set_page(mr, page_addr)))
-                               goto done;
+                       ret = set_page(mr, page_addr);
+                       if (unlikely(ret < 0))
+                               return i ? : ret;
+next_page:
                        page_addr += mr->page_size;
                } while (page_addr < end_dma_addr);
 
@@ -1574,7 +1576,6 @@ int ib_sg_to_pages(struct ib_mr *mr,
                last_page_off = end_dma_addr & ~page_mask;
        }
 
-done:
        return i;
 }
 EXPORT_SYMBOL(ib_sg_to_pages);
index f567160a4a56ed141320b2d153d21f2031cbb464..97d6878f993828085a0f26f941572674ce68b967 100644 (file)
@@ -456,7 +456,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
        props->max_qp_wr           = dev->dev->caps.max_wqes - MLX4_IB_SQ_MAX_SPARE;
        props->max_sge             = min(dev->dev->caps.max_sq_sg,
                                         dev->dev->caps.max_rq_sg);
-       props->max_sge_rd = props->max_sge;
+       props->max_sge_rd          = MLX4_MAX_SGE_RD;
        props->max_cq              = dev->dev->quotas.cq;
        props->max_cqe             = dev->dev->caps.max_cqes;
        props->max_mr              = dev->dev->quotas.mpt;
index a2e4ca56da44e5d9cec5ee4b6a02cf6ab9d7356c..13eaaf45288f80d4bb6658d5a18985a978e8c98d 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/log2.h>
 #include <linux/slab.h>
 #include <linux/netdevice.h>
+#include <linux/vmalloc.h>
 
 #include <rdma/ib_cache.h>
 #include <rdma/ib_pack.h>
@@ -795,8 +796,14 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
                if (err)
                        goto err_mtt;
 
-               qp->sq.wrid  = kmalloc(qp->sq.wqe_cnt * sizeof (u64), gfp);
-               qp->rq.wrid  = kmalloc(qp->rq.wqe_cnt * sizeof (u64), gfp);
+               qp->sq.wrid = kmalloc(qp->sq.wqe_cnt * sizeof(u64), gfp);
+               if (!qp->sq.wrid)
+                       qp->sq.wrid = __vmalloc(qp->sq.wqe_cnt * sizeof(u64),
+                                               gfp, PAGE_KERNEL);
+               qp->rq.wrid = kmalloc(qp->rq.wqe_cnt * sizeof(u64), gfp);
+               if (!qp->rq.wrid)
+                       qp->rq.wrid = __vmalloc(qp->rq.wqe_cnt * sizeof(u64),
+                                               gfp, PAGE_KERNEL);
                if (!qp->sq.wrid || !qp->rq.wrid) {
                        err = -ENOMEM;
                        goto err_wrid;
@@ -886,8 +893,8 @@ err_wrid:
                if (qp_has_rq(init_attr))
                        mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), &qp->db);
        } else {
-               kfree(qp->sq.wrid);
-               kfree(qp->rq.wrid);
+               kvfree(qp->sq.wrid);
+               kvfree(qp->rq.wrid);
        }
 
 err_mtt:
@@ -1062,8 +1069,8 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
                                              &qp->db);
                ib_umem_release(qp->umem);
        } else {
-               kfree(qp->sq.wrid);
-               kfree(qp->rq.wrid);
+               kvfree(qp->sq.wrid);
+               kvfree(qp->rq.wrid);
                if (qp->mlx4_ib_qp_type & (MLX4_IB_QPT_PROXY_SMI_OWNER |
                    MLX4_IB_QPT_PROXY_SMI | MLX4_IB_QPT_PROXY_GSI))
                        free_proxy_bufs(&dev->ib_dev, qp);
index dce5dfe3a70ea957a6780eca47e0c15e0d054300..c394376ebe06f159aebca07ef899ef5933386713 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/mlx4/qp.h>
 #include <linux/mlx4/srq.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 
 #include "mlx4_ib.h"
 #include "user.h"
@@ -172,8 +173,12 @@ struct ib_srq *mlx4_ib_create_srq(struct ib_pd *pd,
 
                srq->wrid = kmalloc(srq->msrq.max * sizeof (u64), GFP_KERNEL);
                if (!srq->wrid) {
-                       err = -ENOMEM;
-                       goto err_mtt;
+                       srq->wrid = __vmalloc(srq->msrq.max * sizeof(u64),
+                                             GFP_KERNEL, PAGE_KERNEL);
+                       if (!srq->wrid) {
+                               err = -ENOMEM;
+                               goto err_mtt;
+                       }
                }
        }
 
@@ -204,7 +209,7 @@ err_wrid:
        if (pd->uobject)
                mlx4_ib_db_unmap_user(to_mucontext(pd->uobject->context), &srq->db);
        else
-               kfree(srq->wrid);
+               kvfree(srq->wrid);
 
 err_mtt:
        mlx4_mtt_cleanup(dev->dev, &srq->mtt);
@@ -281,7 +286,7 @@ int mlx4_ib_destroy_srq(struct ib_srq *srq)
                mlx4_ib_db_unmap_user(to_mucontext(srq->uobject->context), &msrq->db);
                ib_umem_release(msrq->umem);
        } else {
-               kfree(msrq->wrid);
+               kvfree(msrq->wrid);
                mlx4_buf_free(dev->dev, msrq->msrq.max << msrq->msrq.wqe_shift,
                              &msrq->buf);
                mlx4_db_free(dev->dev, &msrq->db);
index ec8993a7b3beea5a91370c1f66979dae583f49d4..6000f7aeede94301cbb7c281bfaae26299770106 100644 (file)
@@ -381,7 +381,19 @@ static void __cache_work_func(struct mlx5_cache_ent *ent)
                        }
                }
        } else if (ent->cur > 2 * ent->limit) {
-               if (!someone_adding(cache) &&
+               /*
+                * The remove_keys() logic is performed as garbage collection
+                * task. Such task is intended to be run when no other active
+                * processes are running.
+                *
+                * The need_resched() will return TRUE if there are user tasks
+                * to be activated in near future.
+                *
+                * In such case, we don't execute remove_keys() and postpone
+                * the garbage collection work to try to run in next cycle,
+                * in order to free CPU resources to other tasks.
+                */
+               if (!need_resched() && !someone_adding(cache) &&
                    time_after(jiffies, cache->last_add + 300 * HZ)) {
                        remove_keys(dev, i, 1);
                        if (ent->cur > ent->limit)
index ae80590aabdf7db6df756c0ee07afa4721f6c37c..040bb8b5cb15a65c34b15ab67c3c5fe14e27524c 100644 (file)
@@ -232,6 +232,10 @@ struct phy_info {
        u16 interface_type;
 };
 
+enum ocrdma_flags {
+       OCRDMA_FLAGS_LINK_STATUS_INIT = 0x01
+};
+
 struct ocrdma_dev {
        struct ib_device ibdev;
        struct ocrdma_dev_attr attr;
@@ -287,6 +291,7 @@ struct ocrdma_dev {
        atomic_t update_sl;
        u16 pvid;
        u32 asic_id;
+       u32 flags;
 
        ulong last_stats_time;
        struct mutex stats_lock; /* provide synch for debugfs operations */
@@ -591,4 +596,9 @@ static inline u8 ocrdma_is_enabled_and_synced(u32 state)
                (state & OCRDMA_STATE_FLAG_SYNC);
 }
 
+static inline u8 ocrdma_get_ae_link_state(u32 ae_state)
+{
+       return ((ae_state & OCRDMA_AE_LSC_LS_MASK) >> OCRDMA_AE_LSC_LS_SHIFT);
+}
+
 #endif
index 30f67bebffa35742189c4fc08b91654f75bfdcfa..283ca842ff7498b308fcec85a1268dcb452d56b0 100644 (file)
@@ -579,6 +579,8 @@ static int ocrdma_mbx_create_mq(struct ocrdma_dev *dev,
 
        cmd->async_event_bitmap = BIT(OCRDMA_ASYNC_GRP5_EVE_CODE);
        cmd->async_event_bitmap |= BIT(OCRDMA_ASYNC_RDMA_EVE_CODE);
+       /* Request link events on this  MQ. */
+       cmd->async_event_bitmap |= BIT(OCRDMA_ASYNC_LINK_EVE_CODE);
 
        cmd->async_cqid_ringsize = cq->id;
        cmd->async_cqid_ringsize |= (ocrdma_encoded_q_len(mq->len) <<
@@ -819,20 +821,42 @@ static void ocrdma_process_grp5_aync(struct ocrdma_dev *dev,
        }
 }
 
+static void ocrdma_process_link_state(struct ocrdma_dev *dev,
+                                     struct ocrdma_ae_mcqe *cqe)
+{
+       struct ocrdma_ae_lnkst_mcqe *evt;
+       u8 lstate;
+
+       evt = (struct ocrdma_ae_lnkst_mcqe *)cqe;
+       lstate = ocrdma_get_ae_link_state(evt->speed_state_ptn);
+
+       if (!(lstate & OCRDMA_AE_LSC_LLINK_MASK))
+               return;
+
+       if (dev->flags & OCRDMA_FLAGS_LINK_STATUS_INIT)
+               ocrdma_update_link_state(dev, (lstate & OCRDMA_LINK_ST_MASK));
+}
+
 static void ocrdma_process_acqe(struct ocrdma_dev *dev, void *ae_cqe)
 {
        /* async CQE processing */
        struct ocrdma_ae_mcqe *cqe = ae_cqe;
        u32 evt_code = (cqe->valid_ae_event & OCRDMA_AE_MCQE_EVENT_CODE_MASK) >>
                        OCRDMA_AE_MCQE_EVENT_CODE_SHIFT;
-
-       if (evt_code == OCRDMA_ASYNC_RDMA_EVE_CODE)
+       switch (evt_code) {
+       case OCRDMA_ASYNC_LINK_EVE_CODE:
+               ocrdma_process_link_state(dev, cqe);
+               break;
+       case OCRDMA_ASYNC_RDMA_EVE_CODE:
                ocrdma_dispatch_ibevent(dev, cqe);
-       else if (evt_code == OCRDMA_ASYNC_GRP5_EVE_CODE)
+               break;
+       case OCRDMA_ASYNC_GRP5_EVE_CODE:
                ocrdma_process_grp5_aync(dev, cqe);
-       else
+               break;
+       default:
                pr_err("%s(%d) invalid evt code=0x%x\n", __func__,
                       dev->id, evt_code);
+       }
 }
 
 static void ocrdma_process_mcqe(struct ocrdma_dev *dev, struct ocrdma_mcqe *cqe)
@@ -1363,7 +1387,8 @@ mbx_err:
        return status;
 }
 
-int ocrdma_mbx_get_link_speed(struct ocrdma_dev *dev, u8 *lnk_speed)
+int ocrdma_mbx_get_link_speed(struct ocrdma_dev *dev, u8 *lnk_speed,
+                             u8 *lnk_state)
 {
        int status = -ENOMEM;
        struct ocrdma_get_link_speed_rsp *rsp;
@@ -1384,8 +1409,11 @@ int ocrdma_mbx_get_link_speed(struct ocrdma_dev *dev, u8 *lnk_speed)
                goto mbx_err;
 
        rsp = (struct ocrdma_get_link_speed_rsp *)cmd;
-       *lnk_speed = (rsp->pflt_pps_ld_pnum & OCRDMA_PHY_PS_MASK)
-                       >> OCRDMA_PHY_PS_SHIFT;
+       if (lnk_speed)
+               *lnk_speed = (rsp->pflt_pps_ld_pnum & OCRDMA_PHY_PS_MASK)
+                             >> OCRDMA_PHY_PS_SHIFT;
+       if (lnk_state)
+               *lnk_state = (rsp->res_lnk_st & OCRDMA_LINK_ST_MASK);
 
 mbx_err:
        kfree(cmd);
@@ -2515,9 +2543,10 @@ static int ocrdma_set_av_params(struct ocrdma_qp *qp,
        ocrdma_cpu_to_le32(&cmd->params.sgid[0], sizeof(cmd->params.sgid));
        cmd->params.vlan_dmac_b4_to_b5 = mac_addr[4] | (mac_addr[5] << 8);
 
-       if (vlan_id < 0x1000) {
-               if (dev->pfc_state) {
-                       vlan_id = 0;
+       if (vlan_id == 0xFFFF)
+               vlan_id = 0;
+       if (vlan_id || dev->pfc_state) {
+               if (!vlan_id) {
                        pr_err("ocrdma%d:Using VLAN with PFC is recommended\n",
                               dev->id);
                        pr_err("ocrdma%d:Using VLAN 0 for this connection\n",
index 7ed885c1851e28740b81a0588493c0d0ca92bc42..ebc1f442aec37aabd691d374deb3fdd41acc4302 100644 (file)
@@ -106,7 +106,8 @@ void ocrdma_ring_cq_db(struct ocrdma_dev *, u16 cq_id, bool armed,
                       bool solicited, u16 cqe_popped);
 
 /* verbs specific mailbox commands */
-int ocrdma_mbx_get_link_speed(struct ocrdma_dev *dev, u8 *lnk_speed);
+int ocrdma_mbx_get_link_speed(struct ocrdma_dev *dev, u8 *lnk_speed,
+                             u8 *lnk_st);
 int ocrdma_query_config(struct ocrdma_dev *,
                        struct ocrdma_mbx_query_config *config);
 
@@ -153,5 +154,6 @@ char *port_speed_string(struct ocrdma_dev *dev);
 void ocrdma_init_service_level(struct ocrdma_dev *);
 void ocrdma_alloc_pd_pool(struct ocrdma_dev *dev);
 void ocrdma_free_pd_range(struct ocrdma_dev *dev);
+void ocrdma_update_link_state(struct ocrdma_dev *dev, u8 lstate);
 
 #endif                         /* __OCRDMA_HW_H__ */
index 62b7009daa6c18a4d21002636637b5a2d258b231..3afb40b85159bd2c10559443536f83af5e4fa9ca 100644 (file)
@@ -290,6 +290,7 @@ static void ocrdma_remove_sysfiles(struct ocrdma_dev *dev)
 static struct ocrdma_dev *ocrdma_add(struct be_dev_info *dev_info)
 {
        int status = 0, i;
+       u8 lstate = 0;
        struct ocrdma_dev *dev;
 
        dev = (struct ocrdma_dev *)ib_alloc_device(sizeof(struct ocrdma_dev));
@@ -319,6 +320,11 @@ static struct ocrdma_dev *ocrdma_add(struct be_dev_info *dev_info)
        if (status)
                goto alloc_err;
 
+       /* Query Link state and update */
+       status = ocrdma_mbx_get_link_speed(dev, NULL, &lstate);
+       if (!status)
+               ocrdma_update_link_state(dev, lstate);
+
        for (i = 0; i < ARRAY_SIZE(ocrdma_attributes); i++)
                if (device_create_file(&dev->ibdev.dev, ocrdma_attributes[i]))
                        goto sysfs_err;
@@ -373,7 +379,7 @@ static void ocrdma_remove(struct ocrdma_dev *dev)
        ocrdma_remove_free(dev);
 }
 
-static int ocrdma_open(struct ocrdma_dev *dev)
+static int ocrdma_dispatch_port_active(struct ocrdma_dev *dev)
 {
        struct ib_event port_event;
 
@@ -384,32 +390,9 @@ static int ocrdma_open(struct ocrdma_dev *dev)
        return 0;
 }
 
-static int ocrdma_close(struct ocrdma_dev *dev)
+static int ocrdma_dispatch_port_error(struct ocrdma_dev *dev)
 {
-       int i;
-       struct ocrdma_qp *qp, **cur_qp;
        struct ib_event err_event;
-       struct ib_qp_attr attrs;
-       int attr_mask = IB_QP_STATE;
-
-       attrs.qp_state = IB_QPS_ERR;
-       mutex_lock(&dev->dev_lock);
-       if (dev->qp_tbl) {
-               cur_qp = dev->qp_tbl;
-               for (i = 0; i < OCRDMA_MAX_QP; i++) {
-                       qp = cur_qp[i];
-                       if (qp && qp->ibqp.qp_type != IB_QPT_GSI) {
-                               /* change the QP state to ERROR */
-                               _ocrdma_modify_qp(&qp->ibqp, &attrs, attr_mask);
-
-                               err_event.event = IB_EVENT_QP_FATAL;
-                               err_event.element.qp = &qp->ibqp;
-                               err_event.device = &dev->ibdev;
-                               ib_dispatch_event(&err_event);
-                       }
-               }
-       }
-       mutex_unlock(&dev->dev_lock);
 
        err_event.event = IB_EVENT_PORT_ERR;
        err_event.element.port_num = 1;
@@ -420,7 +403,7 @@ static int ocrdma_close(struct ocrdma_dev *dev)
 
 static void ocrdma_shutdown(struct ocrdma_dev *dev)
 {
-       ocrdma_close(dev);
+       ocrdma_dispatch_port_error(dev);
        ocrdma_remove(dev);
 }
 
@@ -431,18 +414,28 @@ static void ocrdma_shutdown(struct ocrdma_dev *dev)
 static void ocrdma_event_handler(struct ocrdma_dev *dev, u32 event)
 {
        switch (event) {
-       case BE_DEV_UP:
-               ocrdma_open(dev);
-               break;
-       case BE_DEV_DOWN:
-               ocrdma_close(dev);
-               break;
        case BE_DEV_SHUTDOWN:
                ocrdma_shutdown(dev);
                break;
+       default:
+               break;
        }
 }
 
+void ocrdma_update_link_state(struct ocrdma_dev *dev, u8 lstate)
+{
+       if (!(dev->flags & OCRDMA_FLAGS_LINK_STATUS_INIT)) {
+               dev->flags |= OCRDMA_FLAGS_LINK_STATUS_INIT;
+               if (!lstate)
+                       return;
+       }
+
+       if (!lstate)
+               ocrdma_dispatch_port_error(dev);
+       else
+               ocrdma_dispatch_port_active(dev);
+}
+
 static struct ocrdma_driver ocrdma_drv = {
        .name                   = "ocrdma_driver",
        .add                    = ocrdma_add,
index 6a38268bbe9fb6b981e27f2ec42da8fd10adbfc2..99dd6fdf06d7b44bcea2f0fb28b90edf54aefcc0 100644 (file)
@@ -465,8 +465,11 @@ struct ocrdma_ae_qp_mcqe {
        u32 valid_ae_event;
 };
 
-#define OCRDMA_ASYNC_RDMA_EVE_CODE 0x14
-#define OCRDMA_ASYNC_GRP5_EVE_CODE 0x5
+enum ocrdma_async_event_code {
+       OCRDMA_ASYNC_LINK_EVE_CODE      = 0x01,
+       OCRDMA_ASYNC_GRP5_EVE_CODE      = 0x05,
+       OCRDMA_ASYNC_RDMA_EVE_CODE      = 0x14
+};
 
 enum ocrdma_async_grp5_events {
        OCRDMA_ASYNC_EVENT_QOS_VALUE    = 0x01,
@@ -489,6 +492,44 @@ enum OCRDMA_ASYNC_EVENT_TYPE {
        OCRDMA_MAX_ASYNC_ERRORS
 };
 
+struct ocrdma_ae_lnkst_mcqe {
+       u32 speed_state_ptn;
+       u32 qos_reason_falut;
+       u32 evt_tag;
+       u32 valid_ae_event;
+};
+
+enum {
+       OCRDMA_AE_LSC_PORT_NUM_MASK     = 0x3F,
+       OCRDMA_AE_LSC_PT_SHIFT          = 0x06,
+       OCRDMA_AE_LSC_PT_MASK           = (0x03 <<
+                       OCRDMA_AE_LSC_PT_SHIFT),
+       OCRDMA_AE_LSC_LS_SHIFT          = 0x08,
+       OCRDMA_AE_LSC_LS_MASK           = (0xFF <<
+                       OCRDMA_AE_LSC_LS_SHIFT),
+       OCRDMA_AE_LSC_LD_SHIFT          = 0x10,
+       OCRDMA_AE_LSC_LD_MASK           = (0xFF <<
+                       OCRDMA_AE_LSC_LD_SHIFT),
+       OCRDMA_AE_LSC_PPS_SHIFT         = 0x18,
+       OCRDMA_AE_LSC_PPS_MASK          = (0xFF <<
+                       OCRDMA_AE_LSC_PPS_SHIFT),
+       OCRDMA_AE_LSC_PPF_MASK          = 0xFF,
+       OCRDMA_AE_LSC_ER_SHIFT          = 0x08,
+       OCRDMA_AE_LSC_ER_MASK           = (0xFF <<
+                       OCRDMA_AE_LSC_ER_SHIFT),
+       OCRDMA_AE_LSC_QOS_SHIFT         = 0x10,
+       OCRDMA_AE_LSC_QOS_MASK          = (0xFFFF <<
+                       OCRDMA_AE_LSC_QOS_SHIFT)
+};
+
+enum {
+       OCRDMA_AE_LSC_PLINK_DOWN        = 0x00,
+       OCRDMA_AE_LSC_PLINK_UP          = 0x01,
+       OCRDMA_AE_LSC_LLINK_DOWN        = 0x02,
+       OCRDMA_AE_LSC_LLINK_MASK        = 0x02,
+       OCRDMA_AE_LSC_LLINK_UP          = 0x03
+};
+
 /* mailbox command request and responses */
 enum {
        OCRDMA_MBX_QUERY_CFG_CQ_OVERFLOW_SHIFT          = 2,
@@ -676,7 +717,7 @@ enum {
        OCRDMA_PHY_PFLT_SHIFT   = 0x18,
        OCRDMA_QOS_LNKSP_MASK   = 0xFFFF0000,
        OCRDMA_QOS_LNKSP_SHIFT  = 0x10,
-       OCRDMA_LLST_MASK        = 0xFF,
+       OCRDMA_LINK_ST_MASK     = 0x01,
        OCRDMA_PLFC_MASK        = 0x00000400,
        OCRDMA_PLFC_SHIFT       = 0x8,
        OCRDMA_PLRFC_MASK       = 0x00000200,
@@ -691,7 +732,7 @@ struct ocrdma_get_link_speed_rsp {
 
        u32 pflt_pps_ld_pnum;
        u32 qos_lsp;
-       u32 res_lls;
+       u32 res_lnk_st;
 };
 
 enum {
index 583001bcfb8fc8c10a1e088b451d7de12adc2aa8..76e96f97b3f6459e68d13c444be6e1beb6b578a9 100644 (file)
@@ -171,7 +171,7 @@ static inline void get_link_speed_and_width(struct ocrdma_dev *dev,
        int status;
        u8 speed;
 
-       status = ocrdma_mbx_get_link_speed(dev, &speed);
+       status = ocrdma_mbx_get_link_speed(dev, &speed, NULL);
        if (status)
                speed = OCRDMA_PHYS_LINK_SPEED_ZERO;
 
index 5e27f76805e28af0c0e0acdc9864360f8cf09b41..4c7c3c84a7417c32f2f348f7c91c2ce0e4b4e1b0 100644 (file)
@@ -292,7 +292,7 @@ int qib_refresh_qsfp_cache(struct qib_pportdata *ppd, struct qib_qsfp_cache *cp)
                qib_dev_porterr(ppd->dd, ppd->port,
                                "QSFP byte0 is 0x%02X, S/B 0x0C/D\n", peek[0]);
 
-       if ((peek[2] & 2) == 0) {
+       if ((peek[2] & 4) == 0) {
                /*
                 * If cable is paged, rather than "flat memory", we need to
                 * set the page to zero, Even if it already appears to be zero.
@@ -538,7 +538,7 @@ int qib_qsfp_dump(struct qib_pportdata *ppd, char *buf, int len)
        sofar += scnprintf(buf + sofar, len - sofar, "Date:%.*s\n",
                           QSFP_DATE_LEN, cd.date);
        sofar += scnprintf(buf + sofar, len - sofar, "Lot:%.*s\n",
-                          QSFP_LOT_LEN, cd.date);
+                          QSFP_LOT_LEN, cd.lot);
 
        while (bidx < QSFP_DEFAULT_HDR_CNT) {
                int iidx;
index 2baf5ad251ed24a02682051058e6d1a406419e04..bc803f33d5f6883200ca21e462febebb94393cd4 100644 (file)
@@ -329,9 +329,9 @@ struct qib_sge {
 struct qib_mr {
        struct ib_mr ibmr;
        struct ib_umem *umem;
-       struct qib_mregion mr;  /* must be last */
        u64 *pages;
        u32 npages;
+       struct qib_mregion mr;  /* must be last */
 };
 
 /*
index a93070210109699909075e02212fc6ae70710960..42f4da620f2e9f97062b9183b6ebf3ed54e56cfe 100644 (file)
@@ -1293,7 +1293,7 @@ u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task,
                if (mr_status.fail_status & IB_MR_CHECK_SIG_STATUS) {
                        sector_t sector_off = mr_status.sig_err.sig_err_offset;
 
-                       do_div(sector_off, sector_size + 8);
+                       sector_div(sector_off, sector_size + 8);
                        *sector = scsi_get_lba(iser_task->sc) + sector_off;
 
                        pr_err("PI error found type %d at sector %llx "
index dfbbbb28090b2301c7742fd28b145b62054a76af..8a51c3b5d657e5a49ae50c4e5f104a7298d732f2 100644 (file)
@@ -157,16 +157,9 @@ isert_create_qp(struct isert_conn *isert_conn,
        attr.recv_cq = comp->cq;
        attr.cap.max_send_wr = ISERT_QP_MAX_REQ_DTOS;
        attr.cap.max_recv_wr = ISERT_QP_MAX_RECV_DTOS + 1;
-       /*
-        * FIXME: Use devattr.max_sge - 2 for max_send_sge as
-        * work-around for RDMA_READs with ConnectX-2.
-        *
-        * Also, still make sure to have at least two SGEs for
-        * outgoing control PDU responses.
-        */
-       attr.cap.max_send_sge = max(2, device->dev_attr.max_sge - 2);
-       isert_conn->max_sge = attr.cap.max_send_sge;
-
+       attr.cap.max_send_sge = device->dev_attr.max_sge;
+       isert_conn->max_sge = min(device->dev_attr.max_sge,
+                                 device->dev_attr.max_sge_rd);
        attr.cap.max_recv_sge = 1;
        attr.sq_sig_type = IB_SIGNAL_REQ_WR;
        attr.qp_type = IB_QPT_RC;
index 9909022dc6c3eebd4c52ef3e7dca5221dc8b6038..3db9a659719b0f6283af610bf01b8f65d27292a9 100644 (file)
@@ -488,7 +488,7 @@ static int srp_create_ch_ib(struct srp_rdma_ch *ch)
        struct ib_qp *qp;
        struct ib_fmr_pool *fmr_pool = NULL;
        struct srp_fr_pool *fr_pool = NULL;
-       const int m = 1 + dev->use_fast_reg;
+       const int m = dev->use_fast_reg ? 3 : 1;
        struct ib_cq_init_attr cq_attr = {};
        int ret;
 
@@ -994,16 +994,16 @@ static int srp_connect_ch(struct srp_rdma_ch *ch, bool multich)
 
        ret = srp_lookup_path(ch);
        if (ret)
-               return ret;
+               goto out;
 
        while (1) {
                init_completion(&ch->done);
                ret = srp_send_req(ch, multich);
                if (ret)
-                       return ret;
+                       goto out;
                ret = wait_for_completion_interruptible(&ch->done);
                if (ret < 0)
-                       return ret;
+                       goto out;
 
                /*
                 * The CM event handling code will set status to
@@ -1011,15 +1011,16 @@ static int srp_connect_ch(struct srp_rdma_ch *ch, bool multich)
                 * back, or SRP_DLID_REDIRECT if we get a lid/qp
                 * redirect REJ back.
                 */
-               switch (ch->status) {
+               ret = ch->status;
+               switch (ret) {
                case 0:
                        ch->connected = true;
-                       return 0;
+                       goto out;
 
                case SRP_PORT_REDIRECT:
                        ret = srp_lookup_path(ch);
                        if (ret)
-                               return ret;
+                               goto out;
                        break;
 
                case SRP_DLID_REDIRECT:
@@ -1028,13 +1029,16 @@ static int srp_connect_ch(struct srp_rdma_ch *ch, bool multich)
                case SRP_STALE_CONN:
                        shost_printk(KERN_ERR, target->scsi_host, PFX
                                     "giving up on stale connection\n");
-                       ch->status = -ECONNRESET;
-                       return ch->status;
+                       ret = -ECONNRESET;
+                       goto out;
 
                default:
-                       return ch->status;
+                       goto out;
                }
        }
+
+out:
+       return ret <= 0 ? ret : -ENODEV;
 }
 
 static int srp_inv_rkey(struct srp_rdma_ch *ch, u32 rkey)
@@ -1309,7 +1313,7 @@ reset_state:
 }
 
 static int srp_map_finish_fr(struct srp_map_state *state,
-                            struct srp_rdma_ch *ch)
+                            struct srp_rdma_ch *ch, int sg_nents)
 {
        struct srp_target_port *target = ch->target;
        struct srp_device *dev = target->srp_host->srp_dev;
@@ -1324,10 +1328,10 @@ static int srp_map_finish_fr(struct srp_map_state *state,
 
        WARN_ON_ONCE(!dev->use_fast_reg);
 
-       if (state->sg_nents == 0)
+       if (sg_nents == 0)
                return 0;
 
-       if (state->sg_nents == 1 && target->global_mr) {
+       if (sg_nents == 1 && target->global_mr) {
                srp_map_desc(state, sg_dma_address(state->sg),
                             sg_dma_len(state->sg),
                             target->global_mr->rkey);
@@ -1341,8 +1345,7 @@ static int srp_map_finish_fr(struct srp_map_state *state,
        rkey = ib_inc_rkey(desc->mr->rkey);
        ib_update_fast_reg_key(desc->mr, rkey);
 
-       n = ib_map_mr_sg(desc->mr, state->sg, state->sg_nents,
-                        dev->mr_page_size);
+       n = ib_map_mr_sg(desc->mr, state->sg, sg_nents, dev->mr_page_size);
        if (unlikely(n < 0))
                return n;
 
@@ -1448,16 +1451,15 @@ static int srp_map_sg_fr(struct srp_map_state *state, struct srp_rdma_ch *ch,
        state->fr.next = req->fr_list;
        state->fr.end = req->fr_list + ch->target->cmd_sg_cnt;
        state->sg = scat;
-       state->sg_nents = scsi_sg_count(req->scmnd);
 
-       while (state->sg_nents) {
+       while (count) {
                int i, n;
 
-               n = srp_map_finish_fr(state, ch);
+               n = srp_map_finish_fr(state, ch, count);
                if (unlikely(n < 0))
                        return n;
 
-               state->sg_nents -= n;
+               count -= n;
                for (i = 0; i < n; i++)
                        state->sg = sg_next(state->sg);
        }
@@ -1517,10 +1519,12 @@ static int srp_map_idb(struct srp_rdma_ch *ch, struct srp_request *req,
 
        if (dev->use_fast_reg) {
                state.sg = idb_sg;
-               state.sg_nents = 1;
                sg_set_buf(idb_sg, req->indirect_desc, idb_len);
                idb_sg->dma_address = req->indirect_dma_addr; /* hack! */
-               ret = srp_map_finish_fr(&state, ch);
+#ifdef CONFIG_NEED_SG_DMA_LENGTH
+               idb_sg->dma_length = idb_sg->length;          /* hack^2 */
+#endif
+               ret = srp_map_finish_fr(&state, ch, 1);
                if (ret < 0)
                        return ret;
        } else if (dev->use_fmr) {
@@ -1655,7 +1659,7 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_rdma_ch *ch,
                        return ret;
                req->nmdesc++;
        } else {
-               idb_rkey = target->global_mr->rkey;
+               idb_rkey = cpu_to_be32(target->global_mr->rkey);
        }
 
        indirect_hdr->table_desc.va = cpu_to_be64(req->indirect_dma_addr);
index 87a2a919dc43877141426e6d373d12727dc4b65e..f6af531f9f32c990cd30c7139d247c643144e55d 100644 (file)
@@ -300,10 +300,7 @@ struct srp_map_state {
        dma_addr_t              base_dma_addr;
        u32                     dma_len;
        u32                     total_len;
-       union {
-               unsigned int    npages;
-               int             sg_nents;
-       };
+       unsigned int            npages;
        unsigned int            nmdesc;
        unsigned int            ndesc;
 };
index 932d07307454bd47441da61ff06e3ef03ea93cd4..da326090c2b0e7f07ab4de5668012b1a4d5e92f3 100644 (file)
@@ -592,6 +592,7 @@ static void db9_attach(struct parport *pp)
                return;
        }
 
+       memset(&db9_parport_cb, 0, sizeof(db9_parport_cb));
        db9_parport_cb.flags = PARPORT_FLAG_EXCL;
 
        pd = parport_register_dev_model(pp, "db9", &db9_parport_cb, port_idx);
index 5a672dcac0d8174a151254ac31b591f0189f9d91..eae14d512353aae4902f3ce482c1cf87cba736b6 100644 (file)
@@ -951,6 +951,7 @@ static void gc_attach(struct parport *pp)
        pads = gc_cfg[port_idx].args + 1;
        n_pads = gc_cfg[port_idx].nargs - 1;
 
+       memset(&gc_parport_cb, 0, sizeof(gc_parport_cb));
        gc_parport_cb.flags = PARPORT_FLAG_EXCL;
 
        pd = parport_register_dev_model(pp, "gamecon", &gc_parport_cb,
index 9f5bca26bd2fb85a90ed4fd91bbdcf1a83e84162..77f575dd0901ff2732f47a62ebb7af37b826b608 100644 (file)
@@ -181,6 +181,7 @@ static void tgfx_attach(struct parport *pp)
        n_buttons = tgfx_cfg[port_idx].args + 1;
        n_devs = tgfx_cfg[port_idx].nargs - 1;
 
+       memset(&tgfx_parport_cb, 0, sizeof(tgfx_parport_cb));
        tgfx_parport_cb.flags = PARPORT_FLAG_EXCL;
 
        pd = parport_register_dev_model(pp, "turbografx", &tgfx_parport_cb,
index 9c07fe911075f3e1dba089f07d7d60d10ac327ba..70a893a17467608a103a81546eb7cce4cdf44010 100644 (file)
@@ -218,6 +218,7 @@ static void walkera0701_attach(struct parport *pp)
 
        w->parport = pp;
 
+       memset(&walkera0701_parport_cb, 0, sizeof(walkera0701_parport_cb));
        walkera0701_parport_cb.flags = PARPORT_FLAG_EXCL;
        walkera0701_parport_cb.irq_func = walkera0701_irq_handler;
        walkera0701_parport_cb.private = w;
index 4bf678541496e5971a3aa88cf9ded8e89558786a..d5994a745ffa5b5f4d1b411fec76f0a447a60f94 100644 (file)
@@ -97,8 +97,7 @@ static void arizona_haptics_work(struct work_struct *work)
 
                ret = regmap_update_bits(arizona->regmap,
                                         ARIZONA_HAPTICS_CONTROL_1,
-                                        ARIZONA_HAP_CTRL_MASK,
-                                        1 << ARIZONA_HAP_CTRL_SHIFT);
+                                        ARIZONA_HAP_CTRL_MASK, 0);
                if (ret != 0) {
                        dev_err(arizona->dev, "Failed to stop haptics: %d\n",
                                ret);
index 5e1665bbaa0baca86e2c865ba88162be2f209d2e..2f589857a0395d8c48f685f47bd1c9ceb8445213 100644 (file)
@@ -41,6 +41,7 @@
 
 #define DRIVER_NAME            "elan_i2c"
 #define ELAN_DRIVER_VERSION    "1.6.1"
+#define ELAN_VENDOR_ID         0x04f3
 #define ETP_MAX_PRESSURE       255
 #define ETP_FWIDTH_REDUCE      90
 #define ETP_FINGER_WIDTH       15
@@ -914,6 +915,8 @@ static int elan_setup_input_device(struct elan_tp_data *data)
 
        input->name = "Elan Touchpad";
        input->id.bustype = BUS_I2C;
+       input->id.vendor = ELAN_VENDOR_ID;
+       input->id.product = data->product_id;
        input_set_drvdata(input, data);
 
        error = input_mt_init_slots(input, ETP_MAX_FINGERS,
index 92c31b8f8fb489c317013f1cf77f133993fcc321..1edfac78d4ac742a8fe6d6183660c45652381804 100644 (file)
@@ -145,6 +145,7 @@ static int parkbd_getport(struct parport *pp)
 {
        struct pardev_cb parkbd_parport_cb;
 
+       memset(&parkbd_parport_cb, 0, sizeof(parkbd_parport_cb));
        parkbd_parport_cb.irq_func = parkbd_interrupt;
        parkbd_parport_cb.flags = PARPORT_FLAG_EXCL;
 
index e7f966da6efa318f1901ce912e4e0dd65b5c70f7..78ca44840d60cac1467c90cb563cedf2a05fcaab 100644 (file)
@@ -1819,6 +1819,14 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
        input_set_abs_params(inputdev, ABS_TILT_Y, AIPTEK_TILT_MIN, AIPTEK_TILT_MAX, 0, 0);
        input_set_abs_params(inputdev, ABS_WHEEL, AIPTEK_WHEEL_MIN, AIPTEK_WHEEL_MAX - 1, 0, 0);
 
+       /* Verify that a device really has an endpoint */
+       if (intf->altsetting[0].desc.bNumEndpoints < 1) {
+               dev_err(&intf->dev,
+                       "interface has %d endpoints, but must have minimum 1\n",
+                       intf->altsetting[0].desc.bNumEndpoints);
+               err = -EINVAL;
+               goto fail3;
+       }
        endpoint = &intf->altsetting[0].endpoint[0].desc;
 
        /* Go set up our URB, which is called when the tablet receives
@@ -1861,6 +1869,7 @@ aiptek_probe(struct usb_interface *intf, const struct usb_device_id *id)
        if (i == ARRAY_SIZE(speeds)) {
                dev_info(&intf->dev,
                         "Aiptek tried all speeds, no sane response\n");
+               err = -EINVAL;
                goto fail3;
        }
 
index c5622058c22bba77b14ed336b764dc7b1ac6c617..2d5794ec338b72a1cea0367bccdaf9654db025d4 100644 (file)
@@ -2487,6 +2487,31 @@ static struct mxt_acpi_platform_data samus_platform_data[] = {
        { }
 };
 
+static unsigned int chromebook_tp_buttons[] = {
+       KEY_RESERVED,
+       KEY_RESERVED,
+       KEY_RESERVED,
+       KEY_RESERVED,
+       KEY_RESERVED,
+       BTN_LEFT
+};
+
+static struct mxt_acpi_platform_data chromebook_platform_data[] = {
+       {
+               /* Touchpad */
+               .hid    = "ATML0000",
+               .pdata  = {
+                       .t19_num_keys   = ARRAY_SIZE(chromebook_tp_buttons),
+                       .t19_keymap     = chromebook_tp_buttons,
+               },
+       },
+       {
+               /* Touchscreen */
+               .hid    = "ATML0001",
+       },
+       { }
+};
+
 static const struct dmi_system_id mxt_dmi_table[] = {
        {
                /* 2015 Google Pixel */
@@ -2497,6 +2522,14 @@ static const struct dmi_system_id mxt_dmi_table[] = {
                },
                .driver_data = samus_platform_data,
        },
+       {
+               /* Other Google Chromebooks */
+               .ident = "Chromebook",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
+               },
+               .driver_data = chromebook_platform_data,
+       },
        { }
 };
 
@@ -2701,6 +2734,7 @@ static const struct i2c_device_id mxt_id[] = {
        { "qt602240_ts", 0 },
        { "atmel_mxt_ts", 0 },
        { "atmel_mxt_tp", 0 },
+       { "maxtouch", 0 },
        { "mXT224", 0 },
        { }
 };
index 17cc20ef4923bdb2fb2edcf770d7c303be9d6af5..ac09855fa435d7fc2d87fb801fb277bb55f086ba 100644 (file)
@@ -1316,7 +1316,13 @@ static int __maybe_unused elants_i2c_suspend(struct device *dev)
 
        disable_irq(client->irq);
 
-       if (device_may_wakeup(dev) || ts->keep_power_in_suspend) {
+       if (device_may_wakeup(dev)) {
+               /*
+                * The device will automatically enter idle mode
+                * that has reduced power consumption.
+                */
+               ts->wake_irq_enabled = (enable_irq_wake(client->irq) == 0);
+       } else if (ts->keep_power_in_suspend) {
                for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
                        error = elants_i2c_send(client, set_sleep_cmd,
                                                sizeof(set_sleep_cmd));
@@ -1326,10 +1332,6 @@ static int __maybe_unused elants_i2c_suspend(struct device *dev)
                        dev_err(&client->dev,
                                "suspend command failed: %d\n", error);
                }
-
-               if (device_may_wakeup(dev))
-                       ts->wake_irq_enabled =
-                                       (enable_irq_wake(client->irq) == 0);
        } else {
                elants_i2c_power_off(ts);
        }
@@ -1345,10 +1347,11 @@ static int __maybe_unused elants_i2c_resume(struct device *dev)
        int retry_cnt;
        int error;
 
-       if (device_may_wakeup(dev) && ts->wake_irq_enabled)
-               disable_irq_wake(client->irq);
-
-       if (ts->keep_power_in_suspend) {
+       if (device_may_wakeup(dev)) {
+               if (ts->wake_irq_enabled)
+                       disable_irq_wake(client->irq);
+               elants_i2c_sw_reset(client);
+       } else if (ts->keep_power_in_suspend) {
                for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
                        error = elants_i2c_send(client, set_active_cmd,
                                                sizeof(set_active_cmd));
index d21d4edf7236abac49072c086290b76d2ae201b5..7caf2fa237f22bd7a3b0932c6387ed52e0b26424 100644 (file)
@@ -494,6 +494,22 @@ static void handle_fault_error(struct fault *fault)
        }
 }
 
+static bool access_error(struct vm_area_struct *vma, struct fault *fault)
+{
+       unsigned long requested = 0;
+
+       if (fault->flags & PPR_FAULT_EXEC)
+               requested |= VM_EXEC;
+
+       if (fault->flags & PPR_FAULT_READ)
+               requested |= VM_READ;
+
+       if (fault->flags & PPR_FAULT_WRITE)
+               requested |= VM_WRITE;
+
+       return (requested & ~vma->vm_flags) != 0;
+}
+
 static void do_fault(struct work_struct *work)
 {
        struct fault *fault = container_of(work, struct fault, work);
@@ -516,8 +532,8 @@ static void do_fault(struct work_struct *work)
                goto out;
        }
 
-       if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) {
-               /* handle_mm_fault would BUG_ON() */
+       /* Check if we have the right permissions on the vma */
+       if (access_error(vma, fault)) {
                up_read(&mm->mmap_sem);
                handle_fault_error(fault);
                goto out;
index 3a20db4f8604f77d7bd374c9b9278f65a8c2cb5c..72d6182666cbd24ba785fc59572c655b6f0c2c8f 100644 (file)
 
 #include <linux/device.h>
 #include <linux/dma-iommu.h>
+#include <linux/gfp.h>
 #include <linux/huge_mm.h>
 #include <linux/iommu.h>
 #include <linux/iova.h>
 #include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/vmalloc.h>
 
 int iommu_dma_init(void)
 {
@@ -191,6 +194,7 @@ static struct page **__iommu_dma_alloc_pages(unsigned int count, gfp_t gfp)
 {
        struct page **pages;
        unsigned int i = 0, array_size = count * sizeof(*pages);
+       unsigned int order = MAX_ORDER;
 
        if (array_size <= PAGE_SIZE)
                pages = kzalloc(array_size, GFP_KERNEL);
@@ -204,14 +208,15 @@ static struct page **__iommu_dma_alloc_pages(unsigned int count, gfp_t gfp)
 
        while (count) {
                struct page *page = NULL;
-               int j, order = __fls(count);
+               int j;
 
                /*
                 * Higher-order allocations are a convenience rather
                 * than a necessity, hence using __GFP_NORETRY until
                 * falling back to single-page allocations.
                 */
-               for (order = min(order, MAX_ORDER); order > 0; order--) {
+               for (order = min_t(unsigned int, order, __fls(count));
+                    order > 0; order--) {
                        page = alloc_pages(gfp | __GFP_NORETRY, order);
                        if (!page)
                                continue;
@@ -453,7 +458,7 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
                size_t s_offset = iova_offset(iovad, s->offset);
                size_t s_length = s->length;
 
-               sg_dma_address(s) = s->offset;
+               sg_dma_address(s) = s_offset;
                sg_dma_len(s) = s_length;
                s->offset -= s_offset;
                s_length = iova_align(iovad, s_length + s_offset);
index f1042daef9ada83e931ae450623ce491ebd55959..ac7387686ddc7b2a7c7757f2cb3fbd003c8a23af 100644 (file)
@@ -2159,7 +2159,7 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
                        sg_res = aligned_nrpages(sg->offset, sg->length);
                        sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + sg->offset;
                        sg->dma_length = sg->length;
-                       pteval = (sg_phys(sg) & PAGE_MASK) | prot;
+                       pteval = page_to_phys(sg_page(sg)) | prot;
                        phys_pfn = pteval >> VTD_PAGE_SHIFT;
                }
 
@@ -3704,7 +3704,7 @@ static int intel_nontranslate_map_sg(struct device *hddev,
 
        for_each_sg(sglist, sg, nelems, i) {
                BUG_ON(!sg_page(sg));
-               sg->dma_address = sg_phys(sg);
+               sg->dma_address = page_to_phys(sg_page(sg)) + sg->offset;
                sg->dma_length = sg->length;
        }
        return nelems;
index c69e3f9ec9586bca0cd2ef712a3cf9fc25f4689f..50464833d0b84732a4d397cee8b73ed43a721712 100644 (file)
@@ -484,6 +484,23 @@ struct page_req_dsc {
 };
 
 #define PRQ_RING_MASK ((0x1000 << PRQ_ORDER) - 0x10)
+
+static bool access_error(struct vm_area_struct *vma, struct page_req_dsc *req)
+{
+       unsigned long requested = 0;
+
+       if (req->exe_req)
+               requested |= VM_EXEC;
+
+       if (req->rd_req)
+               requested |= VM_READ;
+
+       if (req->wr_req)
+               requested |= VM_WRITE;
+
+       return (requested & ~vma->vm_flags) != 0;
+}
+
 static irqreturn_t prq_event_thread(int irq, void *d)
 {
        struct intel_iommu *iommu = d;
@@ -539,6 +556,9 @@ static irqreturn_t prq_event_thread(int irq, void *d)
                if (!vma || address < vma->vm_start)
                        goto invalid;
 
+               if (access_error(vma, req))
+                       goto invalid;
+
                ret = handle_mm_fault(svm->mm, vma, address,
                                      req->wr_req ? FAULT_FLAG_WRITE : 0);
                if (ret & VM_FAULT_ERROR)
index abae363c7b9bd8932066e760beea7f76f22e7b8d..0e3b0092ec92c9d4d1dcb06e713edcf99c4a9293 100644 (file)
@@ -1430,7 +1430,7 @@ size_t default_iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
        min_pagesz = 1 << __ffs(domain->ops->pgsize_bitmap);
 
        for_each_sg(sg, s, nents, i) {
-               phys_addr_t phys = sg_phys(s);
+               phys_addr_t phys = page_to_phys(sg_page(s)) + s->offset;
 
                /*
                 * We are mapping on IOMMU page boundaries, so offset within
index 8cf605fa9946013642b2a88f500beb285cc55cfc..dfb868e2d129005d7a7401cea7c6109e7720559d 100644 (file)
@@ -295,7 +295,7 @@ static struct iommu_gather_ops ipmmu_gather_ops = {
 
 static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
 {
-       phys_addr_t ttbr;
+       u64 ttbr;
 
        /*
         * Allocate the page table operations.
index 598ab3f0e0ac54b79f1438c2193f8bc112949975..cadf104e30746b34d242eaa6e91637b8f99e5370 100644 (file)
@@ -210,7 +210,12 @@ int __init fpga_irq_of_init(struct device_node *node,
                parent_irq = -1;
        }
 
+#ifdef CONFIG_ARCH_VERSATILE
+       fpga_irq_init(base, node->name, IRQ_SIC_START, parent_irq, valid_mask,
+                                 node);
+#else
        fpga_irq_init(base, node->name, 0, parent_irq, valid_mask, node);
+#endif
 
        writel(clear_mask, base + IRQ_ENABLE_CLEAR);
        writel(clear_mask, base + FIQ_ENABLE_CLEAR);
index 375be509e95f5bd302da79446cb8867f8ecb8ec7..2a506fe0c8a4500a16e83b1aba70a6ed2d192185 100644 (file)
@@ -67,8 +67,7 @@ static int write_modem(struct cardstate *cs)
        struct sk_buff *skb = bcs->tx_skb;
        int sent = -EOPNOTSUPP;
 
-       if (!tty || !tty->driver || !skb)
-               return -EINVAL;
+       WARN_ON(!tty || !tty->ops || !skb);
 
        if (!skb->len) {
                dev_kfree_skb_any(skb);
@@ -109,8 +108,7 @@ static int send_cb(struct cardstate *cs)
        unsigned long flags;
        int sent = 0;
 
-       if (!tty || !tty->driver)
-               return -EFAULT;
+       WARN_ON(!tty || !tty->ops);
 
        cb = cs->cmdbuf;
        if (!cb)
@@ -370,19 +368,18 @@ static void gigaset_freecshw(struct cardstate *cs)
        tasklet_kill(&cs->write_tasklet);
        if (!cs->hw.ser)
                return;
-       dev_set_drvdata(&cs->hw.ser->dev.dev, NULL);
        platform_device_unregister(&cs->hw.ser->dev);
-       kfree(cs->hw.ser);
-       cs->hw.ser = NULL;
 }
 
 static void gigaset_device_release(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
+       struct cardstate *cs = dev_get_drvdata(dev);
 
-       /* adapted from platform_device_release() in drivers/base/platform.c */
-       kfree(dev->platform_data);
-       kfree(pdev->resource);
+       if (!cs)
+               return;
+       dev_set_drvdata(dev, NULL);
+       kfree(cs->hw.ser);
+       cs->hw.ser = NULL;
 }
 
 /*
@@ -432,7 +429,9 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state,
        struct tty_struct *tty = cs->hw.ser->tty;
        unsigned int set, clear;
 
-       if (!tty || !tty->driver || !tty->ops->tiocmset)
+       WARN_ON(!tty || !tty->ops);
+       /* tiocmset is an optional tty driver method */
+       if (!tty->ops->tiocmset)
                return -EINVAL;
        set = new_state & ~old_state;
        clear = old_state & ~new_state;
index a77eea594b695c59c96903bba4be80063eec1ad7..cb428b9ee441b83819b7d6d4f173b725ba67d360 100644 (file)
@@ -1170,7 +1170,7 @@ mISDNipac_irq(struct ipac_hw *ipac, int maxloop)
 
        if (ipac->type & IPAC_TYPE_IPACX) {
                ista = ReadIPAC(ipac, ISACX_ISTA);
-               while (ista && cnt--) {
+               while (ista && --cnt) {
                        pr_debug("%s: ISTA %02x\n", ipac->name, ista);
                        if (ista & IPACX__ICA)
                                ipac_irq(&ipac->hscx[0], ista);
@@ -1182,7 +1182,7 @@ mISDNipac_irq(struct ipac_hw *ipac, int maxloop)
                }
        } else if (ipac->type & IPAC_TYPE_IPAC) {
                ista = ReadIPAC(ipac, IPAC_ISTA);
-               while (ista && cnt--) {
+               while (ista && --cnt) {
                        pr_debug("%s: ISTA %02x\n", ipac->name, ista);
                        if (ista & (IPAC__ICD | IPAC__EXD)) {
                                istad = ReadISAC(isac, ISAC_ISTA);
@@ -1200,7 +1200,7 @@ mISDNipac_irq(struct ipac_hw *ipac, int maxloop)
                        ista = ReadIPAC(ipac, IPAC_ISTA);
                }
        } else if (ipac->type & IPAC_TYPE_HSCX) {
-               while (cnt) {
+               while (--cnt) {
                        ista = ReadIPAC(ipac, IPAC_ISTAB + ipac->hscx[1].off);
                        pr_debug("%s: B2 ISTA %02x\n", ipac->name, ista);
                        if (ista)
@@ -1211,7 +1211,6 @@ mISDNipac_irq(struct ipac_hw *ipac, int maxloop)
                                mISDNisac_irq(isac, istad);
                        if (0 == (ista | istad))
                                break;
-                       cnt--;
                }
        }
        if (cnt > maxloop) /* only for ISAC/HSCX without PCI IRQ test */
index a16bf56d3f283ece1cd204920ca84aff41eec915..85a339030e4b8ec4a85c46185e561576c47268db 100644 (file)
@@ -18,6 +18,7 @@ if NVM
 
 config NVM_DEBUG
        bool "Open-Channel SSD debugging support"
+       default n
        ---help---
        Exposes a debug management interface to create/remove targets at:
 
index 86ce887b2ed6ab16bfe079300f46652fada2af13..8f41b245cd55b55862911baaf2220d885fc30142 100644 (file)
@@ -74,7 +74,7 @@ EXPORT_SYMBOL(nvm_unregister_target);
 void *nvm_dev_dma_alloc(struct nvm_dev *dev, gfp_t mem_flags,
                                                        dma_addr_t *dma_handler)
 {
-       return dev->ops->dev_dma_alloc(dev->q, dev->ppalist_pool, mem_flags,
+       return dev->ops->dev_dma_alloc(dev, dev->ppalist_pool, mem_flags,
                                                                dma_handler);
 }
 EXPORT_SYMBOL(nvm_dev_dma_alloc);
@@ -97,15 +97,47 @@ static struct nvmm_type *nvm_find_mgr_type(const char *name)
        return NULL;
 }
 
+struct nvmm_type *nvm_init_mgr(struct nvm_dev *dev)
+{
+       struct nvmm_type *mt;
+       int ret;
+
+       lockdep_assert_held(&nvm_lock);
+
+       list_for_each_entry(mt, &nvm_mgrs, list) {
+               ret = mt->register_mgr(dev);
+               if (ret < 0) {
+                       pr_err("nvm: media mgr failed to init (%d) on dev %s\n",
+                                                               ret, dev->name);
+                       return NULL; /* initialization failed */
+               } else if (ret > 0)
+                       return mt;
+       }
+
+       return NULL;
+}
+
 int nvm_register_mgr(struct nvmm_type *mt)
 {
+       struct nvm_dev *dev;
        int ret = 0;
 
        down_write(&nvm_lock);
-       if (nvm_find_mgr_type(mt->name))
+       if (nvm_find_mgr_type(mt->name)) {
                ret = -EEXIST;
-       else
+               goto finish;
+       } else {
                list_add(&mt->list, &nvm_mgrs);
+       }
+
+       /* try to register media mgr if any device have none configured */
+       list_for_each_entry(dev, &nvm_devices, devices) {
+               if (dev->mt)
+                       continue;
+
+               dev->mt = nvm_init_mgr(dev);
+       }
+finish:
        up_write(&nvm_lock);
 
        return ret;
@@ -123,26 +155,6 @@ void nvm_unregister_mgr(struct nvmm_type *mt)
 }
 EXPORT_SYMBOL(nvm_unregister_mgr);
 
-/* register with device with a supported manager */
-static int register_mgr(struct nvm_dev *dev)
-{
-       struct nvmm_type *mt;
-       int ret = 0;
-
-       list_for_each_entry(mt, &nvm_mgrs, list) {
-               ret = mt->register_mgr(dev);
-               if (ret > 0) {
-                       dev->mt = mt;
-                       break; /* successfully initialized */
-               }
-       }
-
-       if (!ret)
-               pr_info("nvm: no compatible nvm manager found.\n");
-
-       return ret;
-}
-
 static struct nvm_dev *nvm_find_nvm_dev(const char *name)
 {
        struct nvm_dev *dev;
@@ -246,7 +258,7 @@ static int nvm_init(struct nvm_dev *dev)
        if (!dev->q || !dev->ops)
                return ret;
 
-       if (dev->ops->identity(dev->q, &dev->identity)) {
+       if (dev->ops->identity(dev, &dev->identity)) {
                pr_err("nvm: device could not be identified\n");
                goto err;
        }
@@ -271,14 +283,6 @@ static int nvm_init(struct nvm_dev *dev)
                goto err;
        }
 
-       down_write(&nvm_lock);
-       ret = register_mgr(dev);
-       up_write(&nvm_lock);
-       if (ret < 0)
-               goto err;
-       if (!ret)
-               return 0;
-
        pr_info("nvm: registered %s [%u/%u/%u/%u/%u/%u]\n",
                        dev->name, dev->sec_per_pg, dev->nr_planes,
                        dev->pgs_per_blk, dev->blks_per_lun, dev->nr_luns,
@@ -326,8 +330,7 @@ int nvm_register(struct request_queue *q, char *disk_name,
        }
 
        if (dev->ops->max_phys_sect > 1) {
-               dev->ppalist_pool = dev->ops->create_dma_pool(dev->q,
-                                                               "ppalist");
+               dev->ppalist_pool = dev->ops->create_dma_pool(dev, "ppalist");
                if (!dev->ppalist_pool) {
                        pr_err("nvm: could not create ppa pool\n");
                        ret = -ENOMEM;
@@ -335,7 +338,9 @@ int nvm_register(struct request_queue *q, char *disk_name,
                }
        }
 
+       /* register device with a supported media manager */
        down_write(&nvm_lock);
+       dev->mt = nvm_init_mgr(dev);
        list_add(&dev->devices, &nvm_devices);
        up_write(&nvm_lock);
 
@@ -380,19 +385,13 @@ static int nvm_create_target(struct nvm_dev *dev,
        struct nvm_tgt_type *tt;
        struct nvm_target *t;
        void *targetdata;
-       int ret = 0;
 
-       down_write(&nvm_lock);
        if (!dev->mt) {
-               ret = register_mgr(dev);
-               if (!ret)
-                       ret = -ENODEV;
-               if (ret < 0) {
-                       up_write(&nvm_lock);
-                       return ret;
-               }
+               pr_info("nvm: device has no media manager registered.\n");
+               return -ENODEV;
        }
 
+       down_write(&nvm_lock);
        tt = nvm_find_target_type(create->tgttype);
        if (!tt) {
                pr_err("nvm: target type %s not found\n", create->tgttype);
index 35dde84b71e97a6e530c2058ca0b68cf574424b2..a54b339951a3e695bfa68e96fb6eaf2e3e451c62 100644 (file)
@@ -75,7 +75,7 @@ static int gennvm_block_bb(struct ppa_addr ppa, int nr_blocks, u8 *blks,
        struct nvm_block *blk;
        int i;
 
-       lun = &gn->luns[(dev->nr_luns * ppa.g.ch) + ppa.g.lun];
+       lun = &gn->luns[(dev->luns_per_chnl * ppa.g.ch) + ppa.g.lun];
 
        for (i = 0; i < nr_blocks; i++) {
                if (blks[i] == 0)
@@ -195,7 +195,7 @@ static int gennvm_blocks_init(struct nvm_dev *dev, struct gen_nvm *gn)
        }
 
        if (dev->ops->get_l2p_tbl) {
-               ret = dev->ops->get_l2p_tbl(dev->q, 0, dev->total_pages,
+               ret = dev->ops->get_l2p_tbl(dev, 0, dev->total_pages,
                                                        gennvm_block_map, dev);
                if (ret) {
                        pr_err("gennvm: could not read L2P table.\n");
@@ -219,6 +219,9 @@ static int gennvm_register(struct nvm_dev *dev)
        struct gen_nvm *gn;
        int ret;
 
+       if (!try_module_get(THIS_MODULE))
+               return -ENODEV;
+
        gn = kzalloc(sizeof(struct gen_nvm), GFP_KERNEL);
        if (!gn)
                return -ENOMEM;
@@ -242,12 +245,14 @@ static int gennvm_register(struct nvm_dev *dev)
        return 1;
 err:
        gennvm_free(dev);
+       module_put(THIS_MODULE);
        return ret;
 }
 
 static void gennvm_unregister(struct nvm_dev *dev)
 {
        gennvm_free(dev);
+       module_put(THIS_MODULE);
 }
 
 static struct nvm_block *gennvm_get_blk(struct nvm_dev *dev,
@@ -262,14 +267,11 @@ static struct nvm_block *gennvm_get_blk(struct nvm_dev *dev,
        if (list_empty(&lun->free_list)) {
                pr_err_ratelimited("gennvm: lun %u have no free pages available",
                                                                lun->vlun.id);
-               spin_unlock(&vlun->lock);
                goto out;
        }
 
-       while (!is_gc && lun->vlun.nr_free_blocks < lun->reserved_blocks) {
-               spin_unlock(&vlun->lock);
+       if (!is_gc && lun->vlun.nr_free_blocks < lun->reserved_blocks)
                goto out;
-       }
 
        blk = list_first_entry(&lun->free_list, struct nvm_block, list);
        list_move_tail(&blk->list, &lun->used_list);
@@ -278,8 +280,8 @@ static struct nvm_block *gennvm_get_blk(struct nvm_dev *dev,
        lun->vlun.nr_free_blocks--;
        lun->vlun.nr_inuse_blocks++;
 
-       spin_unlock(&vlun->lock);
 out:
+       spin_unlock(&vlun->lock);
        return blk;
 }
 
@@ -349,7 +351,7 @@ static int gennvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
        gennvm_generic_to_addr_mode(dev, rqd);
 
        rqd->dev = dev;
-       return dev->ops->submit_io(dev->q, rqd);
+       return dev->ops->submit_io(dev, rqd);
 }
 
 static void gennvm_blk_set_type(struct nvm_dev *dev, struct ppa_addr *ppa,
@@ -385,7 +387,7 @@ static void gennvm_mark_blk_bad(struct nvm_dev *dev, struct nvm_rq *rqd)
        if (!dev->ops->set_bb_tbl)
                return;
 
-       if (dev->ops->set_bb_tbl(dev->q, rqd, 1))
+       if (dev->ops->set_bb_tbl(dev, rqd, 1))
                return;
 
        gennvm_addr_to_generic_mode(dev, rqd);
@@ -453,7 +455,7 @@ static int gennvm_erase_blk(struct nvm_dev *dev, struct nvm_block *blk,
 
        gennvm_generic_to_addr_mode(dev, &rqd);
 
-       ret = dev->ops->erase_block(dev->q, &rqd);
+       ret = dev->ops->erase_block(dev, &rqd);
 
        if (plane_cnt)
                nvm_dev_dma_free(dev, rqd.ppa_list, rqd.dma_ppa_list);
index 75e59c3a3f96d821d93600f2ca698a50e2874182..134e4faba48259434db7d55d446f40f3deb206b9 100644 (file)
@@ -182,7 +182,7 @@ static struct rrpc_block *rrpc_get_blk(struct rrpc *rrpc, struct rrpc_lun *rlun,
        struct nvm_block *blk;
        struct rrpc_block *rblk;
 
-       blk = nvm_get_blk(rrpc->dev, rlun->parent, 0);
+       blk = nvm_get_blk(rrpc->dev, rlun->parent, flags);
        if (!blk)
                return NULL;
 
@@ -202,6 +202,20 @@ static void rrpc_put_blk(struct rrpc *rrpc, struct rrpc_block *rblk)
        nvm_put_blk(rrpc->dev, rblk->parent);
 }
 
+static void rrpc_put_blks(struct rrpc *rrpc)
+{
+       struct rrpc_lun *rlun;
+       int i;
+
+       for (i = 0; i < rrpc->nr_luns; i++) {
+               rlun = &rrpc->luns[i];
+               if (rlun->cur)
+                       rrpc_put_blk(rrpc, rlun->cur);
+               if (rlun->gc_cur)
+                       rrpc_put_blk(rrpc, rlun->gc_cur);
+       }
+}
+
 static struct rrpc_lun *get_next_lun(struct rrpc *rrpc)
 {
        int next = atomic_inc_return(&rrpc->next_lun);
@@ -1002,7 +1016,7 @@ static int rrpc_map_init(struct rrpc *rrpc)
                return 0;
 
        /* Bring up the mapping table from device */
-       ret = dev->ops->get_l2p_tbl(dev->q, 0, dev->total_pages,
+       ret = dev->ops->get_l2p_tbl(dev, 0, dev->total_pages,
                                                        rrpc_l2p_update, rrpc);
        if (ret) {
                pr_err("nvm: rrpc: could not read L2P table.\n");
@@ -1224,18 +1238,21 @@ static int rrpc_luns_configure(struct rrpc *rrpc)
 
                rblk = rrpc_get_blk(rrpc, rlun, 0);
                if (!rblk)
-                       return -EINVAL;
+                       goto err;
 
                rrpc_set_lun_cur(rlun, rblk);
 
                /* Emergency gc block */
                rblk = rrpc_get_blk(rrpc, rlun, 1);
                if (!rblk)
-                       return -EINVAL;
+                       goto err;
                rlun->gc_cur = rblk;
        }
 
        return 0;
+err:
+       rrpc_put_blks(rrpc);
+       return -EINVAL;
 }
 
 static struct nvm_tgt_type tt_rrpc;
index 1fa45695b68a4eb6ed3db388d30f6e88f06fee21..c219a053c7f66d1ebae80a19b005af38914dbe8c 100644 (file)
@@ -1206,6 +1206,12 @@ static int __reserve_metadata_snap(struct dm_pool_metadata *pmd)
        struct dm_block *copy, *sblock;
        dm_block_t held_root;
 
+       /*
+        * We commit to ensure the btree roots which we increment in a
+        * moment are up to date.
+        */
+       __commit_transaction(pmd);
+
        /*
         * Copy the superblock.
         */
@@ -1538,7 +1544,7 @@ static int __remove(struct dm_thin_device *td, dm_block_t block)
 static int __remove_range(struct dm_thin_device *td, dm_block_t begin, dm_block_t end)
 {
        int r;
-       unsigned count;
+       unsigned count, total_count = 0;
        struct dm_pool_metadata *pmd = td->pmd;
        dm_block_t keys[1] = { td->id };
        __le64 value;
@@ -1561,11 +1567,29 @@ static int __remove_range(struct dm_thin_device *td, dm_block_t begin, dm_block_
        if (r)
                return r;
 
-       r = dm_btree_remove_leaves(&pmd->bl_info, mapping_root, &begin, end, &mapping_root, &count);
-       if (r)
-               return r;
+       /*
+        * Remove leaves stops at the first unmapped entry, so we have to
+        * loop round finding mapped ranges.
+        */
+       while (begin < end) {
+               r = dm_btree_lookup_next(&pmd->bl_info, mapping_root, &begin, &begin, &value);
+               if (r == -ENODATA)
+                       break;
+
+               if (r)
+                       return r;
+
+               if (begin >= end)
+                       break;
+
+               r = dm_btree_remove_leaves(&pmd->bl_info, mapping_root, &begin, end, &mapping_root, &count);
+               if (r)
+                       return r;
+
+               total_count += count;
+       }
 
-       td->mapped_blocks -= count;
+       td->mapped_blocks -= total_count;
        td->changed = 1;
 
        /*
index 807095f4c793bb4f1d4119f81abf2653b83240cb..61aacab424cf1860dbb5651f5a4fc6c9f7188027 100644 (file)
@@ -314,8 +314,8 @@ static blk_qc_t md_make_request(struct request_queue *q, struct bio *bio)
  */
 void mddev_suspend(struct mddev *mddev)
 {
-       BUG_ON(mddev->suspended);
-       mddev->suspended = 1;
+       if (mddev->suspended++)
+               return;
        synchronize_rcu();
        wait_event(mddev->sb_wait, atomic_read(&mddev->active_io) == 0);
        mddev->pers->quiesce(mddev, 1);
@@ -326,7 +326,8 @@ EXPORT_SYMBOL_GPL(mddev_suspend);
 
 void mddev_resume(struct mddev *mddev)
 {
-       mddev->suspended = 0;
+       if (--mddev->suspended)
+               return;
        wake_up(&mddev->sb_wait);
        mddev->pers->quiesce(mddev, 0);
 
@@ -1652,7 +1653,7 @@ static int super_1_validate(struct mddev *mddev, struct md_rdev *rdev)
                        rdev->journal_tail = le64_to_cpu(sb->journal_tail);
                        if (mddev->recovery_cp == MaxSector)
                                set_bit(MD_JOURNAL_CLEAN, &mddev->flags);
-                       rdev->raid_disk = mddev->raid_disks;
+                       rdev->raid_disk = 0;
                        break;
                default:
                        rdev->saved_raid_disk = role;
@@ -2773,6 +2774,7 @@ slot_store(struct md_rdev *rdev, const char *buf, size_t len)
                /* Activating a spare .. or possibly reactivating
                 * if we ever get bitmaps working here.
                 */
+               int err;
 
                if (rdev->raid_disk != -1)
                        return -EBUSY;
@@ -2794,9 +2796,15 @@ slot_store(struct md_rdev *rdev, const char *buf, size_t len)
                        rdev->saved_raid_disk = -1;
                clear_bit(In_sync, &rdev->flags);
                clear_bit(Bitmap_sync, &rdev->flags);
-               remove_and_add_spares(rdev->mddev, rdev);
-               if (rdev->raid_disk == -1)
-                       return -EBUSY;
+               err = rdev->mddev->pers->
+                       hot_add_disk(rdev->mddev, rdev);
+               if (err) {
+                       rdev->raid_disk = -1;
+                       return err;
+               } else
+                       sysfs_notify_dirent_safe(rdev->sysfs_state);
+               if (sysfs_link_rdev(rdev->mddev, rdev))
+                       /* failure here is OK */;
                /* don't wakeup anyone, leave that to userspace. */
        } else {
                if (slot >= rdev->mddev->raid_disks &&
@@ -4318,8 +4326,7 @@ action_store(struct mddev *mddev, const char *page, size_t len)
                        }
                        mddev_unlock(mddev);
                }
-       } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
-                  test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
+       } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
                return -EBUSY;
        else if (cmd_match(page, "resync"))
                clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
@@ -4332,8 +4339,12 @@ action_store(struct mddev *mddev, const char *page, size_t len)
                        return -EINVAL;
                err = mddev_lock(mddev);
                if (!err) {
-                       clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
-                       err = mddev->pers->start_reshape(mddev);
+                       if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
+                               err =  -EBUSY;
+                       else {
+                               clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+                               err = mddev->pers->start_reshape(mddev);
+                       }
                        mddev_unlock(mddev);
                }
                if (err)
index 2bea51edfab707645a6d6b8a5b6c79bb0c6dde64..ca0b643fe3c18070b417a66daedb571457b440ca 100644 (file)
@@ -566,7 +566,9 @@ static inline char * mdname (struct mddev * mddev)
 static inline int sysfs_link_rdev(struct mddev *mddev, struct md_rdev *rdev)
 {
        char nm[20];
-       if (!test_bit(Replacement, &rdev->flags) && mddev->kobj.sd) {
+       if (!test_bit(Replacement, &rdev->flags) &&
+           !test_bit(Journal, &rdev->flags) &&
+           mddev->kobj.sd) {
                sprintf(nm, "rd%d", rdev->raid_disk);
                return sysfs_create_link(&mddev->kobj, &rdev->kobj, nm);
        } else
@@ -576,7 +578,9 @@ static inline int sysfs_link_rdev(struct mddev *mddev, struct md_rdev *rdev)
 static inline void sysfs_unlink_rdev(struct mddev *mddev, struct md_rdev *rdev)
 {
        char nm[20];
-       if (!test_bit(Replacement, &rdev->flags) && mddev->kobj.sd) {
+       if (!test_bit(Replacement, &rdev->flags) &&
+           !test_bit(Journal, &rdev->flags) &&
+           mddev->kobj.sd) {
                sprintf(nm, "rd%d", rdev->raid_disk);
                sysfs_remove_link(&mddev->kobj, nm);
        }
index c573402033b2dd9e89dc11ad2f6e1b7e8bbb4263..b1ced58eb5e1475b440a15de0e26811fb90b8159 100644 (file)
@@ -63,6 +63,11 @@ int lower_bound(struct btree_node *n, uint64_t key)
        return bsearch(n, key, 0);
 }
 
+static int upper_bound(struct btree_node *n, uint64_t key)
+{
+       return bsearch(n, key, 1);
+}
+
 void inc_children(struct dm_transaction_manager *tm, struct btree_node *n,
                  struct dm_btree_value_type *vt)
 {
@@ -252,6 +257,16 @@ static void pop_frame(struct del_stack *s)
        dm_tm_unlock(s->tm, f->b);
 }
 
+static void unlock_all_frames(struct del_stack *s)
+{
+       struct frame *f;
+
+       while (unprocessed_frames(s)) {
+               f = s->spine + s->top--;
+               dm_tm_unlock(s->tm, f->b);
+       }
+}
+
 int dm_btree_del(struct dm_btree_info *info, dm_block_t root)
 {
        int r;
@@ -308,9 +323,13 @@ int dm_btree_del(struct dm_btree_info *info, dm_block_t root)
                        pop_frame(s);
                }
        }
-
 out:
+       if (r) {
+               /* cleanup all frames of del_stack */
+               unlock_all_frames(s);
+       }
        kfree(s);
+
        return r;
 }
 EXPORT_SYMBOL_GPL(dm_btree_del);
@@ -392,6 +411,82 @@ int dm_btree_lookup(struct dm_btree_info *info, dm_block_t root,
 }
 EXPORT_SYMBOL_GPL(dm_btree_lookup);
 
+static int dm_btree_lookup_next_single(struct dm_btree_info *info, dm_block_t root,
+                                      uint64_t key, uint64_t *rkey, void *value_le)
+{
+       int r, i;
+       uint32_t flags, nr_entries;
+       struct dm_block *node;
+       struct btree_node *n;
+
+       r = bn_read_lock(info, root, &node);
+       if (r)
+               return r;
+
+       n = dm_block_data(node);
+       flags = le32_to_cpu(n->header.flags);
+       nr_entries = le32_to_cpu(n->header.nr_entries);
+
+       if (flags & INTERNAL_NODE) {
+               i = lower_bound(n, key);
+               if (i < 0 || i >= nr_entries) {
+                       r = -ENODATA;
+                       goto out;
+               }
+
+               r = dm_btree_lookup_next_single(info, value64(n, i), key, rkey, value_le);
+               if (r == -ENODATA && i < (nr_entries - 1)) {
+                       i++;
+                       r = dm_btree_lookup_next_single(info, value64(n, i), key, rkey, value_le);
+               }
+
+       } else {
+               i = upper_bound(n, key);
+               if (i < 0 || i >= nr_entries) {
+                       r = -ENODATA;
+                       goto out;
+               }
+
+               *rkey = le64_to_cpu(n->keys[i]);
+               memcpy(value_le, value_ptr(n, i), info->value_type.size);
+       }
+out:
+       dm_tm_unlock(info->tm, node);
+       return r;
+}
+
+int dm_btree_lookup_next(struct dm_btree_info *info, dm_block_t root,
+                        uint64_t *keys, uint64_t *rkey, void *value_le)
+{
+       unsigned level;
+       int r = -ENODATA;
+       __le64 internal_value_le;
+       struct ro_spine spine;
+
+       init_ro_spine(&spine, info);
+       for (level = 0; level < info->levels - 1u; level++) {
+               r = btree_lookup_raw(&spine, root, keys[level],
+                                    lower_bound, rkey,
+                                    &internal_value_le, sizeof(uint64_t));
+               if (r)
+                       goto out;
+
+               if (*rkey != keys[level]) {
+                       r = -ENODATA;
+                       goto out;
+               }
+
+               root = le64_to_cpu(internal_value_le);
+       }
+
+       r = dm_btree_lookup_next_single(info, root, keys[level], rkey, value_le);
+out:
+       exit_ro_spine(&spine);
+       return r;
+}
+
+EXPORT_SYMBOL_GPL(dm_btree_lookup_next);
+
 /*
  * Splits a node by creating a sibling node and shifting half the nodes
  * contents across.  Assumes there is a parent node, and it has room for
@@ -473,8 +568,10 @@ static int btree_split_sibling(struct shadow_spine *s, unsigned parent_index,
 
        r = insert_at(sizeof(__le64), pn, parent_index + 1,
                      le64_to_cpu(rn->keys[0]), &location);
-       if (r)
+       if (r) {
+               unlock_block(s->info, right);
                return r;
+       }
 
        if (key < le64_to_cpu(rn->keys[0])) {
                unlock_block(s->info, right);
index 11d8cf78621dded80328187e1009ca0dc35c6997..c74301fa5a379517b9c37e7e98ab380d97f3b9b0 100644 (file)
@@ -109,6 +109,13 @@ int dm_btree_del(struct dm_btree_info *info, dm_block_t root);
 int dm_btree_lookup(struct dm_btree_info *info, dm_block_t root,
                    uint64_t *keys, void *value_le);
 
+/*
+ * Tries to find the first key where the bottom level key is >= to that
+ * given.  Useful for skipping empty sections of the btree.
+ */
+int dm_btree_lookup_next(struct dm_btree_info *info, dm_block_t root,
+                        uint64_t *keys, uint64_t *rkey, void *value_le);
+
 /*
  * Insertion (or overwrite an existing value).  O(ln(n))
  */
@@ -135,9 +142,10 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
                    uint64_t *keys, dm_block_t *new_root);
 
 /*
- * Removes values between 'keys' and keys2, where keys2 is keys with the
- * final key replaced with 'end_key'.  'end_key' is the one-past-the-end
- * value.  'keys' may be altered.
+ * Removes a _contiguous_ run of values starting from 'keys' and not
+ * reaching keys2 (where keys2 is keys with the final key replaced with
+ * 'end_key').  'end_key' is the one-past-the-end value.  'keys' may be
+ * altered.
  */
 int dm_btree_remove_leaves(struct dm_btree_info *info, dm_block_t root,
                           uint64_t *keys, uint64_t end_key,
index 53091295fce9b7d9ffec9b91a6a0bdddd20ed67f..fca6dbcf9a4727f85d61f7d161094870f5db24d5 100644 (file)
@@ -136,7 +136,7 @@ static int brb_push(struct bop_ring_buffer *brb,
        return 0;
 }
 
-static int brb_pop(struct bop_ring_buffer *brb, struct block_op *result)
+static int brb_peek(struct bop_ring_buffer *brb, struct block_op *result)
 {
        struct block_op *bop;
 
@@ -147,6 +147,17 @@ static int brb_pop(struct bop_ring_buffer *brb, struct block_op *result)
        result->type = bop->type;
        result->block = bop->block;
 
+       return 0;
+}
+
+static int brb_pop(struct bop_ring_buffer *brb)
+{
+       struct block_op *bop;
+
+       if (brb_empty(brb))
+               return -ENODATA;
+
+       bop = brb->bops + brb->begin;
        brb->begin = brb_next(brb, brb->begin);
 
        return 0;
@@ -211,7 +222,7 @@ static int apply_bops(struct sm_metadata *smm)
        while (!brb_empty(&smm->uncommitted)) {
                struct block_op bop;
 
-               r = brb_pop(&smm->uncommitted, &bop);
+               r = brb_peek(&smm->uncommitted, &bop);
                if (r) {
                        DMERR("bug in bop ring buffer");
                        break;
@@ -220,6 +231,8 @@ static int apply_bops(struct sm_metadata *smm)
                r = commit_bop(smm, &bop);
                if (r)
                        break;
+
+               brb_pop(&smm->uncommitted);
        }
 
        return r;
@@ -683,7 +696,6 @@ static struct dm_space_map bootstrap_ops = {
 static int sm_metadata_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
 {
        int r, i;
-       enum allocation_event ev;
        struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
        dm_block_t old_len = smm->ll.nr_blocks;
 
@@ -705,11 +717,12 @@ static int sm_metadata_extend(struct dm_space_map *sm, dm_block_t extra_blocks)
         * allocate any new blocks.
         */
        do {
-               for (i = old_len; !r && i < smm->begin; i++) {
-                       r = sm_ll_inc(&smm->ll, i, &ev);
-                       if (r)
-                               goto out;
-               }
+               for (i = old_len; !r && i < smm->begin; i++)
+                       r = add_bop(smm, BOP_INC, i);
+
+               if (r)
+                       goto out;
+
                old_len = smm->begin;
 
                r = apply_bops(smm);
@@ -754,7 +767,6 @@ int dm_sm_metadata_create(struct dm_space_map *sm,
 {
        int r;
        dm_block_t i;
-       enum allocation_event ev;
        struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm);
 
        smm->begin = superblock + 1;
@@ -782,7 +794,7 @@ int dm_sm_metadata_create(struct dm_space_map *sm,
         * allocated blocks that they were built from.
         */
        for (i = superblock; !r && i < smm->begin; i++)
-               r = sm_ll_inc(&smm->ll, i, &ev);
+               r = add_bop(smm, BOP_INC, i);
 
        if (r)
                return r;
index 41d70bc9ba2f879a2549868861afb74471140525..84e597e1c4890cd911243c511d1a65e39232e98e 100644 (file)
@@ -1946,6 +1946,8 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
 
        first = i;
        fbio = r10_bio->devs[i].bio;
+       fbio->bi_iter.bi_size = r10_bio->sectors << 9;
+       fbio->bi_iter.bi_idx = 0;
 
        vcnt = (r10_bio->sectors + (PAGE_SIZE >> 9) - 1) >> (PAGE_SHIFT - 9);
        /* now find blocks with errors */
@@ -1989,7 +1991,7 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio)
                bio_reset(tbio);
 
                tbio->bi_vcnt = vcnt;
-               tbio->bi_iter.bi_size = r10_bio->sectors << 9;
+               tbio->bi_iter.bi_size = fbio->bi_iter.bi_size;
                tbio->bi_rw = WRITE;
                tbio->bi_private = r10_bio;
                tbio->bi_iter.bi_sector = r10_bio->devs[i].addr;
index 8616fa8193bca06bb806dc48b14d4e7dc6e21aef..c2e60b4f292d1d8d9791b5c44b0fa76c0ffd854b 100644 (file)
@@ -805,11 +805,11 @@ static void ivtv_init_struct2(struct ivtv *itv)
 {
        int i;
 
-       for (i = 0; i < IVTV_CARD_MAX_VIDEO_INPUTS - 1; i++)
+       for (i = 0; i < IVTV_CARD_MAX_VIDEO_INPUTS; i++)
                if (itv->card->video_inputs[i].video_type == 0)
                        break;
        itv->nof_inputs = i;
-       for (i = 0; i < IVTV_CARD_MAX_AUDIO_INPUTS - 1; i++)
+       for (i = 0; i < IVTV_CARD_MAX_AUDIO_INPUTS; i++)
                if (itv->card->audio_inputs[i].audio_type == 0)
                        break;
        itv->nof_audio_inputs = i;
index fcbb49757614487aa0a88e2740bc0dcd4ff73236..565a59310747680858bb2bf30543e05becd579a0 100644 (file)
@@ -134,7 +134,7 @@ struct airspy {
        int            urbs_submitted;
 
        /* USB control message buffer */
-       #define BUF_SIZE 24
+       #define BUF_SIZE 128
        u8 buf[BUF_SIZE];
 
        /* Current configuration */
index e05bfec90f4608b0d8ebce199351dfe89db11994..0fe5cb2c260c2f771484d99bf25809cc23943ffb 100644 (file)
 #include <media/videobuf2-v4l2.h>
 #include <media/videobuf2-vmalloc.h>
 
+/*
+ * Used Avago MGA-81563 RF amplifier could be destroyed pretty easily with too
+ * strong signal or transmitting to bad antenna.
+ * Set RF gain control to 'grabbed' state by default for sure.
+ */
+static bool hackrf_enable_rf_gain_ctrl;
+module_param_named(enable_rf_gain_ctrl, hackrf_enable_rf_gain_ctrl, bool, 0644);
+MODULE_PARM_DESC(enable_rf_gain_ctrl, "enable RX/TX RF amplifier control (warn: could damage amplifier)");
+
 /* HackRF USB API commands (from HackRF Library) */
 enum {
        CMD_SET_TRANSCEIVER_MODE           = 0x01,
@@ -1451,6 +1460,7 @@ static int hackrf_probe(struct usb_interface *intf,
                dev_err(dev->dev, "Could not initialize controls\n");
                goto err_v4l2_ctrl_handler_free_rx;
        }
+       v4l2_ctrl_grab(dev->rx_rf_gain, !hackrf_enable_rf_gain_ctrl);
        v4l2_ctrl_handler_setup(&dev->rx_ctrl_handler);
 
        /* Register controls for transmitter */
@@ -1471,6 +1481,7 @@ static int hackrf_probe(struct usb_interface *intf,
                dev_err(dev->dev, "Could not initialize controls\n");
                goto err_v4l2_ctrl_handler_free_tx;
        }
+       v4l2_ctrl_grab(dev->tx_rf_gain, !hackrf_enable_rf_gain_ctrl);
        v4l2_ctrl_handler_setup(&dev->tx_ctrl_handler);
 
        /* Register the v4l2_device structure */
@@ -1530,7 +1541,7 @@ err_v4l2_ctrl_handler_free_rx:
 err_kfree:
        kfree(dev);
 err:
-       dev_dbg(dev->dev, "failed=%d\n", ret);
+       dev_dbg(&intf->dev, "failed=%d\n", ret);
        return ret;
 }
 
index e87459f6d686d011d6d11f902b78053f083e1b7a..acd1460cf7871c4ef4cffb0f0e196f41083aae36 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/compiler.h>
+#include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/slab.h>
index d2e75c88f4d2165762913c27c57e5d4487e431ad..f4090979349068b3057d0cd9d8a17d15168ce734 100644 (file)
@@ -497,6 +497,7 @@ static u64 calculate_sr(struct cxl_context *ctx)
 {
        u64 sr = 0;
 
+       set_endian(sr);
        if (ctx->master)
                sr |= CXL_PSL_SR_An_MP;
        if (mfspr(SPRN_LPCR) & LPCR_TC)
@@ -506,7 +507,6 @@ static u64 calculate_sr(struct cxl_context *ctx)
                sr |= CXL_PSL_SR_An_HV;
        } else {
                sr |= CXL_PSL_SR_An_PR | CXL_PSL_SR_An_R;
-               set_endian(sr);
                sr &= ~(CXL_PSL_SR_An_HV);
                if (!test_tsk_thread_flag(current, TIF_32BIT))
                        sr |= CXL_PSL_SR_An_SF;
index 95c13b2ffa799e59f453e8a95813171cd56a13fc..ffa2884748205e26a376712c453b4fca5d3075bf 100644 (file)
@@ -426,15 +426,6 @@ int add_mtd_device(struct mtd_info *mtd)
        mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
        mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
 
-       if (mtd->dev.parent) {
-               if (!mtd->owner && mtd->dev.parent->driver)
-                       mtd->owner = mtd->dev.parent->driver->owner;
-               if (!mtd->name)
-                       mtd->name = dev_name(mtd->dev.parent);
-       } else {
-               pr_debug("mtd device won't show a device symlink in sysfs\n");
-       }
-
        /* Some chips always power up locked. Unlock them now */
        if ((mtd->flags & MTD_WRITEABLE) && (mtd->flags & MTD_POWERUP_LOCK)) {
                error = mtd_unlock(mtd, 0, mtd->size);
@@ -549,6 +540,21 @@ static int mtd_add_device_partitions(struct mtd_info *mtd,
        return 0;
 }
 
+/*
+ * Set a few defaults based on the parent devices, if not provided by the
+ * driver
+ */
+static void mtd_set_dev_defaults(struct mtd_info *mtd)
+{
+       if (mtd->dev.parent) {
+               if (!mtd->owner && mtd->dev.parent->driver)
+                       mtd->owner = mtd->dev.parent->driver->owner;
+               if (!mtd->name)
+                       mtd->name = dev_name(mtd->dev.parent);
+       } else {
+               pr_debug("mtd device won't show a device symlink in sysfs\n");
+       }
+}
 
 /**
  * mtd_device_parse_register - parse partitions and register an MTD device.
@@ -587,6 +593,8 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
        int ret;
        struct mtd_partition *real_parts = NULL;
 
+       mtd_set_dev_defaults(mtd);
+
        ret = parse_mtd_partitions(mtd, types, &real_parts, parser_data);
        if (ret <= 0 && nr_parts && parts) {
                real_parts = kmemdup(parts, sizeof(*parts) * nr_parts,
index 669c3452f278fb0e365570872893855c9ce21e2c..9ed6038e47d210df74ec678de7cf8220797bf815 100644 (file)
@@ -46,10 +46,18 @@ static int parse_ofpart_partitions(struct mtd_info *master,
 
        ofpart_node = of_get_child_by_name(mtd_node, "partitions");
        if (!ofpart_node) {
-               pr_warn("%s: 'partitions' subnode not found on %s. Trying to parse direct subnodes as partitions.\n",
-                       master->name, mtd_node->full_name);
+               /*
+                * We might get here even when ofpart isn't used at all (e.g.,
+                * when using another parser), so don't be louder than
+                * KERN_DEBUG
+                */
+               pr_debug("%s: 'partitions' subnode not found on %s. Trying to parse direct subnodes as partitions.\n",
+                        master->name, mtd_node->full_name);
                ofpart_node = mtd_node;
                dedicated = false;
+       } else if (!of_device_is_compatible(ofpart_node, "fixed-partitions")) {
+               /* The 'partitions' subnode might be used by another parser */
+               return 0;
        }
 
        /* First count the subnodes */
index 49883905a434b68b98af50e515a0356731c62fa6..32477c4eb421390e250645f94b0eefdab871a043 100644 (file)
@@ -516,8 +516,8 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
        status_old = read_sr(nor);
 
        /* Cannot unlock; would unlock larger region than requested */
-       if (stm_is_locked_sr(nor, status_old, ofs - mtd->erasesize,
-                            mtd->erasesize))
+       if (stm_is_locked_sr(nor, ofs - mtd->erasesize, mtd->erasesize,
+                            status_old))
                return -EINVAL;
 
        /*
@@ -1200,8 +1200,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
 
        if (JEDEC_MFR(info) == SNOR_MFR_ATMEL ||
            JEDEC_MFR(info) == SNOR_MFR_INTEL ||
-           JEDEC_MFR(info) == SNOR_MFR_SST ||
-           JEDEC_MFR(info) == SNOR_MFR_WINBOND) {
+           JEDEC_MFR(info) == SNOR_MFR_SST) {
                write_enable(nor);
                write_sr(nor, 0);
        }
@@ -1217,8 +1216,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
        mtd->_read = spi_nor_read;
 
        /* NOR protection support for STmicro/Micron chips and similar */
-       if (JEDEC_MFR(info) == SNOR_MFR_MICRON ||
-           JEDEC_MFR(info) == SNOR_MFR_WINBOND) {
+       if (JEDEC_MFR(info) == SNOR_MFR_MICRON) {
                nor->flash_lock = stm_lock;
                nor->flash_unlock = stm_unlock;
                nor->flash_is_locked = stm_is_locked;
index b077e43b5ba913b2ba208ed54673c3fe291afc66..c4cb15a3098c0933f607e4f0cba170e978f910ff 100644 (file)
@@ -236,7 +236,7 @@ int ubi_debugfs_init(void)
 
        dfs_rootdir = debugfs_create_dir("ubi", NULL);
        if (IS_ERR_OR_NULL(dfs_rootdir)) {
-               int err = dfs_rootdir ? -ENODEV : PTR_ERR(dfs_rootdir);
+               int err = dfs_rootdir ? PTR_ERR(dfs_rootdir) : -ENODEV;
 
                pr_err("UBI error: cannot create \"ubi\" debugfs directory, error %d\n",
                       err);
index 1fc23e48fe8e49fc947c972cca179399a60a37ec..10cf3b549959ce46f9c517b77fbcdd84e274a3d2 100644 (file)
@@ -1299,7 +1299,7 @@ static int self_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
        if (err && err != UBI_IO_BITFLIPS && !mtd_is_eccerr(err))
                goto exit;
 
-       crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_EC_HDR_SIZE_CRC);
+       crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_VID_HDR_SIZE_CRC);
        hdr_crc = be32_to_cpu(vid_hdr->hdr_crc);
        if (hdr_crc != crc) {
                ubi_err(ubi, "bad VID header CRC at PEB %d, calculated %#08x, read %#08x",
index eb4489f9082fe84345d2ec68b0f8723888e5c177..56065632a5b85ebf50022f883e1edc968a069f93 100644 (file)
@@ -603,6 +603,7 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
        return 0;
 }
 
+static int __erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk);
 /**
  * do_sync_erase - run the erase worker synchronously.
  * @ubi: UBI device description object
@@ -615,20 +616,16 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
 static int do_sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
                         int vol_id, int lnum, int torture)
 {
-       struct ubi_work *wl_wrk;
+       struct ubi_work wl_wrk;
 
        dbg_wl("sync erase of PEB %i", e->pnum);
 
-       wl_wrk = kmalloc(sizeof(struct ubi_work), GFP_NOFS);
-       if (!wl_wrk)
-               return -ENOMEM;
-
-       wl_wrk->e = e;
-       wl_wrk->vol_id = vol_id;
-       wl_wrk->lnum = lnum;
-       wl_wrk->torture = torture;
+       wl_wrk.e = e;
+       wl_wrk.vol_id = vol_id;
+       wl_wrk.lnum = lnum;
+       wl_wrk.torture = torture;
 
-       return erase_worker(ubi, wl_wrk, 0);
+       return __erase_worker(ubi, &wl_wrk);
 }
 
 /**
@@ -1014,7 +1011,7 @@ out_unlock:
 }
 
 /**
- * erase_worker - physical eraseblock erase worker function.
+ * __erase_worker - physical eraseblock erase worker function.
  * @ubi: UBI device description object
  * @wl_wrk: the work object
  * @shutdown: non-zero if the worker has to free memory and exit
@@ -1025,8 +1022,7 @@ out_unlock:
  * needed. Returns zero in case of success and a negative error code in case of
  * failure.
  */
-static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
-                       int shutdown)
+static int __erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk)
 {
        struct ubi_wl_entry *e = wl_wrk->e;
        int pnum = e->pnum;
@@ -1034,21 +1030,11 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
        int lnum = wl_wrk->lnum;
        int err, available_consumed = 0;
 
-       if (shutdown) {
-               dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec);
-               kfree(wl_wrk);
-               wl_entry_destroy(ubi, e);
-               return 0;
-       }
-
        dbg_wl("erase PEB %d EC %d LEB %d:%d",
               pnum, e->ec, wl_wrk->vol_id, wl_wrk->lnum);
 
        err = sync_erase(ubi, e, wl_wrk->torture);
        if (!err) {
-               /* Fine, we've erased it successfully */
-               kfree(wl_wrk);
-
                spin_lock(&ubi->wl_lock);
                wl_tree_add(e, &ubi->free);
                ubi->free_count++;
@@ -1066,7 +1052,6 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
        }
 
        ubi_err(ubi, "failed to erase PEB %d, error %d", pnum, err);
-       kfree(wl_wrk);
 
        if (err == -EINTR || err == -ENOMEM || err == -EAGAIN ||
            err == -EBUSY) {
@@ -1075,6 +1060,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
                /* Re-schedule the LEB for erasure */
                err1 = schedule_erase(ubi, e, vol_id, lnum, 0);
                if (err1) {
+                       wl_entry_destroy(ubi, e);
                        err = err1;
                        goto out_ro;
                }
@@ -1150,6 +1136,25 @@ out_ro:
        return err;
 }
 
+static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
+                         int shutdown)
+{
+       int ret;
+
+       if (shutdown) {
+               struct ubi_wl_entry *e = wl_wrk->e;
+
+               dbg_wl("cancel erasure of PEB %d EC %d", e->pnum, e->ec);
+               kfree(wl_wrk);
+               wl_entry_destroy(ubi, e);
+               return 0;
+       }
+
+       ret = __erase_worker(ubi, wl_wrk);
+       kfree(wl_wrk);
+       return ret;
+}
+
 /**
  * ubi_wl_put_peb - return a PEB to the wear-leveling sub-system.
  * @ubi: UBI device description object
index 970781a9e67777a87b0b93f0cf8bf31d4541d855..f6a7161e3b85297eda9503a27280cab93b2ae70b 100644 (file)
@@ -1849,7 +1849,7 @@ static int xgbe_exit(struct xgbe_prv_data *pdata)
        usleep_range(10, 15);
 
        /* Poll Until Poll Condition */
-       while (count-- && XGMAC_IOREAD_BITS(pdata, DMA_MR, SWR))
+       while (--count && XGMAC_IOREAD_BITS(pdata, DMA_MR, SWR))
                usleep_range(500, 600);
 
        if (!count)
@@ -1873,7 +1873,7 @@ static int xgbe_flush_tx_queues(struct xgbe_prv_data *pdata)
        /* Poll Until Poll Condition */
        for (i = 0; i < pdata->tx_q_count; i++) {
                count = 2000;
-               while (count-- && XGMAC_MTL_IOREAD_BITS(pdata, i,
+               while (--count && XGMAC_MTL_IOREAD_BITS(pdata, i,
                                                        MTL_Q_TQOMR, FTQ))
                        usleep_range(500, 600);
 
index 9147a0107c44034f015beba83cfc150398c1ac93..d0ae1a6cc2120cbb4d7d2eb9840e1f552605bd06 100644 (file)
@@ -289,6 +289,7 @@ static int xgene_enet_setup_tx_desc(struct xgene_enet_desc_ring *tx_ring,
                                    struct sk_buff *skb)
 {
        struct device *dev = ndev_to_dev(tx_ring->ndev);
+       struct xgene_enet_pdata *pdata = netdev_priv(tx_ring->ndev);
        struct xgene_enet_raw_desc *raw_desc;
        __le64 *exp_desc = NULL, *exp_bufs = NULL;
        dma_addr_t dma_addr, pbuf_addr, *frag_dma_addr;
@@ -419,6 +420,7 @@ out:
        raw_desc->m0 = cpu_to_le64(SET_VAL(LL, ll) | SET_VAL(NV, nv) |
                                   SET_VAL(USERINFO, tx_ring->tail));
        tx_ring->cp_ring->cp_skb[tx_ring->tail] = skb;
+       pdata->tx_level += count;
        tx_ring->tail = tail;
 
        return count;
@@ -429,14 +431,13 @@ static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb,
 {
        struct xgene_enet_pdata *pdata = netdev_priv(ndev);
        struct xgene_enet_desc_ring *tx_ring = pdata->tx_ring;
-       struct xgene_enet_desc_ring *cp_ring = tx_ring->cp_ring;
-       u32 tx_level, cq_level;
+       u32 tx_level = pdata->tx_level;
        int count;
 
-       tx_level = pdata->ring_ops->len(tx_ring);
-       cq_level = pdata->ring_ops->len(cp_ring);
-       if (unlikely(tx_level > pdata->tx_qcnt_hi ||
-                    cq_level > pdata->cp_qcnt_hi)) {
+       if (tx_level < pdata->txc_level)
+               tx_level += ((typeof(pdata->tx_level))~0U);
+
+       if ((tx_level - pdata->txc_level) > pdata->tx_qcnt_hi) {
                netif_stop_queue(ndev);
                return NETDEV_TX_BUSY;
        }
@@ -539,10 +540,13 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
        struct xgene_enet_raw_desc *raw_desc, *exp_desc;
        u16 head = ring->head;
        u16 slots = ring->slots - 1;
-       int ret, count = 0, processed = 0;
+       int ret, desc_count, count = 0, processed = 0;
+       bool is_completion;
 
        do {
                raw_desc = &ring->raw_desc[head];
+               desc_count = 0;
+               is_completion = false;
                exp_desc = NULL;
                if (unlikely(xgene_enet_is_desc_slot_empty(raw_desc)))
                        break;
@@ -559,18 +563,24 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
                        }
                        dma_rmb();
                        count++;
+                       desc_count++;
                }
-               if (is_rx_desc(raw_desc))
+               if (is_rx_desc(raw_desc)) {
                        ret = xgene_enet_rx_frame(ring, raw_desc);
-               else
+               } else {
                        ret = xgene_enet_tx_completion(ring, raw_desc);
+                       is_completion = true;
+               }
                xgene_enet_mark_desc_slot_empty(raw_desc);
                if (exp_desc)
                        xgene_enet_mark_desc_slot_empty(exp_desc);
 
                head = (head + 1) & slots;
                count++;
+               desc_count++;
                processed++;
+               if (is_completion)
+                       pdata->txc_level += desc_count;
 
                if (ret)
                        break;
@@ -580,10 +590,8 @@ static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring,
                pdata->ring_ops->wr_cmd(ring, -count);
                ring->head = head;
 
-               if (netif_queue_stopped(ring->ndev)) {
-                       if (pdata->ring_ops->len(ring) < pdata->cp_qcnt_low)
-                               netif_wake_queue(ring->ndev);
-               }
+               if (netif_queue_stopped(ring->ndev))
+                       netif_start_queue(ring->ndev);
        }
 
        return processed;
@@ -1033,9 +1041,7 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
        pdata->tx_ring->cp_ring = cp_ring;
        pdata->tx_ring->dst_ring_num = xgene_enet_dst_ring_num(cp_ring);
 
-       pdata->tx_qcnt_hi = pdata->tx_ring->slots / 2;
-       pdata->cp_qcnt_hi = pdata->rx_ring->slots / 2;
-       pdata->cp_qcnt_low = pdata->cp_qcnt_hi / 2;
+       pdata->tx_qcnt_hi = pdata->tx_ring->slots - 128;
 
        return 0;
 
index a6e56b88c0a07a6bee7a1f0e6a050db802e5e989..1aa72c787f8de9464a22bf66a8ea2081a6679269 100644 (file)
@@ -155,11 +155,11 @@ struct xgene_enet_pdata {
        enum xgene_enet_id enet_id;
        struct xgene_enet_desc_ring *tx_ring;
        struct xgene_enet_desc_ring *rx_ring;
+       u16 tx_level;
+       u16 txc_level;
        char *dev_name;
        u32 rx_buff_cnt;
        u32 tx_qcnt_hi;
-       u32 cp_qcnt_hi;
-       u32 cp_qcnt_low;
        u32 rx_irq;
        u32 txc_irq;
        u8 cq_cnt;
index 2795d6db10e1897e3c3c3b367e28e05ea33858c5..8b5988e210d55bcae21f4c6bb8614696cb7b0b64 100644 (file)
@@ -1016,13 +1016,12 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter)
                sizeof(struct atl1c_recv_ret_status) * rx_desc_count +
                8 * 4;
 
-       ring_header->desc = pci_alloc_consistent(pdev, ring_header->size,
-                               &ring_header->dma);
+       ring_header->desc = dma_zalloc_coherent(&pdev->dev, ring_header->size,
+                                               &ring_header->dma, GFP_KERNEL);
        if (unlikely(!ring_header->desc)) {
-               dev_err(&pdev->dev, "pci_alloc_consistend failed\n");
+               dev_err(&pdev->dev, "could not get memory for DMA buffer\n");
                goto err_nomem;
        }
-       memset(ring_header->desc, 0, ring_header->size);
        /* init TPD ring */
 
        tpd_ring[0].dma = roundup(ring_header->dma, 8);
index a3c7106fdf85e78f083a4e85b2e809f6e587a360..8ba7f8ff3434000f57f45968d8a70148f4647cc8 100644 (file)
@@ -13,6 +13,7 @@ if NET_VENDOR_AURORA
 
 config AURORA_NB8800
        tristate "Aurora AU-NB8800 support"
+       depends on HAS_DMA
        select PHYLIB
        help
         Support for the AU-NB8800 gigabit Ethernet controller.
index f8d7a2f06950139b936dc7d793bb884bb579980d..c82ab87fcbe8fb09e59be79f866910751f4b4308 100644 (file)
@@ -3430,25 +3430,29 @@ static u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb)
        return rc;
 }
 
-#if (MAX_SKB_FRAGS >= MAX_FETCH_BD - 3)
+/* VXLAN: 4 = 1 (for linear data BD) + 3 (2 for PBD and last BD) */
+#define BNX2X_NUM_VXLAN_TSO_WIN_SUB_BDS         4
+
+/* Regular: 3 = 1 (for linear data BD) + 2 (for PBD and last BD) */
+#define BNX2X_NUM_TSO_WIN_SUB_BDS               3
+
+#if (MAX_SKB_FRAGS >= MAX_FETCH_BD - BDS_PER_TX_PKT)
 /* check if packet requires linearization (packet is too fragmented)
    no need to check fragmentation if page size > 8K (there will be no
    violation to FW restrictions) */
 static int bnx2x_pkt_req_lin(struct bnx2x *bp, struct sk_buff *skb,
                             u32 xmit_type)
 {
-       int to_copy = 0;
-       int hlen = 0;
-       int first_bd_sz = 0;
+       int first_bd_sz = 0, num_tso_win_sub = BNX2X_NUM_TSO_WIN_SUB_BDS;
+       int to_copy = 0, hlen = 0;
 
-       /* 3 = 1 (for linear data BD) + 2 (for PBD and last BD) */
-       if (skb_shinfo(skb)->nr_frags >= (MAX_FETCH_BD - 3)) {
+       if (xmit_type & XMIT_GSO_ENC)
+               num_tso_win_sub = BNX2X_NUM_VXLAN_TSO_WIN_SUB_BDS;
 
+       if (skb_shinfo(skb)->nr_frags >= (MAX_FETCH_BD - num_tso_win_sub)) {
                if (xmit_type & XMIT_GSO) {
                        unsigned short lso_mss = skb_shinfo(skb)->gso_size;
-                       /* Check if LSO packet needs to be copied:
-                          3 = 1 (for headers BD) + 2 (for PBD and last BD) */
-                       int wnd_size = MAX_FETCH_BD - 3;
+                       int wnd_size = MAX_FETCH_BD - num_tso_win_sub;
                        /* Number of windows to check */
                        int num_wnds = skb_shinfo(skb)->nr_frags - wnd_size;
                        int wnd_idx = 0;
index bdf094fb6ef92062d62d428109e277ba9e9d15f5..07f5f239cb65baca35792dd5ba7a979d2b36b763 100644 (file)
@@ -2693,17 +2693,16 @@ static int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp)
        req.ver_upd = DRV_VER_UPD;
 
        if (BNXT_PF(bp)) {
-               unsigned long vf_req_snif_bmap[4];
+               DECLARE_BITMAP(vf_req_snif_bmap, 256);
                u32 *data = (u32 *)vf_req_snif_bmap;
 
-               memset(vf_req_snif_bmap, 0, 32);
+               memset(vf_req_snif_bmap, 0, sizeof(vf_req_snif_bmap));
                for (i = 0; i < ARRAY_SIZE(bnxt_vf_req_snif); i++)
                        __set_bit(bnxt_vf_req_snif[i], vf_req_snif_bmap);
 
-               for (i = 0; i < 8; i++) {
-                       req.vf_req_fwd[i] = cpu_to_le32(*data);
-                       data++;
-               }
+               for (i = 0; i < 8; i++)
+                       req.vf_req_fwd[i] = cpu_to_le32(data[i]);
+
                req.enables |=
                        cpu_to_le32(FUNC_DRV_RGTR_REQ_ENABLES_VF_REQ_FWD);
        }
@@ -4603,7 +4602,7 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
                        bp->nge_port_cnt = 1;
        }
 
-       bp->state = BNXT_STATE_OPEN;
+       set_bit(BNXT_STATE_OPEN, &bp->state);
        bnxt_enable_int(bp);
        /* Enable TX queues */
        bnxt_tx_enable(bp);
@@ -4679,8 +4678,10 @@ int bnxt_close_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
        /* Change device state to avoid TX queue wake up's */
        bnxt_tx_disable(bp);
 
-       bp->state = BNXT_STATE_CLOSED;
-       cancel_work_sync(&bp->sp_task);
+       clear_bit(BNXT_STATE_OPEN, &bp->state);
+       smp_mb__after_atomic();
+       while (test_bit(BNXT_STATE_IN_SP_TASK, &bp->state))
+               msleep(20);
 
        /* Flush rings before disabling interrupts */
        bnxt_shutdown_nic(bp, irq_re_init);
@@ -5030,8 +5031,10 @@ static void bnxt_dbg_dump_states(struct bnxt *bp)
 static void bnxt_reset_task(struct bnxt *bp)
 {
        bnxt_dbg_dump_states(bp);
-       if (netif_running(bp->dev))
-               bnxt_tx_disable(bp); /* prevent tx timout again */
+       if (netif_running(bp->dev)) {
+               bnxt_close_nic(bp, false, false);
+               bnxt_open_nic(bp, false, false);
+       }
 }
 
 static void bnxt_tx_timeout(struct net_device *dev)
@@ -5081,8 +5084,12 @@ static void bnxt_sp_task(struct work_struct *work)
        struct bnxt *bp = container_of(work, struct bnxt, sp_task);
        int rc;
 
-       if (bp->state != BNXT_STATE_OPEN)
+       set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+       smp_mb__after_atomic();
+       if (!test_bit(BNXT_STATE_OPEN, &bp->state)) {
+               clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
                return;
+       }
 
        if (test_and_clear_bit(BNXT_RX_MASK_SP_EVENT, &bp->sp_event))
                bnxt_cfg_rx_mode(bp);
@@ -5106,8 +5113,19 @@ static void bnxt_sp_task(struct work_struct *work)
                bnxt_hwrm_tunnel_dst_port_free(
                        bp, TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN);
        }
-       if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event))
+       if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event)) {
+               /* bnxt_reset_task() calls bnxt_close_nic() which waits
+                * for BNXT_STATE_IN_SP_TASK to clear.
+                */
+               clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+               rtnl_lock();
                bnxt_reset_task(bp);
+               set_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
+               rtnl_unlock();
+       }
+
+       smp_mb__before_atomic();
+       clear_bit(BNXT_STATE_IN_SP_TASK, &bp->state);
 }
 
 static int bnxt_init_board(struct pci_dev *pdev, struct net_device *dev)
@@ -5186,7 +5204,7 @@ static int bnxt_init_board(struct pci_dev *pdev, struct net_device *dev)
        bp->timer.function = bnxt_timer;
        bp->current_interval = BNXT_TIMER_INTERVAL;
 
-       bp->state = BNXT_STATE_CLOSED;
+       clear_bit(BNXT_STATE_OPEN, &bp->state);
 
        return 0;
 
index 674bc5159b91c7cd4972561fae11dd1bbed7d53c..f199f4cc8ffe05e7c5580dcc8b14b29ab1b8f3e9 100644 (file)
@@ -925,9 +925,9 @@ struct bnxt {
 
        struct timer_list       timer;
 
-       int                     state;
-#define BNXT_STATE_CLOSED      0
-#define BNXT_STATE_OPEN                1
+       unsigned long           state;
+#define BNXT_STATE_OPEN                0
+#define BNXT_STATE_IN_SP_TASK  1
 
        struct bnxt_irq *irq_tbl;
        u8                      mac_addr[ETH_ALEN];
index 7a9af2887d8ed83f6a8672f8c1b6e18cd572c28a..ea044bbcd384886413cea2e2415aea8d25d28cf1 100644 (file)
@@ -21,7 +21,7 @@
 #ifdef CONFIG_BNXT_SRIOV
 static int bnxt_vf_ndo_prep(struct bnxt *bp, int vf_id)
 {
-       if (bp->state != BNXT_STATE_OPEN) {
+       if (!test_bit(BNXT_STATE_OPEN, &bp->state)) {
                netdev_err(bp->dev, "vf ndo called though PF is down\n");
                return -EINVAL;
        }
index 4b7fd63ae57c1d26ab54d9359297c56f35c6105c..5f24d11cb16aad5ae6bd474d538053ac6465c868 100644 (file)
@@ -37,7 +37,6 @@ struct nicpf {
 #define        NIC_GET_BGX_FROM_VF_LMAC_MAP(map)       ((map >> 4) & 0xF)
 #define        NIC_GET_LMAC_FROM_VF_LMAC_MAP(map)      (map & 0xF)
        u8                      vf_lmac_map[MAX_LMAC];
-       u8                      lmac_cnt;
        struct delayed_work     dwork;
        struct workqueue_struct *check_link;
        u8                      link[MAX_LMAC];
@@ -280,7 +279,6 @@ static void nic_set_lmac_vf_mapping(struct nicpf *nic)
        u64 lmac_credit;
 
        nic->num_vf_en = 0;
-       nic->lmac_cnt = 0;
 
        for (bgx = 0; bgx < NIC_MAX_BGX; bgx++) {
                if (!(bgx_map & (1 << bgx)))
@@ -290,7 +288,6 @@ static void nic_set_lmac_vf_mapping(struct nicpf *nic)
                        nic->vf_lmac_map[next_bgx_lmac++] =
                                                NIC_SET_VF_LMAC_MAP(bgx, lmac);
                nic->num_vf_en += lmac_cnt;
-               nic->lmac_cnt += lmac_cnt;
 
                /* Program LMAC credits */
                lmac_credit = (1ull << 1); /* channel credit enable */
@@ -618,6 +615,21 @@ static int nic_config_loopback(struct nicpf *nic, struct set_loopback *lbk)
        return 0;
 }
 
+static void nic_enable_vf(struct nicpf *nic, int vf, bool enable)
+{
+       int bgx, lmac;
+
+       nic->vf_enabled[vf] = enable;
+
+       if (vf >= nic->num_vf_en)
+               return;
+
+       bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+       lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+
+       bgx_lmac_rx_tx_enable(nic->node, bgx, lmac, enable);
+}
+
 /* Interrupt handler to handle mailbox messages from VFs */
 static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
 {
@@ -717,29 +729,14 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
                break;
        case NIC_MBOX_MSG_CFG_DONE:
                /* Last message of VF config msg sequence */
-               nic->vf_enabled[vf] = true;
-               if (vf >= nic->lmac_cnt)
-                       goto unlock;
-
-               bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
-               lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
-
-               bgx_lmac_rx_tx_enable(nic->node, bgx, lmac, true);
+               nic_enable_vf(nic, vf, true);
                goto unlock;
        case NIC_MBOX_MSG_SHUTDOWN:
                /* First msg in VF teardown sequence */
-               nic->vf_enabled[vf] = false;
                if (vf >= nic->num_vf_en)
                        nic->sqs_used[vf - nic->num_vf_en] = false;
                nic->pqs_vf[vf] = 0;
-
-               if (vf >= nic->lmac_cnt)
-                       break;
-
-               bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
-               lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
-
-               bgx_lmac_rx_tx_enable(nic->node, bgx, lmac, false);
+               nic_enable_vf(nic, vf, false);
                break;
        case NIC_MBOX_MSG_ALLOC_SQS:
                nic_alloc_sqs(nic, &mbx.sqs_alloc);
@@ -958,7 +955,7 @@ static void nic_poll_for_link(struct work_struct *work)
 
        mbx.link_status.msg = NIC_MBOX_MSG_BGX_LINK_CHANGE;
 
-       for (vf = 0; vf < nic->lmac_cnt; vf++) {
+       for (vf = 0; vf < nic->num_vf_en; vf++) {
                /* Poll only if VF is UP */
                if (!nic->vf_enabled[vf])
                        continue;
index c308429dd9c7fa0aebf2cee3b951f71f3863d939..11dd91e4db56b061311645567ab8c46f80123a61 100644 (file)
@@ -295,6 +295,10 @@ struct clip_tbl *t4_init_clip_tbl(unsigned int clipt_start,
                INIT_LIST_HEAD(&ctbl->hash_list[i]);
 
        cl_list = t4_alloc_mem(clipt_size*sizeof(struct clip_entry));
+       if (!cl_list) {
+               t4_free_mem(ctbl);
+               return NULL;
+       }
        ctbl->cl_list = (void *)cl_list;
 
        for (i = 0; i < clipt_size; i++) {
index d463563e1f7039ee5176ca36abfdc6bae3f2ed46..6ee78c203ecad7a18ba136e45ea0d2e24ec35930 100644 (file)
@@ -848,8 +848,6 @@ void be_roce_dev_remove(struct be_adapter *);
 /*
  * internal function to open-close roce device during ifup-ifdown.
  */
-void be_roce_dev_open(struct be_adapter *);
-void be_roce_dev_close(struct be_adapter *);
 void be_roce_dev_shutdown(struct be_adapter *);
 
 #endif                         /* BE_H */
index b6ad02909d6b3c87b861d4e35c345426bef30a64..8a1d9fffd7d671ea88023a120c93f4cdefbcff54 100644 (file)
@@ -3299,8 +3299,10 @@ static int be_msix_register(struct be_adapter *adapter)
 
        return 0;
 err_msix:
-       for (i--, eqo = &adapter->eq_obj[i]; i >= 0; i--, eqo--)
+       for (i--; i >= 0; i--) {
+               eqo = &adapter->eq_obj[i];
                free_irq(be_msix_vec_get(adapter, eqo), eqo);
+       }
        dev_warn(&adapter->pdev->dev, "MSIX Request IRQ failed - err %d\n",
                 status);
        be_msix_disable(adapter);
@@ -3432,8 +3434,6 @@ static int be_close(struct net_device *netdev)
 
        be_disable_if_filters(adapter);
 
-       be_roce_dev_close(adapter);
-
        if (adapter->flags & BE_FLAGS_NAPI_ENABLED) {
                for_all_evt_queues(adapter, eqo, i) {
                        napi_disable(&eqo->napi);
@@ -3601,8 +3601,6 @@ static int be_open(struct net_device *netdev)
                be_link_status_update(adapter, link_status);
 
        netif_tx_start_all_queues(netdev);
-       be_roce_dev_open(adapter);
-
 #ifdef CONFIG_BE2NET_VXLAN
        if (skyhawk_chip(adapter))
                vxlan_get_rx_port(netdev);
index 60368207bf584188b4d0293d9f2a8d7235180a8d..4089156a7f5e20177dfee8d29315c404924f4d9e 100644 (file)
@@ -116,40 +116,6 @@ void be_roce_dev_remove(struct be_adapter *adapter)
        }
 }
 
-static void _be_roce_dev_open(struct be_adapter *adapter)
-{
-       if (ocrdma_drv && adapter->ocrdma_dev &&
-           ocrdma_drv->state_change_handler)
-               ocrdma_drv->state_change_handler(adapter->ocrdma_dev,
-                                                BE_DEV_UP);
-}
-
-void be_roce_dev_open(struct be_adapter *adapter)
-{
-       if (be_roce_supported(adapter)) {
-               mutex_lock(&be_adapter_list_lock);
-               _be_roce_dev_open(adapter);
-               mutex_unlock(&be_adapter_list_lock);
-       }
-}
-
-static void _be_roce_dev_close(struct be_adapter *adapter)
-{
-       if (ocrdma_drv && adapter->ocrdma_dev &&
-           ocrdma_drv->state_change_handler)
-               ocrdma_drv->state_change_handler(adapter->ocrdma_dev,
-                                                BE_DEV_DOWN);
-}
-
-void be_roce_dev_close(struct be_adapter *adapter)
-{
-       if (be_roce_supported(adapter)) {
-               mutex_lock(&be_adapter_list_lock);
-               _be_roce_dev_close(adapter);
-               mutex_unlock(&be_adapter_list_lock);
-       }
-}
-
 void be_roce_dev_shutdown(struct be_adapter *adapter)
 {
        if (be_roce_supported(adapter)) {
@@ -177,8 +143,6 @@ int be_roce_register_driver(struct ocrdma_driver *drv)
 
                _be_roce_dev_add(dev);
                netdev = dev->netdev;
-               if (netif_running(netdev) && netif_oper_up(netdev))
-                       _be_roce_dev_open(dev);
        }
        mutex_unlock(&be_adapter_list_lock);
        return 0;
index cde6ef905ec481dce0436858fb1fd78252471146..fde609789483872582bda5a990d6bad357dc25df 100644 (file)
@@ -60,9 +60,7 @@ struct ocrdma_driver {
        void (*state_change_handler) (struct ocrdma_dev *, u32 new_state);
 };
 
-enum {
-       BE_DEV_UP       = 0,
-       BE_DEV_DOWN     = 1,
+enum be_roce_event {
        BE_DEV_SHUTDOWN = 2
 };
 
index 63c2bcf8031a8a8cc39c714bb1510e3f3ae03793..b1026689b78f4075d30b240b4f8dc625d3b9299a 100644 (file)
@@ -48,21 +48,15 @@ static void nps_enet_read_rx_fifo(struct net_device *ndev,
                        *reg = nps_enet_reg_get(priv, NPS_ENET_REG_RX_BUF);
        else { /* !dst_is_aligned */
                for (i = 0; i < len; i++, reg++) {
-                       u32 buf =
-                               nps_enet_reg_get(priv, NPS_ENET_REG_RX_BUF);
-
-                       /* to accommodate word-unaligned address of "reg"
-                        * we have to do memcpy_toio() instead of simple "=".
-                        */
-                       memcpy_toio((void __iomem *)reg, &buf, sizeof(buf));
+                       u32 buf = nps_enet_reg_get(priv, NPS_ENET_REG_RX_BUF);
+                       put_unaligned(buf, reg);
                }
        }
 
        /* copy last bytes (if any) */
        if (last) {
                u32 buf = nps_enet_reg_get(priv, NPS_ENET_REG_RX_BUF);
-
-               memcpy_toio((void __iomem *)reg, &buf, last);
+               memcpy((u8*)reg, &buf, last);
        }
 }
 
@@ -367,7 +361,7 @@ static void nps_enet_send_frame(struct net_device *ndev,
        struct nps_enet_tx_ctl tx_ctrl;
        short length = skb->len;
        u32 i, len = DIV_ROUND_UP(length, sizeof(u32));
-       u32 *src = (u32 *)virt_to_phys(skb->data);
+       u32 *src = (void *)skb->data;
        bool src_is_aligned = IS_ALIGNED((unsigned long)src, sizeof(u32));
 
        tx_ctrl.value = 0;
@@ -375,17 +369,11 @@ static void nps_enet_send_frame(struct net_device *ndev,
        if (src_is_aligned)
                for (i = 0; i < len; i++, src++)
                        nps_enet_reg_set(priv, NPS_ENET_REG_TX_BUF, *src);
-       else { /* !src_is_aligned */
-               for (i = 0; i < len; i++, src++) {
-                       u32 buf;
-
-                       /* to accommodate word-unaligned address of "src"
-                        * we have to do memcpy_fromio() instead of simple "="
-                        */
-                       memcpy_fromio(&buf, (void __iomem *)src, sizeof(buf));
-                       nps_enet_reg_set(priv, NPS_ENET_REG_TX_BUF, buf);
-               }
-       }
+       else /* !src_is_aligned */
+               for (i = 0; i < len; i++, src++)
+                       nps_enet_reg_set(priv, NPS_ENET_REG_TX_BUF,
+                                        get_unaligned(src));
+
        /* Write the length of the Frame */
        tx_ctrl.nt = length;
 
index 08f5b911d96be1b01f99484ee748c24aaed7f483..52e0091b4fb261f983ab0e043d1cb0d48638dc03 100644 (file)
@@ -552,7 +552,7 @@ static void tx_restart(struct net_device *dev)
        cbd_t __iomem *prev_bd;
        cbd_t __iomem *last_tx_bd;
 
-       last_tx_bd = fep->tx_bd_base + (fpi->tx_ring * sizeof(cbd_t));
+       last_tx_bd = fep->tx_bd_base + ((fpi->tx_ring - 1) * sizeof(cbd_t));
 
        /* get the current bd held in TBPTR  and scan back from this point */
        recheck_bd = curr_tbptr = (cbd_t __iomem *)
index 55c36230e17634c3e063bdb20f4bb6a896bce4a6..40071dad1c570686de4d7b062d0b61682c878c2b 100644 (file)
@@ -464,7 +464,7 @@ static int fsl_pq_mdio_probe(struct platform_device *pdev)
                         * address). Print error message but continue anyway.
                         */
                        if ((void *)tbipa > priv->map + resource_size(&res) - 4)
-                               dev_err(&pdev->dev, "invalid register map (should be at least 0x%04x to contain TBI address)\n",
+                               dev_err(&pdev->dev, "invalid register map (should be at least 0x%04zx to contain TBI address)\n",
                                        ((void *)tbipa - priv->map) + 4);
 
                        iowrite32be(be32_to_cpup(prop), tbipa);
index 7cf898455e60076d52c1031422f3d90a3a10f4a3..3e233d924cce3b8bbf6bf5901b61455c5c0cd2dc 100644 (file)
@@ -894,7 +894,8 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev)
                                     FSL_GIANFAR_DEV_HAS_VLAN |
                                     FSL_GIANFAR_DEV_HAS_MAGIC_PACKET |
                                     FSL_GIANFAR_DEV_HAS_EXTENDED_HASH |
-                                    FSL_GIANFAR_DEV_HAS_TIMER;
+                                    FSL_GIANFAR_DEV_HAS_TIMER |
+                                    FSL_GIANFAR_DEV_HAS_RX_FILER;
 
        err = of_property_read_string(np, "phy-connection-type", &ctype);
 
@@ -1396,8 +1397,9 @@ static int gfar_probe(struct platform_device *ofdev)
                priv->rx_queue[i]->rxic = DEFAULT_RXIC;
        }
 
-       /* always enable rx filer */
-       priv->rx_filer_enable = 1;
+       /* Always enable rx filer if available */
+       priv->rx_filer_enable =
+           (priv->device_flags & FSL_GIANFAR_DEV_HAS_RX_FILER) ? 1 : 0;
        /* Enable most messages by default */
        priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1;
        /* use pritority h/w tx queue scheduling for single queue devices */
index f266b20f9ef5be53e6c55f2579484bb72d8794a1..cb77667971a7e4dd761ada53273f04a2047cf259 100644 (file)
@@ -923,6 +923,7 @@ struct gfar {
 #define FSL_GIANFAR_DEV_HAS_BUF_STASHING       0x00000400
 #define FSL_GIANFAR_DEV_HAS_TIMER              0x00000800
 #define FSL_GIANFAR_DEV_HAS_WAKE_ON_FILER      0x00001000
+#define FSL_GIANFAR_DEV_HAS_RX_FILER           0x00002000
 
 #if (MAXGROUPS == 2)
 #define DEFAULT_MAPPING        0xAA
index 2a98eba660c06a4dc3736bf84686a20d87597e20..b674414a4d725569c87fa577aa23f5b822e80d50 100644 (file)
@@ -1259,12 +1259,8 @@ int hns_dsaf_set_mac_uc_entry(
        if (MAC_IS_ALL_ZEROS(mac_entry->addr) ||
            MAC_IS_BROADCAST(mac_entry->addr) ||
            MAC_IS_MULTICAST(mac_entry->addr)) {
-               dev_err(dsaf_dev->dev,
-                       "set_uc %s Mac %02x:%02x:%02x:%02x:%02x:%02x err!\n",
-                       dsaf_dev->ae_dev.name, mac_entry->addr[0],
-                       mac_entry->addr[1], mac_entry->addr[2],
-                       mac_entry->addr[3], mac_entry->addr[4],
-                       mac_entry->addr[5]);
+               dev_err(dsaf_dev->dev, "set_uc %s Mac %pM err!\n",
+                       dsaf_dev->ae_dev.name, mac_entry->addr);
                return -EINVAL;
        }
 
@@ -1331,12 +1327,8 @@ int hns_dsaf_set_mac_mc_entry(
 
        /* mac addr check */
        if (MAC_IS_ALL_ZEROS(mac_entry->addr)) {
-               dev_err(dsaf_dev->dev,
-                       "set uc %s Mac %02x:%02x:%02x:%02x:%02x:%02x err!\n",
-                       dsaf_dev->ae_dev.name, mac_entry->addr[0],
-                       mac_entry->addr[1], mac_entry->addr[2],
-                       mac_entry->addr[3],
-                       mac_entry->addr[4], mac_entry->addr[5]);
+               dev_err(dsaf_dev->dev, "set uc %s Mac %pM err!\n",
+                       dsaf_dev->ae_dev.name, mac_entry->addr);
                return -EINVAL;
        }
 
@@ -1410,11 +1402,8 @@ int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev,
 
        /*chechk mac addr */
        if (MAC_IS_ALL_ZEROS(mac_entry->addr)) {
-               dev_err(dsaf_dev->dev,
-                       "set_entry failed,addr %02x:%02x:%02x:%02x:%02x:%02x!\n",
-                       mac_entry->addr[0], mac_entry->addr[1],
-                       mac_entry->addr[2], mac_entry->addr[3],
-                       mac_entry->addr[4], mac_entry->addr[5]);
+               dev_err(dsaf_dev->dev, "set_entry failed,addr %pM!\n",
+                       mac_entry->addr);
                return -EINVAL;
        }
 
@@ -1497,9 +1486,8 @@ int hns_dsaf_del_mac_entry(struct dsaf_device *dsaf_dev, u16 vlan_id,
 
        /*check mac addr */
        if (MAC_IS_ALL_ZEROS(addr) || MAC_IS_BROADCAST(addr)) {
-               dev_err(dsaf_dev->dev,
-                       "del_entry failed,addr %02x:%02x:%02x:%02x:%02x:%02x!\n",
-                       addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+               dev_err(dsaf_dev->dev, "del_entry failed,addr %pM!\n",
+                       addr);
                return -EINVAL;
        }
 
@@ -1563,11 +1551,8 @@ int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev,
 
        /*check mac addr */
        if (MAC_IS_ALL_ZEROS(mac_entry->addr)) {
-               dev_err(dsaf_dev->dev,
-                       "del_port failed, addr %02x:%02x:%02x:%02x:%02x:%02x!\n",
-                       mac_entry->addr[0], mac_entry->addr[1],
-                       mac_entry->addr[2], mac_entry->addr[3],
-                       mac_entry->addr[4], mac_entry->addr[5]);
+               dev_err(dsaf_dev->dev, "del_port failed, addr %pM!\n",
+                       mac_entry->addr);
                return -EINVAL;
        }
 
@@ -1644,11 +1629,8 @@ int hns_dsaf_get_mac_uc_entry(struct dsaf_device *dsaf_dev,
        /* check macaddr */
        if (MAC_IS_ALL_ZEROS(mac_entry->addr) ||
            MAC_IS_BROADCAST(mac_entry->addr)) {
-               dev_err(dsaf_dev->dev,
-                       "get_entry failed,addr %02x:%02x:%02x:%02x:%02x:%02x\n",
-                       mac_entry->addr[0], mac_entry->addr[1],
-                       mac_entry->addr[2], mac_entry->addr[3],
-                       mac_entry->addr[4], mac_entry->addr[5]);
+               dev_err(dsaf_dev->dev, "get_entry failed,addr %pM\n",
+                       mac_entry->addr);
                return -EINVAL;
        }
 
@@ -1695,11 +1677,8 @@ int hns_dsaf_get_mac_mc_entry(struct dsaf_device *dsaf_dev,
        /*check mac addr */
        if (MAC_IS_ALL_ZEROS(mac_entry->addr) ||
            MAC_IS_BROADCAST(mac_entry->addr)) {
-               dev_err(dsaf_dev->dev,
-                       "get_entry failed,addr %02x:%02x:%02x:%02x:%02x:%02x\n",
-                       mac_entry->addr[0], mac_entry->addr[1],
-                       mac_entry->addr[2], mac_entry->addr[3],
-                       mac_entry->addr[4], mac_entry->addr[5]);
+               dev_err(dsaf_dev->dev, "get_entry failed,addr %pM\n",
+                       mac_entry->addr);
                return -EINVAL;
        }
 
index b475e1bf2e6fdb24d9bade9405aa3e575581664e..bdbd80423b17aaf36d9134109ece6bb8d22c4303 100644 (file)
 #define XGMAC_PAUSE_CTL_RSP_MODE_B     2
 #define XGMAC_PAUSE_CTL_TX_XOFF_B      3
 
-static inline void dsaf_write_reg(void *base, u32 reg, u32 value)
+static inline void dsaf_write_reg(void __iomem *base, u32 reg, u32 value)
 {
        u8 __iomem *reg_addr = ACCESS_ONCE(base);
 
@@ -908,7 +908,7 @@ static inline void dsaf_write_reg(void *base, u32 reg, u32 value)
 #define dsaf_write_dev(a, reg, value) \
        dsaf_write_reg((a)->io_base, (reg), (value))
 
-static inline u32 dsaf_read_reg(u8 *base, u32 reg)
+static inline u32 dsaf_read_reg(u8 __iomem *base, u32 reg)
 {
        u8 __iomem *reg_addr = ACCESS_ONCE(base);
 
@@ -927,8 +927,8 @@ static inline u32 dsaf_read_reg(u8 *base, u32 reg)
 #define dsaf_set_bit(origin, shift, val) \
        dsaf_set_field((origin), (1ull << (shift)), (shift), (val))
 
-static inline void dsaf_set_reg_field(void *base, u32 reg, u32 mask, u32 shift,
-                                     u32 val)
+static inline void dsaf_set_reg_field(void __iomem *base, u32 reg, u32 mask,
+                                     u32 shift, u32 val)
 {
        u32 origin = dsaf_read_reg(base, reg);
 
@@ -947,7 +947,8 @@ static inline void dsaf_set_reg_field(void *base, u32 reg, u32 mask, u32 shift,
 #define dsaf_get_bit(origin, shift) \
        dsaf_get_field((origin), (1ull << (shift)), (shift))
 
-static inline u32 dsaf_get_reg_field(void *base, u32 reg, u32 mask, u32 shift)
+static inline u32 dsaf_get_reg_field(void __iomem *base, u32 reg, u32 mask,
+                                    u32 shift)
 {
        u32 origin;
 
index 0ff8f01e57ee5a4a7de890485e5987fd9eec7f8a..1fd5ea82a9bc88950a29a305e7c4898c3b6b246c 100644 (file)
@@ -567,10 +567,6 @@ i40e_status i40e_init_adminq(struct i40e_hw *hw)
                goto init_adminq_exit;
        }
 
-       /* initialize locks */
-       mutex_init(&hw->aq.asq_mutex);
-       mutex_init(&hw->aq.arq_mutex);
-
        /* Set up register offsets */
        i40e_adminq_init_regs(hw);
 
@@ -664,8 +660,6 @@ i40e_status i40e_shutdown_adminq(struct i40e_hw *hw)
        i40e_shutdown_asq(hw);
        i40e_shutdown_arq(hw);
 
-       /* destroy the locks */
-
        if (hw->nvm_buff.va)
                i40e_free_virt_mem(hw, &hw->nvm_buff);
 
index b825f978d441d1987581b249694298bb5996538d..4a9873ec28c7119d28aabb791bd0628ceccf56ad 100644 (file)
@@ -10295,6 +10295,12 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* set up a default setting for link flow control */
        pf->hw.fc.requested_mode = I40E_FC_NONE;
 
+       /* set up the locks for the AQ, do this only once in probe
+        * and destroy them only once in remove
+        */
+       mutex_init(&hw->aq.asq_mutex);
+       mutex_init(&hw->aq.arq_mutex);
+
        err = i40e_init_adminq(hw);
 
        /* provide nvm, fw, api versions */
@@ -10697,7 +10703,6 @@ static void i40e_remove(struct pci_dev *pdev)
        set_bit(__I40E_DOWN, &pf->state);
        del_timer_sync(&pf->service_timer);
        cancel_work_sync(&pf->service_task);
-       i40e_fdir_teardown(pf);
 
        if (pf->flags & I40E_FLAG_SRIOV_ENABLED) {
                i40e_free_vfs(pf);
@@ -10740,6 +10745,10 @@ static void i40e_remove(struct pci_dev *pdev)
                         "Failed to destroy the Admin Queue resources: %d\n",
                         ret_code);
 
+       /* destroy the locks only once, here */
+       mutex_destroy(&hw->aq.arq_mutex);
+       mutex_destroy(&hw->aq.asq_mutex);
+
        /* Clear all dynamic memory lists of rings, q_vectors, and VSIs */
        i40e_clear_interrupt_scheme(pf);
        for (i = 0; i < pf->num_alloc_vsi; i++) {
index fd123ca60761e84721a02ab991ed677925338126..3f65e39b3fe43b9231ab28bfe32b8728aba95ce1 100644 (file)
@@ -551,10 +551,6 @@ i40e_status i40evf_init_adminq(struct i40e_hw *hw)
                goto init_adminq_exit;
        }
 
-       /* initialize locks */
-       mutex_init(&hw->aq.asq_mutex);
-       mutex_init(&hw->aq.arq_mutex);
-
        /* Set up register offsets */
        i40e_adminq_init_regs(hw);
 
@@ -596,8 +592,6 @@ i40e_status i40evf_shutdown_adminq(struct i40e_hw *hw)
        i40e_shutdown_asq(hw);
        i40e_shutdown_arq(hw);
 
-       /* destroy the locks */
-
        if (hw->nvm_buff.va)
                i40e_free_virt_mem(hw, &hw->nvm_buff);
 
index d962164dfb0fbf579a150223b8d594ecb073b51f..99d2cffae0cd8c2b4c583f4453aa3c09cc58f3eb 100644 (file)
@@ -2476,6 +2476,12 @@ static int i40evf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        hw->bus.device = PCI_SLOT(pdev->devfn);
        hw->bus.func = PCI_FUNC(pdev->devfn);
 
+       /* set up the locks for the AQ, do this only once in probe
+        * and destroy them only once in remove
+        */
+       mutex_init(&hw->aq.asq_mutex);
+       mutex_init(&hw->aq.arq_mutex);
+
        INIT_LIST_HEAD(&adapter->mac_filter_list);
        INIT_LIST_HEAD(&adapter->vlan_filter_list);
 
@@ -2629,6 +2635,10 @@ static void i40evf_remove(struct pci_dev *pdev)
        if (hw->aq.asq.count)
                i40evf_shutdown_adminq(hw);
 
+       /* destroy the locks only once, here */
+       mutex_destroy(&hw->aq.arq_mutex);
+       mutex_destroy(&hw->aq.asq_mutex);
+
        iounmap(hw->hw_addr);
        pci_release_regions(pdev);
 
index 47395ff5d908c43174a4c6afc4a8a089ae948c70..aed8d029b23dc53a7a630d74816e37d35bdbbc4a 100644 (file)
@@ -7920,6 +7920,9 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc)
         */
        if (netif_running(dev))
                ixgbe_close(dev);
+       else
+               ixgbe_reset(adapter);
+
        ixgbe_clear_interrupt_scheme(adapter);
 
 #ifdef CONFIG_IXGBE_DCB
index d9884fd15b453e2486177d58b7fc40bcd5aaf7cc..a4beccf1fd46e26483dc796829d444a15f77723f 100644 (file)
@@ -3413,16 +3413,23 @@ static void mvpp2_bm_pool_bufsize_set(struct mvpp2 *priv,
 }
 
 /* Free all buffers from the pool */
-static void mvpp2_bm_bufs_free(struct mvpp2 *priv, struct mvpp2_bm_pool *bm_pool)
+static void mvpp2_bm_bufs_free(struct device *dev, struct mvpp2 *priv,
+                              struct mvpp2_bm_pool *bm_pool)
 {
        int i;
 
        for (i = 0; i < bm_pool->buf_num; i++) {
+               dma_addr_t buf_phys_addr;
                u32 vaddr;
 
                /* Get buffer virtual address (indirect access) */
-               mvpp2_read(priv, MVPP2_BM_PHY_ALLOC_REG(bm_pool->id));
+               buf_phys_addr = mvpp2_read(priv,
+                                          MVPP2_BM_PHY_ALLOC_REG(bm_pool->id));
                vaddr = mvpp2_read(priv, MVPP2_BM_VIRT_ALLOC_REG);
+
+               dma_unmap_single(dev, buf_phys_addr,
+                                bm_pool->buf_size, DMA_FROM_DEVICE);
+
                if (!vaddr)
                        break;
                dev_kfree_skb_any((struct sk_buff *)vaddr);
@@ -3439,7 +3446,7 @@ static int mvpp2_bm_pool_destroy(struct platform_device *pdev,
 {
        u32 val;
 
-       mvpp2_bm_bufs_free(priv, bm_pool);
+       mvpp2_bm_bufs_free(&pdev->dev, priv, bm_pool);
        if (bm_pool->buf_num) {
                WARN(1, "cannot free all buffers in pool %d\n", bm_pool->id);
                return 0;
@@ -3692,7 +3699,8 @@ mvpp2_bm_pool_use(struct mvpp2_port *port, int pool, enum mvpp2_bm_type type,
                                   MVPP2_BM_LONG_BUF_NUM :
                                   MVPP2_BM_SHORT_BUF_NUM;
                else
-                       mvpp2_bm_bufs_free(port->priv, new_pool);
+                       mvpp2_bm_bufs_free(port->dev->dev.parent,
+                                          port->priv, new_pool);
 
                new_pool->pkt_size = pkt_size;
 
@@ -3756,7 +3764,7 @@ static int mvpp2_bm_update_mtu(struct net_device *dev, int mtu)
        int pkt_size = MVPP2_RX_PKT_SIZE(mtu);
 
        /* Update BM pool with new buffer size */
-       mvpp2_bm_bufs_free(port->priv, port_pool);
+       mvpp2_bm_bufs_free(dev->dev.parent, port->priv, port_pool);
        if (port_pool->buf_num) {
                WARN(1, "cannot free all buffers in pool %d\n", port_pool->id);
                return -EIO;
@@ -4401,11 +4409,10 @@ static void mvpp2_txq_bufs_free(struct mvpp2_port *port,
 
                mvpp2_txq_inc_get(txq_pcpu);
 
-               if (!skb)
-                       continue;
-
                dma_unmap_single(port->dev->dev.parent, buf_phys_addr,
                                 skb_headlen(skb), DMA_TO_DEVICE);
+               if (!skb)
+                       continue;
                dev_kfree_skb_any(skb);
        }
 }
@@ -5092,7 +5099,8 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
                    struct mvpp2_rx_queue *rxq)
 {
        struct net_device *dev = port->dev;
-       int rx_received, rx_filled, i;
+       int rx_received;
+       int rx_done = 0;
        u32 rcvd_pkts = 0;
        u32 rcvd_bytes = 0;
 
@@ -5101,17 +5109,18 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
        if (rx_todo > rx_received)
                rx_todo = rx_received;
 
-       rx_filled = 0;
-       for (i = 0; i < rx_todo; i++) {
+       while (rx_done < rx_todo) {
                struct mvpp2_rx_desc *rx_desc = mvpp2_rxq_next_desc_get(rxq);
                struct mvpp2_bm_pool *bm_pool;
                struct sk_buff *skb;
+               dma_addr_t phys_addr;
                u32 bm, rx_status;
                int pool, rx_bytes, err;
 
-               rx_filled++;
+               rx_done++;
                rx_status = rx_desc->status;
                rx_bytes = rx_desc->data_size - MVPP2_MH_SIZE;
+               phys_addr = rx_desc->buf_phys_addr;
 
                bm = mvpp2_bm_cookie_build(rx_desc);
                pool = mvpp2_bm_cookie_pool_get(bm);
@@ -5128,8 +5137,10 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
                 * comprised by the RX descriptor.
                 */
                if (rx_status & MVPP2_RXD_ERR_SUMMARY) {
+               err_drop_frame:
                        dev->stats.rx_errors++;
                        mvpp2_rx_error(port, rx_desc);
+                       /* Return the buffer to the pool */
                        mvpp2_pool_refill(port, bm, rx_desc->buf_phys_addr,
                                          rx_desc->buf_cookie);
                        continue;
@@ -5137,6 +5148,15 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
 
                skb = (struct sk_buff *)rx_desc->buf_cookie;
 
+               err = mvpp2_rx_refill(port, bm_pool, bm, 0);
+               if (err) {
+                       netdev_err(port->dev, "failed to refill BM pools\n");
+                       goto err_drop_frame;
+               }
+
+               dma_unmap_single(dev->dev.parent, phys_addr,
+                                bm_pool->buf_size, DMA_FROM_DEVICE);
+
                rcvd_pkts++;
                rcvd_bytes += rx_bytes;
                atomic_inc(&bm_pool->in_use);
@@ -5147,12 +5167,6 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
                mvpp2_rx_csum(port, rx_status, skb);
 
                napi_gro_receive(&port->napi, skb);
-
-               err = mvpp2_rx_refill(port, bm_pool, bm, 0);
-               if (err) {
-                       netdev_err(port->dev, "failed to refill BM pools\n");
-                       rx_filled--;
-               }
        }
 
        if (rcvd_pkts) {
@@ -5166,7 +5180,7 @@ static int mvpp2_rx(struct mvpp2_port *port, int rx_todo,
 
        /* Update Rx queue management counters */
        wmb();
-       mvpp2_rxq_status_update(port, rxq->id, rx_todo, rx_filled);
+       mvpp2_rxq_status_update(port, rxq->id, rx_done, rx_done);
 
        return rx_todo;
 }
index 2177e56ed0be7d18ee40d2428b69003bd6f8cca5..d48d5793407d9ec729fe8548a049a2506d02a934 100644 (file)
@@ -1010,7 +1010,7 @@ static int mlx4_MAD_IFC_wrapper(struct mlx4_dev *dev, int slave,
                if (!(smp->mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED &&
                      smp->method == IB_MGMT_METHOD_GET) || network_view) {
                        mlx4_err(dev, "Unprivileged slave %d is trying to execute a Subnet MGMT MAD, class 0x%x, method 0x%x, view=%s for attr 0x%x. Rejecting\n",
-                                slave, smp->method, smp->mgmt_class,
+                                slave, smp->mgmt_class, smp->method,
                                 network_view ? "Network" : "Host",
                                 be16_to_cpu(smp->attr_id));
                        return -EPERM;
index 8a083d73efdbae61e7d71ee364c816b58a16b2f9..038f9ce391e626f02d3fe2f51a19fbd4b08a2711 100644 (file)
@@ -242,6 +242,13 @@ void mlx4_en_init_timestamp(struct mlx4_en_dev *mdev)
        unsigned long flags;
        u64 ns, zero = 0;
 
+       /* mlx4_en_init_timestamp is called for each netdev.
+        * mdev->ptp_clock is common for all ports, skip initialization if
+        * was done for other port.
+        */
+       if (mdev->ptp_clock)
+               return;
+
        rwlock_init(&mdev->clock_lock);
 
        memset(&mdev->cycles, 0, sizeof(mdev->cycles));
index 005f910ec955ecdaaa398c6edcc6d95c01d6c2c4..e0ec280a7fa13a55fd239f84c6f6c24db2c2e5e5 100644 (file)
@@ -232,9 +232,6 @@ static void mlx4_en_remove(struct mlx4_dev *dev, void *endev_ptr)
                if (mdev->pndev[i])
                        mlx4_en_destroy_netdev(mdev->pndev[i]);
 
-       if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
-               mlx4_en_remove_timestamp(mdev);
-
        flush_workqueue(mdev->workqueue);
        destroy_workqueue(mdev->workqueue);
        (void) mlx4_mr_free(dev, &mdev->mr);
@@ -320,10 +317,6 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
        mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH)
                mdev->port_cnt++;
 
-       /* Initialize time stamp mechanism */
-       if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
-               mlx4_en_init_timestamp(mdev);
-
        /* Set default number of RX rings*/
        mlx4_en_set_num_rx_rings(mdev);
 
index 886e1bc86374d990fc92655c7e1b40a3d611b45c..7869f97de5daf94cb99554c51a28a610aca76348 100644 (file)
@@ -2072,6 +2072,9 @@ void mlx4_en_destroy_netdev(struct net_device *dev)
        /* flush any pending task for this netdev */
        flush_workqueue(mdev->workqueue);
 
+       if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
+               mlx4_en_remove_timestamp(mdev);
+
        /* Detach the netdev so tasks would not attempt to access it */
        mutex_lock(&mdev->state_lock);
        mdev->pndev[priv->port] = NULL;
@@ -3058,9 +3061,12 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
        }
        queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
 
+       /* Initialize time stamp mechanism */
        if (mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_TS)
-               queue_delayed_work(mdev->workqueue, &priv->service_task,
-                                  SERVICE_TASK_DELAY);
+               mlx4_en_init_timestamp(mdev);
+
+       queue_delayed_work(mdev->workqueue, &priv->service_task,
+                          SERVICE_TASK_DELAY);
 
        mlx4_en_set_stats_bitmap(mdev->dev, &priv->stats_bitmap,
                                 mdev->profile.prof[priv->port].rx_ppp,
index 6fec3e993d020e34fb2995a221baeac7c25126c6..cad6c44df91c4de9b97d367ede4f2562c65fc86b 100644 (file)
@@ -4306,9 +4306,10 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
                return -EOPNOTSUPP;
 
        ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;
-       ctrl->port = mlx4_slave_convert_port(dev, slave, ctrl->port);
-       if (ctrl->port <= 0)
+       err = mlx4_slave_convert_port(dev, slave, ctrl->port);
+       if (err <= 0)
                return -EINVAL;
+       ctrl->port = err;
        qpn = be32_to_cpu(ctrl->qpn) & 0xffffff;
        err = get_res(dev, slave, qpn, RES_QP, &rqp);
        if (err) {
index b83f7c0fcf9965b30fd179f72fa821b87d928bfd..122c2ee3dfe2aaa5948efd35158bf2fdf32bc0d5 100644 (file)
@@ -1937,6 +1937,12 @@ static void refill_rx(struct net_device *dev)
                                break; /* Better luck next round. */
                        np->rx_dma[entry] = pci_map_single(np->pci_dev,
                                skb->data, buflen, PCI_DMA_FROMDEVICE);
+                       if (pci_dma_mapping_error(np->pci_dev,
+                                                 np->rx_dma[entry])) {
+                               dev_kfree_skb_any(skb);
+                               np->rx_skbuff[entry] = NULL;
+                               break; /* Better luck next round. */
+                       }
                        np->rx_ring[entry].addr = cpu_to_le32(np->rx_dma[entry]);
                }
                np->rx_ring[entry].cmd_status = cpu_to_le32(np->rx_buf_sz);
@@ -2093,6 +2099,12 @@ static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev)
        np->tx_skbuff[entry] = skb;
        np->tx_dma[entry] = pci_map_single(np->pci_dev,
                                skb->data,skb->len, PCI_DMA_TODEVICE);
+       if (pci_dma_mapping_error(np->pci_dev, np->tx_dma[entry])) {
+               np->tx_skbuff[entry] = NULL;
+               dev_kfree_skb_irq(skb);
+               dev->stats.tx_dropped++;
+               return NETDEV_TX_OK;
+       }
 
        np->tx_ring[entry].addr = cpu_to_le32(np->tx_dma[entry]);
 
index ac17d8669b1adad9291a6a39646b51ff80693176..1292c360390cd79d532ca155158858bd630648d5 100644 (file)
@@ -299,6 +299,7 @@ struct qed_hwfn {
 
        /* Flag indicating whether interrupts are enabled or not*/
        bool                            b_int_enabled;
+       bool                            b_int_requested;
 
        struct qed_mcp_info             *mcp_info;
 
@@ -491,6 +492,8 @@ u32 qed_unzip_data(struct qed_hwfn *p_hwfn,
                   u32 input_len, u8 *input_buf,
                   u32 max_size, u8 *unzip_buf);
 
+int qed_slowpath_irq_req(struct qed_hwfn *hwfn);
+
 #define QED_ETH_INTERFACE_VERSION       300
 
 #endif /* _QED_H */
index 803b190ccada97b30b28098666146f9d05ad1c54..817bbd5476ffb5956fca105686fc9029d06339ff 100644 (file)
@@ -1385,52 +1385,63 @@ err0:
        return rc;
 }
 
-static u32 qed_hw_bar_size(struct qed_dev *cdev,
-                          u8 bar_id)
+static u32 qed_hw_bar_size(struct qed_hwfn     *p_hwfn,
+                          u8                   bar_id)
 {
-       u32 size = pci_resource_len(cdev->pdev, (bar_id > 0) ? 2 : 0);
+       u32 bar_reg = (bar_id == 0 ? PGLUE_B_REG_PF_BAR0_SIZE
+                      : PGLUE_B_REG_PF_BAR1_SIZE);
+       u32 val = qed_rd(p_hwfn, p_hwfn->p_main_ptt, bar_reg);
 
-       return size / cdev->num_hwfns;
+       /* Get the BAR size(in KB) from hardware given val */
+       return 1 << (val + 15);
 }
 
 int qed_hw_prepare(struct qed_dev *cdev,
                   int personality)
 {
-       int rc, i;
+       struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
+       int rc;
 
        /* Store the precompiled init data ptrs */
        qed_init_iro_array(cdev);
 
        /* Initialize the first hwfn - will learn number of hwfns */
-       rc = qed_hw_prepare_single(&cdev->hwfns[0], cdev->regview,
+       rc = qed_hw_prepare_single(p_hwfn,
+                                  cdev->regview,
                                   cdev->doorbells, personality);
        if (rc)
                return rc;
 
-       personality = cdev->hwfns[0].hw_info.personality;
+       personality = p_hwfn->hw_info.personality;
 
        /* Initialize the rest of the hwfns */
-       for (i = 1; i < cdev->num_hwfns; i++) {
+       if (cdev->num_hwfns > 1) {
                void __iomem *p_regview, *p_doorbell;
+               u8 __iomem *addr;
+
+               /* adjust bar offset for second engine */
+               addr = cdev->regview + qed_hw_bar_size(p_hwfn, 0) / 2;
+               p_regview = addr;
 
-               p_regview =  cdev->regview +
-                            i * qed_hw_bar_size(cdev, 0);
-               p_doorbell = cdev->doorbells +
-                            i * qed_hw_bar_size(cdev, 1);
-               rc = qed_hw_prepare_single(&cdev->hwfns[i], p_regview,
+               /* adjust doorbell bar offset for second engine */
+               addr = cdev->doorbells + qed_hw_bar_size(p_hwfn, 1) / 2;
+               p_doorbell = addr;
+
+               /* prepare second hw function */
+               rc = qed_hw_prepare_single(&cdev->hwfns[1], p_regview,
                                           p_doorbell, personality);
+
+               /* in case of error, need to free the previously
+                * initiliazed hwfn 0.
+                */
                if (rc) {
-                       /* Cleanup previously initialized hwfns */
-                       while (--i >= 0) {
-                               qed_init_free(&cdev->hwfns[i]);
-                               qed_mcp_free(&cdev->hwfns[i]);
-                               qed_hw_hwfn_free(&cdev->hwfns[i]);
-                       }
-                       return rc;
+                       qed_init_free(p_hwfn);
+                       qed_mcp_free(p_hwfn);
+                       qed_hw_hwfn_free(p_hwfn);
                }
        }
 
-       return 0;
+       return rc;
 }
 
 void qed_hw_remove(struct qed_dev *cdev)
index de50e84902afe3b6a26c422d34a687ec9bc523ec..9cc9d62c1fec64844eba85ca10213a77d3158227 100644 (file)
@@ -783,22 +783,16 @@ void qed_int_igu_enable_int(struct qed_hwfn *p_hwfn,
        qed_wr(p_hwfn, p_ptt, IGU_REG_PF_CONFIGURATION, igu_pf_conf);
 }
 
-void qed_int_igu_enable(struct qed_hwfn *p_hwfn,
-                       struct qed_ptt *p_ptt,
-                       enum qed_int_mode int_mode)
+int qed_int_igu_enable(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
+                      enum qed_int_mode int_mode)
 {
-       int i;
-
-       p_hwfn->b_int_enabled = 1;
+       int rc, i;
 
        /* Mask non-link attentions */
        for (i = 0; i < 9; i++)
                qed_wr(p_hwfn, p_ptt,
                       MISC_REG_AEU_ENABLE1_IGU_OUT_0 + (i << 2), 0);
 
-       /* Enable interrupt Generation */
-       qed_int_igu_enable_int(p_hwfn, p_ptt, int_mode);
-
        /* Configure AEU signal change to produce attentions for link */
        qed_wr(p_hwfn, p_ptt, IGU_REG_LEADING_EDGE_LATCH, 0xfff);
        qed_wr(p_hwfn, p_ptt, IGU_REG_TRAILING_EDGE_LATCH, 0xfff);
@@ -808,6 +802,19 @@ void qed_int_igu_enable(struct qed_hwfn *p_hwfn,
 
        /* Unmask AEU signals toward IGU */
        qed_wr(p_hwfn, p_ptt, MISC_REG_AEU_MASK_ATTN_IGU, 0xff);
+       if ((int_mode != QED_INT_MODE_INTA) || IS_LEAD_HWFN(p_hwfn)) {
+               rc = qed_slowpath_irq_req(p_hwfn);
+               if (rc != 0) {
+                       DP_NOTICE(p_hwfn, "Slowpath IRQ request failed\n");
+                       return -EINVAL;
+               }
+               p_hwfn->b_int_requested = true;
+       }
+       /* Enable interrupt Generation */
+       qed_int_igu_enable_int(p_hwfn, p_ptt, int_mode);
+       p_hwfn->b_int_enabled = 1;
+
+       return rc;
 }
 
 void qed_int_igu_disable_int(struct qed_hwfn *p_hwfn,
@@ -1127,3 +1134,11 @@ int qed_int_get_num_sbs(struct qed_hwfn *p_hwfn,
 
        return info->igu_sb_cnt;
 }
+
+void qed_int_disable_post_isr_release(struct qed_dev *cdev)
+{
+       int i;
+
+       for_each_hwfn(cdev, i)
+               cdev->hwfns[i].b_int_requested = false;
+}
index 16b57518e706728dde646688fb059a3f8f88bb97..51e0b09a7f47d3da8ca9c1d2d0982aa2e77d51f4 100644 (file)
@@ -169,10 +169,14 @@ int qed_int_get_num_sbs(struct qed_hwfn *p_hwfn,
                        int *p_iov_blks);
 
 /**
- * @file
+ * @brief qed_int_disable_post_isr_release - performs the cleanup post ISR
+ *        release. The API need to be called after releasing all slowpath IRQs
+ *        of the device.
+ *
+ * @param cdev
  *
- * @brief Interrupt handler
  */
+void qed_int_disable_post_isr_release(struct qed_dev *cdev);
 
 #define QED_CAU_DEF_RX_TIMER_RES 0
 #define QED_CAU_DEF_TX_TIMER_RES 0
@@ -366,10 +370,11 @@ void qed_int_setup(struct qed_hwfn *p_hwfn,
  * @param p_hwfn
  * @param p_ptt
  * @param int_mode
+ *
+ * @return int
  */
-void qed_int_igu_enable(struct qed_hwfn *p_hwfn,
-                       struct qed_ptt *p_ptt,
-                       enum qed_int_mode int_mode);
+int qed_int_igu_enable(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
+                      enum qed_int_mode int_mode);
 
 /**
  * @brief - Initialize CAU status block entry
index 947c7af72b25b32db163dc3ea47ca7d63db50490..174f7341c5c32c2bbcf81391b02f6d9a6d9327c2 100644 (file)
@@ -476,41 +476,22 @@ static irqreturn_t qed_single_int(int irq, void *dev_instance)
        return rc;
 }
 
-static int qed_slowpath_irq_req(struct qed_dev *cdev)
+int qed_slowpath_irq_req(struct qed_hwfn *hwfn)
 {
-       int i = 0, rc = 0;
+       struct qed_dev *cdev = hwfn->cdev;
+       int rc = 0;
+       u8 id;
 
        if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
-               /* Request all the slowpath MSI-X vectors */
-               for (i = 0; i < cdev->num_hwfns; i++) {
-                       snprintf(cdev->hwfns[i].name, NAME_SIZE,
-                                "sp-%d-%02x:%02x.%02x",
-                                i, cdev->pdev->bus->number,
-                                PCI_SLOT(cdev->pdev->devfn),
-                                cdev->hwfns[i].abs_pf_id);
-
-                       rc = request_irq(cdev->int_params.msix_table[i].vector,
-                                        qed_msix_sp_int, 0,
-                                        cdev->hwfns[i].name,
-                                        cdev->hwfns[i].sp_dpc);
-                       if (rc)
-                               break;
-
-                       DP_VERBOSE(&cdev->hwfns[i],
-                                  (NETIF_MSG_INTR | QED_MSG_SP),
+               id = hwfn->my_id;
+               snprintf(hwfn->name, NAME_SIZE, "sp-%d-%02x:%02x.%02x",
+                        id, cdev->pdev->bus->number,
+                        PCI_SLOT(cdev->pdev->devfn), hwfn->abs_pf_id);
+               rc = request_irq(cdev->int_params.msix_table[id].vector,
+                                qed_msix_sp_int, 0, hwfn->name, hwfn->sp_dpc);
+               if (!rc)
+                       DP_VERBOSE(hwfn, (NETIF_MSG_INTR | QED_MSG_SP),
                                   "Requested slowpath MSI-X\n");
-               }
-
-               if (i != cdev->num_hwfns) {
-                       /* Free already request MSI-X vectors */
-                       for (i--; i >= 0; i--) {
-                               unsigned int vec =
-                                       cdev->int_params.msix_table[i].vector;
-                               synchronize_irq(vec);
-                               free_irq(cdev->int_params.msix_table[i].vector,
-                                        cdev->hwfns[i].sp_dpc);
-                       }
-               }
        } else {
                unsigned long flags = 0;
 
@@ -534,13 +515,17 @@ static void qed_slowpath_irq_free(struct qed_dev *cdev)
 
        if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) {
                for_each_hwfn(cdev, i) {
+                       if (!cdev->hwfns[i].b_int_requested)
+                               break;
                        synchronize_irq(cdev->int_params.msix_table[i].vector);
                        free_irq(cdev->int_params.msix_table[i].vector,
                                 cdev->hwfns[i].sp_dpc);
                }
        } else {
-               free_irq(cdev->pdev->irq, cdev);
+               if (QED_LEADING_HWFN(cdev)->b_int_requested)
+                       free_irq(cdev->pdev->irq, cdev);
        }
+       qed_int_disable_post_isr_release(cdev);
 }
 
 static int qed_nic_stop(struct qed_dev *cdev)
@@ -765,16 +750,11 @@ static int qed_slowpath_start(struct qed_dev *cdev,
        if (rc)
                goto err1;
 
-       /* Request the slowpath IRQ */
-       rc = qed_slowpath_irq_req(cdev);
-       if (rc)
-               goto err2;
-
        /* Allocate stream for unzipping */
        rc = qed_alloc_stream_mem(cdev);
        if (rc) {
                DP_NOTICE(cdev, "Failed to allocate stream memory\n");
-               goto err3;
+               goto err2;
        }
 
        /* Start the slowpath */
index 7a5ce5914ace2287ec73afa20ed2d9d5eb328108..e8df12335a972cd3092cbefa8b675408446f06c9 100644 (file)
                0x7 << 0)
 #define  MCP_REG_NVM_CFG4_FLASH_SIZE_SHIFT \
        0
+#define PGLUE_B_REG_PF_BAR0_SIZE \
+       0x2aae60UL
+#define PGLUE_B_REG_PF_BAR1_SIZE \
+       0x2aae64UL
 #endif
index 31a1f1eb4f56a5d00f0ce3ae75a29af56a96ef12..287fadfab52d754e0a913d4ed044ca7e50cf1a09 100644 (file)
@@ -124,8 +124,12 @@ struct qed_spq {
        dma_addr_t              p_phys;
        struct qed_spq_entry    *p_virt;
 
-       /* Used as index for completions (returns on EQ by FW) */
-       u16                     echo_idx;
+#define SPQ_RING_SIZE \
+       (CORE_SPQE_PAGE_SIZE_BYTES / sizeof(struct slow_path_element))
+
+       /* Bitmap for handling out-of-order completions */
+       DECLARE_BITMAP(p_comp_bitmap, SPQ_RING_SIZE);
+       u8                      comp_bitmap_idx;
 
        /* Statistics */
        u32                     unlimited_pending_count;
index 7c0b8459666ed270ec754a87c9fa1c072d16dd49..3dd548ab8df14aabf9fa6a551cf54aa97f704d12 100644 (file)
@@ -112,8 +112,6 @@ static int
 qed_spq_fill_entry(struct qed_hwfn *p_hwfn,
                   struct qed_spq_entry *p_ent)
 {
-       p_ent->elem.hdr.echo = 0;
-       p_hwfn->p_spq->echo_idx++;
        p_ent->flags = 0;
 
        switch (p_ent->comp_mode) {
@@ -195,10 +193,12 @@ static int qed_spq_hw_post(struct qed_hwfn *p_hwfn,
                           struct qed_spq *p_spq,
                           struct qed_spq_entry *p_ent)
 {
-       struct qed_chain                *p_chain = &p_hwfn->p_spq->chain;
+       struct qed_chain *p_chain = &p_hwfn->p_spq->chain;
+       u16 echo = qed_chain_get_prod_idx(p_chain);
        struct slow_path_element        *elem;
        struct core_db_data             db;
 
+       p_ent->elem.hdr.echo    = cpu_to_le16(echo);
        elem = qed_chain_produce(p_chain);
        if (!elem) {
                DP_NOTICE(p_hwfn, "Failed to produce from SPQ chain\n");
@@ -437,7 +437,9 @@ void qed_spq_setup(struct qed_hwfn *p_hwfn)
        p_spq->comp_count               = 0;
        p_spq->comp_sent_count          = 0;
        p_spq->unlimited_pending_count  = 0;
-       p_spq->echo_idx                 = 0;
+
+       bitmap_zero(p_spq->p_comp_bitmap, SPQ_RING_SIZE);
+       p_spq->comp_bitmap_idx = 0;
 
        /* SPQ cid, cannot fail */
        qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_CORE, &p_spq->cid);
@@ -582,26 +584,32 @@ qed_spq_add_entry(struct qed_hwfn *p_hwfn,
        struct qed_spq *p_spq = p_hwfn->p_spq;
 
        if (p_ent->queue == &p_spq->unlimited_pending) {
-               struct qed_spq_entry *p_en2;
 
                if (list_empty(&p_spq->free_pool)) {
                        list_add_tail(&p_ent->list, &p_spq->unlimited_pending);
                        p_spq->unlimited_pending_count++;
 
                        return 0;
-               }
+               } else {
+                       struct qed_spq_entry *p_en2;
 
-               p_en2 = list_first_entry(&p_spq->free_pool,
-                                        struct qed_spq_entry,
-                                        list);
-               list_del(&p_en2->list);
+                       p_en2 = list_first_entry(&p_spq->free_pool,
+                                                struct qed_spq_entry,
+                                                list);
+                       list_del(&p_en2->list);
+
+                       /* Copy the ring element physical pointer to the new
+                        * entry, since we are about to override the entire ring
+                        * entry and don't want to lose the pointer.
+                        */
+                       p_ent->elem.data_ptr = p_en2->elem.data_ptr;
 
-               /* Strcut assignment */
-               *p_en2 = *p_ent;
+                       *p_en2 = *p_ent;
 
-               kfree(p_ent);
+                       kfree(p_ent);
 
-               p_ent = p_en2;
+                       p_ent = p_en2;
+               }
        }
 
        /* entry is to be placed in 'pending' queue */
@@ -777,13 +785,38 @@ int qed_spq_completion(struct qed_hwfn *p_hwfn,
        list_for_each_entry_safe(p_ent, tmp, &p_spq->completion_pending,
                                 list) {
                if (p_ent->elem.hdr.echo == echo) {
+                       u16 pos = le16_to_cpu(echo) % SPQ_RING_SIZE;
+
                        list_del(&p_ent->list);
 
-                       qed_chain_return_produced(&p_spq->chain);
+                       /* Avoid overriding of SPQ entries when getting
+                        * out-of-order completions, by marking the completions
+                        * in a bitmap and increasing the chain consumer only
+                        * for the first successive completed entries.
+                        */
+                       bitmap_set(p_spq->p_comp_bitmap, pos, SPQ_RING_SIZE);
+
+                       while (test_bit(p_spq->comp_bitmap_idx,
+                                       p_spq->p_comp_bitmap)) {
+                               bitmap_clear(p_spq->p_comp_bitmap,
+                                            p_spq->comp_bitmap_idx,
+                                            SPQ_RING_SIZE);
+                               p_spq->comp_bitmap_idx++;
+                               qed_chain_return_produced(&p_spq->chain);
+                       }
+
                        p_spq->comp_count++;
                        found = p_ent;
                        break;
                }
+
+               /* This is relatively uncommon - depends on scenarios
+                * which have mutliple per-PF sent ramrods.
+                */
+               DP_VERBOSE(p_hwfn, QED_MSG_SPQ,
+                          "Got completion for echo %04x - doesn't match echo %04x in completion pending list\n",
+                          le16_to_cpu(echo),
+                          le16_to_cpu(p_ent->elem.hdr.echo));
        }
 
        /* Release lock before callback, as callback may post
index be7d7a62cc0d8c885c1f669f6c01f0f3a2259ea0..34906750b7e7091f5af122be88c659fd1c77f2e1 100644 (file)
@@ -246,12 +246,13 @@ int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *adapter)
        u32 state;
 
        state = QLCRDX(ahw, QLC_83XX_VNIC_STATE);
-       while (state != QLCNIC_DEV_NPAR_OPER && idc->vnic_wait_limit--) {
+       while (state != QLCNIC_DEV_NPAR_OPER && idc->vnic_wait_limit) {
+               idc->vnic_wait_limit--;
                msleep(1000);
                state = QLCRDX(ahw, QLC_83XX_VNIC_STATE);
        }
 
-       if (!idc->vnic_wait_limit) {
+       if (state != QLCNIC_DEV_NPAR_OPER) {
                dev_err(&adapter->pdev->dev,
                        "vNIC mode not operational, state check timed out.\n");
                return -EIO;
index a5f422f26cb4396a8dc25b65557c83793e956d94..daf05155b7329abdda58e63b1c19be9e06adc699 100644 (file)
@@ -772,8 +772,10 @@ int qlcnic_82xx_config_intrpt(struct qlcnic_adapter *adapter, u8 op_type)
        int i, err = 0;
 
        for (i = 0; i < ahw->num_msix; i++) {
-               qlcnic_alloc_mbx_args(&cmd, adapter,
-                                     QLCNIC_CMD_MQ_TX_CONFIG_INTR);
+               err = qlcnic_alloc_mbx_args(&cmd, adapter,
+                                           QLCNIC_CMD_MQ_TX_CONFIG_INTR);
+               if (err)
+                       return err;
                type = op_type ? QLCNIC_INTRPT_ADD : QLCNIC_INTRPT_DEL;
                val = type | (ahw->intr_tbl[i].type << 4);
                if (ahw->intr_tbl[i].type == QLCNIC_INTRPT_MSIX)
index 02b7115b6aaa64add8632094f6f0dfe354a89b7d..997976426799d90a328cef4ff958b92ce3ba491c 100644 (file)
@@ -4211,8 +4211,9 @@ static int ql_change_rx_buffers(struct ql_adapter *qdev)
 
        /* Wait for an outstanding reset to complete. */
        if (!test_bit(QL_ADAPTER_UP, &qdev->flags)) {
-               int i = 3;
-               while (i-- && !test_bit(QL_ADAPTER_UP, &qdev->flags)) {
+               int i = 4;
+
+               while (--i && !test_bit(QL_ADAPTER_UP, &qdev->flags)) {
                        netif_err(qdev, ifup, qdev->ndev,
                                  "Waiting for adapter UP...\n");
                        ssleep(1);
index ddb2c6c6ec94013efb5ada465d2c6446c34de5f0..689a4a5c8dcfc30fba2675e17293e98691648dd2 100644 (file)
@@ -736,9 +736,8 @@ qcaspi_netdev_tx_timeout(struct net_device *dev)
        netdev_info(qca->net_dev, "Transmit timeout at %ld, latency %ld\n",
                    jiffies, jiffies - dev->trans_start);
        qca->net_dev->stats.tx_errors++;
-       /* wake the queue if there is room */
-       if (qcaspi_tx_ring_has_space(&qca->txr))
-               netif_wake_queue(dev);
+       /* Trigger tx queue flush and QCA7000 reset */
+       qca->sync = QCASPI_SYNC_UNKNOWN;
 }
 
 static int
index ed5da4d476684d502a7d83469ee83566635d3d46..467d41698fd534e724d53ce03e35091bd01cdcdb 100644 (file)
@@ -905,6 +905,9 @@ static int ravb_phy_init(struct net_device *ndev)
                netdev_info(ndev, "limited PHY to 100Mbit/s\n");
        }
 
+       /* 10BASE is not supported */
+       phydev->supported &= ~PHY_10BT_FEATURES;
+
        netdev_info(ndev, "attached PHY %d (IRQ %d) to driver %s\n",
                    phydev->addr, phydev->irq, phydev->drv->name);
 
@@ -1037,7 +1040,7 @@ static const char ravb_gstrings_stats[][ETH_GSTRING_LEN] = {
        "rx_queue_1_mcast_packets",
        "rx_queue_1_errors",
        "rx_queue_1_crc_errors",
-       "rx_queue_1_frame_errors_",
+       "rx_queue_1_frame_errors",
        "rx_queue_1_length_errors",
        "rx_queue_1_missed_errors",
        "rx_queue_1_over_errors",
index e7bab7909ed9e1868dd5f8457b3cfc96c92788f1..6a8fc0f341ff2528fdda1cb97f8e2934d99c5f14 100644 (file)
@@ -52,6 +52,8 @@
                NETIF_MSG_RX_ERR| \
                NETIF_MSG_TX_ERR)
 
+#define SH_ETH_OFFSET_INVALID  ((u16)~0)
+
 #define SH_ETH_OFFSET_DEFAULTS                 \
        [0 ... SH_ETH_MAX_REGISTER_OFFSET - 1] = SH_ETH_OFFSET_INVALID
 
@@ -404,6 +406,28 @@ static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = {
 static void sh_eth_rcv_snd_disable(struct net_device *ndev);
 static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev);
 
+static void sh_eth_write(struct net_device *ndev, u32 data, int enum_index)
+{
+       struct sh_eth_private *mdp = netdev_priv(ndev);
+       u16 offset = mdp->reg_offset[enum_index];
+
+       if (WARN_ON(offset == SH_ETH_OFFSET_INVALID))
+               return;
+
+       iowrite32(data, mdp->addr + offset);
+}
+
+static u32 sh_eth_read(struct net_device *ndev, int enum_index)
+{
+       struct sh_eth_private *mdp = netdev_priv(ndev);
+       u16 offset = mdp->reg_offset[enum_index];
+
+       if (WARN_ON(offset == SH_ETH_OFFSET_INVALID))
+               return ~0U;
+
+       return ioread32(mdp->addr + offset);
+}
+
 static bool sh_eth_is_gether(struct sh_eth_private *mdp)
 {
        return mdp->reg_offset == sh_eth_offset_gigabit;
@@ -1143,6 +1167,7 @@ static void sh_eth_ring_format(struct net_device *ndev)
        int tx_ringsize = sizeof(*txdesc) * mdp->num_tx_ring;
        int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN + 32 - 1;
        dma_addr_t dma_addr;
+       u32 buf_len;
 
        mdp->cur_rx = 0;
        mdp->cur_tx = 0;
@@ -1163,16 +1188,16 @@ static void sh_eth_ring_format(struct net_device *ndev)
                /* RX descriptor */
                rxdesc = &mdp->rx_ring[i];
                /* The size of the buffer is a multiple of 32 bytes. */
-               rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 32);
-               dma_addr = dma_map_single(&ndev->dev, skb->data,
-                                         rxdesc->buffer_length,
+               buf_len = ALIGN(mdp->rx_buf_sz, 32);
+               rxdesc->len = cpu_to_edmac(mdp, buf_len << 16);
+               dma_addr = dma_map_single(&ndev->dev, skb->data, buf_len,
                                          DMA_FROM_DEVICE);
                if (dma_mapping_error(&ndev->dev, dma_addr)) {
                        kfree_skb(skb);
                        break;
                }
                mdp->rx_skbuff[i] = skb;
-               rxdesc->addr = dma_addr;
+               rxdesc->addr = cpu_to_edmac(mdp, dma_addr);
                rxdesc->status = cpu_to_edmac(mdp, RD_RACT | RD_RFP);
 
                /* Rx descriptor address set */
@@ -1196,7 +1221,7 @@ static void sh_eth_ring_format(struct net_device *ndev)
                mdp->tx_skbuff[i] = NULL;
                txdesc = &mdp->tx_ring[i];
                txdesc->status = cpu_to_edmac(mdp, TD_TFP);
-               txdesc->buffer_length = 0;
+               txdesc->len = cpu_to_edmac(mdp, 0);
                if (i == 0) {
                        /* Tx descriptor address set */
                        sh_eth_write(ndev, mdp->tx_desc_dma, TDLAR);
@@ -1403,8 +1428,10 @@ static int sh_eth_txfree(struct net_device *ndev)
                           entry, edmac_to_cpu(mdp, txdesc->status));
                /* Free the original skb. */
                if (mdp->tx_skbuff[entry]) {
-                       dma_unmap_single(&ndev->dev, txdesc->addr,
-                                        txdesc->buffer_length, DMA_TO_DEVICE);
+                       dma_unmap_single(&ndev->dev,
+                                        edmac_to_cpu(mdp, txdesc->addr),
+                                        edmac_to_cpu(mdp, txdesc->len) >> 16,
+                                        DMA_TO_DEVICE);
                        dev_kfree_skb_irq(mdp->tx_skbuff[entry]);
                        mdp->tx_skbuff[entry] = NULL;
                        free_num++;
@@ -1414,7 +1441,7 @@ static int sh_eth_txfree(struct net_device *ndev)
                        txdesc->status |= cpu_to_edmac(mdp, TD_TDLE);
 
                ndev->stats.tx_packets++;
-               ndev->stats.tx_bytes += txdesc->buffer_length;
+               ndev->stats.tx_bytes += edmac_to_cpu(mdp, txdesc->len) >> 16;
        }
        return free_num;
 }
@@ -1433,6 +1460,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
        u32 desc_status;
        int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN + 32 - 1;
        dma_addr_t dma_addr;
+       u32 buf_len;
 
        boguscnt = min(boguscnt, *quota);
        limit = boguscnt;
@@ -1441,7 +1469,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
                /* RACT bit must be checked before all the following reads */
                dma_rmb();
                desc_status = edmac_to_cpu(mdp, rxdesc->status);
-               pkt_len = rxdesc->frame_length;
+               pkt_len = edmac_to_cpu(mdp, rxdesc->len) & RD_RFL;
 
                if (--boguscnt < 0)
                        break;
@@ -1462,6 +1490,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
                if (mdp->cd->shift_rd0)
                        desc_status >>= 16;
 
+               skb = mdp->rx_skbuff[entry];
                if (desc_status & (RD_RFS1 | RD_RFS2 | RD_RFS3 | RD_RFS4 |
                                   RD_RFS5 | RD_RFS6 | RD_RFS10)) {
                        ndev->stats.rx_errors++;
@@ -1477,16 +1506,16 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
                                ndev->stats.rx_missed_errors++;
                        if (desc_status & RD_RFS10)
                                ndev->stats.rx_over_errors++;
-               } else {
+               } else  if (skb) {
+                       dma_addr = edmac_to_cpu(mdp, rxdesc->addr);
                        if (!mdp->cd->hw_swap)
                                sh_eth_soft_swap(
-                                       phys_to_virt(ALIGN(rxdesc->addr, 4)),
+                                       phys_to_virt(ALIGN(dma_addr, 4)),
                                        pkt_len + 2);
-                       skb = mdp->rx_skbuff[entry];
                        mdp->rx_skbuff[entry] = NULL;
                        if (mdp->cd->rpadir)
                                skb_reserve(skb, NET_IP_ALIGN);
-                       dma_unmap_single(&ndev->dev, rxdesc->addr,
+                       dma_unmap_single(&ndev->dev, dma_addr,
                                         ALIGN(mdp->rx_buf_sz, 32),
                                         DMA_FROM_DEVICE);
                        skb_put(skb, pkt_len);
@@ -1506,7 +1535,8 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
                entry = mdp->dirty_rx % mdp->num_rx_ring;
                rxdesc = &mdp->rx_ring[entry];
                /* The size of the buffer is 32 byte boundary. */
-               rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 32);
+               buf_len = ALIGN(mdp->rx_buf_sz, 32);
+               rxdesc->len = cpu_to_edmac(mdp, buf_len << 16);
 
                if (mdp->rx_skbuff[entry] == NULL) {
                        skb = netdev_alloc_skb(ndev, skbuff_size);
@@ -1514,8 +1544,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
                                break;  /* Better luck next round. */
                        sh_eth_set_receive_align(skb);
                        dma_addr = dma_map_single(&ndev->dev, skb->data,
-                                                 rxdesc->buffer_length,
-                                                 DMA_FROM_DEVICE);
+                                                 buf_len, DMA_FROM_DEVICE);
                        if (dma_mapping_error(&ndev->dev, dma_addr)) {
                                kfree_skb(skb);
                                break;
@@ -1523,7 +1552,7 @@ static int sh_eth_rx(struct net_device *ndev, u32 intr_status, int *quota)
                        mdp->rx_skbuff[entry] = skb;
 
                        skb_checksum_none_assert(skb);
-                       rxdesc->addr = dma_addr;
+                       rxdesc->addr = cpu_to_edmac(mdp, dma_addr);
                }
                dma_wmb(); /* RACT bit must be set after all the above writes */
                if (entry >= mdp->num_rx_ring - 1)
@@ -2331,8 +2360,8 @@ static void sh_eth_tx_timeout(struct net_device *ndev)
        /* Free all the skbuffs in the Rx queue. */
        for (i = 0; i < mdp->num_rx_ring; i++) {
                rxdesc = &mdp->rx_ring[i];
-               rxdesc->status = 0;
-               rxdesc->addr = 0xBADF00D0;
+               rxdesc->status = cpu_to_edmac(mdp, 0);
+               rxdesc->addr = cpu_to_edmac(mdp, 0xBADF00D0);
                dev_kfree_skb(mdp->rx_skbuff[i]);
                mdp->rx_skbuff[i] = NULL;
        }
@@ -2350,6 +2379,7 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
        struct sh_eth_private *mdp = netdev_priv(ndev);
        struct sh_eth_txdesc *txdesc;
+       dma_addr_t dma_addr;
        u32 entry;
        unsigned long flags;
 
@@ -2372,15 +2402,15 @@ static int sh_eth_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        txdesc = &mdp->tx_ring[entry];
        /* soft swap. */
        if (!mdp->cd->hw_swap)
-               sh_eth_soft_swap(phys_to_virt(ALIGN(txdesc->addr, 4)),
-                                skb->len + 2);
-       txdesc->addr = dma_map_single(&ndev->dev, skb->data, skb->len,
-                                     DMA_TO_DEVICE);
-       if (dma_mapping_error(&ndev->dev, txdesc->addr)) {
+               sh_eth_soft_swap(PTR_ALIGN(skb->data, 4), skb->len + 2);
+       dma_addr = dma_map_single(&ndev->dev, skb->data, skb->len,
+                                 DMA_TO_DEVICE);
+       if (dma_mapping_error(&ndev->dev, dma_addr)) {
                kfree_skb(skb);
                return NETDEV_TX_OK;
        }
-       txdesc->buffer_length = skb->len;
+       txdesc->addr = cpu_to_edmac(mdp, dma_addr);
+       txdesc->len  = cpu_to_edmac(mdp, skb->len << 16);
 
        dma_wmb(); /* TACT bit must be set after all the above writes */
        if (entry >= mdp->num_tx_ring - 1)
index 50382b1c9ddcf2e5b656c98236c0e7364ee3c1f2..72fcfc9245891e06bc4d37fd0e72a33880b48cd5 100644 (file)
@@ -283,7 +283,7 @@ enum DMAC_IM_BIT {
        DMAC_M_RINT1 = 0x00000001,
 };
 
-/* Receive descriptor bit */
+/* Receive descriptor 0 bits */
 enum RD_STS_BIT {
        RD_RACT = 0x80000000, RD_RDLE = 0x40000000,
        RD_RFP1 = 0x20000000, RD_RFP0 = 0x10000000,
@@ -298,6 +298,12 @@ enum RD_STS_BIT {
 #define RDFEND RD_RFP0
 #define RD_RFP (RD_RFP1|RD_RFP0)
 
+/* Receive descriptor 1 bits */
+enum RD_LEN_BIT {
+       RD_RFL  = 0x0000ffff,   /* receive frame  length */
+       RD_RBL  = 0xffff0000,   /* receive buffer length */
+};
+
 /* FCFTR */
 enum FCFTR_BIT {
        FCFTR_RFF2 = 0x00040000, FCFTR_RFF1 = 0x00020000,
@@ -307,7 +313,7 @@ enum FCFTR_BIT {
 #define DEFAULT_FIFO_F_D_RFF   (FCFTR_RFF2 | FCFTR_RFF1 | FCFTR_RFF0)
 #define DEFAULT_FIFO_F_D_RFD   (FCFTR_RFD2 | FCFTR_RFD1 | FCFTR_RFD0)
 
-/* Transmit descriptor bit */
+/* Transmit descriptor 0 bits */
 enum TD_STS_BIT {
        TD_TACT = 0x80000000, TD_TDLE = 0x40000000,
        TD_TFP1 = 0x20000000, TD_TFP0 = 0x10000000,
@@ -317,6 +323,11 @@ enum TD_STS_BIT {
 #define TDFEND TD_TFP0
 #define TD_TFP (TD_TFP1|TD_TFP0)
 
+/* Transmit descriptor 1 bits */
+enum TD_LEN_BIT {
+       TD_TBL  = 0xffff0000,   /* transmit buffer length */
+};
+
 /* RMCR */
 enum RMCR_BIT {
        RMCR_RNC = 0x00000001,
@@ -425,15 +436,9 @@ enum TSU_FWSLC_BIT {
  */
 struct sh_eth_txdesc {
        u32 status;             /* TD0 */
-#if defined(__LITTLE_ENDIAN)
-       u16 pad0;               /* TD1 */
-       u16 buffer_length;      /* TD1 */
-#else
-       u16 buffer_length;      /* TD1 */
-       u16 pad0;               /* TD1 */
-#endif
+       u32 len;                /* TD1 */
        u32 addr;               /* TD2 */
-       u32 pad1;               /* padding data */
+       u32 pad0;               /* padding data */
 } __aligned(2) __packed;
 
 /* The sh ether Rx buffer descriptors.
@@ -441,13 +446,7 @@ struct sh_eth_txdesc {
  */
 struct sh_eth_rxdesc {
        u32 status;             /* RD0 */
-#if defined(__LITTLE_ENDIAN)
-       u16 frame_length;       /* RD1 */
-       u16 buffer_length;      /* RD1 */
-#else
-       u16 buffer_length;      /* RD1 */
-       u16 frame_length;       /* RD1 */
-#endif
+       u32 len;                /* RD1 */
        u32 addr;               /* RD2 */
        u32 pad0;               /* padding data */
 } __aligned(2) __packed;
@@ -546,31 +545,6 @@ static inline void sh_eth_soft_swap(char *src, int len)
 #endif
 }
 
-#define SH_ETH_OFFSET_INVALID  ((u16) ~0)
-
-static inline void sh_eth_write(struct net_device *ndev, u32 data,
-                               int enum_index)
-{
-       struct sh_eth_private *mdp = netdev_priv(ndev);
-       u16 offset = mdp->reg_offset[enum_index];
-
-       if (WARN_ON(offset == SH_ETH_OFFSET_INVALID))
-               return;
-
-       iowrite32(data, mdp->addr + offset);
-}
-
-static inline u32 sh_eth_read(struct net_device *ndev, int enum_index)
-{
-       struct sh_eth_private *mdp = netdev_priv(ndev);
-       u16 offset = mdp->reg_offset[enum_index];
-
-       if (WARN_ON(offset == SH_ETH_OFFSET_INVALID))
-               return ~0U;
-
-       return ioread32(mdp->addr + offset);
-}
-
 static inline void *sh_eth_tsu_get_offset(struct sh_eth_private *mdp,
                                          int enum_index)
 {
index bc6d21b471be4f4ae2f0c4c1cb26430e92c24803..e6a084a6be12d0627da52a42e783839732c05c5e 100644 (file)
@@ -3299,7 +3299,8 @@ static int efx_ef10_filter_remove_internal(struct efx_nic *efx,
 
                new_spec.priority = EFX_FILTER_PRI_AUTO;
                new_spec.flags = (EFX_FILTER_FLAG_RX |
-                                 EFX_FILTER_FLAG_RX_RSS);
+                                 (efx_rss_enabled(efx) ?
+                                  EFX_FILTER_FLAG_RX_RSS : 0));
                new_spec.dmaq_id = 0;
                new_spec.rss_context = EFX_FILTER_RSS_CONTEXT_DEFAULT;
                rc = efx_ef10_filter_push(efx, &new_spec,
@@ -3921,6 +3922,7 @@ static int efx_ef10_filter_insert_addr_list(struct efx_nic *efx,
 {
        struct efx_ef10_filter_table *table = efx->filter_state;
        struct efx_ef10_dev_addr *addr_list;
+       enum efx_filter_flags filter_flags;
        struct efx_filter_spec spec;
        u8 baddr[ETH_ALEN];
        unsigned int i, j;
@@ -3935,11 +3937,11 @@ static int efx_ef10_filter_insert_addr_list(struct efx_nic *efx,
                addr_count = table->dev_uc_count;
        }
 
+       filter_flags = efx_rss_enabled(efx) ? EFX_FILTER_FLAG_RX_RSS : 0;
+
        /* Insert/renew filters */
        for (i = 0; i < addr_count; i++) {
-               efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO,
-                                  EFX_FILTER_FLAG_RX_RSS,
-                                  0);
+               efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, filter_flags, 0);
                efx_filter_set_eth_local(&spec, EFX_FILTER_VID_UNSPEC,
                                         addr_list[i].addr);
                rc = efx_ef10_filter_insert(efx, &spec, true);
@@ -3968,9 +3970,7 @@ static int efx_ef10_filter_insert_addr_list(struct efx_nic *efx,
 
        if (multicast && rollback) {
                /* Also need an Ethernet broadcast filter */
-               efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO,
-                                  EFX_FILTER_FLAG_RX_RSS,
-                                  0);
+               efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, filter_flags, 0);
                eth_broadcast_addr(baddr);
                efx_filter_set_eth_local(&spec, EFX_FILTER_VID_UNSPEC, baddr);
                rc = efx_ef10_filter_insert(efx, &spec, true);
@@ -4000,13 +4000,14 @@ static int efx_ef10_filter_insert_def(struct efx_nic *efx, bool multicast,
 {
        struct efx_ef10_filter_table *table = efx->filter_state;
        struct efx_ef10_nic_data *nic_data = efx->nic_data;
+       enum efx_filter_flags filter_flags;
        struct efx_filter_spec spec;
        u8 baddr[ETH_ALEN];
        int rc;
 
-       efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO,
-                          EFX_FILTER_FLAG_RX_RSS,
-                          0);
+       filter_flags = efx_rss_enabled(efx) ? EFX_FILTER_FLAG_RX_RSS : 0;
+
+       efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO, filter_flags, 0);
 
        if (multicast)
                efx_filter_set_mc_def(&spec);
@@ -4023,8 +4024,7 @@ static int efx_ef10_filter_insert_def(struct efx_nic *efx, bool multicast,
                if (!nic_data->workaround_26807) {
                        /* Also need an Ethernet broadcast filter */
                        efx_filter_init_rx(&spec, EFX_FILTER_PRI_AUTO,
-                                          EFX_FILTER_FLAG_RX_RSS,
-                                          0);
+                                          filter_flags, 0);
                        eth_broadcast_addr(baddr);
                        efx_filter_set_eth_local(&spec, EFX_FILTER_VID_UNSPEC,
                                                 baddr);
index 1aaf76c1ace866d7563afbd1eb19a87ec5ee2ff0..10827476bc0b38237b9b6999a31a907cd330cf9e 100644 (file)
@@ -76,6 +76,11 @@ void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue);
 #define EFX_TXQ_MAX_ENT(efx)   (EFX_WORKAROUND_35388(efx) ? \
                                 EFX_MAX_DMAQ_SIZE / 2 : EFX_MAX_DMAQ_SIZE)
 
+static inline bool efx_rss_enabled(struct efx_nic *efx)
+{
+       return efx->rss_spread > 1;
+}
+
 /* Filters */
 
 void efx_mac_reconfigure(struct efx_nic *efx);
index 5a1c5a8f278ad1690e678b10cec82444ee45bb12..133e9e35be9e9212bf14531bffd1c0cf78fde742 100644 (file)
@@ -2242,7 +2242,7 @@ efx_farch_filter_init_rx_auto(struct efx_nic *efx,
         */
        spec->priority = EFX_FILTER_PRI_AUTO;
        spec->flags = (EFX_FILTER_FLAG_RX |
-                      (efx->n_rx_channels > 1 ? EFX_FILTER_FLAG_RX_RSS : 0) |
+                      (efx_rss_enabled(efx) ? EFX_FILTER_FLAG_RX_RSS : 0) |
                       (efx->rx_scatter ? EFX_FILTER_FLAG_RX_SCATTER : 0));
        spec->dmaq_id = 0;
 }
index 3d5ee3259885d9486933e5b821c3af2a94c910d2..194f67d9f3bfaa81bd99bf3ad64c6c1568476319 100644 (file)
@@ -418,7 +418,7 @@ static void txc_reset_logic_mmd(struct efx_nic *efx, int mmd)
 
        val |= (1 << TXC_GLCMD_LMTSWRST_LBN);
        efx_mdio_write(efx, mmd, TXC_GLRGS_GLCMD, val);
-       while (tries--) {
+       while (--tries) {
                val = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD);
                if (!(val & (1 << TXC_GLCMD_LMTSWRST_LBN)))
                        break;
index 52b8ed9bd87c2e20707c41ab0eaac247de26afce..adff46375a32297ce01a7fdd519483ccc1226012 100644 (file)
@@ -153,7 +153,11 @@ static int sun7i_gmac_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+       ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+       if (ret)
+               sun7i_gmac_exit(pdev, plat_dat->bsp_priv);
+
+       return ret;
 }
 
 static const struct of_device_id sun7i_dwmac_match[] = {
index 3c6549aee11dee5cf13c92c90c5b4b7a8618f375..a5b869eb46783e338708f93c31f33524116e637f 100644 (file)
@@ -3046,8 +3046,6 @@ int stmmac_suspend(struct net_device *ndev)
        priv->hw->dma->stop_tx(priv->ioaddr);
        priv->hw->dma->stop_rx(priv->ioaddr);
 
-       stmmac_clear_descriptors(priv);
-
        /* Enable Power down mode by programming the PMT regs */
        if (device_may_wakeup(priv->device)) {
                priv->hw->mac->pmt(priv->hw, priv->wolopts);
@@ -3105,7 +3103,12 @@ int stmmac_resume(struct net_device *ndev)
 
        netif_device_attach(ndev);
 
-       init_dma_desc_rings(ndev, GFP_ATOMIC);
+       priv->cur_rx = 0;
+       priv->dirty_rx = 0;
+       priv->dirty_tx = 0;
+       priv->cur_tx = 0;
+       stmmac_clear_descriptors(priv);
+
        stmmac_hw_setup(ndev, false);
        stmmac_init_tx_coalesce(priv);
        stmmac_set_rx_mode(ndev);
index 48b92c9de12a5af4f75ab6b48b4ffd39a77d6ed5..fc958067d10a77d248115968ec0dc4625460aee2 100644 (file)
@@ -2026,45 +2026,54 @@ static int cpsw_probe_dt(struct cpsw_priv *priv,
        for_each_child_of_node(node, slave_node) {
                struct cpsw_slave_data *slave_data = data->slave_data + i;
                const void *mac_addr = NULL;
-               u32 phyid;
                int lenp;
                const __be32 *parp;
-               struct device_node *mdio_node;
-               struct platform_device *mdio;
 
                /* This is no slave child node, continue */
                if (strcmp(slave_node->name, "slave"))
                        continue;
 
                priv->phy_node = of_parse_phandle(slave_node, "phy-handle", 0);
+               parp = of_get_property(slave_node, "phy_id", &lenp);
                if (of_phy_is_fixed_link(slave_node)) {
-                       struct phy_device *pd;
+                       struct device_node *phy_node;
+                       struct phy_device *phy_dev;
 
+                       /* In the case of a fixed PHY, the DT node associated
+                        * to the PHY is the Ethernet MAC DT node.
+                        */
                        ret = of_phy_register_fixed_link(slave_node);
                        if (ret)
                                return ret;
-                       pd = of_phy_find_device(slave_node);
-                       if (!pd)
+                       phy_node = of_node_get(slave_node);
+                       phy_dev = of_phy_find_device(phy_node);
+                       if (!phy_dev)
                                return -ENODEV;
                        snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
-                                PHY_ID_FMT, pd->bus->id, pd->phy_id);
-                       goto no_phy_slave;
-               }
-               parp = of_get_property(slave_node, "phy_id", &lenp);
-               if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) {
-                       dev_err(&pdev->dev, "Missing slave[%d] phy_id property\n", i);
+                                PHY_ID_FMT, phy_dev->bus->id, phy_dev->addr);
+               } else if (parp) {
+                       u32 phyid;
+                       struct device_node *mdio_node;
+                       struct platform_device *mdio;
+
+                       if (lenp != (sizeof(__be32) * 2)) {
+                               dev_err(&pdev->dev, "Invalid slave[%d] phy_id property\n", i);
+                               goto no_phy_slave;
+                       }
+                       mdio_node = of_find_node_by_phandle(be32_to_cpup(parp));
+                       phyid = be32_to_cpup(parp+1);
+                       mdio = of_find_device_by_node(mdio_node);
+                       of_node_put(mdio_node);
+                       if (!mdio) {
+                               dev_err(&pdev->dev, "Missing mdio platform device\n");
+                               return -EINVAL;
+                       }
+                       snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
+                                PHY_ID_FMT, mdio->name, phyid);
+               } else {
+                       dev_err(&pdev->dev, "No slave[%d] phy_id or fixed-link property\n", i);
                        goto no_phy_slave;
                }
-               mdio_node = of_find_node_by_phandle(be32_to_cpup(parp));
-               phyid = be32_to_cpup(parp+1);
-               mdio = of_find_device_by_node(mdio_node);
-               of_node_put(mdio_node);
-               if (!mdio) {
-                       dev_err(&pdev->dev, "Missing mdio platform device\n");
-                       return -EINVAL;
-               }
-               snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
-                        PHY_ID_FMT, mdio->name, phyid);
                slave_data->phy_if = of_get_phy_mode(slave_node);
                if (slave_data->phy_if < 0) {
                        dev_err(&pdev->dev, "Missing or malformed slave[%d] phy-mode property\n",
@@ -2418,7 +2427,7 @@ static int cpsw_probe(struct platform_device *pdev)
        ndev->irq = platform_get_irq(pdev, 1);
        if (ndev->irq < 0) {
                dev_err(priv->dev, "error getting irq resource\n");
-               ret = -ENOENT;
+               ret = ndev->irq;
                goto clean_ale_ret;
        }
 
@@ -2439,8 +2448,10 @@ static int cpsw_probe(struct platform_device *pdev)
 
        /* RX IRQ */
        irq = platform_get_irq(pdev, 1);
-       if (irq < 0)
+       if (irq < 0) {
+               ret = irq;
                goto clean_ale_ret;
+       }
 
        priv->irqs_table[0] = irq;
        ret = devm_request_irq(&pdev->dev, irq, cpsw_rx_interrupt,
@@ -2452,8 +2463,10 @@ static int cpsw_probe(struct platform_device *pdev)
 
        /* TX IRQ */
        irq = platform_get_irq(pdev, 2);
-       if (irq < 0)
+       if (irq < 0) {
+               ret = irq;
                goto clean_ale_ret;
+       }
 
        priv->irqs_table[1] = irq;
        ret = devm_request_irq(&pdev->dev, irq, cpsw_tx_interrupt,
index de5c30c9f059203040cc47e83cce76ae9e5bfde6..58efdec12f300dec69f6790c19f7cd56b10a4b22 100644 (file)
@@ -967,8 +967,6 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
        err = udp_tunnel6_xmit_skb(dst, gs6->sock->sk, skb, dev,
                                   &fl6.saddr, &fl6.daddr, prio, ttl,
                                   sport, geneve->dst_port, !udp_csum);
-
-       iptunnel_xmit_stats(err, &dev->stats, dev->tstats);
        return NETDEV_TX_OK;
 
 tx_error:
@@ -1157,7 +1155,7 @@ static int geneve_configure(struct net *net, struct net_device *dev,
        struct geneve_net *gn = net_generic(net, geneve_net_id);
        struct geneve_dev *t, *geneve = netdev_priv(dev);
        bool tun_collect_md, tun_on_same_port;
-       int err;
+       int err, encap_len;
 
        if (!remote)
                return -EINVAL;
@@ -1189,6 +1187,14 @@ static int geneve_configure(struct net *net, struct net_device *dev,
        if (t)
                return -EBUSY;
 
+       /* make enough headroom for basic scenario */
+       encap_len = GENEVE_BASE_HLEN + ETH_HLEN;
+       if (remote->sa.sa_family == AF_INET)
+               encap_len += sizeof(struct iphdr);
+       else
+               encap_len += sizeof(struct ipv6hdr);
+       dev->needed_headroom = encap_len + ETH_HLEN;
+
        if (metadata) {
                if (tun_on_same_port)
                        return -EPERM;
index 7c4a4151ef0f23fca16b0fd957769c09dc5823d0..5a1e98547031953b1eae1db7ae59a3750d935f40 100644 (file)
@@ -683,14 +683,20 @@ static void sixpack_close(struct tty_struct *tty)
        if (!atomic_dec_and_test(&sp->refcnt))
                down(&sp->dead_sem);
 
-       unregister_netdev(sp->dev);
+       /* We must stop the queue to avoid potentially scribbling
+        * on the free buffers. The sp->dead_sem is not sufficient
+        * to protect us from sp->xbuff access.
+        */
+       netif_stop_queue(sp->dev);
 
-       del_timer(&sp->tx_t);
-       del_timer(&sp->resync_t);
+       del_timer_sync(&sp->tx_t);
+       del_timer_sync(&sp->resync_t);
 
        /* Free all 6pack frame buffers. */
        kfree(sp->rbuff);
        kfree(sp->xbuff);
+
+       unregister_netdev(sp->dev);
 }
 
 /* Perform I/O control on an active 6pack channel. */
index 216bfd350169a9da723035876d152e89b17c8432..85828f1534454dbfd4020e6407e6ad2a136af93c 100644 (file)
@@ -797,14 +797,19 @@ static void mkiss_close(struct tty_struct *tty)
         */
        if (!atomic_dec_and_test(&ax->refcnt))
                down(&ax->dead_sem);
-
-       unregister_netdev(ax->dev);
+       /*
+        * Halt the transmit queue so that a new transmit cannot scribble
+        * on our buffers
+        */
+       netif_stop_queue(ax->dev);
 
        /* Free all AX25 frame buffers. */
        kfree(ax->rbuff);
        kfree(ax->xbuff);
 
        ax->tty = NULL;
+
+       unregister_netdev(ax->dev);
 }
 
 /* Perform I/O control on an active ax25 channel. */
index 908e8d4863429fb6c11f4a625449500f3be36ce1..7f8e7662e28cbcb97891cb8af27d37c9fbb915c0 100644 (file)
@@ -149,9 +149,14 @@ int mdio_mux_init(struct device *dev,
                }
                cb->bus_number = v;
                cb->parent = pb;
+
                cb->mii_bus = mdiobus_alloc();
+               if (!cb->mii_bus) {
+                       ret_val = -ENOMEM;
+                       of_node_put(child_bus_node);
+                       break;
+               }
                cb->mii_bus->priv = cb;
-
                cb->mii_bus->irq = cb->phy_irq;
                cb->mii_bus->name = "mdio_mux";
                snprintf(cb->mii_bus->id, MII_BUS_ID_SIZE, "%x.%x",
index cf6312fafea545fbc3efb96e8ff6c63b35c7420e..e13ad6cdcc2216ca1d43b78bb41cac12933fe2b4 100644 (file)
@@ -339,9 +339,18 @@ static int ksz9021_config_init(struct phy_device *phydev)
 {
        const struct device *dev = &phydev->dev;
        const struct device_node *of_node = dev->of_node;
+       const struct device *dev_walker;
 
-       if (!of_node && dev->parent->of_node)
-               of_node = dev->parent->of_node;
+       /* The Micrel driver has a deprecated option to place phy OF
+        * properties in the MAC node. Walk up the tree of devices to
+        * find a device with an OF node.
+        */
+       dev_walker = &phydev->dev;
+       do {
+               of_node = dev_walker->of_node;
+               dev_walker = dev_walker->parent;
+
+       } while (!of_node && dev_walker);
 
        if (of_node) {
                ksz9021_load_values_from_of(phydev, of_node,
index 5e0b43283bce2c4f5251e5c5db982ca679526d07..0a37f840fcc52d17cee2d23dce50d27723735bad 100644 (file)
@@ -568,6 +568,9 @@ static int pppoe_create(struct net *net, struct socket *sock, int kern)
        sk->sk_family           = PF_PPPOX;
        sk->sk_protocol         = PX_PROTO_OE;
 
+       INIT_WORK(&pppox_sk(sk)->proto.pppoe.padt_work,
+                 pppoe_unbind_sock_work);
+
        return 0;
 }
 
@@ -632,8 +635,6 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
 
        lock_sock(sk);
 
-       INIT_WORK(&po->proto.pppoe.padt_work, pppoe_unbind_sock_work);
-
        error = -EINVAL;
        if (sp->sa_protocol != PX_PROTO_OE)
                goto end;
@@ -663,8 +664,13 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
                        po->pppoe_dev = NULL;
                }
 
-               memset(sk_pppox(po) + 1, 0,
-                      sizeof(struct pppox_sock) - sizeof(struct sock));
+               po->pppoe_ifindex = 0;
+               memset(&po->pppoe_pa, 0, sizeof(po->pppoe_pa));
+               memset(&po->pppoe_relay, 0, sizeof(po->pppoe_relay));
+               memset(&po->chan, 0, sizeof(po->chan));
+               po->next = NULL;
+               po->num = 0;
+
                sk->sk_state = PPPOX_NONE;
        }
 
index fc69e41d09506e96b38f067fa05175bd680fa36b..597c53e0a2ecce6a7fecaaf5032006f31795b307 100644 (file)
@@ -419,6 +419,9 @@ static int pptp_bind(struct socket *sock, struct sockaddr *uservaddr,
        struct pptp_opt *opt = &po->proto.pptp;
        int error = 0;
 
+       if (sockaddr_len < sizeof(struct sockaddr_pppox))
+               return -EINVAL;
+
        lock_sock(sk);
 
        opt->src_addr = sp->sa_addr.pptp;
@@ -440,6 +443,9 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr,
        struct flowi4 fl4;
        int error = 0;
 
+       if (sockaddr_len < sizeof(struct sockaddr_pppox))
+               return -EINVAL;
+
        if (sp->sa_protocol != PX_PROTO_PPTP)
                return -EINVAL;
 
index bbde9884ab8ae7fb952cbf6583feff10c9ce1109..bdd83d95ec0aa677b8443476ef2ee66018aff701 100644 (file)
@@ -100,7 +100,7 @@ static const struct net_device_ops cdc_mbim_netdev_ops = {
        .ndo_stop             = usbnet_stop,
        .ndo_start_xmit       = usbnet_start_xmit,
        .ndo_tx_timeout       = usbnet_tx_timeout,
-       .ndo_change_mtu       = usbnet_change_mtu,
+       .ndo_change_mtu       = cdc_ncm_change_mtu,
        .ndo_set_mac_address  = eth_mac_addr,
        .ndo_validate_addr    = eth_validate_addr,
        .ndo_vlan_rx_add_vid  = cdc_mbim_rx_add_vid,
@@ -158,7 +158,7 @@ static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf)
        if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
                goto err;
 
-       ret = cdc_ncm_bind_common(dev, intf, data_altsetting, 0);
+       ret = cdc_ncm_bind_common(dev, intf, data_altsetting, dev->driver_info->data);
        if (ret)
                goto err;
 
@@ -582,6 +582,26 @@ static const struct driver_info cdc_mbim_info_zlp = {
        .tx_fixup = cdc_mbim_tx_fixup,
 };
 
+/* The spefication explicitly allows NDPs to be placed anywhere in the
+ * frame, but some devices fail unless the NDP is placed after the IP
+ * packets.  Using the CDC_NCM_FLAG_NDP_TO_END flags to force this
+ * behaviour.
+ *
+ * Note: The current implementation of this feature restricts each NTB
+ * to a single NDP, implying that multiplexed sessions cannot share an
+ * NTB. This might affect performace for multiplexed sessions.
+ */
+static const struct driver_info cdc_mbim_info_ndp_to_end = {
+       .description = "CDC MBIM",
+       .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN,
+       .bind = cdc_mbim_bind,
+       .unbind = cdc_mbim_unbind,
+       .manage_power = cdc_mbim_manage_power,
+       .rx_fixup = cdc_mbim_rx_fixup,
+       .tx_fixup = cdc_mbim_tx_fixup,
+       .data = CDC_NCM_FLAG_NDP_TO_END,
+};
+
 static const struct usb_device_id mbim_devs[] = {
        /* This duplicate NCM entry is intentional. MBIM devices can
         * be disguised as NCM by default, and this is necessary to
@@ -597,6 +617,10 @@ static const struct usb_device_id mbim_devs[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(0x0bdb, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
          .driver_info = (unsigned long)&cdc_mbim_info,
        },
+       /* Huawei E3372 fails unless NDP comes after the IP packets */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x12d1, 0x157d, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
+         .driver_info = (unsigned long)&cdc_mbim_info_ndp_to_end,
+       },
        /* default entry */
        { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
          .driver_info = (unsigned long)&cdc_mbim_info_zlp,
index 3b1ba823776842445b5d5b6a709c58208c357f2b..e8a1144c5a8bfa28c1ddca137c56c888b176ab32 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <linux/ctype.h>
+#include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/workqueue.h>
 #include <linux/mii.h>
@@ -689,6 +690,33 @@ static void cdc_ncm_free(struct cdc_ncm_ctx *ctx)
        kfree(ctx);
 }
 
+/* we need to override the usbnet change_mtu ndo for two reasons:
+ *  - respect the negotiated maximum datagram size
+ *  - avoid unwanted changes to rx and tx buffers
+ */
+int cdc_ncm_change_mtu(struct net_device *net, int new_mtu)
+{
+       struct usbnet *dev = netdev_priv(net);
+       struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
+       int maxmtu = ctx->max_datagram_size - cdc_ncm_eth_hlen(dev);
+
+       if (new_mtu <= 0 || new_mtu > maxmtu)
+               return -EINVAL;
+       net->mtu = new_mtu;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(cdc_ncm_change_mtu);
+
+static const struct net_device_ops cdc_ncm_netdev_ops = {
+       .ndo_open            = usbnet_open,
+       .ndo_stop            = usbnet_stop,
+       .ndo_start_xmit      = usbnet_start_xmit,
+       .ndo_tx_timeout      = usbnet_tx_timeout,
+       .ndo_change_mtu      = cdc_ncm_change_mtu,
+       .ndo_set_mac_address = eth_mac_addr,
+       .ndo_validate_addr   = eth_validate_addr,
+};
+
 int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting, int drvflags)
 {
        struct cdc_ncm_ctx *ctx;
@@ -823,6 +851,9 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
        /* add our sysfs attrs */
        dev->net->sysfs_groups[0] = &cdc_ncm_sysfs_attr_group;
 
+       /* must handle MTU changes */
+       dev->net->netdev_ops = &cdc_ncm_netdev_ops;
+
        return 0;
 
 error2:
@@ -955,10 +986,18 @@ static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp(struct cdc_ncm_ctx *ctx, struct sk_
        * NTH16 header as we would normally do. NDP isn't written to the SKB yet, and
        * the wNdpIndex field in the header is actually not consistent with reality. It will be later.
        */
-       if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)
+       if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) {
                if (ctx->delayed_ndp16->dwSignature == sign)
                        return ctx->delayed_ndp16;
 
+               /* We can only push a single NDP to the end. Return
+                * NULL to send what we've already got and queue this
+                * skb for later.
+                */
+               else if (ctx->delayed_ndp16->dwSignature)
+                       return NULL;
+       }
+
        /* follow the chain of NDPs, looking for a match */
        while (ndpoffset) {
                ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb->data + ndpoffset);
@@ -1550,6 +1589,24 @@ static const struct usb_device_id cdc_devs[] = {
          .driver_info = (unsigned long) &wwan_info,
        },
 
+       /* DW5812 LTE Verizon Mobile Broadband Card
+        * Unlike DW5550 this device requires FLAG_NOARP
+        */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x81bb,
+               USB_CLASS_COMM,
+               USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
+         .driver_info = (unsigned long)&wwan_noarp_info,
+       },
+
+       /* DW5813 LTE AT&T Mobile Broadband Card
+        * Unlike DW5550 this device requires FLAG_NOARP
+        */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x413c, 0x81bc,
+               USB_CLASS_COMM,
+               USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
+         .driver_info = (unsigned long)&wwan_noarp_info,
+       },
+
        /* Dell branded MBM devices like DW5550 */
        { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
                | USB_DEVICE_ID_MATCH_VENDOR,
index 9a5be8b851867e53f7427ba31f7a089ad02562fd..5fccc5a8153f4d0f73f0fb212912302c19679c27 100644 (file)
@@ -742,6 +742,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x413c, 0x81a9, 8)},    /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
        {QMI_FIXED_INTF(0x413c, 0x81b1, 8)},    /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */
        {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)},    /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
+       {QMI_FIXED_INTF(0x22de, 0x9061, 3)},    /* WeTelecom WPD-600N */
 
        /* 4. Gobi 1000 devices */
        {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},    /* Acer Gobi Modem Device */
index d9427ca3dba79628f402867b83e735bee78fac3b..2fb637ad594a96fa35f30f686e25973ea70b578a 100644 (file)
@@ -3067,17 +3067,6 @@ static int rtl8152_open(struct net_device *netdev)
 
        mutex_lock(&tp->control);
 
-       /* The WORK_ENABLE may be set when autoresume occurs */
-       if (test_bit(WORK_ENABLE, &tp->flags)) {
-               clear_bit(WORK_ENABLE, &tp->flags);
-               usb_kill_urb(tp->intr_urb);
-               cancel_delayed_work_sync(&tp->schedule);
-
-               /* disable the tx/rx, if the workqueue has enabled them. */
-               if (netif_carrier_ok(netdev))
-                       tp->rtl_ops.disable(tp);
-       }
-
        tp->rtl_ops.up(tp);
 
        rtl8152_set_speed(tp, AUTONEG_ENABLE,
@@ -3124,12 +3113,6 @@ static int rtl8152_close(struct net_device *netdev)
        } else {
                mutex_lock(&tp->control);
 
-               /* The autosuspend may have been enabled and wouldn't
-                * be disable when autoresume occurs, because the
-                * netif_running() would be false.
-                */
-               rtl_runtime_suspend_enable(tp, false);
-
                tp->rtl_ops.down(tp);
 
                mutex_unlock(&tp->control);
@@ -3512,7 +3495,7 @@ static int rtl8152_resume(struct usb_interface *intf)
                netif_device_attach(tp->netdev);
        }
 
-       if (netif_running(tp->netdev)) {
+       if (netif_running(tp->netdev) && tp->netdev->flags & IFF_UP) {
                if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
                        rtl_runtime_suspend_enable(tp, false);
                        clear_bit(SELECTIVE_SUSPEND, &tp->flags);
@@ -3532,6 +3515,8 @@ static int rtl8152_resume(struct usb_interface *intf)
                }
                usb_submit_urb(tp->intr_urb, GFP_KERNEL);
        } else if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
+               if (tp->netdev->flags & IFF_UP)
+                       rtl_runtime_suspend_enable(tp, false);
                clear_bit(SELECTIVE_SUSPEND, &tp->flags);
        }
 
@@ -3540,6 +3525,14 @@ static int rtl8152_resume(struct usb_interface *intf)
        return 0;
 }
 
+static int rtl8152_reset_resume(struct usb_interface *intf)
+{
+       struct r8152 *tp = usb_get_intfdata(intf);
+
+       clear_bit(SELECTIVE_SUSPEND, &tp->flags);
+       return rtl8152_resume(intf);
+}
+
 static void rtl8152_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
        struct r8152 *tp = netdev_priv(dev);
@@ -4291,7 +4284,7 @@ static struct usb_driver rtl8152_driver = {
        .disconnect =   rtl8152_disconnect,
        .suspend =      rtl8152_suspend,
        .resume =       rtl8152_resume,
-       .reset_resume = rtl8152_resume,
+       .reset_resume = rtl8152_reset_resume,
        .pre_reset =    rtl8152_pre_reset,
        .post_reset =   rtl8152_post_reset,
        .supports_autosuspend = 1,
index 0ef4a5ad555739870897bfbb96c7a95847deed20..ba21d072be31c95827833f9e5014f20cfa43bb8b 100644 (file)
@@ -117,12 +117,6 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
                kfree_skb(skb);
                goto drop;
        }
-       /* don't change ip_summed == CHECKSUM_PARTIAL, as that
-        * will cause bad checksum on forwarded packets
-        */
-       if (skb->ip_summed == CHECKSUM_NONE &&
-           rcv->features & NETIF_F_RXCSUM)
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
 
        if (likely(dev_forward_skb(rcv, skb) == NET_RX_SUCCESS)) {
                struct pcpu_vstats *stats = this_cpu_ptr(dev->vstats);
index d8838dedb7a4cd06f54e2fa8a522b6c4bb15091e..f94ab786088fc8fd7f848edeaedd4d2aff160606 100644 (file)
@@ -140,6 +140,12 @@ struct virtnet_info {
 
        /* CPU hot plug notifier */
        struct notifier_block nb;
+
+       /* Control VQ buffers: protected by the rtnl lock */
+       struct virtio_net_ctrl_hdr ctrl_hdr;
+       virtio_net_ctrl_ack ctrl_status;
+       u8 ctrl_promisc;
+       u8 ctrl_allmulti;
 };
 
 struct padded_vnet_hdr {
@@ -976,31 +982,30 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
                                 struct scatterlist *out)
 {
        struct scatterlist *sgs[4], hdr, stat;
-       struct virtio_net_ctrl_hdr ctrl;
-       virtio_net_ctrl_ack status = ~0;
        unsigned out_num = 0, tmp;
 
        /* Caller should know better */
        BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ));
 
-       ctrl.class = class;
-       ctrl.cmd = cmd;
+       vi->ctrl_status = ~0;
+       vi->ctrl_hdr.class = class;
+       vi->ctrl_hdr.cmd = cmd;
        /* Add header */
-       sg_init_one(&hdr, &ctrl, sizeof(ctrl));
+       sg_init_one(&hdr, &vi->ctrl_hdr, sizeof(vi->ctrl_hdr));
        sgs[out_num++] = &hdr;
 
        if (out)
                sgs[out_num++] = out;
 
        /* Add return status. */
-       sg_init_one(&stat, &status, sizeof(status));
+       sg_init_one(&stat, &vi->ctrl_status, sizeof(vi->ctrl_status));
        sgs[out_num] = &stat;
 
        BUG_ON(out_num + 1 > ARRAY_SIZE(sgs));
        virtqueue_add_sgs(vi->cvq, sgs, out_num, 1, vi, GFP_ATOMIC);
 
        if (unlikely(!virtqueue_kick(vi->cvq)))
-               return status == VIRTIO_NET_OK;
+               return vi->ctrl_status == VIRTIO_NET_OK;
 
        /* Spin for a response, the kick causes an ioport write, trapping
         * into the hypervisor, so the request should be handled immediately.
@@ -1009,7 +1014,7 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
               !virtqueue_is_broken(vi->cvq))
                cpu_relax();
 
-       return status == VIRTIO_NET_OK;
+       return vi->ctrl_status == VIRTIO_NET_OK;
 }
 
 static int virtnet_set_mac_address(struct net_device *dev, void *p)
@@ -1151,7 +1156,6 @@ static void virtnet_set_rx_mode(struct net_device *dev)
 {
        struct virtnet_info *vi = netdev_priv(dev);
        struct scatterlist sg[2];
-       u8 promisc, allmulti;
        struct virtio_net_ctrl_mac *mac_data;
        struct netdev_hw_addr *ha;
        int uc_count;
@@ -1163,22 +1167,22 @@ static void virtnet_set_rx_mode(struct net_device *dev)
        if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX))
                return;
 
-       promisc = ((dev->flags & IFF_PROMISC) != 0);
-       allmulti = ((dev->flags & IFF_ALLMULTI) != 0);
+       vi->ctrl_promisc = ((dev->flags & IFF_PROMISC) != 0);
+       vi->ctrl_allmulti = ((dev->flags & IFF_ALLMULTI) != 0);
 
-       sg_init_one(sg, &promisc, sizeof(promisc));
+       sg_init_one(sg, &vi->ctrl_promisc, sizeof(vi->ctrl_promisc));
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
                                  VIRTIO_NET_CTRL_RX_PROMISC, sg))
                dev_warn(&dev->dev, "Failed to %sable promisc mode.\n",
-                        promisc ? "en" : "dis");
+                        vi->ctrl_promisc ? "en" : "dis");
 
-       sg_init_one(sg, &allmulti, sizeof(allmulti));
+       sg_init_one(sg, &vi->ctrl_allmulti, sizeof(vi->ctrl_allmulti));
 
        if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
                                  VIRTIO_NET_CTRL_RX_ALLMULTI, sg))
                dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n",
-                        allmulti ? "en" : "dis");
+                        vi->ctrl_allmulti ? "en" : "dis");
 
        uc_count = netdev_uc_count(dev);
        mc_count = netdev_mc_count(dev);
index 417903715437ebda5b07a859effdca86a62d196b..0cbf520cea778fc703c9657ab2d085eee522634b 100644 (file)
@@ -1380,10 +1380,10 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
                                        skip_page_frags = true;
                                        goto rcd_done;
                                }
-                               new_dma_addr = dma_map_page(&adapter->pdev->dev
-                                                       , rbi->page,
-                                                       0, PAGE_SIZE,
-                                                       PCI_DMA_FROMDEVICE);
+                               new_dma_addr = dma_map_page(&adapter->pdev->dev,
+                                                           new_page,
+                                                           0, PAGE_SIZE,
+                                                           PCI_DMA_FROMDEVICE);
                                if (dma_mapping_error(&adapter->pdev->dev,
                                                      new_dma_addr)) {
                                        put_page(new_page);
index 4c58c83dc2253a43b7c6150866d67bcd0c02e250..bdb8a6c0f8aa2c62e22edc64d3900530477b6fa8 100644 (file)
 /*
  * Version numbers
  */
-#define VMXNET3_DRIVER_VERSION_STRING   "1.4.4.0-k"
+#define VMXNET3_DRIVER_VERSION_STRING   "1.4.5.0-k"
 
 /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */
-#define VMXNET3_DRIVER_VERSION_NUM      0x01040400
+#define VMXNET3_DRIVER_VERSION_NUM      0x01040500
 
 #if defined(CONFIG_PCI_MSI)
        /* RSS only makes sense if MSI-X is supported. */
index 4f9748457f5a722658e5cfb01b6cbcc0f488d14f..0a242b200df4c9e8198a9a74764eb05f89f13cbd 100644 (file)
@@ -800,7 +800,7 @@ static struct rtable *vrf_get_rtable(const struct net_device *dev,
 }
 
 /* called under rcu_read_lock */
-static void vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4)
+static int vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4)
 {
        struct fib_result res = { .tclassid = 0 };
        struct net *net = dev_net(dev);
@@ -808,9 +808,10 @@ static void vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4)
        u8 flags = fl4->flowi4_flags;
        u8 scope = fl4->flowi4_scope;
        u8 tos = RT_FL_TOS(fl4);
+       int rc;
 
        if (unlikely(!fl4->daddr))
-               return;
+               return 0;
 
        fl4->flowi4_flags |= FLOWI_FLAG_SKIP_NH_OIF;
        fl4->flowi4_iif = LOOPBACK_IFINDEX;
@@ -818,7 +819,8 @@ static void vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4)
        fl4->flowi4_scope = ((tos & RTO_ONLINK) ?
                             RT_SCOPE_LINK : RT_SCOPE_UNIVERSE);
 
-       if (!fib_lookup(net, fl4, &res, 0)) {
+       rc = fib_lookup(net, fl4, &res, 0);
+       if (!rc) {
                if (res.type == RTN_LOCAL)
                        fl4->saddr = res.fi->fib_prefsrc ? : fl4->daddr;
                else
@@ -828,6 +830,8 @@ static void vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4)
        fl4->flowi4_flags = flags;
        fl4->flowi4_tos = orig_tos;
        fl4->flowi4_scope = scope;
+
+       return rc;
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
index 6369a5734d4c3e899e96ec74469b0af4b3bca865..ba363cedef80820feb11b5ce6f5f347f8a575d12 100644 (file)
@@ -1158,7 +1158,6 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb,
        struct pcpu_sw_netstats *stats;
        union vxlan_addr saddr;
        int err = 0;
-       union vxlan_addr *remote_ip;
 
        /* For flow based devices, map all packets to VNI 0 */
        if (vs->flags & VXLAN_F_COLLECT_METADATA)
@@ -1169,7 +1168,6 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb,
        if (!vxlan)
                goto drop;
 
-       remote_ip = &vxlan->default_dst.remote_ip;
        skb_reset_mac_header(skb);
        skb_scrub_packet(skb, !net_eq(vxlan->net, dev_net(vxlan->dev)));
        skb->protocol = eth_type_trans(skb, vxlan->dev);
@@ -1179,8 +1177,8 @@ static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb,
        if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr))
                goto drop;
 
-       /* Re-examine inner Ethernet packet */
-       if (remote_ip->sa.sa_family == AF_INET) {
+       /* Get data from the outer IP header */
+       if (vxlan_get_sk_family(vs) == AF_INET) {
                oip = ip_hdr(skb);
                saddr.sin.sin_addr.s_addr = oip->saddr;
                saddr.sa.sa_family = AF_INET;
@@ -1848,6 +1846,34 @@ static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk
                                   !(vxflags & VXLAN_F_UDP_CSUM));
 }
 
+#if IS_ENABLED(CONFIG_IPV6)
+static struct dst_entry *vxlan6_get_route(struct vxlan_dev *vxlan,
+                                         struct sk_buff *skb, int oif,
+                                         const struct in6_addr *daddr,
+                                         struct in6_addr *saddr)
+{
+       struct dst_entry *ndst;
+       struct flowi6 fl6;
+       int err;
+
+       memset(&fl6, 0, sizeof(fl6));
+       fl6.flowi6_oif = oif;
+       fl6.daddr = *daddr;
+       fl6.saddr = vxlan->cfg.saddr.sin6.sin6_addr;
+       fl6.flowi6_mark = skb->mark;
+       fl6.flowi6_proto = IPPROTO_UDP;
+
+       err = ipv6_stub->ipv6_dst_lookup(vxlan->net,
+                                        vxlan->vn6_sock->sock->sk,
+                                        &ndst, &fl6);
+       if (err < 0)
+               return ERR_PTR(err);
+
+       *saddr = fl6.saddr;
+       return ndst;
+}
+#endif
+
 /* Bypass encapsulation if the destination is local */
 static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
                               struct vxlan_dev *dst_vxlan)
@@ -2035,21 +2061,17 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
 #if IS_ENABLED(CONFIG_IPV6)
        } else {
                struct dst_entry *ndst;
-               struct flowi6 fl6;
+               struct in6_addr saddr;
                u32 rt6i_flags;
 
                if (!vxlan->vn6_sock)
                        goto drop;
                sk = vxlan->vn6_sock->sock->sk;
 
-               memset(&fl6, 0, sizeof(fl6));
-               fl6.flowi6_oif = rdst ? rdst->remote_ifindex : 0;
-               fl6.daddr = dst->sin6.sin6_addr;
-               fl6.saddr = vxlan->cfg.saddr.sin6.sin6_addr;
-               fl6.flowi6_mark = skb->mark;
-               fl6.flowi6_proto = IPPROTO_UDP;
-
-               if (ipv6_stub->ipv6_dst_lookup(vxlan->net, sk, &ndst, &fl6)) {
+               ndst = vxlan6_get_route(vxlan, skb,
+                                       rdst ? rdst->remote_ifindex : 0,
+                                       &dst->sin6.sin6_addr, &saddr);
+               if (IS_ERR(ndst)) {
                        netdev_dbg(dev, "no route to %pI6\n",
                                   &dst->sin6.sin6_addr);
                        dev->stats.tx_carrier_errors++;
@@ -2081,7 +2103,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                }
 
                ttl = ttl ? : ip6_dst_hoplimit(ndst);
-               err = vxlan6_xmit_skb(ndst, sk, skb, dev, &fl6.saddr, &fl6.daddr,
+               err = vxlan6_xmit_skb(ndst, sk, skb, dev, &saddr, &dst->sin6.sin6_addr,
                                      0, ttl, src_port, dst_port, htonl(vni << 8), md,
                                      !net_eq(vxlan->net, dev_net(vxlan->dev)),
                                      flags);
@@ -2395,9 +2417,30 @@ static int vxlan_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
                                  vxlan->cfg.port_max, true);
        dport = info->key.tp_dst ? : vxlan->cfg.dst_port;
 
-       if (ip_tunnel_info_af(info) == AF_INET)
+       if (ip_tunnel_info_af(info) == AF_INET) {
+               if (!vxlan->vn4_sock)
+                       return -EINVAL;
                return egress_ipv4_tun_info(dev, skb, info, sport, dport);
-       return -EINVAL;
+       } else {
+#if IS_ENABLED(CONFIG_IPV6)
+               struct dst_entry *ndst;
+
+               if (!vxlan->vn6_sock)
+                       return -EINVAL;
+               ndst = vxlan6_get_route(vxlan, skb, 0,
+                                       &info->key.u.ipv6.dst,
+                                       &info->key.u.ipv6.src);
+               if (IS_ERR(ndst))
+                       return PTR_ERR(ndst);
+               dst_release(ndst);
+
+               info->key.tp_src = sport;
+               info->key.tp_dst = dport;
+#else /* !CONFIG_IPV6 */
+               return -EPFNOSUPPORT;
+#endif
+       }
+       return 0;
 }
 
 static const struct net_device_ops vxlan_netdev_ops = {
index bf88ec3a65fab3e04aab4398185236bdb955126b..d9a4aee246a6379c6a6aee7d6185ff680387c55e 100644 (file)
 #include "iwl-agn-hw.h"
 
 /* Highest firmware API version supported */
-#define IWL7260_UCODE_API_MAX  19
+#define IWL7260_UCODE_API_MAX  17
+#define IWL7265_UCODE_API_MAX  19
+#define IWL7265D_UCODE_API_MAX 19
 
 /* Oldest version we won't warn about */
 #define IWL7260_UCODE_API_OK   13
+#define IWL7265_UCODE_API_OK   13
+#define IWL7265D_UCODE_API_OK  13
 
 /* Lowest firmware API version supported */
 #define IWL7260_UCODE_API_MIN  13
+#define IWL7265_UCODE_API_MIN  13
+#define IWL7265D_UCODE_API_MIN 13
 
 /* NVM versions */
 #define IWL7260_NVM_VERSION            0x0a1d
@@ -149,10 +155,7 @@ static const struct iwl_ht_params iwl7000_ht_params = {
        .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
 };
 
-#define IWL_DEVICE_7000                                                \
-       .ucode_api_max = IWL7260_UCODE_API_MAX,                 \
-       .ucode_api_ok = IWL7260_UCODE_API_OK,                   \
-       .ucode_api_min = IWL7260_UCODE_API_MIN,                 \
+#define IWL_DEVICE_7000_COMMON                                 \
        .device_family = IWL_DEVICE_FAMILY_7000,                \
        .max_inst_size = IWL60_RTC_INST_SIZE,                   \
        .max_data_size = IWL60_RTC_DATA_SIZE,                   \
@@ -163,6 +166,24 @@ static const struct iwl_ht_params iwl7000_ht_params = {
        .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,    \
        .dccm_offset = IWL7000_DCCM_OFFSET
 
+#define IWL_DEVICE_7000                                                \
+       IWL_DEVICE_7000_COMMON,                                 \
+       .ucode_api_max = IWL7260_UCODE_API_MAX,                 \
+       .ucode_api_ok = IWL7260_UCODE_API_OK,                   \
+       .ucode_api_min = IWL7260_UCODE_API_MIN
+
+#define IWL_DEVICE_7005                                                \
+       IWL_DEVICE_7000_COMMON,                                 \
+       .ucode_api_max = IWL7265_UCODE_API_MAX,                 \
+       .ucode_api_ok = IWL7265_UCODE_API_OK,                   \
+       .ucode_api_min = IWL7265_UCODE_API_MIN
+
+#define IWL_DEVICE_7005D                                       \
+       IWL_DEVICE_7000_COMMON,                                 \
+       .ucode_api_max = IWL7265D_UCODE_API_MAX,                \
+       .ucode_api_ok = IWL7265D_UCODE_API_OK,                  \
+       .ucode_api_min = IWL7265D_UCODE_API_MIN
+
 const struct iwl_cfg iwl7260_2ac_cfg = {
        .name = "Intel(R) Dual Band Wireless AC 7260",
        .fw_name_pre = IWL7260_FW_PRE,
@@ -266,7 +287,7 @@ static const struct iwl_ht_params iwl7265_ht_params = {
 const struct iwl_cfg iwl3165_2ac_cfg = {
        .name = "Intel(R) Dual Band Wireless AC 3165",
        .fw_name_pre = IWL7265D_FW_PRE,
-       IWL_DEVICE_7000,
+       IWL_DEVICE_7005D,
        .ht_params = &iwl7000_ht_params,
        .nvm_ver = IWL3165_NVM_VERSION,
        .nvm_calib_ver = IWL3165_TX_POWER_VERSION,
@@ -277,7 +298,7 @@ const struct iwl_cfg iwl3165_2ac_cfg = {
 const struct iwl_cfg iwl7265_2ac_cfg = {
        .name = "Intel(R) Dual Band Wireless AC 7265",
        .fw_name_pre = IWL7265_FW_PRE,
-       IWL_DEVICE_7000,
+       IWL_DEVICE_7005,
        .ht_params = &iwl7265_ht_params,
        .nvm_ver = IWL7265_NVM_VERSION,
        .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
@@ -288,7 +309,7 @@ const struct iwl_cfg iwl7265_2ac_cfg = {
 const struct iwl_cfg iwl7265_2n_cfg = {
        .name = "Intel(R) Dual Band Wireless N 7265",
        .fw_name_pre = IWL7265_FW_PRE,
-       IWL_DEVICE_7000,
+       IWL_DEVICE_7005,
        .ht_params = &iwl7265_ht_params,
        .nvm_ver = IWL7265_NVM_VERSION,
        .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
@@ -299,7 +320,7 @@ const struct iwl_cfg iwl7265_2n_cfg = {
 const struct iwl_cfg iwl7265_n_cfg = {
        .name = "Intel(R) Wireless N 7265",
        .fw_name_pre = IWL7265_FW_PRE,
-       IWL_DEVICE_7000,
+       IWL_DEVICE_7005,
        .ht_params = &iwl7265_ht_params,
        .nvm_ver = IWL7265_NVM_VERSION,
        .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
@@ -310,7 +331,7 @@ const struct iwl_cfg iwl7265_n_cfg = {
 const struct iwl_cfg iwl7265d_2ac_cfg = {
        .name = "Intel(R) Dual Band Wireless AC 7265",
        .fw_name_pre = IWL7265D_FW_PRE,
-       IWL_DEVICE_7000,
+       IWL_DEVICE_7005D,
        .ht_params = &iwl7265_ht_params,
        .nvm_ver = IWL7265D_NVM_VERSION,
        .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
@@ -321,7 +342,7 @@ const struct iwl_cfg iwl7265d_2ac_cfg = {
 const struct iwl_cfg iwl7265d_2n_cfg = {
        .name = "Intel(R) Dual Band Wireless N 7265",
        .fw_name_pre = IWL7265D_FW_PRE,
-       IWL_DEVICE_7000,
+       IWL_DEVICE_7005D,
        .ht_params = &iwl7265_ht_params,
        .nvm_ver = IWL7265D_NVM_VERSION,
        .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
@@ -332,7 +353,7 @@ const struct iwl_cfg iwl7265d_2n_cfg = {
 const struct iwl_cfg iwl7265d_n_cfg = {
        .name = "Intel(R) Wireless N 7265",
        .fw_name_pre = IWL7265D_FW_PRE,
-       IWL_DEVICE_7000,
+       IWL_DEVICE_7005D,
        .ht_params = &iwl7265_ht_params,
        .nvm_ver = IWL7265D_NVM_VERSION,
        .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
@@ -342,5 +363,5 @@ const struct iwl_cfg iwl7265d_n_cfg = {
 
 MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
 MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
-MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
-MODULE_FIRMWARE(IWL7265D_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
+MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7265_UCODE_API_OK));
+MODULE_FIRMWARE(IWL7265D_MODULE_FIRMWARE(IWL7265D_UCODE_API_OK));
index 354acbde088e9e6fad0927a9ef73787ab235558c..2b976b110207f87532162e6f8587c1fcd0063c83 100644 (file)
@@ -1222,8 +1222,8 @@ static u8 iwl_mvm_get_key_sta_id(struct iwl_mvm *mvm,
            mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
                u8 sta_id = mvmvif->ap_sta_id;
 
-               sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
-                                               lockdep_is_held(&mvm->mutex));
+               sta = rcu_dereference_check(mvm->fw_id_to_mac_id[sta_id],
+                                           lockdep_is_held(&mvm->mutex));
                /*
                 * It is possible that the 'sta' parameter is NULL,
                 * for example when a GTK is removed - the sta_id will then
@@ -1590,14 +1590,15 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
                             u16 *phase1key)
 {
        struct iwl_mvm_sta *mvm_sta;
-       u8 sta_id = iwl_mvm_get_key_sta_id(mvm, vif, sta);
+       u8 sta_id;
        bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
 
-       if (WARN_ON_ONCE(sta_id == IWL_MVM_STATION_COUNT))
-               return;
-
        rcu_read_lock();
 
+       sta_id = iwl_mvm_get_key_sta_id(mvm, vif, sta);
+       if (WARN_ON_ONCE(sta_id == IWL_MVM_STATION_COUNT))
+               goto unlock;
+
        if (!sta) {
                sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
                if (WARN_ON(IS_ERR_OR_NULL(sta))) {
@@ -1609,6 +1610,8 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
        mvm_sta = iwl_mvm_sta_from_mac80211(sta);
        iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
                             iv32, phase1key, CMD_ASYNC, keyconf->hw_key_idx);
+
+ unlock:
        rcu_read_unlock();
 }
 
index e481f3710bd38a330d00501c8bd4afadff9de8ff..1049c34e7d430fab13e8d36e54af1b049eb02a03 100644 (file)
@@ -258,18 +258,18 @@ static struct xenvif_rx_meta *get_next_rx_buffer(struct xenvif_queue *queue,
                                                 struct netrx_pending_operations *npo)
 {
        struct xenvif_rx_meta *meta;
-       struct xen_netif_rx_request *req;
+       struct xen_netif_rx_request req;
 
-       req = RING_GET_REQUEST(&queue->rx, queue->rx.req_cons++);
+       RING_COPY_REQUEST(&queue->rx, queue->rx.req_cons++, &req);
 
        meta = npo->meta + npo->meta_prod++;
        meta->gso_type = XEN_NETIF_GSO_TYPE_NONE;
        meta->gso_size = 0;
        meta->size = 0;
-       meta->id = req->id;
+       meta->id = req.id;
 
        npo->copy_off = 0;
-       npo->copy_gref = req->gref;
+       npo->copy_gref = req.gref;
 
        return meta;
 }
@@ -424,7 +424,7 @@ static int xenvif_gop_skb(struct sk_buff *skb,
        struct xenvif *vif = netdev_priv(skb->dev);
        int nr_frags = skb_shinfo(skb)->nr_frags;
        int i;
-       struct xen_netif_rx_request *req;
+       struct xen_netif_rx_request req;
        struct xenvif_rx_meta *meta;
        unsigned char *data;
        int head = 1;
@@ -443,15 +443,15 @@ static int xenvif_gop_skb(struct sk_buff *skb,
 
        /* Set up a GSO prefix descriptor, if necessary */
        if ((1 << gso_type) & vif->gso_prefix_mask) {
-               req = RING_GET_REQUEST(&queue->rx, queue->rx.req_cons++);
+               RING_COPY_REQUEST(&queue->rx, queue->rx.req_cons++, &req);
                meta = npo->meta + npo->meta_prod++;
                meta->gso_type = gso_type;
                meta->gso_size = skb_shinfo(skb)->gso_size;
                meta->size = 0;
-               meta->id = req->id;
+               meta->id = req.id;
        }
 
-       req = RING_GET_REQUEST(&queue->rx, queue->rx.req_cons++);
+       RING_COPY_REQUEST(&queue->rx, queue->rx.req_cons++, &req);
        meta = npo->meta + npo->meta_prod++;
 
        if ((1 << gso_type) & vif->gso_mask) {
@@ -463,9 +463,9 @@ static int xenvif_gop_skb(struct sk_buff *skb,
        }
 
        meta->size = 0;
-       meta->id = req->id;
+       meta->id = req.id;
        npo->copy_off = 0;
-       npo->copy_gref = req->gref;
+       npo->copy_gref = req.gref;
 
        data = skb->data;
        while (data < skb_tail_pointer(skb)) {
@@ -679,9 +679,7 @@ static void tx_add_credit(struct xenvif_queue *queue)
         * Allow a burst big enough to transmit a jumbo packet of up to 128kB.
         * Otherwise the interface can seize up due to insufficient credit.
         */
-       max_burst = RING_GET_REQUEST(&queue->tx, queue->tx.req_cons)->size;
-       max_burst = min(max_burst, 131072UL);
-       max_burst = max(max_burst, queue->credit_bytes);
+       max_burst = max(131072UL, queue->credit_bytes);
 
        /* Take care that adding a new chunk of credit doesn't wrap to zero. */
        max_credit = queue->remaining_credit + queue->credit_bytes;
@@ -711,7 +709,7 @@ static void xenvif_tx_err(struct xenvif_queue *queue,
                spin_unlock_irqrestore(&queue->response_lock, flags);
                if (cons == end)
                        break;
-               txp = RING_GET_REQUEST(&queue->tx, cons++);
+               RING_COPY_REQUEST(&queue->tx, cons++, txp);
        } while (1);
        queue->tx.req_cons = cons;
 }
@@ -778,8 +776,7 @@ static int xenvif_count_requests(struct xenvif_queue *queue,
                if (drop_err)
                        txp = &dropped_tx;
 
-               memcpy(txp, RING_GET_REQUEST(&queue->tx, cons + slots),
-                      sizeof(*txp));
+               RING_COPY_REQUEST(&queue->tx, cons + slots, txp);
 
                /* If the guest submitted a frame >= 64 KiB then
                 * first->size overflowed and following slots will
@@ -1112,8 +1109,7 @@ static int xenvif_get_extras(struct xenvif_queue *queue,
                        return -EBADR;
                }
 
-               memcpy(&extra, RING_GET_REQUEST(&queue->tx, cons),
-                      sizeof(extra));
+               RING_COPY_REQUEST(&queue->tx, cons, &extra);
                if (unlikely(!extra.type ||
                             extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
                        queue->tx.req_cons = ++cons;
@@ -1322,7 +1318,7 @@ static void xenvif_tx_build_gops(struct xenvif_queue *queue,
 
                idx = queue->tx.req_cons;
                rmb(); /* Ensure that we see the request before we copy it. */
-               memcpy(&txreq, RING_GET_REQUEST(&queue->tx, idx), sizeof(txreq));
+               RING_COPY_REQUEST(&queue->tx, idx, &txreq);
 
                /* Credit-based scheduling. */
                if (txreq.size > queue->remaining_credit &&
index 06c3364102350e7f90d3a357bfdfc54b728f724f..15f2acb4d5cd4937ee350e7daaf67f1b8ec56ad6 100644 (file)
@@ -271,9 +271,9 @@ static int init_grps(struct nvm_id *nvm_id, struct nvme_nvm_id *nvme_nvm_id)
        return 0;
 }
 
-static int nvme_nvm_identity(struct request_queue *q, struct nvm_id *nvm_id)
+static int nvme_nvm_identity(struct nvm_dev *nvmdev, struct nvm_id *nvm_id)
 {
-       struct nvme_ns *ns = q->queuedata;
+       struct nvme_ns *ns = nvmdev->q->queuedata;
        struct nvme_dev *dev = ns->dev;
        struct nvme_nvm_id *nvme_nvm_id;
        struct nvme_nvm_command c = {};
@@ -308,10 +308,10 @@ out:
        return ret;
 }
 
-static int nvme_nvm_get_l2p_tbl(struct request_queue *q, u64 slba, u32 nlb,
+static int nvme_nvm_get_l2p_tbl(struct nvm_dev *nvmdev, u64 slba, u32 nlb,
                                nvm_l2p_update_fn *update_l2p, void *priv)
 {
-       struct nvme_ns *ns = q->queuedata;
+       struct nvme_ns *ns = nvmdev->q->queuedata;
        struct nvme_dev *dev = ns->dev;
        struct nvme_nvm_command c = {};
        u32 len = queue_max_hw_sectors(dev->admin_q) << 9;
@@ -415,10 +415,10 @@ out:
        return ret;
 }
 
-static int nvme_nvm_set_bb_tbl(struct request_queue *q, struct nvm_rq *rqd,
+static int nvme_nvm_set_bb_tbl(struct nvm_dev *nvmdev, struct nvm_rq *rqd,
                                                                int type)
 {
-       struct nvme_ns *ns = q->queuedata;
+       struct nvme_ns *ns = nvmdev->q->queuedata;
        struct nvme_dev *dev = ns->dev;
        struct nvme_nvm_command c = {};
        int ret = 0;
@@ -455,7 +455,7 @@ static void nvme_nvm_end_io(struct request *rq, int error)
        struct nvm_rq *rqd = rq->end_io_data;
        struct nvm_dev *dev = rqd->dev;
 
-       if (dev->mt->end_io(rqd, error))
+       if (dev->mt && dev->mt->end_io(rqd, error))
                pr_err("nvme: err status: %x result: %lx\n",
                                rq->errors, (unsigned long)rq->special);
 
@@ -463,8 +463,9 @@ static void nvme_nvm_end_io(struct request *rq, int error)
        blk_mq_free_request(rq);
 }
 
-static int nvme_nvm_submit_io(struct request_queue *q, struct nvm_rq *rqd)
+static int nvme_nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
 {
+       struct request_queue *q = dev->q;
        struct nvme_ns *ns = q->queuedata;
        struct request *rq;
        struct bio *bio = rqd->bio;
@@ -502,8 +503,9 @@ static int nvme_nvm_submit_io(struct request_queue *q, struct nvm_rq *rqd)
        return 0;
 }
 
-static int nvme_nvm_erase_block(struct request_queue *q, struct nvm_rq *rqd)
+static int nvme_nvm_erase_block(struct nvm_dev *dev, struct nvm_rq *rqd)
 {
+       struct request_queue *q = dev->q;
        struct nvme_ns *ns = q->queuedata;
        struct nvme_nvm_command c = {};
 
@@ -515,9 +517,9 @@ static int nvme_nvm_erase_block(struct request_queue *q, struct nvm_rq *rqd)
        return nvme_submit_sync_cmd(q, (struct nvme_command *)&c, NULL, 0);
 }
 
-static void *nvme_nvm_create_dma_pool(struct request_queue *q, char *name)
+static void *nvme_nvm_create_dma_pool(struct nvm_dev *nvmdev, char *name)
 {
-       struct nvme_ns *ns = q->queuedata;
+       struct nvme_ns *ns = nvmdev->q->queuedata;
        struct nvme_dev *dev = ns->dev;
 
        return dma_pool_create(name, dev->dev, PAGE_SIZE, PAGE_SIZE, 0);
@@ -530,7 +532,7 @@ static void nvme_nvm_destroy_dma_pool(void *pool)
        dma_pool_destroy(dma_pool);
 }
 
-static void *nvme_nvm_dev_dma_alloc(struct request_queue *q, void *pool,
+static void *nvme_nvm_dev_dma_alloc(struct nvm_dev *dev, void *pool,
                                    gfp_t mem_flags, dma_addr_t *dma_handler)
 {
        return dma_pool_alloc(pool, mem_flags, dma_handler);
index 9e294ff4e652a2bb8daa9e3f4a94cc09e8bb8b88..0c67b57be83c4630a89c670acbbd150b65ec667f 100644 (file)
@@ -2540,8 +2540,17 @@ static void nvme_ns_remove(struct nvme_ns *ns)
 {
        bool kill = nvme_io_incapable(ns->dev) && !blk_queue_dying(ns->queue);
 
-       if (kill)
+       if (kill) {
                blk_set_queue_dying(ns->queue);
+
+               /*
+                * The controller was shutdown first if we got here through
+                * device removal. The shutdown may requeue outstanding
+                * requests. These need to be aborted immediately so
+                * del_gendisk doesn't block indefinitely for their completion.
+                */
+               blk_mq_abort_requeue_list(ns->queue);
+       }
        if (ns->disk->flags & GENHD_FL_UP)
                del_gendisk(ns->disk);
        if (kill || !blk_queue_dying(ns->queue)) {
@@ -2977,6 +2986,15 @@ static void nvme_dev_remove(struct nvme_dev *dev)
 {
        struct nvme_ns *ns, *next;
 
+       if (nvme_io_incapable(dev)) {
+               /*
+                * If the device is not capable of IO (surprise hot-removal,
+                * for example), we need to quiesce prior to deleting the
+                * namespaces. This will end outstanding requests and prevent
+                * attempts to sync dirty data.
+                */
+               nvme_dev_shutdown(dev);
+       }
        list_for_each_entry_safe(ns, next, &dev->namespaces, list)
                nvme_ns_remove(ns);
 }
index cd53fe4a0c8684900a94fb4bee76f9bd668e3837..9582c5703b3c905486da173d08a2f986883bda26 100644 (file)
@@ -485,9 +485,10 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
        int rone;
        u64 offset = OF_BAD_ADDR;
 
-       /* Normally, an absence of a "ranges" property means we are
+       /*
+        * Normally, an absence of a "ranges" property means we are
         * crossing a non-translatable boundary, and thus the addresses
-        * below the current not cannot be converted to CPU physical ones.
+        * below the current cannot be converted to CPU physical ones.
         * Unfortunately, while this is very clear in the spec, it's not
         * what Apple understood, and they do have things like /uni-n or
         * /ht nodes with no "ranges" property and a lot of perfectly
index d2430298a309a86d3f2110623d3728b9dedb228f..655f79db7899ffd0628714d51203847630a8075c 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/initrd.h>
 #include <linux/memblock.h>
+#include <linux/mutex.h>
 #include <linux/of.h>
 #include <linux/of_fdt.h>
 #include <linux/of_reserved_mem.h>
@@ -436,6 +437,8 @@ static void *kernel_tree_alloc(u64 size, u64 align)
        return kzalloc(size, GFP_KERNEL);
 }
 
+static DEFINE_MUTEX(of_fdt_unflatten_mutex);
+
 /**
  * of_fdt_unflatten_tree - create tree of device_nodes from flat blob
  *
@@ -447,7 +450,9 @@ static void *kernel_tree_alloc(u64 size, u64 align)
 void of_fdt_unflatten_tree(const unsigned long *blob,
                        struct device_node **mynodes)
 {
+       mutex_lock(&of_fdt_unflatten_mutex);
        __unflatten_device_tree(blob, mynodes, &kernel_tree_alloc);
+       mutex_unlock(&of_fdt_unflatten_mutex);
 }
 EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
 
@@ -1041,7 +1046,7 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
 int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,
                                        phys_addr_t size, bool nomap)
 {
-       pr_err("Reserved memory not supported, ignoring range 0x%pa - 0x%pa%s\n",
+       pr_err("Reserved memory not supported, ignoring range %pa - %pa%s\n",
                  &base, &size, nomap ? " (nomap)" : "");
        return -ENOSYS;
 }
index 902b89be7217137726be7eb1ab19263c0372635a..4fa916dffc91924a0354c3c779ae5bf41cb79cec 100644 (file)
@@ -53,7 +53,7 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
  * Returns a pointer to the interrupt parent node, or NULL if the interrupt
  * parent could not be determined.
  */
-static struct device_node *of_irq_find_parent(struct device_node *child)
+struct device_node *of_irq_find_parent(struct device_node *child)
 {
        struct device_node *p;
        const __be32 *parp;
@@ -77,6 +77,7 @@ static struct device_node *of_irq_find_parent(struct device_node *child)
 
        return p;
 }
+EXPORT_SYMBOL_GPL(of_irq_find_parent);
 
 /**
  * of_irq_parse_raw - Low level interrupt tree parsing
index be77e75c587db95c55a51e556f228f97810e051c..1a3556a9e9ea126b451b2a3c68e0407135af242f 100644 (file)
@@ -206,7 +206,13 @@ static int __init __rmem_cmp(const void *a, const void *b)
 {
        const struct reserved_mem *ra = a, *rb = b;
 
-       return ra->base - rb->base;
+       if (ra->base < rb->base)
+               return -1;
+
+       if (ra->base > rb->base)
+               return 1;
+
+       return 0;
 }
 
 static void __init __rmem_check_for_overlap(void)
index 761e77bfce5d2f43f251ebb74f82245d52c5f5f3..e56f1569f6c396f8c29448e9adb26214e26ba9fc 100644 (file)
@@ -104,7 +104,11 @@ iommu_coalesce_chunks(struct ioc *ioc, struct device *dev,
        struct scatterlist *contig_sg;     /* contig chunk head */
        unsigned long dma_offset, dma_len; /* start/len of DMA stream */
        unsigned int n_mappings = 0;
-       unsigned int max_seg_size = dma_get_max_seg_size(dev);
+       unsigned int max_seg_size = min(dma_get_max_seg_size(dev),
+                                       (unsigned)DMA_CHUNK_SIZE);
+       unsigned int max_seg_boundary = dma_get_seg_boundary(dev) + 1;
+       if (max_seg_boundary)   /* check if the addition above didn't overflow */
+               max_seg_size = min(max_seg_size, max_seg_boundary);
 
        while (nents > 0) {
 
@@ -138,14 +142,11 @@ iommu_coalesce_chunks(struct ioc *ioc, struct device *dev,
 
                        /*
                        ** First make sure current dma stream won't
-                       ** exceed DMA_CHUNK_SIZE if we coalesce the
+                       ** exceed max_seg_size if we coalesce the
                        ** next entry.
                        */   
-                       if(unlikely(ALIGN(dma_len + dma_offset + startsg->length,
-                                           IOVP_SIZE) > DMA_CHUNK_SIZE))
-                               break;
-
-                       if (startsg->length + dma_len > max_seg_size)
+                       if (unlikely(ALIGN(dma_len + dma_offset + startsg->length, IOVP_SIZE) >
+                                    max_seg_size))
                                break;
 
                        /*
index f131ba947dc6fe47941b09b0e6d1d35f2a53c255..c0ad9aaa16a75a815cb4fc605a270dbcadb07198 100644 (file)
@@ -5,6 +5,7 @@ config PCI_DRA7XX
        bool "TI DRA7xx PCIe controller"
        select PCIE_DW
        depends on OF && HAS_IOMEM && TI_PIPE3
+       depends on BROKEN
        help
         Enables support for the PCIe controller in the DRA7xx SoC.  There
         are two instances of PCIe controller in DRA7xx.  This controller can
index e5dda38bdde5e1735a50b4de9fcd2cd6307d13c5..99da549d5d06a067b58d3bbe08c39041a9d90605 100644 (file)
 #define TLP_CFG_DW2(bus, devfn, offset)        \
                                (((bus) << 24) | ((devfn) << 16) | (offset))
 #define TLP_REQ_ID(bus, devfn)         (((bus) << 8) | (devfn))
+#define TLP_COMP_STATUS(s)             (((s) >> 12) & 7)
 #define TLP_HDR_SIZE                   3
 #define TLP_LOOP                       500
+#define RP_DEVFN                       0
 
 #define INTX_NUM                       4
 
@@ -166,34 +168,41 @@ static bool altera_pcie_valid_config(struct altera_pcie *pcie,
 
 static int tlp_read_packet(struct altera_pcie *pcie, u32 *value)
 {
-       u8 loop;
+       int i;
        bool sop = 0;
        u32 ctrl;
        u32 reg0, reg1;
+       u32 comp_status = 1;
 
        /*
         * Minimum 2 loops to read TLP headers and 1 loop to read data
         * payload.
         */
-       for (loop = 0; loop < TLP_LOOP; loop++) {
+       for (i = 0; i < TLP_LOOP; i++) {
                ctrl = cra_readl(pcie, RP_RXCPL_STATUS);
                if ((ctrl & RP_RXCPL_SOP) || (ctrl & RP_RXCPL_EOP) || sop) {
                        reg0 = cra_readl(pcie, RP_RXCPL_REG0);
                        reg1 = cra_readl(pcie, RP_RXCPL_REG1);
 
-                       if (ctrl & RP_RXCPL_SOP)
+                       if (ctrl & RP_RXCPL_SOP) {
                                sop = true;
+                               comp_status = TLP_COMP_STATUS(reg1);
+                       }
 
                        if (ctrl & RP_RXCPL_EOP) {
+                               if (comp_status)
+                                       return PCIBIOS_DEVICE_NOT_FOUND;
+
                                if (value)
                                        *value = reg0;
+
                                return PCIBIOS_SUCCESSFUL;
                        }
                }
                udelay(5);
        }
 
-       return -ENOENT;
+       return PCIBIOS_DEVICE_NOT_FOUND;
 }
 
 static void tlp_write_packet(struct altera_pcie *pcie, u32 *headers,
@@ -233,7 +242,7 @@ static int tlp_cfg_dword_read(struct altera_pcie *pcie, u8 bus, u32 devfn,
        else
                headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGRD1);
 
-       headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, devfn),
+       headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, RP_DEVFN),
                                        TLP_READ_TAG, byte_en);
        headers[2] = TLP_CFG_DW2(bus, devfn, where);
 
@@ -253,7 +262,7 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn,
        else
                headers[0] = TLP_CFG_DW0(TLP_FMTTYPE_CFGWR1);
 
-       headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, devfn),
+       headers[1] = TLP_CFG_DW1(TLP_REQ_ID(pcie->root_bus_nr, RP_DEVFN),
                                        TLP_WRITE_TAG, byte_en);
        headers[2] = TLP_CFG_DW2(bus, devfn, where);
 
@@ -458,7 +467,7 @@ static int altera_pcie_init_irq_domain(struct altera_pcie *pcie)
        struct device_node *node = dev->of_node;
 
        /* Setup INTx */
-       pcie->irq_domain = irq_domain_add_linear(node, INTX_NUM,
+       pcie->irq_domain = irq_domain_add_linear(node, INTX_NUM + 1,
                                        &intx_domain_ops, pcie);
        if (!pcie->irq_domain) {
                dev_err(dev, "Failed to get a INTx IRQ domain\n");
index 163671a4f798dfc18bb24f3490ad7138753efac1..77f7c669a1b9bb497528874c10262430c868959d 100644 (file)
@@ -61,7 +61,9 @@ static int hisi_pcie_cfg_read(struct pcie_port *pp, int where, int size,
                *val = *(u8 __force *) walker;
        else if (size == 2)
                *val = *(u16 __force *) walker;
-       else if (size != 4)
+       else if (size == 4)
+               *val = reg_val;
+       else
                return PCIBIOS_BAD_REGISTER_NUMBER;
 
        return PCIBIOS_SUCCESSFUL;
index 53e463244bb7e35ac368ff088a4976c2153fce3d..7eaa4c87fec71c8dd792ccffc919b322711d91dd 100644 (file)
@@ -54,7 +54,7 @@ static int pci_msi_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
        struct irq_domain *domain;
 
        domain = pci_msi_get_domain(dev);
-       if (domain)
+       if (domain && irq_domain_is_hierarchy(domain))
                return pci_msi_domain_alloc_irqs(domain, dev, nvec, type);
 
        return arch_setup_msi_irqs(dev, nvec, type);
@@ -65,7 +65,7 @@ static void pci_msi_teardown_msi_irqs(struct pci_dev *dev)
        struct irq_domain *domain;
 
        domain = pci_msi_get_domain(dev);
-       if (domain)
+       if (domain && irq_domain_is_hierarchy(domain))
                pci_msi_domain_free_irqs(domain, dev);
        else
                arch_teardown_msi_irqs(dev);
index 7eb5859dd035fefabea842f40722580cfcdfe64a..03cb3ea2d2c035b32254022b1506fcf52d770655 100644 (file)
@@ -233,6 +233,7 @@ config PHY_SUN9I_USB
        tristate "Allwinner sun9i SoC USB PHY driver"
        depends on ARCH_SUNXI && HAS_IOMEM && OF
        depends on RESET_CONTROLLER
+       depends on USB_COMMON
        select GENERIC_PHY
        help
          Enable this to support the transceiver that is part of Allwinner
index 7ad72b7d2b981b6ff4ae59011fdd5e6c5538ef51..082c03f6438f796af868cb83127f1ce9ca56f83b 100644 (file)
@@ -128,6 +128,7 @@ static int cygnus_pcie_phy_probe(struct platform_device *pdev)
        struct phy_provider *provider;
        struct resource *res;
        unsigned cnt = 0;
+       int ret;
 
        if (of_get_child_count(node) == 0) {
                dev_err(dev, "PHY no child node\n");
@@ -154,24 +155,28 @@ static int cygnus_pcie_phy_probe(struct platform_device *pdev)
                if (of_property_read_u32(child, "reg", &id)) {
                        dev_err(dev, "missing reg property for %s\n",
                                child->name);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto put_child;
                }
 
                if (id >= MAX_NUM_PHYS) {
                        dev_err(dev, "invalid PHY id: %u\n", id);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto put_child;
                }
 
                if (core->phys[id].phy) {
                        dev_err(dev, "duplicated PHY id: %u\n", id);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto put_child;
                }
 
                p = &core->phys[id];
                p->phy = devm_phy_create(dev, child, &cygnus_pcie_phy_ops);
                if (IS_ERR(p->phy)) {
                        dev_err(dev, "failed to create PHY\n");
-                       return PTR_ERR(p->phy);
+                       ret = PTR_ERR(p->phy);
+                       goto put_child;
                }
 
                p->core = core;
@@ -191,6 +196,9 @@ static int cygnus_pcie_phy_probe(struct platform_device *pdev)
        dev_dbg(dev, "registered %u PCIe PHY(s)\n", cnt);
 
        return 0;
+put_child:
+       of_node_put(child);
+       return ret;
 }
 
 static const struct of_device_id cygnus_pcie_phy_match_table[] = {
index 77a2e054fdea0f46ccd3d2841f5f837f80a985e1..f84a33a1bdd935c5a6c171929d172b1a1a67840c 100644 (file)
@@ -195,7 +195,7 @@ static int phy_berlin_sata_probe(struct platform_device *pdev)
        struct phy_provider *phy_provider;
        struct phy_berlin_priv *priv;
        struct resource *res;
-       int i = 0;
+       int ret, i = 0;
        u32 phy_id;
 
        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -237,22 +237,27 @@ static int phy_berlin_sata_probe(struct platform_device *pdev)
                if (of_property_read_u32(child, "reg", &phy_id)) {
                        dev_err(dev, "missing reg property in node %s\n",
                                child->name);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto put_child;
                }
 
                if (phy_id >= ARRAY_SIZE(phy_berlin_power_down_bits)) {
                        dev_err(dev, "invalid reg in node %s\n", child->name);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto put_child;
                }
 
                phy_desc = devm_kzalloc(dev, sizeof(*phy_desc), GFP_KERNEL);
-               if (!phy_desc)
-                       return -ENOMEM;
+               if (!phy_desc) {
+                       ret = -ENOMEM;
+                       goto put_child;
+               }
 
                phy = devm_phy_create(dev, NULL, &phy_berlin_sata_ops);
                if (IS_ERR(phy)) {
                        dev_err(dev, "failed to create PHY %d\n", phy_id);
-                       return PTR_ERR(phy);
+                       ret = PTR_ERR(phy);
+                       goto put_child;
                }
 
                phy_desc->phy = phy;
@@ -269,6 +274,9 @@ static int phy_berlin_sata_probe(struct platform_device *pdev)
        phy_provider =
                devm_of_phy_provider_register(dev, phy_berlin_sata_phy_xlate);
        return PTR_ERR_OR_ZERO(phy_provider);
+put_child:
+       of_node_put(child);
+       return ret;
 }
 
 static const struct of_device_id phy_berlin_sata_of_match[] = {
index 8a2cb16a1937d20e88b045868beec28db966be5c..cd9dba8205668d98665d938b13a5e254b74bdb17 100644 (file)
@@ -140,7 +140,7 @@ static int brcm_sata_phy_probe(struct platform_device *pdev)
        struct brcm_sata_phy *priv;
        struct resource *res;
        struct phy_provider *provider;
-       int count = 0;
+       int ret, count = 0;
 
        if (of_get_child_count(dn) == 0)
                return -ENODEV;
@@ -163,16 +163,19 @@ static int brcm_sata_phy_probe(struct platform_device *pdev)
                if (of_property_read_u32(child, "reg", &id)) {
                        dev_err(dev, "missing reg property in node %s\n",
                                        child->name);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto put_child;
                }
 
                if (id >= MAX_PORTS) {
                        dev_err(dev, "invalid reg: %u\n", id);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto put_child;
                }
                if (priv->phys[id].phy) {
                        dev_err(dev, "already registered port %u\n", id);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto put_child;
                }
 
                port = &priv->phys[id];
@@ -182,7 +185,8 @@ static int brcm_sata_phy_probe(struct platform_device *pdev)
                port->ssc_en = of_property_read_bool(child, "brcm,enable-ssc");
                if (IS_ERR(port->phy)) {
                        dev_err(dev, "failed to create PHY\n");
-                       return PTR_ERR(port->phy);
+                       ret = PTR_ERR(port->phy);
+                       goto put_child;
                }
 
                phy_set_drvdata(port->phy, port);
@@ -198,6 +202,9 @@ static int brcm_sata_phy_probe(struct platform_device *pdev)
        dev_info(dev, "registered %d port(s)\n", count);
 
        return 0;
+put_child:
+       of_node_put(child);
+       return ret;
 }
 
 static struct platform_driver brcm_sata_phy_driver = {
index fc48fac003a62ba124bd7c6820f24d5d040fcbf7..8c7f27db6ad352260f8ad8675758ed365b6390a6 100644 (file)
@@ -636,8 +636,9 @@ EXPORT_SYMBOL_GPL(devm_of_phy_get);
  * @np: node containing the phy
  * @index: index of the phy
  *
- * Gets the phy using _of_phy_get(), and associates a device with it using
- * devres. On driver detach, release function is invoked on the devres data,
+ * Gets the phy using _of_phy_get(), then gets a refcount to it,
+ * and associates a device with it using devres. On driver detach,
+ * release function is invoked on the devres data,
  * then, devres data is freed.
  *
  */
@@ -651,13 +652,21 @@ struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np,
                return ERR_PTR(-ENOMEM);
 
        phy = _of_phy_get(np, index);
-       if (!IS_ERR(phy)) {
-               *ptr = phy;
-               devres_add(dev, ptr);
-       } else {
+       if (IS_ERR(phy)) {
                devres_free(ptr);
+               return phy;
        }
 
+       if (!try_module_get(phy->ops->owner)) {
+               devres_free(ptr);
+               return ERR_PTR(-EPROBE_DEFER);
+       }
+
+       get_device(&phy->dev);
+
+       *ptr = phy;
+       devres_add(dev, ptr);
+
        return phy;
 }
 EXPORT_SYMBOL_GPL(devm_of_phy_get_by_index);
index c47b56b4a2b8892810f00179a53e9eceba7c612c..3acd2a1808dfbf9ccfa5d58467b6defdb793c2bb 100644 (file)
@@ -1226,15 +1226,18 @@ static int miphy28lp_probe(struct platform_device *pdev)
 
                miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy),
                                         GFP_KERNEL);
-               if (!miphy_phy)
-                       return -ENOMEM;
+               if (!miphy_phy) {
+                       ret = -ENOMEM;
+                       goto put_child;
+               }
 
                miphy_dev->phys[port] = miphy_phy;
 
                phy = devm_phy_create(&pdev->dev, child, &miphy28lp_ops);
                if (IS_ERR(phy)) {
                        dev_err(&pdev->dev, "failed to create PHY\n");
-                       return PTR_ERR(phy);
+                       ret = PTR_ERR(phy);
+                       goto put_child;
                }
 
                miphy_dev->phys[port]->phy = phy;
@@ -1242,11 +1245,11 @@ static int miphy28lp_probe(struct platform_device *pdev)
 
                ret = miphy28lp_of_probe(child, miphy_phy);
                if (ret)
-                       return ret;
+                       goto put_child;
 
                ret = miphy28lp_probe_resets(child, miphy_dev->phys[port]);
                if (ret)
-                       return ret;
+                       goto put_child;
 
                phy_set_drvdata(phy, miphy_dev->phys[port]);
                port++;
@@ -1255,6 +1258,9 @@ static int miphy28lp_probe(struct platform_device *pdev)
 
        provider = devm_of_phy_provider_register(&pdev->dev, miphy28lp_xlate);
        return PTR_ERR_OR_ZERO(provider);
+put_child:
+       of_node_put(child);
+       return ret;
 }
 
 static const struct of_device_id miphy28lp_of_match[] = {
index 00a686a073ed6ee804ea96ebcdb0ef3813482a85..e661f3b36eaa0cdf992cde8f88d92644ff585c5e 100644 (file)
@@ -566,22 +566,25 @@ static int miphy365x_probe(struct platform_device *pdev)
 
                miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy),
                                         GFP_KERNEL);
-               if (!miphy_phy)
-                       return -ENOMEM;
+               if (!miphy_phy) {
+                       ret = -ENOMEM;
+                       goto put_child;
+               }
 
                miphy_dev->phys[port] = miphy_phy;
 
                phy = devm_phy_create(&pdev->dev, child, &miphy365x_ops);
                if (IS_ERR(phy)) {
                        dev_err(&pdev->dev, "failed to create PHY\n");
-                       return PTR_ERR(phy);
+                       ret = PTR_ERR(phy);
+                       goto put_child;
                }
 
                miphy_dev->phys[port]->phy = phy;
 
                ret = miphy365x_of_probe(child, miphy_phy);
                if (ret)
-                       return ret;
+                       goto put_child;
 
                phy_set_drvdata(phy, miphy_dev->phys[port]);
 
@@ -591,12 +594,15 @@ static int miphy365x_probe(struct platform_device *pdev)
                                        &miphy_phy->ctrlreg);
                if (ret) {
                        dev_err(&pdev->dev, "No sysconfig offset found\n");
-                       return ret;
+                       goto put_child;
                }
        }
 
        provider = devm_of_phy_provider_register(&pdev->dev, miphy365x_xlate);
        return PTR_ERR_OR_ZERO(provider);
+put_child:
+       of_node_put(child);
+       return ret;
 }
 
 static const struct of_device_id miphy365x_of_match[] = {
index f30b28bd41fe7b11a8cce95e889ae894fef20518..e427c3b788ff35e23a49808116936f0d5f39ffa4 100644 (file)
@@ -415,7 +415,7 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev)
        struct resource *sif_res;
        struct mt65xx_u3phy *u3phy;
        struct resource res;
-       int port;
+       int port, retval;
 
        u3phy = devm_kzalloc(dev, sizeof(*u3phy), GFP_KERNEL);
        if (!u3phy)
@@ -447,31 +447,34 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev)
        for_each_child_of_node(np, child_np) {
                struct mt65xx_phy_instance *instance;
                struct phy *phy;
-               int retval;
 
                instance = devm_kzalloc(dev, sizeof(*instance), GFP_KERNEL);
-               if (!instance)
-                       return -ENOMEM;
+               if (!instance) {
+                       retval = -ENOMEM;
+                       goto put_child;
+               }
 
                u3phy->phys[port] = instance;
 
                phy = devm_phy_create(dev, child_np, &mt65xx_u3phy_ops);
                if (IS_ERR(phy)) {
                        dev_err(dev, "failed to create phy\n");
-                       return PTR_ERR(phy);
+                       retval = PTR_ERR(phy);
+                       goto put_child;
                }
 
                retval = of_address_to_resource(child_np, 0, &res);
                if (retval) {
                        dev_err(dev, "failed to get address resource(id-%d)\n",
                                port);
-                       return retval;
+                       goto put_child;
                }
 
                instance->port_base = devm_ioremap_resource(&phy->dev, &res);
                if (IS_ERR(instance->port_base)) {
                        dev_err(dev, "failed to remap phy regs\n");
-                       return PTR_ERR(instance->port_base);
+                       retval = PTR_ERR(instance->port_base);
+                       goto put_child;
                }
 
                instance->phy = phy;
@@ -483,6 +486,9 @@ static int mt65xx_u3phy_probe(struct platform_device *pdev)
        provider = devm_of_phy_provider_register(dev, mt65xx_phy_xlate);
 
        return PTR_ERR_OR_ZERO(provider);
+put_child:
+       of_node_put(child_np);
+       return retval;
 }
 
 static const struct of_device_id mt65xx_u3phy_id_table[] = {
index 91d6f342c56596fc2e3fcff18213dba004546c3e..62c43c435194313e7d5ea7049d568cb673857da9 100644 (file)
@@ -108,13 +108,16 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
 
        for_each_available_child_of_node(dev->of_node, child) {
                rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL);
-               if (!rk_phy)
-                       return -ENOMEM;
+               if (!rk_phy) {
+                       err = -ENOMEM;
+                       goto put_child;
+               }
 
                if (of_property_read_u32(child, "reg", &reg_offset)) {
                        dev_err(dev, "missing reg property in node %s\n",
                                child->name);
-                       return -EINVAL;
+                       err = -EINVAL;
+                       goto put_child;
                }
 
                rk_phy->reg_offset = reg_offset;
@@ -127,18 +130,22 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev)
                rk_phy->phy = devm_phy_create(dev, child, &ops);
                if (IS_ERR(rk_phy->phy)) {
                        dev_err(dev, "failed to create PHY\n");
-                       return PTR_ERR(rk_phy->phy);
+                       err = PTR_ERR(rk_phy->phy);
+                       goto put_child;
                }
                phy_set_drvdata(rk_phy->phy, rk_phy);
 
                /* only power up usb phy when it use, so disable it when init*/
                err = rockchip_usb_phy_power(rk_phy, 1);
                if (err)
-                       return err;
+                       goto put_child;
        }
 
        phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
        return PTR_ERR_OR_ZERO(phy_provider);
+put_child:
+       of_node_put(child);
+       return err;
 }
 
 static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
index a1ea565fcd46490e58d48e4363318c2ce6970ebc..2e6ca69635aa001531d2b9aca128d001b97d9aca 100644 (file)
@@ -342,12 +342,6 @@ static int bcm2835_gpio_get(struct gpio_chip *chip, unsigned offset)
        return bcm2835_gpio_get_bit(pc, GPLEV0, offset);
 }
 
-static int bcm2835_gpio_direction_output(struct gpio_chip *chip,
-               unsigned offset, int value)
-{
-       return pinctrl_gpio_direction_output(chip->base + offset);
-}
-
 static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
        struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->dev);
@@ -355,6 +349,13 @@ static void bcm2835_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
        bcm2835_gpio_set_bit(pc, value ? GPSET0 : GPCLR0, offset);
 }
 
+static int bcm2835_gpio_direction_output(struct gpio_chip *chip,
+               unsigned offset, int value)
+{
+       bcm2835_gpio_set(chip, offset, value);
+       return pinctrl_gpio_direction_output(chip->base + offset);
+}
+
 static int bcm2835_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
        struct bcm2835_pinctrl *pc = dev_get_drvdata(chip->dev);
index 37a037543d299115a09e6a4106f1592acc9566a9..587d1ff6210efb62341b792d0318b412c0a4d046 100644 (file)
@@ -299,7 +299,7 @@ static const struct pinctrl_pin_desc vf610_pinctrl_pads[] = {
 static struct imx_pinctrl_soc_info vf610_pinctrl_info = {
        .pins = vf610_pinctrl_pads,
        .npins = ARRAY_SIZE(vf610_pinctrl_pads),
-       .flags = SHARE_MUX_CONF_REG,
+       .flags = SHARE_MUX_CONF_REG | ZERO_OFFSET_VALID,
 };
 
 static const struct of_device_id vf610_pinctrl_of_match[] = {
index e42d5d4183f57ff0dc0d942254f5925dabd3c07a..5979d38c46b254965e8a7782de9a6c902894ce9a 100644 (file)
@@ -28,6 +28,7 @@
                .padcfglock_offset = BXT_PADCFGLOCK,    \
                .hostown_offset = BXT_HOSTSW_OWN,       \
                .ie_offset = BXT_GPI_IE,                \
+               .gpp_size = 32,                         \
                .pin_base = (s),                        \
                .npins = ((e) - (s) + 1),               \
        }
index 392e28d3f48d0bee1a4087154e904c7dfdc0faa7..26f6b6ffea5b23fac04224d9772996db12bc6176 100644 (file)
@@ -25,9 +25,6 @@
 
 #include "pinctrl-intel.h"
 
-/* Maximum number of pads in each group */
-#define NPADS_IN_GPP                   24
-
 /* Offset from regs */
 #define PADBAR                         0x00c
 #define GPI_IS                         0x100
@@ -37,6 +34,7 @@
 #define PADOWN_BITS                    4
 #define PADOWN_SHIFT(p)                        ((p) % 8 * PADOWN_BITS)
 #define PADOWN_MASK(p)                 (0xf << PADOWN_SHIFT(p))
+#define PADOWN_GPP(p)                  ((p) / 8)
 
 /* Offset from pad_regs */
 #define PADCFG0                                0x000
@@ -142,7 +140,7 @@ static void __iomem *intel_get_padcfg(struct intel_pinctrl *pctrl, unsigned pin,
 static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned pin)
 {
        const struct intel_community *community;
-       unsigned padno, gpp, gpp_offset, offset;
+       unsigned padno, gpp, offset, group;
        void __iomem *padown;
 
        community = intel_get_community(pctrl, pin);
@@ -152,9 +150,9 @@ static bool intel_pad_owned_by_host(struct intel_pinctrl *pctrl, unsigned pin)
                return true;
 
        padno = pin_to_padno(community, pin);
-       gpp = padno / NPADS_IN_GPP;
-       gpp_offset = padno % NPADS_IN_GPP;
-       offset = community->padown_offset + gpp * 16 + (gpp_offset / 8) * 4;
+       group = padno / community->gpp_size;
+       gpp = PADOWN_GPP(padno % community->gpp_size);
+       offset = community->padown_offset + 0x10 * group + gpp * 4;
        padown = community->regs + offset;
 
        return !(readl(padown) & PADOWN_MASK(padno));
@@ -173,11 +171,11 @@ static bool intel_pad_acpi_mode(struct intel_pinctrl *pctrl, unsigned pin)
                return false;
 
        padno = pin_to_padno(community, pin);
-       gpp = padno / NPADS_IN_GPP;
+       gpp = padno / community->gpp_size;
        offset = community->hostown_offset + gpp * 4;
        hostown = community->regs + offset;
 
-       return !(readl(hostown) & BIT(padno % NPADS_IN_GPP));
+       return !(readl(hostown) & BIT(padno % community->gpp_size));
 }
 
 static bool intel_pad_locked(struct intel_pinctrl *pctrl, unsigned pin)
@@ -193,7 +191,7 @@ static bool intel_pad_locked(struct intel_pinctrl *pctrl, unsigned pin)
                return false;
 
        padno = pin_to_padno(community, pin);
-       gpp = padno / NPADS_IN_GPP;
+       gpp = padno / community->gpp_size;
 
        /*
         * If PADCFGLOCK and PADCFGLOCKTX bits are both clear for this pad,
@@ -202,12 +200,12 @@ static bool intel_pad_locked(struct intel_pinctrl *pctrl, unsigned pin)
         */
        offset = community->padcfglock_offset + gpp * 8;
        value = readl(community->regs + offset);
-       if (value & BIT(pin % NPADS_IN_GPP))
+       if (value & BIT(pin % community->gpp_size))
                return true;
 
        offset = community->padcfglock_offset + 4 + gpp * 8;
        value = readl(community->regs + offset);
-       if (value & BIT(pin % NPADS_IN_GPP))
+       if (value & BIT(pin % community->gpp_size))
                return true;
 
        return false;
@@ -663,8 +661,8 @@ static void intel_gpio_irq_ack(struct irq_data *d)
        community = intel_get_community(pctrl, pin);
        if (community) {
                unsigned padno = pin_to_padno(community, pin);
-               unsigned gpp_offset = padno % NPADS_IN_GPP;
-               unsigned gpp = padno / NPADS_IN_GPP;
+               unsigned gpp_offset = padno % community->gpp_size;
+               unsigned gpp = padno / community->gpp_size;
 
                writel(BIT(gpp_offset), community->regs + GPI_IS + gpp * 4);
        }
@@ -685,8 +683,8 @@ static void intel_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
        community = intel_get_community(pctrl, pin);
        if (community) {
                unsigned padno = pin_to_padno(community, pin);
-               unsigned gpp_offset = padno % NPADS_IN_GPP;
-               unsigned gpp = padno / NPADS_IN_GPP;
+               unsigned gpp_offset = padno % community->gpp_size;
+               unsigned gpp = padno / community->gpp_size;
                void __iomem *reg;
                u32 value;
 
@@ -780,8 +778,8 @@ static int intel_gpio_irq_wake(struct irq_data *d, unsigned int on)
                return -EINVAL;
 
        padno = pin_to_padno(community, pin);
-       gpp = padno / NPADS_IN_GPP;
-       gpp_offset = padno % NPADS_IN_GPP;
+       gpp = padno / community->gpp_size;
+       gpp_offset = padno % community->gpp_size;
 
        /* Clear the existing wake status */
        writel(BIT(gpp_offset), community->regs + GPI_GPE_STS + gpp * 4);
@@ -819,14 +817,14 @@ static irqreturn_t intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl,
                /* Only interrupts that are enabled */
                pending &= enabled;
 
-               for_each_set_bit(gpp_offset, &pending, NPADS_IN_GPP) {
+               for_each_set_bit(gpp_offset, &pending, community->gpp_size) {
                        unsigned padno, irq;
 
                        /*
                         * The last group in community can have less pins
                         * than NPADS_IN_GPP.
                         */
-                       padno = gpp_offset + gpp * NPADS_IN_GPP;
+                       padno = gpp_offset + gpp * community->gpp_size;
                        if (padno >= community->npins)
                                break;
 
@@ -1002,7 +1000,8 @@ int intel_pinctrl_probe(struct platform_device *pdev,
 
                community->regs = regs;
                community->pad_regs = regs + padbar;
-               community->ngpps = DIV_ROUND_UP(community->npins, NPADS_IN_GPP);
+               community->ngpps = DIV_ROUND_UP(community->npins,
+                                               community->gpp_size);
        }
 
        irq = platform_get_irq(pdev, 0);
index 4ec8b572a288fbc337f5b40affdfbd012634a028..b60215793017bb95b42d39692020aa2f4c41ac0d 100644 (file)
@@ -55,6 +55,8 @@ struct intel_function {
  *                  ACPI).
  * @ie_offset: Register offset of GPI_IE from @regs.
  * @pin_base: Starting pin of pins in this community
+ * @gpp_size: Maximum number of pads in each group, such as PADCFGLOCK,
+ *            HOSTSW_OWN,  GPI_IS, GPI_IE, etc.
  * @npins: Number of pins in this community
  * @regs: Community specific common registers (reserved for core driver)
  * @pad_regs: Community specific pad registers (reserved for core driver)
@@ -68,6 +70,7 @@ struct intel_community {
        unsigned hostown_offset;
        unsigned ie_offset;
        unsigned pin_base;
+       unsigned gpp_size;
        size_t npins;
        void __iomem *regs;
        void __iomem *pad_regs;
index 1de9ae5010db285b53c01d7e67dec2bde7ce5233..c725a5313b4e692df92630535237e4b8374658a7 100644 (file)
@@ -30,6 +30,7 @@
                .padcfglock_offset = SPT_PADCFGLOCK,    \
                .hostown_offset = SPT_HOSTSW_OWN,       \
                .ie_offset = SPT_GPI_IE,                \
+               .gpp_size = 24,                         \
                .pin_base = (s),                        \
                .npins = ((e) - (s) + 1),               \
        }
index cc97f0869791d371c85f7e21c0ca04e1e595ac23..48747c28a43d4ac2fc1bed10f29cd1224ddd10f0 100644 (file)
@@ -1341,10 +1341,13 @@ static int rapl_detect_domains(struct rapl_package *rp, int cpu)
 
        for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
                /* check if the domain is locked by BIOS */
-               if (rapl_read_data_raw(rd, FW_LOCK, false, &locked)) {
+               ret = rapl_read_data_raw(rd, FW_LOCK, false, &locked);
+               if (ret)
+                       return ret;
+               if (locked) {
                        pr_info("RAPL package %d domain %s locked by BIOS\n",
                                rp->id, rd->name);
-                               rd->state |= DOMAIN_STATE_BIOS_LOCKED;
+                       rd->state |= DOMAIN_STATE_BIOS_LOCKED;
                }
        }
 
index 284b587da65c5fb20f6e96b8c843e52c0b420415..d6c853bbfa9fcbe0fee8968dda872041c6c8545a 100644 (file)
@@ -483,24 +483,23 @@ static int da9063_rtc_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, rtc);
 
+       rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, DA9063_DRVNAME_RTC,
+                                          &da9063_rtc_ops, THIS_MODULE);
+       if (IS_ERR(rtc->rtc_dev))
+               return PTR_ERR(rtc->rtc_dev);
+
+       da9063_data_to_tm(data, &rtc->alarm_time, rtc);
+       rtc->rtc_sync = false;
+
        irq_alarm = platform_get_irq_byname(pdev, "ALARM");
        ret = devm_request_threaded_irq(&pdev->dev, irq_alarm, NULL,
                                        da9063_alarm_event,
                                        IRQF_TRIGGER_LOW | IRQF_ONESHOT,
                                        "ALARM", rtc);
-       if (ret) {
+       if (ret)
                dev_err(&pdev->dev, "Failed to request ALARM IRQ %d: %d\n",
                        irq_alarm, ret);
-               return ret;
-       }
-
-       rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, DA9063_DRVNAME_RTC,
-                                          &da9063_rtc_ops, THIS_MODULE);
-       if (IS_ERR(rtc->rtc_dev))
-               return PTR_ERR(rtc->rtc_dev);
 
-       da9063_data_to_tm(data, &rtc->alarm_time, rtc);
-       rtc->rtc_sync = false;
        return ret;
 }
 
index 91ca0bc1b484b4af1120b3e1701a931a4e1ff6fc..35c9aada07c8ef3a19f44cf8d4a3e8811f484e3f 100644 (file)
@@ -56,6 +56,42 @@ struct rk808_rtc {
        int irq;
 };
 
+/*
+ * The Rockchip calendar used by the RK808 counts November with 31 days. We use
+ * these translation functions to convert its dates to/from the Gregorian
+ * calendar used by the rest of the world. We arbitrarily define Jan 1st, 2016
+ * as the day when both calendars were in sync, and treat all other dates
+ * relative to that.
+ * NOTE: Other system software (e.g. firmware) that reads the same hardware must
+ * implement this exact same conversion algorithm, with the same anchor date.
+ */
+static time64_t nov2dec_transitions(struct rtc_time *tm)
+{
+       return (tm->tm_year + 1900) - 2016 + (tm->tm_mon + 1 > 11 ? 1 : 0);
+}
+
+static void rockchip_to_gregorian(struct rtc_time *tm)
+{
+       /* If it's Nov 31st, rtc_tm_to_time64() will count that like Dec 1st */
+       time64_t time = rtc_tm_to_time64(tm);
+       rtc_time64_to_tm(time + nov2dec_transitions(tm) * 86400, tm);
+}
+
+static void gregorian_to_rockchip(struct rtc_time *tm)
+{
+       time64_t extra_days = nov2dec_transitions(tm);
+       time64_t time = rtc_tm_to_time64(tm);
+       rtc_time64_to_tm(time - extra_days * 86400, tm);
+
+       /* Compensate if we went back over Nov 31st (will work up to 2381) */
+       if (nov2dec_transitions(tm) < extra_days) {
+               if (tm->tm_mon + 1 == 11)
+                       tm->tm_mday++;  /* This may result in 31! */
+               else
+                       rtc_time64_to_tm(time - (extra_days - 1) * 86400, tm);
+       }
+}
+
 /* Read current time and date in RTC */
 static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm)
 {
@@ -101,9 +137,10 @@ static int rk808_rtc_readtime(struct device *dev, struct rtc_time *tm)
        tm->tm_mon = (bcd2bin(rtc_data[4] & MONTHS_REG_MSK)) - 1;
        tm->tm_year = (bcd2bin(rtc_data[5] & YEARS_REG_MSK)) + 100;
        tm->tm_wday = bcd2bin(rtc_data[6] & WEEKS_REG_MSK);
+       rockchip_to_gregorian(tm);
        dev_dbg(dev, "RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
                1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
-               tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec);
+               tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);
 
        return ret;
 }
@@ -116,6 +153,10 @@ static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm)
        u8 rtc_data[NUM_TIME_REGS];
        int ret;
 
+       dev_dbg(dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
+               1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
+               tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);
+       gregorian_to_rockchip(tm);
        rtc_data[0] = bin2bcd(tm->tm_sec);
        rtc_data[1] = bin2bcd(tm->tm_min);
        rtc_data[2] = bin2bcd(tm->tm_hour);
@@ -123,9 +164,6 @@ static int rk808_rtc_set_time(struct device *dev, struct rtc_time *tm)
        rtc_data[4] = bin2bcd(tm->tm_mon + 1);
        rtc_data[5] = bin2bcd(tm->tm_year - 100);
        rtc_data[6] = bin2bcd(tm->tm_wday);
-       dev_dbg(dev, "set RTC date/time %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
-               1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
-               tm->tm_wday, tm->tm_hour , tm->tm_min, tm->tm_sec);
 
        /* Stop RTC while updating the RTC registers */
        ret = regmap_update_bits(rk808->regmap, RK808_RTC_CTRL_REG,
@@ -170,6 +208,7 @@ static int rk808_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
        alrm->time.tm_mday = bcd2bin(alrm_data[3] & DAYS_REG_MSK);
        alrm->time.tm_mon = (bcd2bin(alrm_data[4] & MONTHS_REG_MSK)) - 1;
        alrm->time.tm_year = (bcd2bin(alrm_data[5] & YEARS_REG_MSK)) + 100;
+       rockchip_to_gregorian(&alrm->time);
 
        ret = regmap_read(rk808->regmap, RK808_RTC_INT_REG, &int_reg);
        if (ret) {
@@ -227,6 +266,7 @@ static int rk808_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
                alrm->time.tm_mday, alrm->time.tm_wday, alrm->time.tm_hour,
                alrm->time.tm_min, alrm->time.tm_sec);
 
+       gregorian_to_rockchip(&alrm->time);
        alrm_data[0] = bin2bcd(alrm->time.tm_sec);
        alrm_data[1] = bin2bcd(alrm->time.tm_min);
        alrm_data[2] = bin2bcd(alrm->time.tm_hour);
index 61f768518a34b0e963cd6b569610045a3f65188b..24ec282e15d8ae436e7dab130a4696708e34be9e 100644 (file)
@@ -599,8 +599,10 @@ static enum ap_wait ap_sm_read(struct ap_device *ap_dev)
        status = ap_sm_recv(ap_dev);
        switch (status.response_code) {
        case AP_RESPONSE_NORMAL:
-               if (ap_dev->queue_count > 0)
+               if (ap_dev->queue_count > 0) {
+                       ap_dev->state = AP_STATE_WORKING;
                        return AP_WAIT_AGAIN;
+               }
                ap_dev->state = AP_STATE_IDLE;
                return AP_WAIT_NONE;
        case AP_RESPONSE_NO_PENDING_REPLY:
index b2a1a81e6fc8f048c202b7eca54b2b0b6c22b368..1b831598df7c6544057f23ef69da5ea54bbafcdd 100644 (file)
@@ -984,6 +984,36 @@ static struct virtqueue *virtio_ccw_vq_by_ind(struct virtio_ccw_device *vcdev,
        return vq;
 }
 
+static void virtio_ccw_check_activity(struct virtio_ccw_device *vcdev,
+                                     __u32 activity)
+{
+       if (vcdev->curr_io & activity) {
+               switch (activity) {
+               case VIRTIO_CCW_DOING_READ_FEAT:
+               case VIRTIO_CCW_DOING_WRITE_FEAT:
+               case VIRTIO_CCW_DOING_READ_CONFIG:
+               case VIRTIO_CCW_DOING_WRITE_CONFIG:
+               case VIRTIO_CCW_DOING_WRITE_STATUS:
+               case VIRTIO_CCW_DOING_SET_VQ:
+               case VIRTIO_CCW_DOING_SET_IND:
+               case VIRTIO_CCW_DOING_SET_CONF_IND:
+               case VIRTIO_CCW_DOING_RESET:
+               case VIRTIO_CCW_DOING_READ_VQ_CONF:
+               case VIRTIO_CCW_DOING_SET_IND_ADAPTER:
+               case VIRTIO_CCW_DOING_SET_VIRTIO_REV:
+                       vcdev->curr_io &= ~activity;
+                       wake_up(&vcdev->wait_q);
+                       break;
+               default:
+                       /* don't know what to do... */
+                       dev_warn(&vcdev->cdev->dev,
+                                "Suspicious activity '%08x'\n", activity);
+                       WARN_ON(1);
+                       break;
+               }
+       }
+}
+
 static void virtio_ccw_int_handler(struct ccw_device *cdev,
                                   unsigned long intparm,
                                   struct irb *irb)
@@ -995,6 +1025,12 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev,
 
        if (!vcdev)
                return;
+       if (IS_ERR(irb)) {
+               vcdev->err = PTR_ERR(irb);
+               virtio_ccw_check_activity(vcdev, activity);
+               /* Don't poke around indicators, something's wrong. */
+               return;
+       }
        /* Check if it's a notification from the host. */
        if ((intparm == 0) &&
            (scsw_stctl(&irb->scsw) ==
@@ -1010,31 +1046,7 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev,
                        /* Map everything else to -EIO. */
                        vcdev->err = -EIO;
        }
-       if (vcdev->curr_io & activity) {
-               switch (activity) {
-               case VIRTIO_CCW_DOING_READ_FEAT:
-               case VIRTIO_CCW_DOING_WRITE_FEAT:
-               case VIRTIO_CCW_DOING_READ_CONFIG:
-               case VIRTIO_CCW_DOING_WRITE_CONFIG:
-               case VIRTIO_CCW_DOING_WRITE_STATUS:
-               case VIRTIO_CCW_DOING_SET_VQ:
-               case VIRTIO_CCW_DOING_SET_IND:
-               case VIRTIO_CCW_DOING_SET_CONF_IND:
-               case VIRTIO_CCW_DOING_RESET:
-               case VIRTIO_CCW_DOING_READ_VQ_CONF:
-               case VIRTIO_CCW_DOING_SET_IND_ADAPTER:
-               case VIRTIO_CCW_DOING_SET_VIRTIO_REV:
-                       vcdev->curr_io &= ~activity;
-                       wake_up(&vcdev->wait_q);
-                       break;
-               default:
-                       /* don't know what to do... */
-                       dev_warn(&cdev->dev, "Suspicious activity '%08x'\n",
-                                activity);
-                       WARN_ON(1);
-                       break;
-               }
-       }
+       virtio_ccw_check_activity(vcdev, activity);
        for_each_set_bit(i, &vcdev->indicators,
                         sizeof(vcdev->indicators) * BITS_PER_BYTE) {
                /* The bit clear must happen before the vring kick. */
index e4b7998379485454d26e39f6a5a91917a155ffbb..459abe1dcc87a6dfc1beca5672dc3d59d88bdbd2 100644 (file)
@@ -219,13 +219,13 @@ static int sdev_runtime_suspend(struct device *dev)
        struct scsi_device *sdev = to_scsi_device(dev);
        int err = 0;
 
-       if (pm && pm->runtime_suspend) {
-               err = blk_pre_runtime_suspend(sdev->request_queue);
-               if (err)
-                       return err;
+       err = blk_pre_runtime_suspend(sdev->request_queue);
+       if (err)
+               return err;
+       if (pm && pm->runtime_suspend)
                err = pm->runtime_suspend(dev);
-               blk_post_runtime_suspend(sdev->request_queue, err);
-       }
+       blk_post_runtime_suspend(sdev->request_queue, err);
+
        return err;
 }
 
@@ -248,11 +248,11 @@ static int sdev_runtime_resume(struct device *dev)
        const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
        int err = 0;
 
-       if (pm && pm->runtime_resume) {
-               blk_pre_runtime_resume(sdev->request_queue);
+       blk_pre_runtime_resume(sdev->request_queue);
+       if (pm && pm->runtime_resume)
                err = pm->runtime_resume(dev);
-               blk_post_runtime_resume(sdev->request_queue, err);
-       }
+       blk_post_runtime_resume(sdev->request_queue, err);
+
        return err;
 }
 
index 3d22fc3e3c1a7ba6df90665f59cf10e8d38ef715..4e08d1cd704d1c261c82a98067649154f433ecd1 100644 (file)
@@ -2885,10 +2885,13 @@ static int sd_revalidate_disk(struct gendisk *disk)
 
        /*
         * Use the device's preferred I/O size for reads and writes
-        * unless the reported value is unreasonably large (or garbage).
+        * unless the reported value is unreasonably small, large, or
+        * garbage.
         */
-       if (sdkp->opt_xfer_blocks && sdkp->opt_xfer_blocks <= dev_max &&
-           sdkp->opt_xfer_blocks <= SD_DEF_XFER_BLOCKS)
+       if (sdkp->opt_xfer_blocks &&
+           sdkp->opt_xfer_blocks <= dev_max &&
+           sdkp->opt_xfer_blocks <= SD_DEF_XFER_BLOCKS &&
+           sdkp->opt_xfer_blocks * sdp->sector_size >= PAGE_CACHE_SIZE)
                rw_max = q->limits.io_opt =
                        logical_to_sectors(sdp, sdkp->opt_xfer_blocks);
        else
index dcb0d76d7312847d37809df1f5763206567d5daf..044d06410d4c86c0dc88071bb0de668dd91bb0e2 100644 (file)
@@ -84,6 +84,7 @@ static void init_device_slot_control(unsigned char *dest_desc,
 static int ses_recv_diag(struct scsi_device *sdev, int page_code,
                         void *buf, int bufflen)
 {
+       int ret;
        unsigned char cmd[] = {
                RECEIVE_DIAGNOSTIC,
                1,              /* Set PCV bit */
@@ -92,9 +93,26 @@ static int ses_recv_diag(struct scsi_device *sdev, int page_code,
                bufflen & 0xff,
                0
        };
+       unsigned char recv_page_code;
 
-       return scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, bufflen,
+       ret =  scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, bufflen,
                                NULL, SES_TIMEOUT, SES_RETRIES, NULL);
+       if (unlikely(!ret))
+               return ret;
+
+       recv_page_code = ((unsigned char *)buf)[0];
+
+       if (likely(recv_page_code == page_code))
+               return ret;
+
+       /* successful diagnostic but wrong page code.  This happens to some
+        * USB devices, just print a message and pretend there was an error */
+
+       sdev_printk(KERN_ERR, sdev,
+                   "Wrong diagnostic page; asked for %d got %u\n",
+                   page_code, recv_page_code);
+
+       return -EINVAL;
 }
 
 static int ses_send_diag(struct scsi_device *sdev, int page_code,
@@ -541,7 +559,15 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
                        if (desc_ptr)
                                desc_ptr += len;
 
-                       if (addl_desc_ptr)
+                       if (addl_desc_ptr &&
+                           /* only find additional descriptions for specific devices */
+                           (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE ||
+                            type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE ||
+                            type_ptr[0] == ENCLOSURE_COMPONENT_SAS_EXPANDER ||
+                            /* these elements are optional */
+                            type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_TARGET_PORT ||
+                            type_ptr[0] == ENCLOSURE_COMPONENT_SCSI_INITIATOR_PORT ||
+                            type_ptr[0] == ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS))
                                addl_desc_ptr += addl_desc_ptr[1] + 2;
 
                }
index 59a11437db7090f9c8464f8ca0584c789be2e997..39412c9097c6a240466c51c941ec890a4612542e 100644 (file)
@@ -167,7 +167,7 @@ static inline int is_double_byte_mode(struct fsl_dspi *dspi)
 {
        unsigned int val;
 
-       regmap_read(dspi->regmap, SPI_CTAR(dspi->cs), &val);
+       regmap_read(dspi->regmap, SPI_CTAR(0), &val);
 
        return ((val & SPI_FRAME_BITS_MASK) == SPI_FRAME_BITS(8)) ? 0 : 1;
 }
@@ -257,7 +257,7 @@ static u32 dspi_data_to_pushr(struct fsl_dspi *dspi, int tx_word)
 
        return  SPI_PUSHR_TXDATA(d16) |
                SPI_PUSHR_PCS(dspi->cs) |
-               SPI_PUSHR_CTAS(dspi->cs) |
+               SPI_PUSHR_CTAS(0) |
                SPI_PUSHR_CONT;
 }
 
@@ -290,7 +290,7 @@ static int dspi_eoq_write(struct fsl_dspi *dspi)
                 */
                if (tx_word && (dspi->len == 1)) {
                        dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM;
-                       regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs),
+                       regmap_update_bits(dspi->regmap, SPI_CTAR(0),
                                        SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8));
                        tx_word = 0;
                }
@@ -339,7 +339,7 @@ static int dspi_tcfq_write(struct fsl_dspi *dspi)
 
        if (tx_word && (dspi->len == 1)) {
                dspi->dataflags |= TRAN_STATE_WORD_ODD_NUM;
-               regmap_update_bits(dspi->regmap, SPI_CTAR(dspi->cs),
+               regmap_update_bits(dspi->regmap, SPI_CTAR(0),
                                SPI_FRAME_BITS_MASK, SPI_FRAME_BITS(8));
                tx_word = 0;
        }
@@ -407,7 +407,7 @@ static int dspi_transfer_one_message(struct spi_master *master,
                regmap_update_bits(dspi->regmap, SPI_MCR,
                                SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF,
                                SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF);
-               regmap_write(dspi->regmap, SPI_CTAR(dspi->cs),
+               regmap_write(dspi->regmap, SPI_CTAR(0),
                                dspi->cur_chip->ctar_val);
 
                trans_mode = dspi->devtype_data->trans_mode;
@@ -566,7 +566,7 @@ static irqreturn_t dspi_interrupt(int irq, void *dev_id)
                if (!dspi->len) {
                        if (dspi->dataflags & TRAN_STATE_WORD_ODD_NUM) {
                                regmap_update_bits(dspi->regmap,
-                                                  SPI_CTAR(dspi->cs),
+                                                  SPI_CTAR(0),
                                                   SPI_FRAME_BITS_MASK,
                                                   SPI_FRAME_BITS(16));
                                dspi->dataflags &= ~TRAN_STATE_WORD_ODD_NUM;
index 2b0a8ec3affb87333f8bdb2e9a2d9ad95855d4c1..dee1cb87d24f4aaca1fd3d2e43b8101d3bf6e246 100644 (file)
@@ -1705,7 +1705,7 @@ struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
        master->bus_num = -1;
        master->num_chipselect = 1;
        master->dev.class = &spi_master_class;
-       master->dev.parent = get_device(dev);
+       master->dev.parent = dev;
        spi_master_set_devdata(master, &master[1]);
 
        return master;
index 91a0fcd72423080900c6c733f6aeb7e800a85538..d0e7dfc647cf21a729696cbe499f7fc6dbf53b02 100644 (file)
@@ -651,11 +651,11 @@ static int spidev_release(struct inode *inode, struct file *filp)
                kfree(spidev->rx_buffer);
                spidev->rx_buffer = NULL;
 
+               spin_lock_irq(&spidev->spi_lock);
                if (spidev->spi)
                        spidev->speed_hz = spidev->spi->max_speed_hz;
 
                /* ... after we unbound from the underlying device? */
-               spin_lock_irq(&spidev->spi_lock);
                dofree = (spidev->spi == NULL);
                spin_unlock_irq(&spidev->spi_lock);
 
index 195c41d7bd53b3b6926507cdfea2a8de42d45578..0813163f962f09e328d6fc448238201f84cc55cd 100644 (file)
@@ -81,7 +81,7 @@ static int ion_chunk_heap_allocate(struct ion_heap *heap,
 err:
        sg = table->sgl;
        for (i -= 1; i >= 0; i--) {
-               gen_pool_free(chunk_heap->pool, sg_phys(sg) & PAGE_MASK,
+               gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)),
                              sg->length);
                sg = sg_next(sg);
        }
@@ -109,7 +109,7 @@ static void ion_chunk_heap_free(struct ion_buffer *buffer)
                                                        DMA_BIDIRECTIONAL);
 
        for_each_sg(table->sgl, sg, table->nents, i) {
-               gen_pool_free(chunk_heap->pool, sg_phys(sg) & PAGE_MASK,
+               gen_pool_free(chunk_heap->pool, page_to_phys(sg_page(sg)),
                              sg->length);
        }
        chunk_heap->allocated -= allocated_size;
index bfbf1c56bd22630e19ac739eadd514157071ab2b..6eb600ff70569ef6ceb902afcc49ddce08b09953 100644 (file)
@@ -159,7 +159,7 @@ static irqreturn_t iio_simple_dummy_get_timestamp(int irq, void *private)
        struct iio_dummy_state *st = iio_priv(indio_dev);
 
        st->event_timestamp = iio_get_time_ns();
-       return IRQ_HANDLED;
+       return IRQ_WAKE_THREAD;
 }
 
 /**
index 69b203651905e93f77149754a5b9d6a021b6bf32..e489a3271f0697fe8a9f35708434412072a3f2a1 100644 (file)
@@ -118,12 +118,20 @@ failed:
        return rc;
 }
 
-static const char *ll_follow_link(struct dentry *dentry, void **cookie)
+static void ll_put_link(void *p)
+{
+       ptlrpc_req_finished(p);
+}
+
+static const char *ll_get_link(struct dentry *dentry,
+                              struct inode *inode,
+                              struct delayed_call *done)
 {
-       struct inode *inode = d_inode(dentry);
        struct ptlrpc_request *request = NULL;
        int rc;
        char *symname = NULL;
+       if (!dentry)
+               return ERR_PTR(-ECHILD);
 
        CDEBUG(D_VFSTRACE, "VFS Op\n");
        ll_inode_size_lock(inode);
@@ -135,22 +143,16 @@ static const char *ll_follow_link(struct dentry *dentry, void **cookie)
        }
 
        /* symname may contain a pointer to the request message buffer,
-        * we delay request releasing until ll_put_link then.
+        * we delay request releasing then.
         */
-       *cookie = request;
+       set_delayed_call(done, ll_put_link, request);
        return symname;
 }
 
-static void ll_put_link(struct inode *unused, void *cookie)
-{
-       ptlrpc_req_finished(cookie);
-}
-
 struct inode_operations ll_fast_symlink_inode_operations = {
        .readlink       = generic_readlink,
        .setattr        = ll_setattr,
-       .follow_link    = ll_follow_link,
-       .put_link       = ll_put_link,
+       .get_link       = ll_get_link,
        .getattr        = ll_getattr,
        .permission     = ll_inode_permission,
        .setxattr       = ll_setxattr,
index f61ef669644cdadfc10c54539c5743c012082d09..a4a9a763ff023821644197fca610e7783d773129 100644 (file)
@@ -1270,6 +1270,7 @@ static int
 echo_copyout_lsm(struct lov_stripe_md *lsm, void *_ulsm, int ulsm_nob)
 {
        struct lov_stripe_md *ulsm = _ulsm;
+       struct lov_oinfo **p;
        int nob, i;
 
        nob = offsetof(struct lov_stripe_md, lsm_oinfo[lsm->lsm_stripe_count]);
@@ -1279,9 +1280,10 @@ echo_copyout_lsm(struct lov_stripe_md *lsm, void *_ulsm, int ulsm_nob)
        if (copy_to_user(ulsm, lsm, sizeof(*ulsm)))
                return -EFAULT;
 
-       for (i = 0; i < lsm->lsm_stripe_count; i++) {
-               if (copy_to_user(ulsm->lsm_oinfo[i], lsm->lsm_oinfo[i],
-                                     sizeof(lsm->lsm_oinfo[0])))
+       for (i = 0, p = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++, p++) {
+               struct lov_oinfo __user *up;
+               if (get_user(up, ulsm->lsm_oinfo + i) ||
+                   copy_to_user(up, *p, sizeof(struct lov_oinfo)))
                        return -EFAULT;
        }
        return 0;
@@ -1289,9 +1291,10 @@ echo_copyout_lsm(struct lov_stripe_md *lsm, void *_ulsm, int ulsm_nob)
 
 static int
 echo_copyin_lsm(struct echo_device *ed, struct lov_stripe_md *lsm,
-                void *ulsm, int ulsm_nob)
+               struct lov_stripe_md __user *ulsm, int ulsm_nob)
 {
        struct echo_client_obd *ec = ed->ed_ec;
+       struct lov_oinfo **p;
        int                  i;
 
        if (ulsm_nob < sizeof(*lsm))
@@ -1306,11 +1309,10 @@ echo_copyin_lsm(struct echo_device *ed, struct lov_stripe_md *lsm,
            ((__u64)lsm->lsm_stripe_size * lsm->lsm_stripe_count > ~0UL))
                return -EINVAL;
 
-       for (i = 0; i < lsm->lsm_stripe_count; i++) {
-               if (copy_from_user(lsm->lsm_oinfo[i],
-                                      ((struct lov_stripe_md *)ulsm)-> \
-                                      lsm_oinfo[i],
-                                      sizeof(lsm->lsm_oinfo[0])))
+       for (i = 0, p = lsm->lsm_oinfo; i < lsm->lsm_stripe_count; i++, p++) {
+               struct lov_oinfo __user *up;
+               if (get_user(up, ulsm->lsm_oinfo + i) ||
+                   copy_from_user(*p, up, sizeof(struct lov_oinfo)))
                        return -EFAULT;
        }
        return 0;
index ed776149261ea1022fc0586ce3be200967ec4c0b..e49c2bce551d31db115b97f0a12807339258b69b 100644 (file)
@@ -2054,13 +2054,13 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
        size_t eol;
        size_t tail;
        int ret, found = 0;
-       bool eof_push = 0;
 
        /* N.B. avoid overrun if nr == 0 */
-       n = min(*nr, smp_load_acquire(&ldata->canon_head) - ldata->read_tail);
-       if (!n)
+       if (!*nr)
                return 0;
 
+       n = min(*nr + 1, smp_load_acquire(&ldata->canon_head) - ldata->read_tail);
+
        tail = ldata->read_tail & (N_TTY_BUF_SIZE - 1);
        size = min_t(size_t, tail + n, N_TTY_BUF_SIZE);
 
@@ -2081,12 +2081,11 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
        n = eol - tail;
        if (n > N_TTY_BUF_SIZE)
                n += N_TTY_BUF_SIZE;
-       n += found;
-       c = n;
+       c = n + found;
 
-       if (found && !ldata->push && read_buf(ldata, eol) == __DISABLED_CHAR) {
-               n--;
-               eof_push = !n && ldata->read_tail != ldata->line_start;
+       if (!found || read_buf(ldata, eol) != __DISABLED_CHAR) {
+               c = min(*nr, c);
+               n = c;
        }
 
        n_tty_trace("%s: eol:%zu found:%d n:%zu c:%zu size:%zu more:%zu\n",
@@ -2116,7 +2115,7 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
                        ldata->push = 0;
                tty_audit_push(tty);
        }
-       return eof_push ? -EAGAIN : 0;
+       return 0;
 }
 
 extern ssize_t redirected_tty_write(struct file *, const char __user *,
@@ -2273,10 +2272,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
 
                if (ldata->icanon && !L_EXTPROC(tty)) {
                        retval = canon_copy_from_read_buf(tty, &b, &nr);
-                       if (retval == -EAGAIN) {
-                               retval = 0;
-                               continue;
-                       } else if (retval)
+                       if (retval)
                                break;
                } else {
                        int uncopied;
index d11621e2cf1df083ca4c58309ef610df6c9c70fa..245edbb68d4ba5fe98e6e8fa915bf518cc4f28a5 100644 (file)
@@ -115,12 +115,16 @@ static void uniphier_serial_out(struct uart_port *p, int offset, int value)
  */
 static int uniphier_serial_dl_read(struct uart_8250_port *up)
 {
-       return readl(up->port.membase + UNIPHIER_UART_DLR);
+       int offset = UNIPHIER_UART_DLR << up->port.regshift;
+
+       return readl(up->port.membase + offset);
 }
 
 static void uniphier_serial_dl_write(struct uart_8250_port *up, int value)
 {
-       writel(value, up->port.membase + UNIPHIER_UART_DLR);
+       int offset = UNIPHIER_UART_DLR << up->port.regshift;
+
+       writel(value, up->port.membase + offset);
 }
 
 static int uniphier_of_serial_setup(struct device *dev, struct uart_port *port,
index f09636083426d5fc2fdb18a65a2a1af49a0093b7..b5b2f2be6be7c613b5c051c0d9730d3fa3b5e177 100644 (file)
@@ -115,6 +115,7 @@ static int __init register_earlycon(char *buf, const struct earlycon_id *match)
        if (buf && !parse_options(&early_console_dev, buf))
                buf = NULL;
 
+       spin_lock_init(&port->lock);
        port->uartclk = BASE_BAUD * 16;
        if (port->mapbase)
                port->membase = earlycon_map(port->mapbase, 64);
@@ -202,6 +203,7 @@ int __init of_setup_earlycon(unsigned long addr,
        int err;
        struct uart_port *port = &early_console_dev.port;
 
+       spin_lock_init(&port->lock);
        port->iotype = UPIO_MEM;
        port->mapbase = addr;
        port->uartclk = BASE_BAUD * 16;
index 960e50a97558cff52a1fb9eb8ed8879a5238991c..51c7507b0444957bcbc9c2c832bd6048a5f3b596 100644 (file)
@@ -1437,7 +1437,7 @@ static void sci_request_dma(struct uart_port *port)
                        sg_init_table(sg, 1);
                        s->rx_buf[i] = buf;
                        sg_dma_address(sg) = dma;
-                       sg->length = s->buf_len_rx;
+                       sg_dma_len(sg) = s->buf_len_rx;
 
                        buf += s->buf_len_rx;
                        dma += s->buf_len_rx;
index 064031870ba0d1b0bf09fd3bcb299d17dcaf76d5..ca0d3802f2af45fb8be9cad11d9763fb615e516a 100644 (file)
@@ -148,8 +148,10 @@ static int receive_chars_read(struct uart_port *port)
                        uart_handle_dcd_change(port, 1);
                }
 
-               for (i = 0; i < bytes_read; i++)
-                       uart_handle_sysrq_char(port, con_read_page[i]);
+               if (port->sysrq != 0 &&  *con_read_page) {
+                       for (i = 0; i < bytes_read; i++)
+                               uart_handle_sysrq_char(port, con_read_page[i]);
+               }
 
                if (port->state == NULL)
                        continue;
@@ -168,17 +170,17 @@ struct sunhv_ops {
        int (*receive_chars)(struct uart_port *port);
 };
 
-static struct sunhv_ops bychar_ops = {
+static const struct sunhv_ops bychar_ops = {
        .transmit_chars = transmit_chars_putchar,
        .receive_chars = receive_chars_getchar,
 };
 
-static struct sunhv_ops bywrite_ops = {
+static const struct sunhv_ops bywrite_ops = {
        .transmit_chars = transmit_chars_write,
        .receive_chars = receive_chars_read,
 };
 
-static struct sunhv_ops *sunhv_ops = &bychar_ops;
+static const struct sunhv_ops *sunhv_ops = &bychar_ops;
 
 static struct tty_port *receive_chars(struct uart_port *port)
 {
index 9a479e61791a2a80cd0ae3fd5c93c6d0873d6998..3cd31e0d4bd9545b5357cda0ffa14373d181e670 100644 (file)
@@ -450,7 +450,7 @@ receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count)
                count = disc->ops->receive_buf2(tty, p, f, count);
        else {
                count = min_t(int, count, tty->receive_room);
-               if (count)
+               if (count && disc->ops->receive_buf)
                        disc->ops->receive_buf(tty, p, f, count);
        }
        return count;
index b30e7423549b04b0e7d442a128048b4221c68062..26ca4f910cb020aae539f29b260a98fe1eee92b0 100644 (file)
@@ -1838,6 +1838,11 @@ static const struct usb_device_id acm_ids[] = {
        },
 #endif
 
+       /* Exclude Infineon Flash Loader utility */
+       { USB_DEVICE(0x058b, 0x0041),
+       .driver_info = IGNORE_DEVICE,
+       },
+
        /* control interfaces without any protocol set */
        { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
                USB_CDC_PROTO_NONE) },
index 7caff020106e23f26f9c3bb9c34585885064848d..5050760f5e17cf3872952ae5fa6a40d01aab394b 100644 (file)
@@ -115,7 +115,8 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
                   USB_SS_MULT(desc->bmAttributes) > 3) {
                dev_warn(ddev, "Isoc endpoint has Mult of %d in "
                                "config %d interface %d altsetting %d ep %d: "
-                               "setting to 3\n", desc->bmAttributes + 1,
+                               "setting to 3\n",
+                               USB_SS_MULT(desc->bmAttributes),
                                cfgno, inum, asnum, ep->desc.bEndpointAddress);
                ep->ss_ep_comp.bmAttributes = 2;
        }
index bdeadc112d29f9b4545bf3ab82645b52982f5cfd..ddbf32d599cba4e51aeb81eea8519500a8bbea01 100644 (file)
@@ -124,6 +124,10 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev)
 
 int usb_device_supports_lpm(struct usb_device *udev)
 {
+       /* Some devices have trouble with LPM */
+       if (udev->quirks & USB_QUIRK_NO_LPM)
+               return 0;
+
        /* USB 2.1 (and greater) devices indicate LPM support through
         * their USB 2.0 Extended Capabilities BOS descriptor.
         */
@@ -1031,10 +1035,20 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
        unsigned delay;
 
        /* Continue a partial initialization */
-       if (type == HUB_INIT2)
-               goto init2;
-       if (type == HUB_INIT3)
+       if (type == HUB_INIT2 || type == HUB_INIT3) {
+               device_lock(hub->intfdev);
+
+               /* Was the hub disconnected while we were waiting? */
+               if (hub->disconnected) {
+                       device_unlock(hub->intfdev);
+                       kref_put(&hub->kref, hub_release);
+                       return;
+               }
+               if (type == HUB_INIT2)
+                       goto init2;
                goto init3;
+       }
+       kref_get(&hub->kref);
 
        /* The superspeed hub except for root hub has to use Hub Depth
         * value as an offset into the route string to locate the bits
@@ -1232,6 +1246,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
                        queue_delayed_work(system_power_efficient_wq,
                                        &hub->init_work,
                                        msecs_to_jiffies(delay));
+                       device_unlock(hub->intfdev);
                        return;         /* Continues at init3: below */
                } else {
                        msleep(delay);
@@ -1253,6 +1268,11 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
        /* Allow autosuspend if it was suppressed */
        if (type <= HUB_INIT3)
                usb_autopm_put_interface_async(to_usb_interface(hub->intfdev));
+
+       if (type == HUB_INIT2 || type == HUB_INIT3)
+               device_unlock(hub->intfdev);
+
+       kref_put(&hub->kref, hub_release);
 }
 
 /* Implement the continuations for the delays above */
@@ -4512,6 +4532,8 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
                goto fail;
        }
 
+       usb_detect_quirks(udev);
+
        if (udev->wusb == 0 && le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201) {
                retval = usb_get_bos_descriptor(udev);
                if (!retval) {
@@ -4710,7 +4732,6 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
                if (status < 0)
                        goto loop;
 
-               usb_detect_quirks(udev);
                if (udev->quirks & USB_QUIRK_DELAY_INIT)
                        msleep(1000);
 
@@ -5326,9 +5347,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
        if (udev->usb2_hw_lpm_enabled == 1)
                usb_set_usb2_hardware_lpm(udev, 0);
 
-       bos = udev->bos;
-       udev->bos = NULL;
-
        /* Disable LPM and LTM while we reset the device and reinstall the alt
         * settings.  Device-initiated LPM settings, and system exit latency
         * settings are cleared when the device is reset, so we have to set
@@ -5337,15 +5355,18 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
        ret = usb_unlocked_disable_lpm(udev);
        if (ret) {
                dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__);
-               goto re_enumerate;
+               goto re_enumerate_no_bos;
        }
        ret = usb_disable_ltm(udev);
        if (ret) {
                dev_err(&udev->dev, "%s Failed to disable LTM\n.",
                                __func__);
-               goto re_enumerate;
+               goto re_enumerate_no_bos;
        }
 
+       bos = udev->bos;
+       udev->bos = NULL;
+
        for (i = 0; i < SET_CONFIG_TRIES; ++i) {
 
                /* ep0 maxpacket size may change; let the HCD know about it.
@@ -5442,10 +5463,11 @@ done:
        return 0;
 
 re_enumerate:
-       /* LPM state doesn't matter when we're about to destroy the device. */
-       hub_port_logical_disconnect(parent_hub, port1);
        usb_release_bos_descriptor(udev);
        udev->bos = bos;
+re_enumerate_no_bos:
+       /* LPM state doesn't matter when we're about to destroy the device. */
+       hub_port_logical_disconnect(parent_hub, port1);
        return -ENODEV;
 }
 
index 210618319f10a4110bc53191fc8a06a860992c3a..5487fe308f01b7be30bcecebc12726a295f9daa9 100644 (file)
@@ -206,7 +206,7 @@ static int link_peers(struct usb_port *left, struct usb_port *right)
                else
                        method = "default";
 
-               pr_warn("usb: failed to peer %s and %s by %s (%s:%s) (%s:%s)\n",
+               pr_debug("usb: failed to peer %s and %s by %s (%s:%s) (%s:%s)\n",
                        dev_name(&left->dev), dev_name(&right->dev), method,
                        dev_name(&left->dev),
                        lpeer ? dev_name(&lpeer->dev) : "none",
@@ -265,7 +265,7 @@ static void link_peers_report(struct usb_port *left, struct usb_port *right)
        if (rc == 0) {
                dev_dbg(&left->dev, "peered to %s\n", dev_name(&right->dev));
        } else {
-               dev_warn(&left->dev, "failed to peer to %s (%d)\n",
+               dev_dbg(&left->dev, "failed to peer to %s (%d)\n",
                                dev_name(&right->dev), rc);
                pr_warn_once("usb: port power management may be unreliable\n");
                usb_port_block_power_off = 1;
index f5a381945db2886a77e23a8fcf40ba9a34bb7fe7..6dc810bce295ab22dbb10b47755dddb421f96957 100644 (file)
@@ -125,6 +125,9 @@ static const struct usb_device_id usb_quirk_list[] = {
        { USB_DEVICE(0x04f3, 0x016f), .driver_info =
                        USB_QUIRK_DEVICE_QUALIFIER },
 
+       { USB_DEVICE(0x04f3, 0x21b8), .driver_info =
+                       USB_QUIRK_DEVICE_QUALIFIER },
+
        /* Roland SC-8820 */
        { USB_DEVICE(0x0582, 0x0007), .driver_info = USB_QUIRK_RESET_RESUME },
 
@@ -199,6 +202,12 @@ static const struct usb_device_id usb_quirk_list[] = {
        { USB_DEVICE(0x1a0a, 0x0200), .driver_info =
                        USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
 
+       /* Blackmagic Design Intensity Shuttle */
+       { USB_DEVICE(0x1edb, 0xbd3b), .driver_info = USB_QUIRK_NO_LPM },
+
+       /* Blackmagic Design UltraStudio SDI */
+       { USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM },
+
        { }  /* terminating entry must be last */
 };
 
index e61d773cf65e71e27a41f3c7d8e5306939d08908..39c1cbf0e75d9a5957b1567def5d23fb3631a015 100644 (file)
@@ -125,9 +125,11 @@ static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg)
        if (ret)
                return ret;
 
-       ret = clk_prepare_enable(hsotg->clk);
-       if (ret)
-               return ret;
+       if (hsotg->clk) {
+               ret = clk_prepare_enable(hsotg->clk);
+               if (ret)
+                       return ret;
+       }
 
        if (hsotg->uphy)
                ret = usb_phy_init(hsotg->uphy);
@@ -175,7 +177,8 @@ static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg)
        if (ret)
                return ret;
 
-       clk_disable_unprepare(hsotg->clk);
+       if (hsotg->clk)
+               clk_disable_unprepare(hsotg->clk);
 
        ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies),
                                     hsotg->supplies);
@@ -212,14 +215,41 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
         */
        hsotg->phy = devm_phy_get(hsotg->dev, "usb2-phy");
        if (IS_ERR(hsotg->phy)) {
-               hsotg->phy = NULL;
+               ret = PTR_ERR(hsotg->phy);
+               switch (ret) {
+               case -ENODEV:
+               case -ENOSYS:
+                       hsotg->phy = NULL;
+                       break;
+               case -EPROBE_DEFER:
+                       return ret;
+               default:
+                       dev_err(hsotg->dev, "error getting phy %d\n", ret);
+                       return ret;
+               }
+       }
+
+       if (!hsotg->phy) {
                hsotg->uphy = devm_usb_get_phy(hsotg->dev, USB_PHY_TYPE_USB2);
-               if (IS_ERR(hsotg->uphy))
-                       hsotg->uphy = NULL;
-               else
-                       hsotg->plat = dev_get_platdata(hsotg->dev);
+               if (IS_ERR(hsotg->uphy)) {
+                       ret = PTR_ERR(hsotg->uphy);
+                       switch (ret) {
+                       case -ENODEV:
+                       case -ENXIO:
+                               hsotg->uphy = NULL;
+                               break;
+                       case -EPROBE_DEFER:
+                               return ret;
+                       default:
+                               dev_err(hsotg->dev, "error getting usb phy %d\n",
+                                       ret);
+                               return ret;
+                       }
+               }
        }
 
+       hsotg->plat = dev_get_platdata(hsotg->dev);
+
        if (hsotg->phy) {
                /*
                 * If using the generic PHY framework, check if the PHY bus
@@ -229,11 +259,6 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
                        hsotg->phyif = GUSBCFG_PHYIF8;
        }
 
-       if (!hsotg->phy && !hsotg->uphy && !hsotg->plat) {
-               dev_err(hsotg->dev, "no platform data or transceiver defined\n");
-               return -EPROBE_DEFER;
-       }
-
        /* Clock */
        hsotg->clk = devm_clk_get(hsotg->dev, "otg");
        if (IS_ERR(hsotg->clk)) {
@@ -342,20 +367,6 @@ static int dwc2_driver_probe(struct platform_device *dev)
        if (retval)
                return retval;
 
-       irq = platform_get_irq(dev, 0);
-       if (irq < 0) {
-               dev_err(&dev->dev, "missing IRQ resource\n");
-               return irq;
-       }
-
-       dev_dbg(hsotg->dev, "registering common handler for irq%d\n",
-               irq);
-       retval = devm_request_irq(hsotg->dev, irq,
-                                 dwc2_handle_common_intr, IRQF_SHARED,
-                                 dev_name(hsotg->dev), hsotg);
-       if (retval)
-               return retval;
-
        res = platform_get_resource(dev, IORESOURCE_MEM, 0);
        hsotg->regs = devm_ioremap_resource(&dev->dev, res);
        if (IS_ERR(hsotg->regs))
@@ -390,6 +401,20 @@ static int dwc2_driver_probe(struct platform_device *dev)
 
        dwc2_set_all_params(hsotg->core_params, -1);
 
+       irq = platform_get_irq(dev, 0);
+       if (irq < 0) {
+               dev_err(&dev->dev, "missing IRQ resource\n");
+               return irq;
+       }
+
+       dev_dbg(hsotg->dev, "registering common handler for irq%d\n",
+               irq);
+       retval = devm_request_irq(hsotg->dev, irq,
+                                 dwc2_handle_common_intr, IRQF_SHARED,
+                                 dev_name(hsotg->dev), hsotg);
+       if (retval)
+               return retval;
+
        retval = dwc2_lowlevel_hw_enable(hsotg);
        if (retval)
                return retval;
index e24a01cc98df4a43f2fd556e44b1557dce778d33..a58376fd65fe6d788fa817d5600696bfd431c791 100644 (file)
@@ -1078,6 +1078,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
         * little bit faster.
         */
        if (!usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
+                       !usb_endpoint_xfer_int(dep->endpoint.desc) &&
                        !(dep->flags & DWC3_EP_BUSY)) {
                ret = __dwc3_gadget_kick_transfer(dep, 0, true);
                goto out;
index adc6d52efa4639387c30bcde2ae7cee95331b1bc..cf43e9e18368dcd84668b9378b1036b17276b593 100644 (file)
@@ -423,7 +423,7 @@ static ssize_t __ffs_ep0_read_events(struct ffs_data *ffs, char __user *buf,
        spin_unlock_irq(&ffs->ev.waitq.lock);
        mutex_unlock(&ffs->mutex);
 
-       return unlikely(__copy_to_user(buf, events, size)) ? -EFAULT : size;
+       return unlikely(copy_to_user(buf, events, size)) ? -EFAULT : size;
 }
 
 static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
@@ -513,7 +513,7 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
 
                /* unlocks spinlock */
                ret = __ffs_ep0_queue_wait(ffs, data, len);
-               if (likely(ret > 0) && unlikely(__copy_to_user(buf, data, len)))
+               if (likely(ret > 0) && unlikely(copy_to_user(buf, data, len)))
                        ret = -EFAULT;
                goto done_mutex;
 
@@ -3493,7 +3493,7 @@ static char *ffs_prepare_buffer(const char __user *buf, size_t len)
        if (unlikely(!data))
                return ERR_PTR(-ENOMEM);
 
-       if (unlikely(__copy_from_user(data, buf, len))) {
+       if (unlikely(copy_from_user(data, buf, len))) {
                kfree(data);
                return ERR_PTR(-EFAULT);
        }
index 42acb45e1ab42dd9436244bec16d4903603d6089..898a570319f17c3128b7a44878ebc09ea7242961 100644 (file)
@@ -370,6 +370,7 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
                if (err) {
                        ERROR(midi, "%s queue req: %d\n",
                                    midi->out_ep->name, err);
+                       free_ep_req(midi->out_ep, req);
                }
        }
 
@@ -545,7 +546,7 @@ static void f_midi_transmit(struct f_midi *midi, struct usb_request *req)
                }
        }
 
-       if (req->length > 0) {
+       if (req->length > 0 && ep->enabled) {
                int err;
 
                err = usb_ep_queue(ep, req, GFP_ATOMIC);
index 289ebca316d3f4ab0e136a14858bb7275eee53c0..ad8c9b05572d7421885ff161d32543f8942eb90d 100644 (file)
@@ -20,7 +20,7 @@
 #define UVC_ATTR(prefix, cname, aname) \
 static struct configfs_attribute prefix##attr_##cname = { \
        .ca_name        = __stringify(aname),                           \
-       .ca_mode        = S_IRUGO,                                      \
+       .ca_mode        = S_IRUGO | S_IWUGO,                            \
        .ca_owner       = THIS_MODULE,                                  \
        .show           = prefix##cname##_show,                         \
        .store          = prefix##cname##_store,                        \
index 670ac0b12f00842ad7a5b840c941f2e8a8a7f1cc..001a3b74a993ea677dd65650a4457f5f14376a7c 100644 (file)
@@ -2536,6 +2536,9 @@ static int pxa_udc_suspend(struct platform_device *_dev, pm_message_t state)
        udc->pullup_resume = udc->pullup_on;
        dplus_pullup(udc, 0);
 
+       if (udc->driver)
+               udc->driver->disconnect(&udc->gadget);
+
        return 0;
 }
 
index 342ffd1401222179589906ccc1d09ec102a1f03b..8c6e15bd6ff0b27ce2e8cb22c2fe03e9866f1768 100644 (file)
@@ -473,6 +473,8 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
        if (!pdata)
                return -ENOMEM;
 
+       pdev->dev.platform_data = pdata;
+
        if (!of_property_read_u32(np, "num-ports", &ports))
                pdata->ports = ports;
 
@@ -483,6 +485,7 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
                 */
                if (i >= pdata->ports) {
                        pdata->vbus_pin[i] = -EINVAL;
+                       pdata->overcurrent_pin[i] = -EINVAL;
                        continue;
                }
 
@@ -513,10 +516,8 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
        }
 
        at91_for_each_port(i) {
-               if (i >= pdata->ports) {
-                       pdata->overcurrent_pin[i] = -EINVAL;
-                       continue;
-               }
+               if (i >= pdata->ports)
+                       break;
 
                pdata->overcurrent_pin[i] =
                        of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags);
@@ -552,8 +553,6 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
                }
        }
 
-       pdev->dev.platform_data = pdata;
-
        device_init_wakeup(&pdev->dev, 1);
        return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev);
 }
index dc31c425ce0179551b27e2d7a900f1bb7b411ad8..9f1c0538b211217d21184ef2527f764933aace0d 100644 (file)
@@ -377,6 +377,10 @@ static int qset_fill_page_list(struct whc *whc, struct whc_std *std, gfp_t mem_f
        if (std->pl_virt == NULL)
                return -ENOMEM;
        std->dma_addr = dma_map_single(whc->wusbhc.dev, std->pl_virt, pl_len, DMA_TO_DEVICE);
+       if (dma_mapping_error(whc->wusbhc.dev, std->dma_addr)) {
+               kfree(std->pl_virt);
+               return -EFAULT;
+       }
 
        for (p = 0; p < std->num_pointers; p++) {
                std->pl_virt[p].buf_ptr = cpu_to_le64(dma_addr);
index 0230965fb78cf3433702932625aee270dbf90535..f980c239eded9bd5e9615ebf96deefce5c7ec591 100644 (file)
@@ -733,8 +733,30 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
                if ((raw_port_status & PORT_RESET) ||
                                !(raw_port_status & PORT_PE))
                        return 0xffffffff;
-               if (time_after_eq(jiffies,
-                                       bus_state->resume_done[wIndex])) {
+               /* did port event handler already start resume timing? */
+               if (!bus_state->resume_done[wIndex]) {
+                       /* If not, maybe we are in a host initated resume? */
+                       if (test_bit(wIndex, &bus_state->resuming_ports)) {
+                               /* Host initated resume doesn't time the resume
+                                * signalling using resume_done[].
+                                * It manually sets RESUME state, sleeps 20ms
+                                * and sets U0 state. This should probably be
+                                * changed, but not right now.
+                                */
+                       } else {
+                               /* port resume was discovered now and here,
+                                * start resume timing
+                                */
+                               unsigned long timeout = jiffies +
+                                       msecs_to_jiffies(USB_RESUME_TIMEOUT);
+
+                               set_bit(wIndex, &bus_state->resuming_ports);
+                               bus_state->resume_done[wIndex] = timeout;
+                               mod_timer(&hcd->rh_timer, timeout);
+                       }
+               /* Has resume been signalled for USB_RESUME_TIME yet? */
+               } else if (time_after_eq(jiffies,
+                                        bus_state->resume_done[wIndex])) {
                        int time_left;
 
                        xhci_dbg(xhci, "Resume USB2 port %d\n",
@@ -775,13 +797,26 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
                } else {
                        /*
                         * The resume has been signaling for less than
-                        * 20ms. Report the port status as SUSPEND,
-                        * let the usbcore check port status again
-                        * and clear resume signaling later.
+                        * USB_RESUME_TIME. Report the port status as SUSPEND,
+                        * let the usbcore check port status again and clear
+                        * resume signaling later.
                         */
                        status |= USB_PORT_STAT_SUSPEND;
                }
        }
+       /*
+        * Clear stale usb2 resume signalling variables in case port changed
+        * state during resume signalling. For example on error
+        */
+       if ((bus_state->resume_done[wIndex] ||
+            test_bit(wIndex, &bus_state->resuming_ports)) &&
+           (raw_port_status & PORT_PLS_MASK) != XDEV_U3 &&
+           (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME) {
+               bus_state->resume_done[wIndex] = 0;
+               clear_bit(wIndex, &bus_state->resuming_ports);
+       }
+
+
        if ((raw_port_status & PORT_PLS_MASK) == XDEV_U0 &&
            (raw_port_status & PORT_POWER)) {
                if (bus_state->suspended_ports & (1 << wIndex)) {
@@ -1115,6 +1150,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                                if ((temp & PORT_PE) == 0)
                                        goto error;
 
+                               set_bit(wIndex, &bus_state->resuming_ports);
                                xhci_set_link_state(xhci, port_array, wIndex,
                                                        XDEV_RESUME);
                                spin_unlock_irqrestore(&xhci->lock, flags);
@@ -1122,6 +1158,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                                spin_lock_irqsave(&xhci->lock, flags);
                                xhci_set_link_state(xhci, port_array, wIndex,
                                                        XDEV_U0);
+                               clear_bit(wIndex, &bus_state->resuming_ports);
                        }
                        bus_state->port_c_suspend |= 1 << wIndex;
 
index 17f6897acde2a5a7674ccff44ddc55f0db192166..c62109091d12855f7b5bb0e2b44a0b6b516cc88b 100644 (file)
@@ -188,10 +188,14 @@ static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev)
                0xb7, 0x0c, 0x34, 0xac, 0x01, 0xe9, 0xbf, 0x45,
                0xb7, 0xe6, 0x2b, 0x34, 0xec, 0x93, 0x1e, 0x23,
        };
-       acpi_evaluate_dsm(ACPI_HANDLE(&dev->dev), intel_dsm_uuid, 3, 1, NULL);
+       union acpi_object *obj;
+
+       obj = acpi_evaluate_dsm(ACPI_HANDLE(&dev->dev), intel_dsm_uuid, 3, 1,
+                               NULL);
+       ACPI_FREE(obj);
 }
 #else
-       static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { }
+static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { }
 #endif /* CONFIG_ACPI */
 
 /* called during probe() after chip reset completes */
index 6c5e8133cf87c4b203e2072de5b7275c4d944365..eeaa6c6bd540870f8065338a61ee37d838c6b07e 100644 (file)
@@ -1583,7 +1583,8 @@ static void handle_port_status(struct xhci_hcd *xhci,
                         */
                        bogus_port_status = true;
                        goto cleanup;
-               } else {
+               } else if (!test_bit(faked_port_index,
+                                    &bus_state->resuming_ports)) {
                        xhci_dbg(xhci, "resume HS port %d\n", port_id);
                        bus_state->resume_done[faked_port_index] = jiffies +
                                msecs_to_jiffies(USB_RESUME_TIMEOUT);
index dfa44d3e8eee469c9b8321fed57056ebe5813a2a..3f912705dcef93a5f27e6979f8aea9a6972b44eb 100644 (file)
@@ -4778,8 +4778,16 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
        ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
        slot_ctx = xhci_get_slot_ctx(xhci, config_cmd->in_ctx);
        slot_ctx->dev_info |= cpu_to_le32(DEV_HUB);
+       /*
+        * refer to section 6.2.2: MTT should be 0 for full speed hub,
+        * but it may be already set to 1 when setup an xHCI virtual
+        * device, so clear it anyway.
+        */
        if (tt->multi)
                slot_ctx->dev_info |= cpu_to_le32(DEV_MTT);
+       else if (hdev->speed == USB_SPEED_FULL)
+               slot_ctx->dev_info &= cpu_to_le32(~DEV_MTT);
+
        if (xhci->hci_version > 0x95) {
                xhci_dbg(xhci, "xHCI version %x needs hub "
                                "TT think time and number of ports\n",
index 1f2037bbeb0d1619572a2912bda7fa6e2c168ac0..45c83baf675dfb341089ca2f399ae636b45b0de5 100644 (file)
@@ -159,7 +159,7 @@ config USB_TI_CPPI_DMA
 
 config USB_TI_CPPI41_DMA
        bool 'TI CPPI 4.1 (AM335x)'
-       depends on ARCH_OMAP
+       depends on ARCH_OMAP && DMADEVICES
        select TI_CPPI41
 
 config USB_TUSB_OMAP_DMA
index 18cfc0a361cb340612bdf943d79a6302694afc43..ee9ff7028b926b1a7303afb261c3b261f91c9da4 100644 (file)
@@ -2017,7 +2017,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
        /* We need musb_read/write functions initialized for PM */
        pm_runtime_use_autosuspend(musb->controller);
        pm_runtime_set_autosuspend_delay(musb->controller, 200);
-       pm_runtime_irq_safe(musb->controller);
        pm_runtime_enable(musb->controller);
 
        /* The musb_platform_init() call:
@@ -2095,6 +2094,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 #ifndef CONFIG_MUSB_PIO_ONLY
        if (!musb->ops->dma_init || !musb->ops->dma_exit) {
                dev_err(dev, "DMA controller not set\n");
+               status = -ENODEV;
                goto fail2;
        }
        musb_dma_controller_create = musb->ops->dma_init;
@@ -2218,6 +2218,12 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
 
        pm_runtime_put(musb->controller);
 
+       /*
+        * For why this is currently needed, see commit 3e43a0725637
+        * ("usb: musb: core: add pm_runtime_irq_safe()")
+        */
+       pm_runtime_irq_safe(musb->controller);
+
        return 0;
 
 fail5:
index 80eb991c2506c758315cc2e6e1f39b6ebbf319f4..0d19a6d61a71f7ccb7a55e1b90a7d5d5f27db535 100644 (file)
@@ -1506,7 +1506,6 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
 {
        struct msm_otg_platform_data *pdata;
        struct extcon_dev *ext_id, *ext_vbus;
-       const struct of_device_id *id;
        struct device_node *node = pdev->dev.of_node;
        struct property *prop;
        int len, ret, words;
@@ -1518,8 +1517,9 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
 
        motg->pdata = pdata;
 
-       id = of_match_device(msm_otg_dt_match, &pdev->dev);
-       pdata->phy_type = (enum msm_usb_phy_type) id->data;
+       pdata->phy_type = (enum msm_usb_phy_type)of_device_get_match_data(&pdev->dev);
+       if (!pdata->phy_type)
+               return 1;
 
        motg->link_rst = devm_reset_control_get(&pdev->dev, "link");
        if (IS_ERR(motg->link_rst))
index b7536af777ab9c4f083d7b88ff2bfe093fca9e21..c2936dc48ca7b45b0e5c186859d2879569719323 100644 (file)
@@ -143,12 +143,17 @@ static const struct mxs_phy_data imx6sx_phy_data = {
        .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS,
 };
 
+static const struct mxs_phy_data imx6ul_phy_data = {
+       .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS,
+};
+
 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, },
        { .compatible = "fsl,vf610-usbphy", .data = &vf610_phy_data, },
+       { .compatible = "fsl,imx6ul-usbphy", .data = &imx6ul_phy_data, },
        { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids);
index de4f97d84a822ffd746b5550dcb68da08b581438..8f7a78e7097598a50e9d7ba3cc72831b41af25b8 100644 (file)
@@ -131,7 +131,8 @@ static void __usbhsg_queue_pop(struct usbhsg_uep *uep,
        struct device *dev = usbhsg_gpriv_to_dev(gpriv);
        struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
 
-       dev_dbg(dev, "pipe %d : queue pop\n", usbhs_pipe_number(pipe));
+       if (pipe)
+               dev_dbg(dev, "pipe %d : queue pop\n", usbhs_pipe_number(pipe));
 
        ureq->req.status = status;
        spin_unlock(usbhs_priv_to_lock(priv));
@@ -685,7 +686,13 @@ static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
        struct usbhsg_request *ureq = usbhsg_req_to_ureq(req);
        struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
 
-       usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq));
+       if (pipe)
+               usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq));
+
+       /*
+        * To dequeue a request, this driver should call the usbhsg_queue_pop()
+        * even if the pipe is NULL.
+        */
        usbhsg_queue_pop(uep, ureq, -ECONNRESET);
 
        return 0;
index eac7ccaa3c859cc3bae90e897fc071caa7168cfd..7d4f51a32e66fcb2b7568af975fcd5574edd7f88 100644 (file)
@@ -132,7 +132,6 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
        { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
        { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
-       { USB_DEVICE(0x10C4, 0xEA80) }, /* Silicon Labs factory default */
        { USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */
        { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
        { USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */
index f51a5d52c0edab01b9c9fbd91b8c1d7389d00f78..ec1b8f2c11837fecd39468c1e053880d72da9f94 100644 (file)
@@ -531,7 +531,8 @@ static int ipaq_open(struct tty_struct *tty,
         * through. Since this has a reasonably high failure rate, we retry
         * several times.
         */
-       while (retries--) {
+       while (retries) {
+               retries--;
                result = usb_control_msg(serial->dev,
                                usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
                                0x1, 0, NULL, 0, 100);
index 3658662898fcb170fcdca07a8a676383e4d70347..a204782ae530e1de8f7982f869a94f9b80ce9dad 100644 (file)
@@ -53,6 +53,7 @@ DEVICE(funsoft, FUNSOFT_IDS);
 
 /* Infineon Flashloader driver */
 #define FLASHLOADER_IDS()              \
+       { USB_DEVICE_INTERFACE_CLASS(0x058b, 0x0041, USB_CLASS_CDC_DATA) }, \
        { USB_DEVICE(0x8087, 0x0716) }
 DEVICE(flashloader, FLASHLOADER_IDS);
 
index e6915166443607283f8229eaca83fac38ed68377..5c66d3f7a6d070c54632751af97ef3c3d660744b 100644 (file)
@@ -796,6 +796,10 @@ static int uas_slave_configure(struct scsi_device *sdev)
        if (devinfo->flags & US_FL_NO_REPORT_OPCODES)
                sdev->no_report_opcodes = 1;
 
+       /* A few buggy USB-ATA bridges don't understand FUA */
+       if (devinfo->flags & US_FL_BROKEN_FUA)
+               sdev->broken_fua = 1;
+
        scsi_change_queue_depth(sdev, devinfo->qdepth - 2);
        return 0;
 }
index 6b2479123de7762f7145c93fdcd58efb11f51093..7ffe4209067bb35b62220660997b4d83344706ed 100644 (file)
@@ -1987,7 +1987,7 @@ UNUSUAL_DEV(  0x14cd, 0x6600, 0x0201, 0x0201,
                US_FL_IGNORE_RESIDUE ),
 
 /* Reported by Michael Büsch <m@bues.ch> */
-UNUSUAL_DEV(  0x152d, 0x0567, 0x0114, 0x0114,
+UNUSUAL_DEV(  0x152d, 0x0567, 0x0114, 0x0116,
                "JMicron",
                "USB to ATA/ATAPI Bridge",
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
index c85ea530085f12d86ca691d82122f04e9f2166ae..ccc113e83d88e2b1e69e207989a5d5b49d526ae2 100644 (file)
@@ -132,7 +132,7 @@ UNUSUAL_DEV(0x152d, 0x0567, 0x0000, 0x9999,
                "JMicron",
                "JMS567",
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
-               US_FL_NO_REPORT_OPCODES),
+               US_FL_BROKEN_FUA | US_FL_NO_REPORT_OPCODES),
 
 /* Reported-by: Hans de Goede <hdegoede@redhat.com> */
 UNUSUAL_DEV(0x2109, 0x0711, 0x0000, 0x9999,
index da6e2ce77495b21ec127209664567b7e2f8f467e..850d86ca685b273344271eda7c95ad4f82b28244 100644 (file)
@@ -31,21 +31,6 @@ menuconfig VFIO
 
          If you don't know what to do here, say N.
 
-menuconfig VFIO_NOIOMMU
-       bool "VFIO No-IOMMU support"
-       depends on VFIO
-       help
-         VFIO is built on the ability to isolate devices using the IOMMU.
-         Only with an IOMMU can userspace access to DMA capable devices be
-         considered secure.  VFIO No-IOMMU mode enables IOMMU groups for
-         devices without IOMMU backing for the purpose of re-using the VFIO
-         infrastructure in a non-secure mode.  Use of this mode will result
-         in an unsupportable kernel and will therefore taint the kernel.
-         Device assignment to virtual machines is also not possible with
-         this mode since there is no IOMMU to provide DMA translation.
-
-         If you don't know what to do here, say N.
-
 source "drivers/vfio/pci/Kconfig"
 source "drivers/vfio/platform/Kconfig"
 source "virt/lib/Kconfig"
index 32b88bd2c82c7e3a3f4cd8cae11a253a171c76fa..56bf6dbb93db7ac281a0af4fa01a8d212fd87670 100644 (file)
@@ -940,13 +940,13 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL)
                return -EINVAL;
 
-       group = vfio_iommu_group_get(&pdev->dev);
+       group = iommu_group_get(&pdev->dev);
        if (!group)
                return -EINVAL;
 
        vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
        if (!vdev) {
-               vfio_iommu_group_put(group, &pdev->dev);
+               iommu_group_put(group);
                return -ENOMEM;
        }
 
@@ -957,7 +957,7 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        ret = vfio_add_group_dev(&pdev->dev, &vfio_pci_ops, vdev);
        if (ret) {
-               vfio_iommu_group_put(group, &pdev->dev);
+               iommu_group_put(group);
                kfree(vdev);
                return ret;
        }
@@ -993,7 +993,7 @@ static void vfio_pci_remove(struct pci_dev *pdev)
        if (!vdev)
                return;
 
-       vfio_iommu_group_put(pdev->dev.iommu_group, &pdev->dev);
+       iommu_group_put(pdev->dev.iommu_group);
        kfree(vdev);
 
        if (vfio_pci_is_vga(pdev)) {
@@ -1035,7 +1035,7 @@ static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev,
        return PCI_ERS_RESULT_CAN_RECOVER;
 }
 
-static struct pci_error_handlers vfio_err_handlers = {
+static const struct pci_error_handlers vfio_err_handlers = {
        .error_detected = vfio_pci_aer_err_detected,
 };
 
index f1625dcfbb23d49d6b0586977a203462df0e75a5..b1cc3a768784426fbf7616316aa9731f21b77ddb 100644 (file)
@@ -92,7 +92,6 @@ static struct platform_driver vfio_platform_driver = {
        .remove         = vfio_platform_remove,
        .driver = {
                .name   = "vfio-platform",
-               .owner  = THIS_MODULE,
        },
 };
 
index a1c50d63079200ce90741ccd55e60bc703c73eb2..418cdd9ba3f4841353c5cbdddb345e9363578736 100644 (file)
@@ -51,13 +51,10 @@ static vfio_platform_reset_fn_t vfio_platform_lookup_reset(const char *compat,
 
 static void vfio_platform_get_reset(struct vfio_platform_device *vdev)
 {
-       char modname[256];
-
        vdev->reset = vfio_platform_lookup_reset(vdev->compat,
                                                &vdev->reset_module);
        if (!vdev->reset) {
-               snprintf(modname, 256, "vfio-reset:%s", vdev->compat);
-               request_module(modname);
+               request_module("vfio-reset:%s", vdev->compat);
                vdev->reset = vfio_platform_lookup_reset(vdev->compat,
                                                         &vdev->reset_module);
        }
index de632da2e22f60d4eee042631821c1a4a9b7e558..6070b793cbcb244d98a784bf6c41a5f0fabb662b 100644 (file)
@@ -62,7 +62,6 @@ struct vfio_container {
        struct rw_semaphore             group_lock;
        struct vfio_iommu_driver        *iommu_driver;
        void                            *iommu_data;
-       bool                            noiommu;
 };
 
 struct vfio_unbound_dev {
@@ -85,7 +84,6 @@ struct vfio_group {
        struct list_head                unbound_list;
        struct mutex                    unbound_lock;
        atomic_t                        opened;
-       bool                            noiommu;
 };
 
 struct vfio_device {
@@ -97,147 +95,6 @@ struct vfio_device {
        void                            *device_data;
 };
 
-#ifdef CONFIG_VFIO_NOIOMMU
-static bool noiommu __read_mostly;
-module_param_named(enable_unsafe_noiommu_support,
-                  noiommu, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(enable_unsafe_noiommu_mode, "Enable UNSAFE, no-IOMMU mode.  This mode provides no device isolation, no DMA translation, no host kernel protection, cannot be used for device assignment to virtual machines, requires RAWIO permissions, and will taint the kernel.  If you do not know what this is for, step away. (default: false)");
-#endif
-
-/*
- * vfio_iommu_group_{get,put} are only intended for VFIO bus driver probe
- * and remove functions, any use cases other than acquiring the first
- * reference for the purpose of calling vfio_add_group_dev() or removing
- * that symmetric reference after vfio_del_group_dev() should use the raw
- * iommu_group_{get,put} functions.  In particular, vfio_iommu_group_put()
- * removes the device from the dummy group and cannot be nested.
- */
-struct iommu_group *vfio_iommu_group_get(struct device *dev)
-{
-       struct iommu_group *group;
-       int __maybe_unused ret;
-
-       group = iommu_group_get(dev);
-
-#ifdef CONFIG_VFIO_NOIOMMU
-       /*
-        * With noiommu enabled, an IOMMU group will be created for a device
-        * that doesn't already have one and doesn't have an iommu_ops on their
-        * bus.  We use iommu_present() again in the main code to detect these
-        * fake groups.
-        */
-       if (group || !noiommu || iommu_present(dev->bus))
-               return group;
-
-       group = iommu_group_alloc();
-       if (IS_ERR(group))
-               return NULL;
-
-       iommu_group_set_name(group, "vfio-noiommu");
-       ret = iommu_group_add_device(group, dev);
-       iommu_group_put(group);
-       if (ret)
-               return NULL;
-
-       /*
-        * Where to taint?  At this point we've added an IOMMU group for a
-        * device that is not backed by iommu_ops, therefore any iommu_
-        * callback using iommu_ops can legitimately Oops.  So, while we may
-        * be about to give a DMA capable device to a user without IOMMU
-        * protection, which is clearly taint-worthy, let's go ahead and do
-        * it here.
-        */
-       add_taint(TAINT_USER, LOCKDEP_STILL_OK);
-       dev_warn(dev, "Adding kernel taint for vfio-noiommu group on device\n");
-#endif
-
-       return group;
-}
-EXPORT_SYMBOL_GPL(vfio_iommu_group_get);
-
-void vfio_iommu_group_put(struct iommu_group *group, struct device *dev)
-{
-#ifdef CONFIG_VFIO_NOIOMMU
-       if (!iommu_present(dev->bus))
-               iommu_group_remove_device(dev);
-#endif
-
-       iommu_group_put(group);
-}
-EXPORT_SYMBOL_GPL(vfio_iommu_group_put);
-
-#ifdef CONFIG_VFIO_NOIOMMU
-static void *vfio_noiommu_open(unsigned long arg)
-{
-       if (arg != VFIO_NOIOMMU_IOMMU)
-               return ERR_PTR(-EINVAL);
-       if (!capable(CAP_SYS_RAWIO))
-               return ERR_PTR(-EPERM);
-
-       return NULL;
-}
-
-static void vfio_noiommu_release(void *iommu_data)
-{
-}
-
-static long vfio_noiommu_ioctl(void *iommu_data,
-                              unsigned int cmd, unsigned long arg)
-{
-       if (cmd == VFIO_CHECK_EXTENSION)
-               return arg == VFIO_NOIOMMU_IOMMU ? 1 : 0;
-
-       return -ENOTTY;
-}
-
-static int vfio_iommu_present(struct device *dev, void *unused)
-{
-       return iommu_present(dev->bus) ? 1 : 0;
-}
-
-static int vfio_noiommu_attach_group(void *iommu_data,
-                                    struct iommu_group *iommu_group)
-{
-       return iommu_group_for_each_dev(iommu_group, NULL,
-                                       vfio_iommu_present) ? -EINVAL : 0;
-}
-
-static void vfio_noiommu_detach_group(void *iommu_data,
-                                     struct iommu_group *iommu_group)
-{
-}
-
-static struct vfio_iommu_driver_ops vfio_noiommu_ops = {
-       .name = "vfio-noiommu",
-       .owner = THIS_MODULE,
-       .open = vfio_noiommu_open,
-       .release = vfio_noiommu_release,
-       .ioctl = vfio_noiommu_ioctl,
-       .attach_group = vfio_noiommu_attach_group,
-       .detach_group = vfio_noiommu_detach_group,
-};
-
-static struct vfio_iommu_driver vfio_noiommu_driver = {
-       .ops = &vfio_noiommu_ops,
-};
-
-/*
- * Wrap IOMMU drivers, the noiommu driver is the one and only driver for
- * noiommu groups (and thus containers) and not available for normal groups.
- */
-#define vfio_for_each_iommu_driver(con, pos)                           \
-       for (pos = con->noiommu ? &vfio_noiommu_driver :                \
-            list_first_entry(&vfio.iommu_drivers_list,                 \
-                             struct vfio_iommu_driver, vfio_next);     \
-            (con->noiommu ? pos != NULL :                              \
-                       &pos->vfio_next != &vfio.iommu_drivers_list);   \
-             pos = con->noiommu ? NULL : list_next_entry(pos, vfio_next))
-#else
-#define vfio_for_each_iommu_driver(con, pos)                           \
-       list_for_each_entry(pos, &vfio.iommu_drivers_list, vfio_next)
-#endif
-
-
 /**
  * IOMMU driver registration
  */
@@ -342,8 +199,7 @@ static void vfio_group_unlock_and_free(struct vfio_group *group)
 /**
  * Group objects - create, release, get, put, search
  */
-static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group,
-                                           bool noiommu)
+static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
 {
        struct vfio_group *group, *tmp;
        struct device *dev;
@@ -361,7 +217,6 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group,
        atomic_set(&group->container_users, 0);
        atomic_set(&group->opened, 0);
        group->iommu_group = iommu_group;
-       group->noiommu = noiommu;
 
        group->nb.notifier_call = vfio_iommu_group_notifier;
 
@@ -397,8 +252,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group,
 
        dev = device_create(vfio.class, NULL,
                            MKDEV(MAJOR(vfio.group_devt), minor),
-                           group, "%s%d", noiommu ? "noiommu-" : "",
-                           iommu_group_id(iommu_group));
+                           group, "%d", iommu_group_id(iommu_group));
        if (IS_ERR(dev)) {
                vfio_free_group_minor(minor);
                vfio_group_unlock_and_free(group);
@@ -682,7 +536,7 @@ static int vfio_group_nb_add_dev(struct vfio_group *group, struct device *dev)
                return 0;
 
        /* TODO Prevent device auto probing */
-       WARN("Device %s added to live group %d!\n", dev_name(dev),
+       WARN(1, "Device %s added to live group %d!\n", dev_name(dev),
             iommu_group_id(group->iommu_group));
 
        return 0;
@@ -786,8 +640,7 @@ int vfio_add_group_dev(struct device *dev,
 
        group = vfio_group_get_from_iommu(iommu_group);
        if (!group) {
-               group = vfio_create_group(iommu_group,
-                                         !iommu_present(dev->bus));
+               group = vfio_create_group(iommu_group);
                if (IS_ERR(group)) {
                        iommu_group_put(iommu_group);
                        return PTR_ERR(group);
@@ -999,7 +852,8 @@ static long vfio_ioctl_check_extension(struct vfio_container *container,
                 */
                if (!driver) {
                        mutex_lock(&vfio.iommu_drivers_lock);
-                       vfio_for_each_iommu_driver(container, driver) {
+                       list_for_each_entry(driver, &vfio.iommu_drivers_list,
+                                           vfio_next) {
                                if (!try_module_get(driver->ops->owner))
                                        continue;
 
@@ -1068,7 +922,7 @@ static long vfio_ioctl_set_iommu(struct vfio_container *container,
        }
 
        mutex_lock(&vfio.iommu_drivers_lock);
-       vfio_for_each_iommu_driver(container, driver) {
+       list_for_each_entry(driver, &vfio.iommu_drivers_list, vfio_next) {
                void *data;
 
                if (!try_module_get(driver->ops->owner))
@@ -1333,9 +1187,6 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)
        if (atomic_read(&group->container_users))
                return -EINVAL;
 
-       if (group->noiommu && !capable(CAP_SYS_RAWIO))
-               return -EPERM;
-
        f = fdget(container_fd);
        if (!f.file)
                return -EBADF;
@@ -1351,13 +1202,6 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)
 
        down_write(&container->group_lock);
 
-       /* Real groups and fake groups cannot mix */
-       if (!list_empty(&container->group_list) &&
-           container->noiommu != group->noiommu) {
-               ret = -EPERM;
-               goto unlock_out;
-       }
-
        driver = container->iommu_driver;
        if (driver) {
                ret = driver->ops->attach_group(container->iommu_data,
@@ -1367,7 +1211,6 @@ static int vfio_group_set_container(struct vfio_group *group, int container_fd)
        }
 
        group->container = container;
-       container->noiommu = group->noiommu;
        list_add(&group->container_next, &container->group_list);
 
        /* Get a reference on the container and mark a user within the group */
@@ -1398,9 +1241,6 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
            !group->container->iommu_driver || !vfio_group_viable(group))
                return -EINVAL;
 
-       if (group->noiommu && !capable(CAP_SYS_RAWIO))
-               return -EPERM;
-
        device = vfio_device_get_from_name(group, buf);
        if (!device)
                return -ENODEV;
@@ -1443,10 +1283,6 @@ static int vfio_group_get_device_fd(struct vfio_group *group, char *buf)
 
        fd_install(ret, filep);
 
-       if (group->noiommu)
-               dev_warn(device->dev, "vfio-noiommu device opened by user "
-                        "(%s:%d)\n", current->comm, task_pid_nr(current));
-
        return ret;
 }
 
@@ -1535,11 +1371,6 @@ static int vfio_group_fops_open(struct inode *inode, struct file *filep)
        if (!group)
                return -ENODEV;
 
-       if (group->noiommu && !capable(CAP_SYS_RAWIO)) {
-               vfio_group_put(group);
-               return -EPERM;
-       }
-
        /* Do we need multiple instances of the group open?  Seems not. */
        opened = atomic_cmpxchg(&group->opened, 0, 1);
        if (opened) {
@@ -1702,11 +1533,6 @@ struct vfio_group *vfio_group_get_external_user(struct file *filep)
        if (!atomic_inc_not_zero(&group->container_users))
                return ERR_PTR(-EINVAL);
 
-       if (group->noiommu) {
-               atomic_dec(&group->container_users);
-               return ERR_PTR(-EPERM);
-       }
-
        if (!group->container->iommu_driver ||
                        !vfio_group_viable(group)) {
                atomic_dec(&group->container_users);
index eec2f11809ff2463d2a714224925af9c679fead1..ad2146a9ab2d4b19cca5469402c203ade61e8545 100644 (file)
@@ -819,7 +819,7 @@ long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp)
                BUILD_BUG_ON(__alignof__ *vq->used > VRING_USED_ALIGN_SIZE);
                if ((a.avail_user_addr & (VRING_AVAIL_ALIGN_SIZE - 1)) ||
                    (a.used_user_addr & (VRING_USED_ALIGN_SIZE - 1)) ||
-                   (a.log_guest_addr & (sizeof(u64) - 1))) {
+                   (a.log_guest_addr & (VRING_USED_ALIGN_SIZE - 1))) {
                        r = -EINVAL;
                        break;
                }
@@ -1369,7 +1369,7 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq,
        /* Grab the next descriptor number they're advertising, and increment
         * the index we've seen. */
        if (unlikely(__get_user(ring_head,
-                               &vq->avail->ring[last_avail_idx % vq->num]))) {
+                               &vq->avail->ring[last_avail_idx & (vq->num - 1)]))) {
                vq_err(vq, "Failed to read head: idx %d address %p\n",
                       last_avail_idx,
                       &vq->avail->ring[last_avail_idx % vq->num]);
@@ -1489,7 +1489,7 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq,
        u16 old, new;
        int start;
 
-       start = vq->last_used_idx % vq->num;
+       start = vq->last_used_idx & (vq->num - 1);
        used = vq->used->ring + start;
        if (count == 1) {
                if (__put_user(heads[0].id, &used->id)) {
@@ -1531,7 +1531,7 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads,
 {
        int start, n, r;
 
-       start = vq->last_used_idx % vq->num;
+       start = vq->last_used_idx & (vq->num - 1);
        n = vq->num - start;
        if (n < count) {
                r = __vhost_add_used_n(vq, heads, n);
index b335c1ae8625106efff818d696ebad532ade7f17..fe00a07c122e69f0735baf8832fdd112677b4dd6 100644 (file)
@@ -479,7 +479,10 @@ static enum fsl_diu_monitor_port fsl_diu_name_to_port(const char *s)
                        port = FSL_DIU_PORT_DLVDS;
        }
 
-       return diu_ops.valid_monitor_port(port);
+       if (diu_ops.valid_monitor_port)
+               port = diu_ops.valid_monitor_port(port);
+
+       return port;
 }
 
 /*
@@ -1915,6 +1918,14 @@ static int __init fsl_diu_init(void)
 #else
        monitor_port = fsl_diu_name_to_port(monitor_string);
 #endif
+
+       /*
+        * Must to verify set_pixel_clock. If not implement on platform,
+        * then that means that there is no platform support for the DIU.
+        */
+       if (!diu_ops.set_pixel_clock)
+               return -ENODEV;
+
        pr_info("Freescale Display Interface Unit (DIU) framebuffer driver\n");
 
 #ifdef CONFIG_NOT_COHERENT_CACHE
index 99ca268c1cddf24332308b58fbeb051d565b8dca..d05a54922ba6953bb686f07ba2ac4315f91aeace 100644 (file)
@@ -275,6 +275,12 @@ const struct omap_video_timings omap_dss_pal_timings = {
        .vbp            = 41,
 
        .interlace      = true,
+
+       .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
+       .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
+       .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
+       .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
+       .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
 };
 EXPORT_SYMBOL(omap_dss_pal_timings);
 
@@ -290,6 +296,12 @@ const struct omap_video_timings omap_dss_ntsc_timings = {
        .vbp            = 31,
 
        .interlace      = true,
+
+       .hsync_level = OMAPDSS_SIG_ACTIVE_LOW,
+       .vsync_level = OMAPDSS_SIG_ACTIVE_LOW,
+       .data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE,
+       .de_level = OMAPDSS_SIG_ACTIVE_HIGH,
+       .sync_pclk_edge = OMAPDSS_DRIVE_SIG_FALLING_EDGE,
 };
 EXPORT_SYMBOL(omap_dss_ntsc_timings);
 
index b1877d73fa563d6d48f2d55b7958f02daa8d9ad7..7062bb0975a521f1a28125c092c2f0d0bbd35787 100644 (file)
@@ -412,6 +412,7 @@ static int virtio_init(void)
 static void __exit virtio_exit(void)
 {
        bus_unregister(&virtio_bus);
+       ida_destroy(&virtio_index_ida);
 }
 core_initcall(virtio_init);
 module_exit(virtio_exit);
index 096b857e7b75abad526f487c84392d863c3c6b06..ee663c458b20a449c353c5ea0df4632933087e66 100644 (file)
@@ -80,6 +80,12 @@ struct vring_virtqueue {
        /* Last used index we've seen. */
        u16 last_used_idx;
 
+       /* Last written value to avail->flags */
+       u16 avail_flags_shadow;
+
+       /* Last written value to avail->idx in guest byte order */
+       u16 avail_idx_shadow;
+
        /* How to notify other side. FIXME: commonalize hcalls! */
        bool (*notify)(struct virtqueue *vq);
 
@@ -109,7 +115,7 @@ static struct vring_desc *alloc_indirect(struct virtqueue *_vq,
         * otherwise virt_to_phys will give us bogus addresses in the
         * virtqueue.
         */
-       gfp &= ~(__GFP_HIGHMEM | __GFP_HIGH);
+       gfp &= ~__GFP_HIGHMEM;
 
        desc = kmalloc(total_sg * sizeof(struct vring_desc), gfp);
        if (!desc)
@@ -235,13 +241,14 @@ static inline int virtqueue_add(struct virtqueue *_vq,
 
        /* Put entry in available array (but don't update avail->idx until they
         * do sync). */
-       avail = virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx) & (vq->vring.num - 1);
+       avail = vq->avail_idx_shadow & (vq->vring.num - 1);
        vq->vring.avail->ring[avail] = cpu_to_virtio16(_vq->vdev, head);
 
        /* Descriptors and available array need to be set before we expose the
         * new available array entries. */
        virtio_wmb(vq->weak_barriers);
-       vq->vring.avail->idx = cpu_to_virtio16(_vq->vdev, virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx) + 1);
+       vq->avail_idx_shadow++;
+       vq->vring.avail->idx = cpu_to_virtio16(_vq->vdev, vq->avail_idx_shadow);
        vq->num_added++;
 
        pr_debug("Added buffer head %i to %p\n", head, vq);
@@ -354,8 +361,8 @@ bool virtqueue_kick_prepare(struct virtqueue *_vq)
         * event. */
        virtio_mb(vq->weak_barriers);
 
-       old = virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx) - vq->num_added;
-       new = virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx);
+       old = vq->avail_idx_shadow - vq->num_added;
+       new = vq->avail_idx_shadow;
        vq->num_added = 0;
 
 #ifdef DEBUG
@@ -510,7 +517,7 @@ void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len)
        /* If we expect an interrupt for the next entry, tell host
         * by writing event index and flush out the write before
         * the read in the next get_buf call. */
-       if (!(vq->vring.avail->flags & cpu_to_virtio16(_vq->vdev, VRING_AVAIL_F_NO_INTERRUPT))) {
+       if (!(vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT)) {
                vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, vq->last_used_idx);
                virtio_mb(vq->weak_barriers);
        }
@@ -537,7 +544,11 @@ void virtqueue_disable_cb(struct virtqueue *_vq)
 {
        struct vring_virtqueue *vq = to_vvq(_vq);
 
-       vq->vring.avail->flags |= cpu_to_virtio16(_vq->vdev, VRING_AVAIL_F_NO_INTERRUPT);
+       if (!(vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT)) {
+               vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT;
+               vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow);
+       }
+
 }
 EXPORT_SYMBOL_GPL(virtqueue_disable_cb);
 
@@ -565,7 +576,10 @@ unsigned virtqueue_enable_cb_prepare(struct virtqueue *_vq)
        /* Depending on the VIRTIO_RING_F_EVENT_IDX feature, we need to
         * either clear the flags bit or point the event index at the next
         * entry. Always do both to keep code simple. */
-       vq->vring.avail->flags &= cpu_to_virtio16(_vq->vdev, ~VRING_AVAIL_F_NO_INTERRUPT);
+       if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) {
+               vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT;
+               vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow);
+       }
        vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, last_used_idx = vq->last_used_idx);
        END_USE(vq);
        return last_used_idx;
@@ -633,9 +647,12 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *_vq)
        /* Depending on the VIRTIO_RING_F_USED_EVENT_IDX feature, we need to
         * either clear the flags bit or point the event index at the next
         * entry. Always do both to keep code simple. */
-       vq->vring.avail->flags &= cpu_to_virtio16(_vq->vdev, ~VRING_AVAIL_F_NO_INTERRUPT);
+       if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) {
+               vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT;
+               vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow);
+       }
        /* TODO: tune this threshold */
-       bufs = (u16)(virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx) - vq->last_used_idx) * 3 / 4;
+       bufs = (u16)(vq->avail_idx_shadow - vq->last_used_idx) * 3 / 4;
        vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, vq->last_used_idx + bufs);
        virtio_mb(vq->weak_barriers);
        if (unlikely((u16)(virtio16_to_cpu(_vq->vdev, vq->vring.used->idx) - vq->last_used_idx) > bufs)) {
@@ -670,7 +687,8 @@ void *virtqueue_detach_unused_buf(struct virtqueue *_vq)
                /* detach_buf clears data, so grab it now. */
                buf = vq->data[i];
                detach_buf(vq, i);
-               vq->vring.avail->idx = cpu_to_virtio16(_vq->vdev, virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx) - 1);
+               vq->avail_idx_shadow--;
+               vq->vring.avail->idx = cpu_to_virtio16(_vq->vdev, vq->avail_idx_shadow);
                END_USE(vq);
                return buf;
        }
@@ -735,6 +753,8 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
        vq->weak_barriers = weak_barriers;
        vq->broken = false;
        vq->last_used_idx = 0;
+       vq->avail_flags_shadow = 0;
+       vq->avail_idx_shadow = 0;
        vq->num_added = 0;
        list_add_tail(&vq->vq.list, &vdev->vqs);
 #ifdef DEBUG
@@ -746,8 +766,10 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
        vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
 
        /* No callback?  Tell other side not to bother us. */
-       if (!callback)
-               vq->vring.avail->flags |= cpu_to_virtio16(vdev, VRING_AVAIL_F_NO_INTERRUPT);
+       if (!callback) {
+               vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT;
+               vq->vring.avail->flags = cpu_to_virtio16(vdev, vq->avail_flags_shadow);
+       }
 
        /* Put everything in free lists. */
        vq->free_head = 0;
index e3e9e3d46d1bf55028cf4a7902fa72b494fb3ce6..96a1b8da53715e7501d09369ee9ef375f421e936 100644 (file)
@@ -281,7 +281,8 @@ static void handle_irq_for_port(unsigned port)
 
 static void consume_one_event(unsigned cpu,
                              struct evtchn_fifo_control_block *control_block,
-                             unsigned priority, unsigned long *ready)
+                             unsigned priority, unsigned long *ready,
+                             bool drop)
 {
        struct evtchn_fifo_queue *q = &per_cpu(cpu_queue, cpu);
        uint32_t head;
@@ -313,13 +314,17 @@ static void consume_one_event(unsigned cpu,
        if (head == 0)
                clear_bit(priority, ready);
 
-       if (evtchn_fifo_is_pending(port) && !evtchn_fifo_is_masked(port))
-               handle_irq_for_port(port);
+       if (evtchn_fifo_is_pending(port) && !evtchn_fifo_is_masked(port)) {
+               if (unlikely(drop))
+                       pr_warn("Dropping pending event for port %u\n", port);
+               else
+                       handle_irq_for_port(port);
+       }
 
        q->head[priority] = head;
 }
 
-static void evtchn_fifo_handle_events(unsigned cpu)
+static void __evtchn_fifo_handle_events(unsigned cpu, bool drop)
 {
        struct evtchn_fifo_control_block *control_block;
        unsigned long ready;
@@ -331,11 +336,16 @@ static void evtchn_fifo_handle_events(unsigned cpu)
 
        while (ready) {
                q = find_first_bit(&ready, EVTCHN_FIFO_MAX_QUEUES);
-               consume_one_event(cpu, control_block, q, &ready);
+               consume_one_event(cpu, control_block, q, &ready, drop);
                ready |= xchg(&control_block->ready, 0);
        }
 }
 
+static void evtchn_fifo_handle_events(unsigned cpu)
+{
+       __evtchn_fifo_handle_events(cpu, false);
+}
+
 static void evtchn_fifo_resume(void)
 {
        unsigned cpu;
@@ -420,6 +430,9 @@ static int evtchn_fifo_cpu_notification(struct notifier_block *self,
                if (!per_cpu(cpu_control_block, cpu))
                        ret = evtchn_fifo_alloc_control_block(cpu);
                break;
+       case CPU_DEAD:
+               __evtchn_fifo_handle_events(cpu, true);
+               break;
        default:
                break;
        }
index 58e38d586f524fd6b78b18594cbf2de593c1119e..4d529f3e40df93941c99f6fffee06da540f28ca2 100644 (file)
@@ -37,6 +37,7 @@ struct xen_pcibk_device {
        struct xen_pci_sharedinfo *sh_info;
        unsigned long flags;
        struct work_struct op_work;
+       struct xen_pci_op op;
 };
 
 struct xen_pcibk_dev_data {
index c4a0666de6f5e08a17edf4fcbcb001478d0e303b..73dafdc494aa8322e037f1d4a9ad4ec5530c5743 100644 (file)
@@ -70,6 +70,13 @@ static void xen_pcibk_control_isr(struct pci_dev *dev, int reset)
                enable ? "enable" : "disable");
 
        if (enable) {
+               /*
+                * The MSI or MSI-X should not have an IRQ handler. Otherwise
+                * if the guest terminates we BUG_ON in free_msi_irqs.
+                */
+               if (dev->msi_enabled || dev->msix_enabled)
+                       goto out;
+
                rc = request_irq(dev_data->irq,
                                xen_pcibk_guest_interrupt, IRQF_SHARED,
                                dev_data->irq_name, dev);
@@ -144,7 +151,12 @@ int xen_pcibk_enable_msi(struct xen_pcibk_device *pdev,
        if (unlikely(verbose_request))
                printk(KERN_DEBUG DRV_NAME ": %s: enable MSI\n", pci_name(dev));
 
-       status = pci_enable_msi(dev);
+       if (dev->msi_enabled)
+               status = -EALREADY;
+       else if (dev->msix_enabled)
+               status = -ENXIO;
+       else
+               status = pci_enable_msi(dev);
 
        if (status) {
                pr_warn_ratelimited("%s: error enabling MSI for guest %u: err %d\n",
@@ -173,20 +185,23 @@ static
 int xen_pcibk_disable_msi(struct xen_pcibk_device *pdev,
                          struct pci_dev *dev, struct xen_pci_op *op)
 {
-       struct xen_pcibk_dev_data *dev_data;
-
        if (unlikely(verbose_request))
                printk(KERN_DEBUG DRV_NAME ": %s: disable MSI\n",
                       pci_name(dev));
-       pci_disable_msi(dev);
 
+       if (dev->msi_enabled) {
+               struct xen_pcibk_dev_data *dev_data;
+
+               pci_disable_msi(dev);
+
+               dev_data = pci_get_drvdata(dev);
+               if (dev_data)
+                       dev_data->ack_intr = 1;
+       }
        op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
        if (unlikely(verbose_request))
                printk(KERN_DEBUG DRV_NAME ": %s: MSI: %d\n", pci_name(dev),
                        op->value);
-       dev_data = pci_get_drvdata(dev);
-       if (dev_data)
-               dev_data->ack_intr = 1;
        return 0;
 }
 
@@ -197,13 +212,26 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev,
        struct xen_pcibk_dev_data *dev_data;
        int i, result;
        struct msix_entry *entries;
+       u16 cmd;
 
        if (unlikely(verbose_request))
                printk(KERN_DEBUG DRV_NAME ": %s: enable MSI-X\n",
                       pci_name(dev));
+
        if (op->value > SH_INFO_MAX_VEC)
                return -EINVAL;
 
+       if (dev->msix_enabled)
+               return -EALREADY;
+
+       /*
+        * PCI_COMMAND_MEMORY must be enabled, otherwise we may not be able
+        * to access the BARs where the MSI-X entries reside.
+        */
+       pci_read_config_word(dev, PCI_COMMAND, &cmd);
+       if (dev->msi_enabled || !(cmd & PCI_COMMAND_MEMORY))
+               return -ENXIO;
+
        entries = kmalloc(op->value * sizeof(*entries), GFP_KERNEL);
        if (entries == NULL)
                return -ENOMEM;
@@ -245,23 +273,27 @@ static
 int xen_pcibk_disable_msix(struct xen_pcibk_device *pdev,
                           struct pci_dev *dev, struct xen_pci_op *op)
 {
-       struct xen_pcibk_dev_data *dev_data;
        if (unlikely(verbose_request))
                printk(KERN_DEBUG DRV_NAME ": %s: disable MSI-X\n",
                        pci_name(dev));
-       pci_disable_msix(dev);
 
+       if (dev->msix_enabled) {
+               struct xen_pcibk_dev_data *dev_data;
+
+               pci_disable_msix(dev);
+
+               dev_data = pci_get_drvdata(dev);
+               if (dev_data)
+                       dev_data->ack_intr = 1;
+       }
        /*
         * SR-IOV devices (which don't have any legacy IRQ) have
         * an undefined IRQ value of zero.
         */
        op->value = dev->irq ? xen_pirq_from_irq(dev->irq) : 0;
        if (unlikely(verbose_request))
-               printk(KERN_DEBUG DRV_NAME ": %s: MSI-X: %d\n", pci_name(dev),
-                       op->value);
-       dev_data = pci_get_drvdata(dev);
-       if (dev_data)
-               dev_data->ack_intr = 1;
+               printk(KERN_DEBUG DRV_NAME ": %s: MSI-X: %d\n",
+                      pci_name(dev), op->value);
        return 0;
 }
 #endif
@@ -298,9 +330,11 @@ void xen_pcibk_do_op(struct work_struct *data)
                container_of(data, struct xen_pcibk_device, op_work);
        struct pci_dev *dev;
        struct xen_pcibk_dev_data *dev_data = NULL;
-       struct xen_pci_op *op = &pdev->sh_info->op;
+       struct xen_pci_op *op = &pdev->op;
        int test_intx = 0;
 
+       *op = pdev->sh_info->op;
+       barrier();
        dev = xen_pcibk_get_pci_dev(pdev, op->domain, op->bus, op->devfn);
 
        if (dev == NULL)
@@ -342,6 +376,17 @@ void xen_pcibk_do_op(struct work_struct *data)
                if ((dev_data->enable_intx != test_intx))
                        xen_pcibk_control_isr(dev, 0 /* no reset */);
        }
+       pdev->sh_info->op.err = op->err;
+       pdev->sh_info->op.value = op->value;
+#ifdef CONFIG_PCI_MSI
+       if (op->cmd == XEN_PCI_OP_enable_msix && op->err == 0) {
+               unsigned int i;
+
+               for (i = 0; i < op->value; i++)
+                       pdev->sh_info->op.msix_entries[i].vector =
+                               op->msix_entries[i].vector;
+       }
+#endif
        /* Tell the driver domain that we're done. */
        wmb();
        clear_bit(_XEN_PCIF_active, (unsigned long *)&pdev->sh_info->flags);
index 98bc345f296ef866eaf0e3b1ffffad12ca35fb7e..4843741e703a336da72162af91165392f0560490 100644 (file)
@@ -44,7 +44,6 @@ static struct xen_pcibk_device *alloc_pdev(struct xenbus_device *xdev)
        dev_dbg(&xdev->dev, "allocated pdev @ 0x%p\n", pdev);
 
        pdev->xdev = xdev;
-       dev_set_drvdata(&xdev->dev, pdev);
 
        mutex_init(&pdev->dev_lock);
 
@@ -58,6 +57,9 @@ static struct xen_pcibk_device *alloc_pdev(struct xenbus_device *xdev)
                kfree(pdev);
                pdev = NULL;
        }
+
+       dev_set_drvdata(&xdev->dev, pdev);
+
 out:
        return pdev;
 }
index 43bcae852546ad2e5021b4a1d326dda375ae4023..ad4eb1024d1ffb7663db4e770fdd4c5c2663e821 100644 (file)
@@ -726,7 +726,7 @@ static int scsiback_do_cmd_fn(struct vscsibk_info *info)
                if (!pending_req)
                        return 1;
 
-               ring_req = *RING_GET_REQUEST(ring, rc);
+               RING_COPY_REQUEST(ring, rc, &ring_req);
                ring->req_cons = ++rc;
 
                err = prepare_pending_reqs(info, &ring_req, pending_req);
index 699941e906672b87eb1b5199f7966e29528e0116..c7cc7c30f0c8b9aab15816584763f9d32fec37f0 100644 (file)
@@ -451,9 +451,9 @@ void v9fs_evict_inode(struct inode *inode)
 {
        struct v9fs_inode *v9inode = V9FS_I(inode);
 
-       truncate_inode_pages_final(inode->i_mapping);
+       truncate_inode_pages_final(&inode->i_data);
        clear_inode(inode);
-       filemap_fdatawrite(inode->i_mapping);
+       filemap_fdatawrite(&inode->i_data);
 
        v9fs_cache_inode_put_cookie(inode);
        /* clunk the fid stashed in writeback_fid */
@@ -1223,18 +1223,26 @@ ino_t v9fs_qid2ino(struct p9_qid *qid)
 }
 
 /**
- * v9fs_vfs_follow_link - follow a symlink path
+ * v9fs_vfs_get_link - follow a symlink path
  * @dentry: dentry for symlink
- * @cookie: place to pass the data to put_link()
+ * @inode: inode for symlink
+ * @done: delayed call for when we are done with the return value
  */
 
-static const char *v9fs_vfs_follow_link(struct dentry *dentry, void **cookie)
+static const char *v9fs_vfs_get_link(struct dentry *dentry,
+                                    struct inode *inode,
+                                    struct delayed_call *done)
 {
-       struct v9fs_session_info *v9ses = v9fs_dentry2v9ses(dentry);
-       struct p9_fid *fid = v9fs_fid_lookup(dentry);
+       struct v9fs_session_info *v9ses;
+       struct p9_fid *fid;
        struct p9_wstat *st;
        char *res;
 
+       if (!dentry)
+               return ERR_PTR(-ECHILD);
+
+       v9ses = v9fs_dentry2v9ses(dentry);
+       fid = v9fs_fid_lookup(dentry);
        p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);
 
        if (IS_ERR(fid))
@@ -1259,7 +1267,8 @@ static const char *v9fs_vfs_follow_link(struct dentry *dentry, void **cookie)
 
        p9stat_free(st);
        kfree(st);
-       return *cookie = res;
+       set_delayed_call(done, kfree_link, res);
+       return res;
 }
 
 /**
@@ -1452,8 +1461,7 @@ static const struct inode_operations v9fs_file_inode_operations = {
 
 static const struct inode_operations v9fs_symlink_inode_operations = {
        .readlink = generic_readlink,
-       .follow_link = v9fs_vfs_follow_link,
-       .put_link = kfree_put_link,
+       .get_link = v9fs_vfs_get_link,
        .getattr = v9fs_vfs_getattr,
        .setattr = v9fs_vfs_setattr,
 };
index cb899af1babc3bf42b48a6064d7f9345ae0bb4a8..a34702c998f593f60515d72fcf093cd556f5d951 100644 (file)
@@ -899,26 +899,34 @@ error:
 }
 
 /**
- * v9fs_vfs_follow_link_dotl - follow a symlink path
+ * v9fs_vfs_get_link_dotl - follow a symlink path
  * @dentry: dentry for symlink
- * @cookie: place to pass the data to put_link()
+ * @inode: inode for symlink
+ * @done: destructor for return value
  */
 
 static const char *
-v9fs_vfs_follow_link_dotl(struct dentry *dentry, void **cookie)
+v9fs_vfs_get_link_dotl(struct dentry *dentry,
+                      struct inode *inode,
+                      struct delayed_call *done)
 {
-       struct p9_fid *fid = v9fs_fid_lookup(dentry);
+       struct p9_fid *fid;
        char *target;
        int retval;
 
+       if (!dentry)
+               return ERR_PTR(-ECHILD);
+
        p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);
 
+       fid = v9fs_fid_lookup(dentry);
        if (IS_ERR(fid))
                return ERR_CAST(fid);
        retval = p9_client_readlink(fid, &target);
        if (retval)
                return ERR_PTR(retval);
-       return *cookie = target;
+       set_delayed_call(done, kfree_link, target);
+       return target;
 }
 
 int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode)
@@ -984,8 +992,7 @@ const struct inode_operations v9fs_file_inode_operations_dotl = {
 
 const struct inode_operations v9fs_symlink_inode_operations_dotl = {
        .readlink = generic_readlink,
-       .follow_link = v9fs_vfs_follow_link_dotl,
-       .put_link = kfree_put_link,
+       .get_link = v9fs_vfs_get_link_dotl,
        .getattr = v9fs_vfs_getattr_dotl,
        .setattr = v9fs_vfs_setattr_dotl,
        .setxattr = generic_setxattr,
index 17349500592d55b8b0a9a087809301c05995c696..0fdb0f5b2239df24b69363a7449a7a7ff360003c 100644 (file)
@@ -140,6 +140,7 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino)
                break;
        case ST_SOFTLINK:
                inode->i_mode |= S_IFLNK;
+               inode_nohighmem(inode);
                inode->i_op = &affs_symlink_inode_operations;
                inode->i_data.a_ops = &affs_symlink_aops;
                break;
index 181e05b46e7261d32ab9390daf7007b017af1e84..00d3002a6780b339cf456417b742bf5c9f991ec8 100644 (file)
@@ -344,6 +344,7 @@ affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
                return -ENOSPC;
 
        inode->i_op = &affs_symlink_inode_operations;
+       inode_nohighmem(inode);
        inode->i_data.a_ops = &affs_symlink_aops;
        inode->i_mode = S_IFLNK | 0777;
        mode_to_prot(inode);
index ea5b69a18ba9ce9165d8ea083bfffbb40e13a600..69b03dbb792f7a080abc70f5d45ff4bf50d458b9 100644 (file)
@@ -14,13 +14,13 @@ static int affs_symlink_readpage(struct file *file, struct page *page)
 {
        struct buffer_head *bh;
        struct inode *inode = page->mapping->host;
-       char *link = kmap(page);
+       char *link = page_address(page);
        struct slink_front *lf;
        int                      i, j;
        char                     c;
        char                     lc;
 
-       pr_debug("follow_link(ino=%lu)\n", inode->i_ino);
+       pr_debug("get_link(ino=%lu)\n", inode->i_ino);
 
        bh = affs_bread(inode->i_sb, inode->i_ino);
        if (!bh)
@@ -57,12 +57,10 @@ static int affs_symlink_readpage(struct file *file, struct page *page)
        link[i] = '\0';
        affs_brelse(bh);
        SetPageUptodate(page);
-       kunmap(page);
        unlock_page(page);
        return 0;
 fail:
        SetPageError(page);
-       kunmap(page);
        unlock_page(page);
        return -EIO;
 }
@@ -73,7 +71,6 @@ const struct address_space_operations affs_symlink_aops = {
 
 const struct inode_operations affs_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = page_follow_link_light,
-       .put_link       = page_put_link,
+       .get_link       = page_get_link,
        .setattr        = affs_notify_change,
 };
index e06f5a23352ac65415f8bcb54450af2620588e95..86cc7264c21cda727a3bb71e73af9a7ddc35eec5 100644 (file)
@@ -56,6 +56,7 @@ static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key)
        case AFS_FTYPE_SYMLINK:
                inode->i_mode   = S_IFLNK | vnode->status.mode;
                inode->i_op     = &page_symlink_inode_operations;
+               inode_nohighmem(inode);
                break;
        default:
                printk("kAFS: AFS vnode with undefined type\n");
index da0c33481bc0387788bcf4ce1792b38e141804e4..84e037d1d129336a7d052ad2881db238785bd350 100644 (file)
 
 #include "autofs_i.h"
 
-static const char *autofs4_follow_link(struct dentry *dentry, void **cookie)
+static const char *autofs4_get_link(struct dentry *dentry,
+                                   struct inode *inode,
+                                   struct delayed_call *done)
 {
-       struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb);
-       struct autofs_info *ino = autofs4_dentry_ino(dentry);
+       struct autofs_sb_info *sbi;
+       struct autofs_info *ino;
+       if (!dentry)
+               return ERR_PTR(-ECHILD);
+       sbi = autofs4_sbi(dentry->d_sb);
+       ino = autofs4_dentry_ino(dentry);
        if (ino && !autofs4_oz_mode(sbi))
                ino->last_used = jiffies;
        return d_inode(dentry)->i_private;
@@ -23,5 +29,5 @@ static const char *autofs4_follow_link(struct dentry *dentry, void **cookie)
 
 const struct inode_operations autofs4_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = autofs4_follow_link
+       .get_link       = autofs4_get_link
 };
index 46aedacfa6a8d4131563a83a8402daf89d590ddb..25250fa87086316a95d8877935d810cd8d305196 100644 (file)
@@ -42,7 +42,7 @@ static struct inode *befs_iget(struct super_block *, unsigned long);
 static struct inode *befs_alloc_inode(struct super_block *sb);
 static void befs_destroy_inode(struct inode *inode);
 static void befs_destroy_inodecache(void);
-static const char *befs_follow_link(struct dentry *, void **);
+static int befs_symlink_readpage(struct file *, struct page *);
 static int befs_utf2nls(struct super_block *sb, const char *in, int in_len,
                        char **out, int *out_len);
 static int befs_nls2utf(struct super_block *sb, const char *in, int in_len,
@@ -79,10 +79,8 @@ static const struct address_space_operations befs_aops = {
        .bmap           = befs_bmap,
 };
 
-static const struct inode_operations befs_symlink_inode_operations = {
-       .readlink       = generic_readlink,
-       .follow_link    = befs_follow_link,
-       .put_link       = kfree_put_link,
+static const struct address_space_operations befs_symlink_aops = {
+       .readpage       = befs_symlink_readpage,
 };
 
 /* 
@@ -398,7 +396,9 @@ static struct inode *befs_iget(struct super_block *sb, unsigned long ino)
                inode->i_fop = &befs_dir_operations;
        } else if (S_ISLNK(inode->i_mode)) {
                if (befs_ino->i_flags & BEFS_LONG_SYMLINK) {
-                       inode->i_op = &befs_symlink_inode_operations;
+                       inode->i_op = &page_symlink_inode_operations;
+                       inode_nohighmem(inode);
+                       inode->i_mapping->a_ops = &befs_symlink_aops;
                } else {
                        inode->i_link = befs_ino->i_data.symlink;
                        inode->i_op = &simple_symlink_inode_operations;
@@ -463,31 +463,33 @@ befs_destroy_inodecache(void)
  * The data stream become link name. Unless the LONG_SYMLINK
  * flag is set.
  */
-static const char *
-befs_follow_link(struct dentry *dentry, void **cookie)
+static int befs_symlink_readpage(struct file *unused, struct page *page)
 {
-       struct super_block *sb = dentry->d_sb;
-       struct befs_inode_info *befs_ino = BEFS_I(d_inode(dentry));
+       struct inode *inode = page->mapping->host;
+       struct super_block *sb = inode->i_sb;
+       struct befs_inode_info *befs_ino = BEFS_I(inode);
        befs_data_stream *data = &befs_ino->i_data.ds;
        befs_off_t len = data->size;
-       char *link;
+       char *link = page_address(page);
 
-       if (len == 0) {
+       if (len == 0 || len > PAGE_SIZE) {
                befs_error(sb, "Long symlink with illegal length");
-               return ERR_PTR(-EIO);
+               goto fail;
        }
        befs_debug(sb, "Follow long symlink");
 
-       link = kmalloc(len, GFP_NOFS);
-       if (!link)
-               return ERR_PTR(-ENOMEM);
        if (befs_read_lsymlink(sb, data, link, len) != len) {
-               kfree(link);
                befs_error(sb, "Failed to read entire long symlink");
-               return ERR_PTR(-EIO);
+               goto fail;
        }
        link[len - 1] = '\0';
-       return *cookie = link;
+       SetPageUptodate(page);
+       unlock_page(page);
+       return 0;
+fail:
+       SetPageError(page);
+       unlock_page(page);
+       return -EIO;
 }
 
 /*
index c25639e907bd21a194aecedc6c60a93fb4994375..44d4a1e9244e74e923d7b26018d4b420aa2e1323 100644 (file)
@@ -1523,11 +1523,14 @@ static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part)
                WARN_ON_ONCE(bdev->bd_holders);
                sync_blockdev(bdev);
                kill_bdev(bdev);
+
+               bdev_write_inode(bdev);
                /*
-                * ->release can cause the queue to disappear, so flush all
-                * dirty data before.
+                * Detaching bdev inode from its wb in __destroy_inode()
+                * is too late: the queue which embeds its bdi (along with
+                * root wb) can be gone as soon as we put_disk() below.
                 */
-               bdev_write_inode(bdev);
+               inode_detach_wb(bdev->bd_inode);
        }
        if (bdev->bd_contains == bdev) {
                if (disk->fops->release)
index 4b89680a192338c7a70a4c909e3c4374abe41284..c4661db2b72ae4c412adaaecb7cbc236fbe1e7cf 100644 (file)
@@ -10480,11 +10480,15 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
                 * until transaction commit to do the actual discard.
                 */
                if (trimming) {
-                       WARN_ON(!list_empty(&block_group->bg_list));
-                       spin_lock(&trans->transaction->deleted_bgs_lock);
+                       spin_lock(&fs_info->unused_bgs_lock);
+                       /*
+                        * A concurrent scrub might have added us to the list
+                        * fs_info->unused_bgs, so use a list_move operation
+                        * to add the block group to the deleted_bgs list.
+                        */
                        list_move(&block_group->bg_list,
                                  &trans->transaction->deleted_bgs);
-                       spin_unlock(&trans->transaction->deleted_bgs_lock);
+                       spin_unlock(&fs_info->unused_bgs_lock);
                        btrfs_get_block_group(block_group);
                }
 end_trans:
index 72e73461c0643bbf128504c93a9c47dd377784aa..0f09526aa7d9d2017bb229eb4310f777c4b3b578 100644 (file)
@@ -1291,7 +1291,8 @@ out:
  * on error we return an unlocked page and the error value
  * on success we return a locked page and 0
  */
-static int prepare_uptodate_page(struct page *page, u64 pos,
+static int prepare_uptodate_page(struct inode *inode,
+                                struct page *page, u64 pos,
                                 bool force_uptodate)
 {
        int ret = 0;
@@ -1306,6 +1307,10 @@ static int prepare_uptodate_page(struct page *page, u64 pos,
                        unlock_page(page);
                        return -EIO;
                }
+               if (page->mapping != inode->i_mapping) {
+                       unlock_page(page);
+                       return -EAGAIN;
+               }
        }
        return 0;
 }
@@ -1324,6 +1329,7 @@ static noinline int prepare_pages(struct inode *inode, struct page **pages,
        int faili;
 
        for (i = 0; i < num_pages; i++) {
+again:
                pages[i] = find_or_create_page(inode->i_mapping, index + i,
                                               mask | __GFP_WRITE);
                if (!pages[i]) {
@@ -1333,13 +1339,17 @@ static noinline int prepare_pages(struct inode *inode, struct page **pages,
                }
 
                if (i == 0)
-                       err = prepare_uptodate_page(pages[i], pos,
+                       err = prepare_uptodate_page(inode, pages[i], pos,
                                                    force_uptodate);
-               if (i == num_pages - 1)
-                       err = prepare_uptodate_page(pages[i],
+               if (!err && i == num_pages - 1)
+                       err = prepare_uptodate_page(inode, pages[i],
                                                    pos + write_bytes, false);
                if (err) {
                        page_cache_release(pages[i]);
+                       if (err == -EAGAIN) {
+                               err = 0;
+                               goto again;
+                       }
                        faili = i - 1;
                        goto fail;
                }
index 85a1f8621b51f09f0893abae9ffab90382efdcfc..cfe99bec49dedd723e2a7fff04ace299be37ef87 100644 (file)
@@ -891,7 +891,7 @@ out:
                spin_unlock(&block_group->lock);
                ret = 0;
 
-               btrfs_warn(fs_info, "failed to load free space cache for block group %llu, rebuild it now",
+               btrfs_warn(fs_info, "failed to load free space cache for block group %llu, rebuilding it now",
                        block_group->key.objectid);
        }
 
@@ -2972,7 +2972,7 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,
                     u64 cont1_bytes, u64 min_bytes)
 {
        struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
-       struct btrfs_free_space *entry;
+       struct btrfs_free_space *entry = NULL;
        int ret = -ENOSPC;
        u64 bitmap_offset = offset_to_bitmap(ctl, offset);
 
@@ -2983,8 +2983,10 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,
         * The bitmap that covers offset won't be in the list unless offset
         * is just its start offset.
         */
-       entry = list_first_entry(bitmaps, struct btrfs_free_space, list);
-       if (entry->offset != bitmap_offset) {
+       if (!list_empty(bitmaps))
+               entry = list_first_entry(bitmaps, struct btrfs_free_space, list);
+
+       if (!entry || entry->offset != bitmap_offset) {
                entry = tree_search_offset(ctl, bitmap_offset, 1, 0);
                if (entry && list_empty(&entry->list))
                        list_add(&entry->list, bitmaps);
index 4fb8d6e28b2152310c399e250e9bec681b691622..3b8856e182ae7b7ee0d6ee4c32454cfc9bffdc3a 100644 (file)
@@ -3774,6 +3774,7 @@ cache_acl:
                break;
        case S_IFLNK:
                inode->i_op = &btrfs_symlink_inode_operations;
+               inode_nohighmem(inode);
                inode->i_mapping->a_ops = &btrfs_symlink_aops;
                break;
        default:
@@ -9705,6 +9706,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
        btrfs_free_path(path);
 
        inode->i_op = &btrfs_symlink_inode_operations;
+       inode_nohighmem(inode);
        inode->i_mapping->a_ops = &btrfs_symlink_aops;
        inode_set_bytes(inode, name_len);
        btrfs_i_size_write(inode, name_len);
@@ -10094,8 +10096,7 @@ static const struct inode_operations btrfs_special_inode_operations = {
 };
 static const struct inode_operations btrfs_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = page_follow_link_light,
-       .put_link       = page_put_link,
+       .get_link       = page_get_link,
        .getattr        = btrfs_getattr,
        .setattr        = btrfs_setattr,
        .permission     = btrfs_permission,
index 3367a3c6f214f5ca248a79fff36c6404a49fbf4f..be8eae80ff6572608a478610f9c2b16f3bcb1871 100644 (file)
@@ -274,7 +274,6 @@ loop:
        cur_trans->num_dirty_bgs = 0;
        spin_lock_init(&cur_trans->dirty_bgs_lock);
        INIT_LIST_HEAD(&cur_trans->deleted_bgs);
-       spin_lock_init(&cur_trans->deleted_bgs_lock);
        spin_lock_init(&cur_trans->dropped_roots_lock);
        list_add_tail(&cur_trans->list, &fs_info->trans_list);
        extent_io_tree_init(&cur_trans->dirty_pages,
index 0da21ca9b3fb312a7ec77b4e8314a9e4b3410075..64c8221b6165bb7a6b786ac74e1833f2b93a197b 100644 (file)
@@ -77,8 +77,8 @@ struct btrfs_transaction {
         */
        struct mutex cache_write_mutex;
        spinlock_t dirty_bgs_lock;
+       /* Protected by spin lock fs_info->unused_bgs_lock. */
        struct list_head deleted_bgs;
-       spinlock_t deleted_bgs_lock;
        spinlock_t dropped_roots_lock;
        struct btrfs_delayed_ref_root delayed_refs;
        int aborted;
index 45645220660996773b1f76cd1d526d4aeae33dac..a23399e8e3aba2f63d4c0cee90932d073d3bd113 100644 (file)
@@ -3548,12 +3548,11 @@ again:
 
                        ret = btrfs_force_chunk_alloc(trans, chunk_root,
                                                      BTRFS_BLOCK_GROUP_DATA);
+                       btrfs_end_transaction(trans, chunk_root);
                        if (ret < 0) {
                                mutex_unlock(&fs_info->delete_unused_bgs_mutex);
                                goto error;
                        }
-
-                       btrfs_end_transaction(trans, chunk_root);
                        chunk_reserved = 1;
                }
 
index 498dcfa2dcdbedf393ae26fc9f7f68cf90bceb90..da55eb8bcffab89755baf5229b92ededf49dd484 100644 (file)
@@ -1756,7 +1756,7 @@ retry:
  */
 static const struct inode_operations ceph_symlink_iops = {
        .readlink = generic_readlink,
-       .follow_link = simple_follow_link,
+       .get_link = simple_get_link,
        .setattr = ceph_setattr,
        .getattr = ceph_getattr,
        .setxattr = ceph_setxattr,
index cbc0f4bca0c0dfa73b6a545fb6978a72b1a702ef..90e4e2b398b66b08c9a35ed3448f34c91fbcb1df 100644 (file)
@@ -900,8 +900,7 @@ const struct inode_operations cifs_file_inode_ops = {
 
 const struct inode_operations cifs_symlink_inode_ops = {
        .readlink = generic_readlink,
-       .follow_link = cifs_follow_link,
-       .put_link = kfree_put_link,
+       .get_link = cifs_get_link,
        .permission = cifs_permission,
        /* BB add the following two eventually */
        /* revalidate: cifs_revalidate,
index c3cc1609025fa3a966c2d5b10f32626214a9e4ef..26a1187d4323f227ca89072504d94619d8eb5df5 100644 (file)
@@ -120,9 +120,8 @@ extern struct vfsmount *cifs_dfs_d_automount(struct path *path);
 #endif
 
 /* Functions related to symlinks */
-extern const char *cifs_follow_link(struct dentry *direntry, void **cookie);
-extern int cifs_readlink(struct dentry *direntry, char __user *buffer,
-                        int buflen);
+extern const char *cifs_get_link(struct dentry *, struct inode *,
+                       struct delayed_call *);
 extern int cifs_symlink(struct inode *inode, struct dentry *direntry,
                        const char *symname);
 extern int     cifs_removexattr(struct dentry *, const char *);
index 6b66dd5d15408676ab6510f7ce415164fe5c0571..a329f5ba35aad8649ce3f644b9b11913c57cc5f8 100644 (file)
@@ -1831,11 +1831,11 @@ cifs_invalidate_mapping(struct inode *inode)
  * @word: long word containing the bit lock
  */
 static int
-cifs_wait_bit_killable(struct wait_bit_key *key)
+cifs_wait_bit_killable(struct wait_bit_key *key, int mode)
 {
-       if (fatal_signal_pending(current))
-               return -ERESTARTSYS;
        freezable_schedule_unsafe();
+       if (signal_pending_state(mode, current))
+               return -ERESTARTSYS;
        return 0;
 }
 
index e3548f73bdeaa980ef1c282246688e1e3f5f21e8..062c2375549a87acf716957593a58f213a972e06 100644 (file)
@@ -627,9 +627,9 @@ cifs_hl_exit:
 }
 
 const char *
-cifs_follow_link(struct dentry *direntry, void **cookie)
+cifs_get_link(struct dentry *direntry, struct inode *inode,
+             struct delayed_call *done)
 {
-       struct inode *inode = d_inode(direntry);
        int rc = -ENOMEM;
        unsigned int xid;
        char *full_path = NULL;
@@ -639,6 +639,9 @@ cifs_follow_link(struct dentry *direntry, void **cookie)
        struct cifs_tcon *tcon;
        struct TCP_Server_Info *server;
 
+       if (!direntry)
+               return ERR_PTR(-ECHILD);
+
        xid = get_xid();
 
        tlink = cifs_sb_tlink(cifs_sb);
@@ -678,7 +681,8 @@ cifs_follow_link(struct dentry *direntry, void **cookie)
                kfree(target_path);
                return ERR_PTR(rc);
        }
-       return *cookie = target_path;
+       set_delayed_call(done, kfree_link, target_path);
+       return target_path;
 }
 
 int
index 7740b1c871c183ea55994e84812273effa58a476..1bfb7ba4e85e3ecc05000a3543a01917a7ed40a4 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/coda.h>
 #include <linux/coda_psdev.h>
+#include <linux/pagemap.h>
 #include "coda_linux.h"
 
 static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2)
@@ -17,8 +18,7 @@ static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2)
 
 static const struct inode_operations coda_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = page_follow_link_light,
-       .put_link       = page_put_link,
+       .get_link       = page_get_link,
        .setattr        = coda_setattr,
 };
 
@@ -35,6 +35,7 @@ static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
                 inode->i_fop = &coda_dir_operations;
         } else if (S_ISLNK(inode->i_mode)) {
                inode->i_op = &coda_symlink_inode_operations;
+               inode_nohighmem(inode);
                inode->i_data.a_ops = &coda_symlink_aops;
                inode->i_mapping = &inode->i_data;
        } else
index ab94ef63caefed0767e8f2cccf6364038ca94825..03736e20d72076cec96eb0c57aa0c9bf8f901e59 100644 (file)
@@ -26,7 +26,7 @@ static int coda_symlink_filler(struct file *file, struct page *page)
        int error;
        struct coda_inode_info *cii;
        unsigned int len = PAGE_SIZE;
-       char *p = kmap(page);
+       char *p = page_address(page);
 
        cii = ITOC(inode);
 
@@ -34,13 +34,11 @@ static int coda_symlink_filler(struct file *file, struct page *page)
        if (error)
                goto fail;
        SetPageUptodate(page);
-       kunmap(page);
        unlock_page(page);
        return 0;
 
 fail:
        SetPageError(page);
-       kunmap(page);
        unlock_page(page);
        return error;
 }
index dcf26537c935f25ed10a534a13e31492802c5369..9144b779d10ef454d0f42bb15f7560878265b5ba 100644 (file)
@@ -58,6 +58,8 @@
 #include <linux/atalk.h>
 #include <linux/gfp.h>
 
+#include "internal.h"
+
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_sock.h>
 #include <net/bluetooth/rfcomm.h>
 #include <asm/fbio.h>
 #endif
 
-static int w_long(unsigned int fd, unsigned int cmd,
-               compat_ulong_t __user *argp)
+#define convert_in_user(srcptr, dstptr)                        \
+({                                                     \
+       typeof(*srcptr) val;                            \
+                                                       \
+       get_user(val, srcptr) || put_user(val, dstptr); \
+})
+
+static int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       int err;
+
+       err = security_file_ioctl(file, cmd, arg);
+       if (err)
+               return err;
+
+       return vfs_ioctl(file, cmd, arg);
+}
+
+static int w_long(struct file *file,
+               unsigned int cmd, compat_ulong_t __user *argp)
 {
-       mm_segment_t old_fs = get_fs();
        int err;
-       unsigned long val;
+       unsigned long __user *valp = compat_alloc_user_space(sizeof(*valp));
 
-       set_fs (KERNEL_DS);
-       err = sys_ioctl(fd, cmd, (unsigned long)&val);
-       set_fs (old_fs);
-       if (!err && put_user(val, argp))
+       if (valp == NULL)
                return -EFAULT;
-       return err;
+       err = do_ioctl(file, cmd, (unsigned long)valp);
+       if (err)
+               return err;
+       if (convert_in_user(valp, argp))
+               return -EFAULT;
+       return 0;
 }
 
 struct compat_video_event {
@@ -139,23 +160,23 @@ struct compat_video_event {
        } u;
 };
 
-static int do_video_get_event(unsigned int fd, unsigned int cmd,
-               struct compat_video_event __user *up)
+static int do_video_get_event(struct file *file,
+               unsigned int cmd, struct compat_video_event __user *up)
 {
-       struct video_event kevent;
-       mm_segment_t old_fs = get_fs();
+       struct video_event __user *kevent =
+               compat_alloc_user_space(sizeof(*kevent));
        int err;
 
-       set_fs(KERNEL_DS);
-       err = sys_ioctl(fd, cmd, (unsigned long) &kevent);
-       set_fs(old_fs);
+       if (kevent == NULL)
+               return -EFAULT;
 
+       err = do_ioctl(file, cmd, (unsigned long)kevent);
        if (!err) {
-               err  = put_user(kevent.type, &up->type);
-               err |= put_user(kevent.timestamp, &up->timestamp);
-               err |= put_user(kevent.u.size.w, &up->u.size.w);
-               err |= put_user(kevent.u.size.h, &up->u.size.h);
-               err |= put_user(kevent.u.size.aspect_ratio,
+               err  = convert_in_user(&kevent->type, &up->type);
+               err |= convert_in_user(&kevent->timestamp, &up->timestamp);
+               err |= convert_in_user(&kevent->u.size.w, &up->u.size.w);
+               err |= convert_in_user(&kevent->u.size.h, &up->u.size.h);
+               err |= convert_in_user(&kevent->u.size.aspect_ratio,
                                &up->u.size.aspect_ratio);
                if (err)
                        err = -EFAULT;
@@ -169,8 +190,8 @@ struct compat_video_still_picture {
         int32_t size;
 };
 
-static int do_video_stillpicture(unsigned int fd, unsigned int cmd,
-       struct compat_video_still_picture __user *up)
+static int do_video_stillpicture(struct file *file,
+               unsigned int cmd, struct compat_video_still_picture __user *up)
 {
        struct video_still_picture __user *up_native;
        compat_uptr_t fp;
@@ -190,7 +211,7 @@ static int do_video_stillpicture(unsigned int fd, unsigned int cmd,
        if (err)
                return -EFAULT;
 
-       err = sys_ioctl(fd, cmd, (unsigned long) up_native);
+       err = do_ioctl(file, cmd, (unsigned long) up_native);
 
        return err;
 }
@@ -200,8 +221,8 @@ struct compat_video_spu_palette {
        compat_uptr_t palette;
 };
 
-static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd,
-               struct compat_video_spu_palette __user *up)
+static int do_video_set_spu_palette(struct file *file,
+               unsigned int cmd, struct compat_video_spu_palette __user *up)
 {
        struct video_spu_palette __user *up_native;
        compat_uptr_t palp;
@@ -218,7 +239,7 @@ static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd,
        if (err)
                return -EFAULT;
 
-       err = sys_ioctl(fd, cmd, (unsigned long) up_native);
+       err = do_ioctl(file, cmd, (unsigned long) up_native);
 
        return err;
 }
@@ -276,7 +297,7 @@ static int sg_build_iovec(sg_io_hdr_t __user *sgio, void __user *dxferp, u16 iov
        return 0;
 }
 
-static int sg_ioctl_trans(unsigned int fd, unsigned int cmd,
+static int sg_ioctl_trans(struct file *file, unsigned int cmd,
                        sg_io_hdr32_t __user *sgio32)
 {
        sg_io_hdr_t __user *sgio;
@@ -289,7 +310,7 @@ static int sg_ioctl_trans(unsigned int fd, unsigned int cmd,
        if (get_user(interface_id, &sgio32->interface_id))
                return -EFAULT;
        if (interface_id != 'S')
-               return sys_ioctl(fd, cmd, (unsigned long)sgio32);
+               return do_ioctl(file, cmd, (unsigned long)sgio32);
 
        if (get_user(iovec_count, &sgio32->iovec_count))
                return -EFAULT;
@@ -349,7 +370,7 @@ static int sg_ioctl_trans(unsigned int fd, unsigned int cmd,
        if (put_user(compat_ptr(data), &sgio->usr_ptr))
                return -EFAULT;
 
-       err = sys_ioctl(fd, cmd, (unsigned long) sgio);
+       err = do_ioctl(file, cmd, (unsigned long) sgio);
 
        if (err >= 0) {
                void __user *datap;
@@ -380,13 +401,13 @@ struct compat_sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */
        int unused;
 };
 
-static int sg_grt_trans(unsigned int fd, unsigned int cmd, struct
-                       compat_sg_req_info __user *o)
+static int sg_grt_trans(struct file *file,
+               unsigned int cmd, struct compat_sg_req_info __user *o)
 {
        int err, i;
        sg_req_info_t __user *r;
        r = compat_alloc_user_space(sizeof(sg_req_info_t)*SG_MAX_QUEUE);
-       err = sys_ioctl(fd,cmd,(unsigned long)r);
+       err = do_ioctl(file, cmd, (unsigned long)r);
        if (err < 0)
                return err;
        for (i = 0; i < SG_MAX_QUEUE; i++) {
@@ -412,8 +433,8 @@ struct sock_fprog32 {
 #define PPPIOCSPASS32  _IOW('t', 71, struct sock_fprog32)
 #define PPPIOCSACTIVE32        _IOW('t', 70, struct sock_fprog32)
 
-static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd,
-                       struct sock_fprog32 __user *u_fprog32)
+static int ppp_sock_fprog_ioctl_trans(struct file *file,
+               unsigned int cmd, struct sock_fprog32 __user *u_fprog32)
 {
        struct sock_fprog __user *u_fprog64 = compat_alloc_user_space(sizeof(struct sock_fprog));
        void __user *fptr64;
@@ -435,7 +456,7 @@ static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd,
        else
                cmd = PPPIOCSACTIVE;
 
-       return sys_ioctl(fd, cmd, (unsigned long) u_fprog64);
+       return do_ioctl(file, cmd, (unsigned long) u_fprog64);
 }
 
 struct ppp_option_data32 {
@@ -451,7 +472,7 @@ struct ppp_idle32 {
 };
 #define PPPIOCGIDLE32          _IOR('t', 63, struct ppp_idle32)
 
-static int ppp_gidle(unsigned int fd, unsigned int cmd,
+static int ppp_gidle(struct file *file, unsigned int cmd,
                struct ppp_idle32 __user *idle32)
 {
        struct ppp_idle __user *idle;
@@ -460,7 +481,7 @@ static int ppp_gidle(unsigned int fd, unsigned int cmd,
 
        idle = compat_alloc_user_space(sizeof(*idle));
 
-       err = sys_ioctl(fd, PPPIOCGIDLE, (unsigned long) idle);
+       err = do_ioctl(file, PPPIOCGIDLE, (unsigned long) idle);
 
        if (!err) {
                if (get_user(xmit, &idle->xmit_idle) ||
@@ -472,7 +493,7 @@ static int ppp_gidle(unsigned int fd, unsigned int cmd,
        return err;
 }
 
-static int ppp_scompress(unsigned int fd, unsigned int cmd,
+static int ppp_scompress(struct file *file, unsigned int cmd,
        struct ppp_option_data32 __user *odata32)
 {
        struct ppp_option_data __user *odata;
@@ -492,7 +513,7 @@ static int ppp_scompress(unsigned int fd, unsigned int cmd,
                         sizeof(__u32) + sizeof(int)))
                return -EFAULT;
 
-       return sys_ioctl(fd, PPPIOCSCOMPRESS, (unsigned long) odata);
+       return do_ioctl(file, PPPIOCSCOMPRESS, (unsigned long) odata);
 }
 
 #ifdef CONFIG_BLOCK
@@ -512,12 +533,13 @@ struct mtpos32 {
 };
 #define MTIOCPOS32     _IOR('m', 3, struct mtpos32)
 
-static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, void __user *argp)
+static int mt_ioctl_trans(struct file *file,
+               unsigned int cmd, void __user *argp)
 {
-       mm_segment_t old_fs = get_fs();
-       struct mtget get;
+       /* NULL initialization to make gcc shut up */
+       struct mtget __user *get = NULL;
        struct mtget32 __user *umget32;
-       struct mtpos pos;
+       struct mtpos __user *pos = NULL;
        struct mtpos32 __user *upos32;
        unsigned long kcmd;
        void *karg;
@@ -526,32 +548,34 @@ static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, void __user *argp)
        switch(cmd) {
        case MTIOCPOS32:
                kcmd = MTIOCPOS;
-               karg = &pos;
+               pos = compat_alloc_user_space(sizeof(*pos));
+               karg = pos;
                break;
        default:        /* MTIOCGET32 */
                kcmd = MTIOCGET;
-               karg = &get;
+               get = compat_alloc_user_space(sizeof(*get));
+               karg = get;
                break;
        }
-       set_fs (KERNEL_DS);
-       err = sys_ioctl (fd, kcmd, (unsigned long)karg);
-       set_fs (old_fs);
+       if (karg == NULL)
+               return -EFAULT;
+       err = do_ioctl(file, kcmd, (unsigned long)karg);
        if (err)
                return err;
        switch (cmd) {
        case MTIOCPOS32:
                upos32 = argp;
-               err = __put_user(pos.mt_blkno, &upos32->mt_blkno);
+               err = convert_in_user(&pos->mt_blkno, &upos32->mt_blkno);
                break;
        case MTIOCGET32:
                umget32 = argp;
-               err = __put_user(get.mt_type, &umget32->mt_type);
-               err |= __put_user(get.mt_resid, &umget32->mt_resid);
-               err |= __put_user(get.mt_dsreg, &umget32->mt_dsreg);
-               err |= __put_user(get.mt_gstat, &umget32->mt_gstat);
-               err |= __put_user(get.mt_erreg, &umget32->mt_erreg);
-               err |= __put_user(get.mt_fileno, &umget32->mt_fileno);
-               err |= __put_user(get.mt_blkno, &umget32->mt_blkno);
+               err = convert_in_user(&get->mt_type, &umget32->mt_type);
+               err |= convert_in_user(&get->mt_resid, &umget32->mt_resid);
+               err |= convert_in_user(&get->mt_dsreg, &umget32->mt_dsreg);
+               err |= convert_in_user(&get->mt_gstat, &umget32->mt_gstat);
+               err |= convert_in_user(&get->mt_erreg, &umget32->mt_erreg);
+               err |= convert_in_user(&get->mt_fileno, &umget32->mt_fileno);
+               err |= convert_in_user(&get->mt_blkno, &umget32->mt_blkno);
                break;
        }
        return err ? -EFAULT: 0;
@@ -605,42 +629,41 @@ struct serial_struct32 {
         compat_int_t    reserved[1];
 };
 
-static int serial_struct_ioctl(unsigned fd, unsigned cmd,
-                       struct serial_struct32 __user *ss32)
+static int serial_struct_ioctl(struct file *file,
+               unsigned cmd, struct serial_struct32 __user *ss32)
 {
         typedef struct serial_struct32 SS32;
         int err;
-        struct serial_struct ss;
-        mm_segment_t oldseg = get_fs();
+       struct serial_struct __user *ss = compat_alloc_user_space(sizeof(*ss));
         __u32 udata;
        unsigned int base;
+       unsigned char *iomem_base;
 
+       if (ss == NULL)
+               return -EFAULT;
         if (cmd == TIOCSSERIAL) {
-                if (!access_ok(VERIFY_READ, ss32, sizeof(SS32)))
-                        return -EFAULT;
-                if (__copy_from_user(&ss, ss32, offsetof(SS32, iomem_base)))
+               if (copy_in_user(ss, ss32, offsetof(SS32, iomem_base)) ||
+                   get_user(udata, &ss32->iomem_base))
                        return -EFAULT;
-                if (__get_user(udata, &ss32->iomem_base))
+               iomem_base = compat_ptr(udata);
+               if (put_user(iomem_base, &ss->iomem_base) ||
+                   convert_in_user(&ss32->iomem_reg_shift,
+                     &ss->iomem_reg_shift) ||
+                   convert_in_user(&ss32->port_high, &ss->port_high) ||
+                   put_user(0UL, &ss->iomap_base))
                        return -EFAULT;
-                ss.iomem_base = compat_ptr(udata);
-                if (__get_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift) ||
-                   __get_user(ss.port_high, &ss32->port_high))
-                       return -EFAULT;
-                ss.iomap_base = 0UL;
         }
-        set_fs(KERNEL_DS);
-                err = sys_ioctl(fd,cmd,(unsigned long)(&ss));
-        set_fs(oldseg);
+       err = do_ioctl(file, cmd, (unsigned long)ss);
         if (cmd == TIOCGSERIAL && err >= 0) {
-                if (!access_ok(VERIFY_WRITE, ss32, sizeof(SS32)))
-                        return -EFAULT;
-                if (__copy_to_user(ss32,&ss,offsetof(SS32,iomem_base)))
+               if (copy_in_user(ss32, ss, offsetof(SS32, iomem_base)) ||
+                   get_user(iomem_base, &ss->iomem_base))
                        return -EFAULT;
-               base = (unsigned long)ss.iomem_base  >> 32 ?
-                       0xffffffff : (unsigned)(unsigned long)ss.iomem_base;
-               if (__put_user(base, &ss32->iomem_base) ||
-                   __put_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift) ||
-                   __put_user(ss.port_high, &ss32->port_high))
+               base = (unsigned long)iomem_base  >> 32 ?
+                       0xffffffff : (unsigned)(unsigned long)iomem_base;
+               if (put_user(base, &ss32->iomem_base) ||
+                   convert_in_user(&ss->iomem_reg_shift,
+                     &ss32->iomem_reg_shift) ||
+                   convert_in_user(&ss->port_high, &ss32->port_high))
                        return -EFAULT;
         }
         return err;
@@ -674,8 +697,8 @@ struct i2c_rdwr_aligned {
        struct i2c_msg msgs[0];
 };
 
-static int do_i2c_rdwr_ioctl(unsigned int fd, unsigned int cmd,
-                       struct i2c_rdwr_ioctl_data32    __user *udata)
+static int do_i2c_rdwr_ioctl(struct file *file,
+       unsigned int cmd, struct i2c_rdwr_ioctl_data32 __user *udata)
 {
        struct i2c_rdwr_aligned         __user *tdata;
        struct i2c_msg                  __user *tmsgs;
@@ -708,11 +731,11 @@ static int do_i2c_rdwr_ioctl(unsigned int fd, unsigned int cmd,
                    put_user(compat_ptr(datap), &tmsgs[i].buf))
                        return -EFAULT;
        }
-       return sys_ioctl(fd, cmd, (unsigned long)tdata);
+       return do_ioctl(file, cmd, (unsigned long)tdata);
 }
 
-static int do_i2c_smbus_ioctl(unsigned int fd, unsigned int cmd,
-                       struct i2c_smbus_ioctl_data32   __user *udata)
+static int do_i2c_smbus_ioctl(struct file *file,
+               unsigned int cmd, struct i2c_smbus_ioctl_data32   __user *udata)
 {
        struct i2c_smbus_ioctl_data     __user *tdata;
        compat_caddr_t                  datap;
@@ -734,7 +757,7 @@ static int do_i2c_smbus_ioctl(unsigned int fd, unsigned int cmd,
            __put_user(compat_ptr(datap), &tdata->data))
                return -EFAULT;
 
-       return sys_ioctl(fd, cmd, (unsigned long)tdata);
+       return do_ioctl(file, cmd, (unsigned long)tdata);
 }
 
 #define RTC_IRQP_READ32                _IOR('p', 0x0b, compat_ulong_t)
@@ -742,29 +765,27 @@ static int do_i2c_smbus_ioctl(unsigned int fd, unsigned int cmd,
 #define RTC_EPOCH_READ32       _IOR('p', 0x0d, compat_ulong_t)
 #define RTC_EPOCH_SET32                _IOW('p', 0x0e, compat_ulong_t)
 
-static int rtc_ioctl(unsigned fd, unsigned cmd, void __user *argp)
+static int rtc_ioctl(struct file *file,
+               unsigned cmd, void __user *argp)
 {
-       mm_segment_t oldfs = get_fs();
-       compat_ulong_t val32;
-       unsigned long kval;
+       unsigned long __user *valp = compat_alloc_user_space(sizeof(*valp));
        int ret;
 
+       if (valp == NULL)
+               return -EFAULT;
        switch (cmd) {
        case RTC_IRQP_READ32:
        case RTC_EPOCH_READ32:
-               set_fs(KERNEL_DS);
-               ret = sys_ioctl(fd, (cmd == RTC_IRQP_READ32) ?
+               ret = do_ioctl(file, (cmd == RTC_IRQP_READ32) ?
                                        RTC_IRQP_READ : RTC_EPOCH_READ,
-                                       (unsigned long)&kval);
-               set_fs(oldfs);
+                                       (unsigned long)valp);
                if (ret)
                        return ret;
-               val32 = kval;
-               return put_user(val32, (unsigned int __user *)argp);
+               return convert_in_user(valp, (unsigned int __user *)argp);
        case RTC_IRQP_SET32:
-               return sys_ioctl(fd, RTC_IRQP_SET, (unsigned long)argp);
+               return do_ioctl(file, RTC_IRQP_SET, (unsigned long)argp);
        case RTC_EPOCH_SET32:
-               return sys_ioctl(fd, RTC_EPOCH_SET, (unsigned long)argp);
+               return do_ioctl(file, RTC_EPOCH_SET, (unsigned long)argp);
        }
 
        return -ENOIOCTLCMD;
@@ -1436,53 +1457,53 @@ IGNORE_IOCTL(FBIOGCURSOR32)
  * a compat_ioctl operation in the place that handleÑ• the
  * ioctl for the native case.
  */
-static long do_ioctl_trans(int fd, unsigned int cmd,
+static long do_ioctl_trans(unsigned int cmd,
                 unsigned long arg, struct file *file)
 {
        void __user *argp = compat_ptr(arg);
 
        switch (cmd) {
        case PPPIOCGIDLE32:
-               return ppp_gidle(fd, cmd, argp);
+               return ppp_gidle(file, cmd, argp);
        case PPPIOCSCOMPRESS32:
-               return ppp_scompress(fd, cmd, argp);
+               return ppp_scompress(file, cmd, argp);
        case PPPIOCSPASS32:
        case PPPIOCSACTIVE32:
-               return ppp_sock_fprog_ioctl_trans(fd, cmd, argp);
+               return ppp_sock_fprog_ioctl_trans(file, cmd, argp);
 #ifdef CONFIG_BLOCK
        case SG_IO:
-               return sg_ioctl_trans(fd, cmd, argp);
+               return sg_ioctl_trans(file, cmd, argp);
        case SG_GET_REQUEST_TABLE:
-               return sg_grt_trans(fd, cmd, argp);
+               return sg_grt_trans(file, cmd, argp);
        case MTIOCGET32:
        case MTIOCPOS32:
-               return mt_ioctl_trans(fd, cmd, argp);
+               return mt_ioctl_trans(file, cmd, argp);
 #endif
        /* Serial */
        case TIOCGSERIAL:
        case TIOCSSERIAL:
-               return serial_struct_ioctl(fd, cmd, argp);
+               return serial_struct_ioctl(file, cmd, argp);
        /* i2c */
        case I2C_FUNCS:
-               return w_long(fd, cmd, argp);
+               return w_long(file, cmd, argp);
        case I2C_RDWR:
-               return do_i2c_rdwr_ioctl(fd, cmd, argp);
+               return do_i2c_rdwr_ioctl(file, cmd, argp);
        case I2C_SMBUS:
-               return do_i2c_smbus_ioctl(fd, cmd, argp);
+               return do_i2c_smbus_ioctl(file, cmd, argp);
        /* Not implemented in the native kernel */
        case RTC_IRQP_READ32:
        case RTC_IRQP_SET32:
        case RTC_EPOCH_READ32:
        case RTC_EPOCH_SET32:
-               return rtc_ioctl(fd, cmd, argp);
+               return rtc_ioctl(file, cmd, argp);
 
        /* dvb */
        case VIDEO_GET_EVENT:
-               return do_video_get_event(fd, cmd, argp);
+               return do_video_get_event(file, cmd, argp);
        case VIDEO_STILLPICTURE:
-               return do_video_stillpicture(fd, cmd, argp);
+               return do_video_stillpicture(file, cmd, argp);
        case VIDEO_SET_SPU_PALETTE:
-               return do_video_set_spu_palette(fd, cmd, argp);
+               return do_video_set_spu_palette(file, cmd, argp);
        }
 
        /*
@@ -1513,7 +1534,7 @@ static long do_ioctl_trans(int fd, unsigned int cmd,
        case NBD_SET_BLKSIZE:
        case NBD_SET_SIZE:
        case NBD_SET_SIZE_BLOCKS:
-               return do_vfs_ioctl(file, fd, cmd, arg);
+               return vfs_ioctl(file, cmd, arg);
        }
 
        return -ENOIOCTLCMD;
@@ -1602,7 +1623,7 @@ COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd,
        if (compat_ioctl_check_table(XFORM(cmd)))
                goto found_handler;
 
-       error = do_ioctl_trans(fd, cmd, arg, f.file);
+       error = do_ioctl_trans(cmd, arg, f.file);
        if (error == -ENOIOCTLCMD)
                error = -ENOTTY;
 
index ec5c8325b503d1a1602863769ae43c067d13a047..db6d692896088ebc9745d9c05c85309280885b38 100644 (file)
@@ -279,27 +279,33 @@ static int configfs_getlink(struct dentry *dentry, char * path)
 
 }
 
-static const char *configfs_follow_link(struct dentry *dentry, void **cookie)
+static const char *configfs_get_link(struct dentry *dentry,
+                                    struct inode *inode,
+                                    struct delayed_call *done)
 {
-       unsigned long page = get_zeroed_page(GFP_KERNEL);
+       char *body;
        int error;
 
-       if (!page)
+       if (!dentry)
+               return ERR_PTR(-ECHILD);
+
+       body = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!body)
                return ERR_PTR(-ENOMEM);
 
-       error = configfs_getlink(dentry, (char *)page);
+       error = configfs_getlink(dentry, body);
        if (!error) {
-               return *cookie = (void *)page;
+               set_delayed_call(done, kfree_link, body);
+               return body;
        }
 
-       free_page(page);
+       kfree(body);
        return ERR_PTR(error);
 }
 
 const struct inode_operations configfs_symlink_inode_operations = {
-       .follow_link = configfs_follow_link,
+       .get_link = configfs_get_link,
        .readlink = generic_readlink,
-       .put_link = free_page_put_link,
        .setattr = configfs_setattr,
 };
 
index 355c522f3585a5e3a7667225681383ff85b93a48..b862bc219cd7c7d269a7ba9e786559d1595315d7 100644 (file)
@@ -100,6 +100,7 @@ static struct inode *get_cramfs_inode(struct super_block *sb,
                break;
        case S_IFLNK:
                inode->i_op = &page_symlink_inode_operations;
+               inode_nohighmem(inode);
                inode->i_data.a_ops = &cramfs_aops;
                break;
        default:
index 5c33aeb0f68febdd03e6f478c7949fd847e9fdcd..d27f0909d9f61141b6f6073996ed56858f2249c7 100644 (file)
@@ -1734,7 +1734,7 @@ static unsigned d_flags_for_inode(struct inode *inode)
        }
 
        if (unlikely(!(inode->i_opflags & IOP_NOFOLLOW))) {
-               if (unlikely(inode->i_op->follow_link)) {
+               if (unlikely(inode->i_op->get_link)) {
                        add_flags = DCACHE_SYMLINK_TYPE;
                        goto type_determined;
                }
index 1c75a3a07f8f02a2ddd3b85e02c74866ff5b1f08..602e8441bc0fb6b094ec96dfb3273ff73b8b1506 100644 (file)
@@ -1175,6 +1175,7 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
                if (dio->flags & DIO_LOCKING)
                        mutex_unlock(&inode->i_mutex);
                kmem_cache_free(dio_cache, dio);
+               retval = 0;
                goto out;
        }
 
index e2e47ba5d313a5f2aca58589e08d2d3df969bed2..a4dddc61594cbdb7797b1a75cd50fae0ec3a6e77 100644 (file)
@@ -674,16 +674,24 @@ out:
        return rc ? ERR_PTR(rc) : buf;
 }
 
-static const char *ecryptfs_follow_link(struct dentry *dentry, void **cookie)
+static const char *ecryptfs_get_link(struct dentry *dentry,
+                                    struct inode *inode,
+                                    struct delayed_call *done)
 {
        size_t len;
-       char *buf = ecryptfs_readlink_lower(dentry, &len);
+       char *buf;
+
+       if (!dentry)
+               return ERR_PTR(-ECHILD);
+
+       buf = ecryptfs_readlink_lower(dentry, &len);
        if (IS_ERR(buf))
                return buf;
        fsstack_copy_attr_atime(d_inode(dentry),
                                d_inode(ecryptfs_dentry_to_lower(dentry)));
        buf[len] = '\0';
-       return *cookie = buf;
+       set_delayed_call(done, kfree_link, buf);
+       return buf;
 }
 
 /**
@@ -1095,8 +1103,7 @@ out:
 
 const struct inode_operations ecryptfs_symlink_iops = {
        .readlink = generic_readlink,
-       .follow_link = ecryptfs_follow_link,
-       .put_link = kfree_put_link,
+       .get_link = ecryptfs_get_link,
        .permission = ecryptfs_permission,
        .setattr = ecryptfs_setattr,
        .getattr = ecryptfs_getattr_link,
index 079d20306ee18990f09943c7eff4f9548cf9d761..cdf0872382afa3e4755d5276fa1588be03d272a1 100644 (file)
@@ -151,6 +151,7 @@ struct inode *efs_iget(struct super_block *super, unsigned long ino)
                        break;
                case S_IFLNK:
                        inode->i_op = &page_symlink_inode_operations;
+                       inode_nohighmem(inode);
                        inode->i_data.a_ops = &efs_symlink_aops;
                        break;
                case S_IFCHR:
index 75117d0dac2b174f5b231234b1543cecd95bdbfa..4870cc82deb014be3e28a5f55704ecedfb3b0c91 100644 (file)
@@ -13,7 +13,7 @@
 
 static int efs_symlink_readpage(struct file *file, struct page *page)
 {
-       char *link = kmap(page);
+       char *link = page_address(page);
        struct buffer_head * bh;
        struct inode * inode = page->mapping->host;
        efs_block_t size = inode->i_size;
@@ -39,12 +39,10 @@ static int efs_symlink_readpage(struct file *file, struct page *page)
        }
        link[size] = '\0';
        SetPageUptodate(page);
-       kunmap(page);
        unlock_page(page);
        return 0;
 fail:
        SetPageError(page);
-       kunmap(page);
        unlock_page(page);
        return err;
 }
index 73c64daa0f5517b4ff8271bd17e25740bb83d506..9eaf595aeaf8840cf74f0f02141411a9fed65c1e 100644 (file)
@@ -592,10 +592,7 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate)
                        }
                        unlock_page(page);
                }
-               if (PageDirty(page) || PageWriteback(page))
-                       *uptodate = true;
-               else
-                       *uptodate = PageUptodate(page);
+               *uptodate = PageUptodate(page);
                EXOFS_DBGMSG2("index=0x%lx uptodate=%d\n", index, *uptodate);
                return page;
        } else {
@@ -1227,6 +1224,7 @@ struct inode *exofs_iget(struct super_block *sb, unsigned long ino)
                        inode->i_link = (char *)oi->i_data;
                } else {
                        inode->i_op = &page_symlink_inode_operations;
+                       inode_nohighmem(inode);
                        inode->i_mapping->a_ops = &exofs_aops;
                }
        } else {
index 994e078da4bb746fd8c088f70efbfaa19a4665a3..c20d77df2679abb185e29a79f5ceab8349204d65 100644 (file)
@@ -111,6 +111,7 @@ static int exofs_symlink(struct inode *dir, struct dentry *dentry,
        if (l > sizeof(oi->i_data)) {
                /* slow symlink */
                inode->i_op = &page_symlink_inode_operations;
+               inode_nohighmem(inode);
                inode->i_mapping->a_ops = &exofs_aops;
                memset(oi->i_data, 0, sizeof(oi->i_data));
 
index 0aa9bf6e6e53e2d1ac14d26917d6afa1b6fae233..338eefda70c6fc4e2055c0165b590febf1295acb 100644 (file)
@@ -1420,6 +1420,7 @@ struct inode *ext2_iget (struct super_block *sb, unsigned long ino)
                                sizeof(ei->i_data) - 1);
                } else {
                        inode->i_op = &ext2_symlink_inode_operations;
+                       inode_nohighmem(inode);
                        if (test_opt(inode->i_sb, NOBH))
                                inode->i_mapping->a_ops = &ext2_nobh_aops;
                        else
index 3267a80dbbe26f4fbefb14c82fdb832d9169d6a8..7a2be8f7f3c37a69135cab528b1244e51c5fc2a2 100644 (file)
@@ -183,6 +183,7 @@ static int ext2_symlink (struct inode * dir, struct dentry * dentry,
        if (l > sizeof (EXT2_I(inode)->i_data)) {
                /* slow symlink */
                inode->i_op = &ext2_symlink_inode_operations;
+               inode_nohighmem(inode);
                if (test_opt(inode->i_sb, NOBH))
                        inode->i_mapping->a_ops = &ext2_nobh_aops;
                else
index ae17179f3810b2dd635c81203643a14f8f4c0c10..3495d8ae4b33b1e8dc5a1d9341fa7d6d9835e4c5 100644 (file)
@@ -22,8 +22,7 @@
 
 const struct inode_operations ext2_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = page_follow_link_light,
-       .put_link       = page_put_link,
+       .get_link       = page_get_link,
        .setattr        = ext2_setattr,
 #ifdef CONFIG_EXT2_FS_XATTR
        .setxattr       = generic_setxattr,
@@ -35,7 +34,7 @@ const struct inode_operations ext2_symlink_inode_operations = {
  
 const struct inode_operations ext2_fast_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = simple_follow_link,
+       .get_link       = simple_get_link,
        .setattr        = ext2_setattr,
 #ifdef CONFIG_EXT2_FS_XATTR
        .setxattr       = generic_setxattr,
index af06830bfc00c743369737551e7bceea3b61eede..1a0835073663ff3f1dad1f376328de5e2b1332ce 100644 (file)
@@ -389,7 +389,7 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex)
        struct ext4_crypto_ctx  *ctx;
        struct page             *ciphertext_page = NULL;
        struct bio              *bio;
-       ext4_lblk_t             lblk = ex->ee_block;
+       ext4_lblk_t             lblk = le32_to_cpu(ex->ee_block);
        ext4_fsblk_t            pblk = ext4_ext_pblock(ex);
        unsigned int            len = ext4_ext_get_actual_len(ex);
        int                     ret, err = 0;
index 750063f7a50c6cc2b9808318538762be67ce098d..cc7ca4e87144a540332213ce03b63e80e601f40e 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/seqlock.h>
 #include <linux/mutex.h>
 #include <linux/timer.h>
+#include <linux/version.h>
 #include <linux/wait.h>
 #include <linux/blockgroup_lock.h>
 #include <linux/percpu_counter.h>
@@ -727,19 +728,55 @@ struct move_extent {
        <= (EXT4_GOOD_OLD_INODE_SIZE +                  \
            (einode)->i_extra_isize))                   \
 
+/*
+ * We use an encoding that preserves the times for extra epoch "00":
+ *
+ * extra  msb of                         adjust for signed
+ * epoch  32-bit                         32-bit tv_sec to
+ * bits   time    decoded 64-bit tv_sec  64-bit tv_sec      valid time range
+ * 0 0    1    -0x80000000..-0x00000001  0x000000000 1901-12-13..1969-12-31
+ * 0 0    0    0x000000000..0x07fffffff  0x000000000 1970-01-01..2038-01-19
+ * 0 1    1    0x080000000..0x0ffffffff  0x100000000 2038-01-19..2106-02-07
+ * 0 1    0    0x100000000..0x17fffffff  0x100000000 2106-02-07..2174-02-25
+ * 1 0    1    0x180000000..0x1ffffffff  0x200000000 2174-02-25..2242-03-16
+ * 1 0    0    0x200000000..0x27fffffff  0x200000000 2242-03-16..2310-04-04
+ * 1 1    1    0x280000000..0x2ffffffff  0x300000000 2310-04-04..2378-04-22
+ * 1 1    0    0x300000000..0x37fffffff  0x300000000 2378-04-22..2446-05-10
+ *
+ * Note that previous versions of the kernel on 64-bit systems would
+ * incorrectly use extra epoch bits 1,1 for dates between 1901 and
+ * 1970.  e2fsck will correct this, assuming that it is run on the
+ * affected filesystem before 2242.
+ */
+
 static inline __le32 ext4_encode_extra_time(struct timespec *time)
 {
-       return cpu_to_le32((sizeof(time->tv_sec) > 4 ?
-                          (time->tv_sec >> 32) & EXT4_EPOCH_MASK : 0) |
-                          ((time->tv_nsec << EXT4_EPOCH_BITS) & EXT4_NSEC_MASK));
+       u32 extra = sizeof(time->tv_sec) > 4 ?
+               ((time->tv_sec - (s32)time->tv_sec) >> 32) & EXT4_EPOCH_MASK : 0;
+       return cpu_to_le32(extra | (time->tv_nsec << EXT4_EPOCH_BITS));
 }
 
 static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra)
 {
-       if (sizeof(time->tv_sec) > 4)
-              time->tv_sec |= (__u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK)
-                              << 32;
-       time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
+       if (unlikely(sizeof(time->tv_sec) > 4 &&
+                       (extra & cpu_to_le32(EXT4_EPOCH_MASK)))) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)
+               /* Handle legacy encoding of pre-1970 dates with epoch
+                * bits 1,1.  We assume that by kernel version 4.20,
+                * everyone will have run fsck over the affected
+                * filesystems to correct the problem.  (This
+                * backwards compatibility may be removed before this
+                * time, at the discretion of the ext4 developers.)
+                */
+               u64 extra_bits = le32_to_cpu(extra) & EXT4_EPOCH_MASK;
+               if (extra_bits == 3 && ((time->tv_sec) & 0x80000000) != 0)
+                       extra_bits = 0;
+               time->tv_sec += extra_bits << 32;
+#else
+               time->tv_sec += (u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK) << 32;
+#endif
+       }
+       time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
 }
 
 #define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode)                         \
index ea433a7f4bca21511ba84fbfbe52f71883680661..b3bd912df6bfaf475f9304eba7fb1b9ce6368e87 100644 (file)
@@ -4283,6 +4283,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
                        inode->i_op = &ext4_symlink_inode_operations;
                        ext4_set_aops(inode);
                }
+               inode_nohighmem(inode);
        } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
              S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
                inode->i_op = &ext4_special_inode_operations;
index a969ab39f3026187242dbea0881d5ebdb991d978..f27e0c2598c59edb5685c27310c2766d0860838d 100644 (file)
@@ -3132,6 +3132,7 @@ static int ext4_symlink(struct inode *dir,
        if ((disk_link.len > EXT4_N_BLOCKS * 4)) {
                if (!encryption_required)
                        inode->i_op = &ext4_symlink_inode_operations;
+               inode_nohighmem(inode);
                ext4_set_aops(inode);
                /*
                 * We cannot call page_symlink() with transaction started
index abe2401ce405669f0d315319f5275a9fc321c697..6f7ee30a89ce806ec0e4fbe27d7a0538ccd1f5c7 100644 (file)
 #include "xattr.h"
 
 #ifdef CONFIG_EXT4_FS_ENCRYPTION
-static const char *ext4_encrypted_follow_link(struct dentry *dentry, void **cookie)
+static const char *ext4_encrypted_get_link(struct dentry *dentry,
+                                          struct inode *inode,
+                                          struct delayed_call *done)
 {
        struct page *cpage = NULL;
        char *caddr, *paddr = NULL;
        struct ext4_str cstr, pstr;
-       struct inode *inode = d_inode(dentry);
        struct ext4_encrypted_symlink_data *sd;
        loff_t size = min_t(loff_t, i_size_read(inode), PAGE_SIZE - 1);
        int res;
        u32 plen, max_size = inode->i_sb->s_blocksize;
 
+       if (!dentry)
+               return ERR_PTR(-ECHILD);
+
        res = ext4_get_encryption_info(inode);
        if (res)
                return ERR_PTR(res);
@@ -45,14 +49,14 @@ static const char *ext4_encrypted_follow_link(struct dentry *dentry, void **cook
                cpage = read_mapping_page(inode->i_mapping, 0, NULL);
                if (IS_ERR(cpage))
                        return ERR_CAST(cpage);
-               caddr = kmap(cpage);
+               caddr = page_address(cpage);
                caddr[size] = 0;
        }
 
        /* Symlink is encrypted */
        sd = (struct ext4_encrypted_symlink_data *)caddr;
        cstr.name = sd->encrypted_path;
-       cstr.len  = le32_to_cpu(sd->len);
+       cstr.len  = le16_to_cpu(sd->len);
        if ((cstr.len +
             sizeof(struct ext4_encrypted_symlink_data) - 1) >
            max_size) {
@@ -75,24 +79,20 @@ static const char *ext4_encrypted_follow_link(struct dentry *dentry, void **cook
        /* Null-terminate the name */
        if (res <= plen)
                paddr[res] = '\0';
-       if (cpage) {
-               kunmap(cpage);
+       if (cpage)
                page_cache_release(cpage);
-       }
-       return *cookie = paddr;
+       set_delayed_call(done, kfree_link, paddr);
+       return paddr;
 errout:
-       if (cpage) {
-               kunmap(cpage);
+       if (cpage)
                page_cache_release(cpage);
-       }
        kfree(paddr);
        return ERR_PTR(res);
 }
 
 const struct inode_operations ext4_encrypted_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = ext4_encrypted_follow_link,
-       .put_link       = kfree_put_link,
+       .get_link       = ext4_encrypted_get_link,
        .setattr        = ext4_setattr,
        .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
@@ -103,8 +103,7 @@ const struct inode_operations ext4_encrypted_symlink_inode_operations = {
 
 const struct inode_operations ext4_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = page_follow_link_light,
-       .put_link       = page_put_link,
+       .get_link       = page_get_link,
        .setattr        = ext4_setattr,
        .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
@@ -114,7 +113,7 @@ const struct inode_operations ext4_symlink_inode_operations = {
 
 const struct inode_operations ext4_fast_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = simple_follow_link,
+       .get_link       = simple_get_link,
        .setattr        = ext4_setattr,
        .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
index 1b57c72f4a009aafc8c3510eac81dd9d8a5f9482..1420a3c614afb1a4c06e87471163acf01b3b98d8 100644 (file)
@@ -358,7 +358,7 @@ static int name##_open(struct inode *inode, struct file *file) \
        return single_open(file, ext4_seq_##name##_show, PDE_DATA(inode)); \
 } \
 \
-const struct file_operations ext4_seq_##name##_fops = { \
+static const struct file_operations ext4_seq_##name##_fops = { \
        .owner          = THIS_MODULE, \
        .open           = name##_open, \
        .read           = seq_read, \
index 97e20decacb4e17677fc3c43cfb5d45a6ab290bc..5528801a5baf3a13a75ffd16c831c1d7b1a650f4 100644 (file)
@@ -202,6 +202,7 @@ make_now:
                        inode->i_op = &f2fs_encrypted_symlink_inode_operations;
                else
                        inode->i_op = &f2fs_symlink_inode_operations;
+               inode_nohighmem(inode);
                inode->i_mapping->a_ops = &f2fs_dblock_aops;
        } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||
                        S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
index 2c32110f9fc082408b318cac2142602ab7888a9e..e7587fce1b8065bf80f35571d4a2c25b40b7c265 100644 (file)
@@ -315,12 +315,15 @@ fail:
        return err;
 }
 
-static const char *f2fs_follow_link(struct dentry *dentry, void **cookie)
+static const char *f2fs_get_link(struct dentry *dentry,
+                                struct inode *inode,
+                                struct delayed_call *done)
 {
-       const char *link = page_follow_link_light(dentry, cookie);
+       const char *link = page_get_link(dentry, inode, done);
        if (!IS_ERR(link) && !*link) {
                /* this is broken symlink case */
-               page_put_link(NULL, *cookie);
+               do_delayed_call(done);
+               clear_delayed_call(done);
                link = ERR_PTR(-ENOENT);
        }
        return link;
@@ -351,6 +354,7 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
                inode->i_op = &f2fs_encrypted_symlink_inode_operations;
        else
                inode->i_op = &f2fs_symlink_inode_operations;
+       inode_nohighmem(inode);
        inode->i_mapping->a_ops = &f2fs_dblock_aops;
 
        f2fs_lock_op(sbi);
@@ -923,18 +927,22 @@ static int f2fs_rename2(struct inode *old_dir, struct dentry *old_dentry,
 }
 
 #ifdef CONFIG_F2FS_FS_ENCRYPTION
-static const char *f2fs_encrypted_follow_link(struct dentry *dentry, void **cookie)
+static const char *f2fs_encrypted_get_link(struct dentry *dentry,
+                                          struct inode *inode,
+                                          struct delayed_call *done)
 {
        struct page *cpage = NULL;
        char *caddr, *paddr = NULL;
        struct f2fs_str cstr;
        struct f2fs_str pstr = FSTR_INIT(NULL, 0);
-       struct inode *inode = d_inode(dentry);
        struct f2fs_encrypted_symlink_data *sd;
        loff_t size = min_t(loff_t, i_size_read(inode), PAGE_SIZE - 1);
        u32 max_size = inode->i_sb->s_blocksize;
        int res;
 
+       if (!dentry)
+               return ERR_PTR(-ECHILD);
+
        res = f2fs_get_encryption_info(inode);
        if (res)
                return ERR_PTR(res);
@@ -942,7 +950,7 @@ static const char *f2fs_encrypted_follow_link(struct dentry *dentry, void **cook
        cpage = read_mapping_page(inode->i_mapping, 0, NULL);
        if (IS_ERR(cpage))
                return ERR_CAST(cpage);
-       caddr = kmap(cpage);
+       caddr = page_address(cpage);
        caddr[size] = 0;
 
        /* Symlink is encrypted */
@@ -982,21 +990,19 @@ static const char *f2fs_encrypted_follow_link(struct dentry *dentry, void **cook
        /* Null-terminate the name */
        paddr[res] = '\0';
 
-       kunmap(cpage);
        page_cache_release(cpage);
-       return *cookie = paddr;
+       set_delayed_call(done, kfree_link, paddr);
+       return paddr;
 errout:
        kfree(cstr.name);
        f2fs_fname_crypto_free_buffer(&pstr);
-       kunmap(cpage);
        page_cache_release(cpage);
        return ERR_PTR(res);
 }
 
 const struct inode_operations f2fs_encrypted_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = f2fs_encrypted_follow_link,
-       .put_link       = kfree_put_link,
+       .get_link       = f2fs_encrypted_get_link,
        .getattr        = f2fs_getattr,
        .setattr        = f2fs_setattr,
        .setxattr       = generic_setxattr,
@@ -1031,8 +1037,7 @@ const struct inode_operations f2fs_dir_inode_operations = {
 
 const struct inode_operations f2fs_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = f2fs_follow_link,
-       .put_link       = page_put_link,
+       .get_link       = f2fs_get_link,
        .getattr        = f2fs_getattr,
        .setattr        = f2fs_setattr,
 #ifdef CONFIG_F2FS_FS_XATTR
index ef73ed674a27162917845b0507269bdf86b273da..3e2ccade61edb4e4a9a7d27d9229d5ed37175dbc 100644 (file)
@@ -326,6 +326,7 @@ vxfs_iget(struct super_block *sbp, ino_t ino)
        } else if (S_ISLNK(ip->i_mode)) {
                if (!VXFS_ISIMMED(vip)) {
                        ip->i_op = &page_symlink_inode_operations;
+                       inode_nohighmem(ip);
                        ip->i_mapping->a_ops = &vxfs_aops;
                } else {
                        ip->i_op = &simple_symlink_inode_operations;
index eae2c11268bcb484075cfd08482beeb172dd66bc..8e3ee1936c7e38ba381b33c26b2f1847422a613f 100644 (file)
@@ -549,6 +549,8 @@ static int cuse_channel_release(struct inode *inode, struct file *file)
                unregister_chrdev_region(cc->cdev->dev, 1);
                cdev_del(cc->cdev);
        }
+       /* Base reference is now owned by "fud" */
+       fuse_conn_put(&cc->fc);
 
        rc = fuse_dev_release(inode, file);     /* puts the base reference */
 
index 5e2e08712d3ba614a46687d5688fc2f01cd835be..712601f299b8a1436d69f0a31362ab57032f24b7 100644 (file)
@@ -1365,15 +1365,19 @@ static int fuse_readdir(struct file *file, struct dir_context *ctx)
        return err;
 }
 
-static const char *fuse_follow_link(struct dentry *dentry, void **cookie)
+static const char *fuse_get_link(struct dentry *dentry,
+                                struct inode *inode,
+                                struct delayed_call *done)
 {
-       struct inode *inode = d_inode(dentry);
        struct fuse_conn *fc = get_fuse_conn(inode);
        FUSE_ARGS(args);
        char *link;
        ssize_t ret;
 
-       link = (char *) __get_free_page(GFP_KERNEL);
+       if (!dentry)
+               return ERR_PTR(-ECHILD);
+
+       link = kmalloc(PAGE_SIZE, GFP_KERNEL);
        if (!link)
                return ERR_PTR(-ENOMEM);
 
@@ -1385,11 +1389,11 @@ static const char *fuse_follow_link(struct dentry *dentry, void **cookie)
        args.out.args[0].value = link;
        ret = fuse_simple_request(fc, &args);
        if (ret < 0) {
-               free_page((unsigned long) link);
+               kfree(link);
                link = ERR_PTR(ret);
        } else {
                link[ret] = '\0';
-               *cookie = link;
+               set_delayed_call(done, kfree_link, link);
        }
        fuse_invalidate_atime(inode);
        return link;
@@ -1909,8 +1913,7 @@ static const struct inode_operations fuse_common_inode_operations = {
 
 static const struct inode_operations fuse_symlink_inode_operations = {
        .setattr        = fuse_setattr,
-       .follow_link    = fuse_follow_link,
-       .put_link       = free_page_put_link,
+       .get_link       = fuse_get_link,
        .readlink       = generic_readlink,
        .getattr        = fuse_getattr,
        .setxattr       = fuse_setxattr,
index e0faf8f2c868a26b80331ef78c89db85091715ea..570ca4053c805eb76acd76a44161f8349a9a6325 100644 (file)
@@ -1049,6 +1049,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req,
                tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes);
                flush_dcache_page(page);
 
+               iov_iter_advance(ii, tmp);
                if (!tmp) {
                        unlock_page(page);
                        page_cache_release(page);
@@ -1061,7 +1062,6 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req,
                req->page_descs[req->num_pages].length = tmp;
                req->num_pages++;
 
-               iov_iter_advance(ii, tmp);
                count += tmp;
                pos += tmp;
                offset += tmp;
index 063fdfcf82758a0c77f4cc44fe7b1f873b3cbb21..1bae189f32453c5e1bb46c11547768974c49c9ba 100644 (file)
@@ -1712,24 +1712,30 @@ static int gfs2_rename2(struct inode *odir, struct dentry *odentry,
 }
 
 /**
- * gfs2_follow_link - Follow a symbolic link
+ * gfs2_get_link - Follow a symbolic link
  * @dentry: The dentry of the link
- * @nd: Data that we pass to vfs_follow_link()
+ * @inode: The inode of the link
+ * @done: destructor for return value
  *
  * This can handle symlinks of any size.
  *
  * Returns: 0 on success or error code
  */
 
-static const char *gfs2_follow_link(struct dentry *dentry, void **cookie)
+static const char *gfs2_get_link(struct dentry *dentry,
+                                struct inode *inode,
+                                struct delayed_call *done)
 {
-       struct gfs2_inode *ip = GFS2_I(d_inode(dentry));
+       struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder i_gh;
        struct buffer_head *dibh;
        unsigned int size;
        char *buf;
        int error;
 
+       if (!dentry)
+               return ERR_PTR(-ECHILD);
+
        gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh);
        error = gfs2_glock_nq(&i_gh);
        if (error) {
@@ -1759,7 +1765,7 @@ static const char *gfs2_follow_link(struct dentry *dentry, void **cookie)
 out:
        gfs2_glock_dq_uninit(&i_gh);
        if (!IS_ERR(buf))
-               *cookie = buf;
+               set_delayed_call(done, kfree_link, buf);
        return buf;
 }
 
@@ -2132,8 +2138,7 @@ const struct inode_operations gfs2_dir_iops = {
 
 const struct inode_operations gfs2_symlink_iops = {
        .readlink = generic_readlink,
-       .follow_link = gfs2_follow_link,
-       .put_link = kfree_put_link,
+       .get_link = gfs2_get_link,
        .permission = gfs2_permission,
        .setattr = gfs2_setattr,
        .getattr = gfs2_getattr,
index 6dd107d7421ec05368845846d6a9cd9f558e9d23..19b33f8151f1ab2cb0957b7e5772ff1206659aad 100644 (file)
@@ -403,6 +403,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, umode_t mode)
        } else if (S_ISLNK(inode->i_mode)) {
                sbi->file_count++;
                inode->i_op = &page_symlink_inode_operations;
+               inode_nohighmem(inode);
                inode->i_mapping->a_ops = &hfsplus_aops;
                hip->clump_blocks = 1;
        } else
@@ -526,6 +527,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
                        inode->i_mapping->a_ops = &hfsplus_aops;
                } else if (S_ISLNK(inode->i_mode)) {
                        inode->i_op = &page_symlink_inode_operations;
+                       inode_nohighmem(inode);
                        inode->i_mapping->a_ops = &hfsplus_aops;
                } else {
                        init_special_inode(inode, inode->i_mode,
index 2ac99db3750ef7b2d2bf3e9ea9e90e69320a0d83..7db524cc85b6bf12358ce2ea1ea7df998b523be0 100644 (file)
@@ -892,9 +892,14 @@ static const struct inode_operations hostfs_dir_iops = {
        .setattr        = hostfs_setattr,
 };
 
-static const char *hostfs_follow_link(struct dentry *dentry, void **cookie)
+static const char *hostfs_get_link(struct dentry *dentry,
+                                  struct inode *inode,
+                                  struct delayed_call *done)
 {
-       char *link = __getname();
+       char *link;
+       if (!dentry)
+               return ERR_PTR(-ECHILD);
+       link = kmalloc(PATH_MAX, GFP_KERNEL);
        if (link) {
                char *path = dentry_name(dentry);
                int err = -ENOMEM;
@@ -905,25 +910,20 @@ static const char *hostfs_follow_link(struct dentry *dentry, void **cookie)
                        __putname(path);
                }
                if (err < 0) {
-                       __putname(link);
+                       kfree(link);
                        return ERR_PTR(err);
                }
        } else {
                return ERR_PTR(-ENOMEM);
        }
 
-       return *cookie = link;
-}
-
-static void hostfs_put_link(struct inode *unused, void *cookie)
-{
-       __putname(cookie);
+       set_delayed_call(done, kfree_link, link);
+       return link;
 }
 
 static const struct inode_operations hostfs_link_iops = {
        .readlink       = generic_readlink,
-       .follow_link    = hostfs_follow_link,
-       .put_link       = hostfs_put_link,
+       .get_link       = hostfs_get_link,
 };
 
 static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent)
index 933c73780813198b8953376eaa1e595d786e36e1..1f3c6d76200bea68aa7d879955f0351b74b9cdc0 100644 (file)
@@ -77,6 +77,7 @@ void hpfs_read_inode(struct inode *i)
                        kfree(ea);
                        i->i_mode = S_IFLNK | 0777;
                        i->i_op = &page_symlink_inode_operations;
+                       inode_nohighmem(i);
                        i->i_data.a_ops = &hpfs_symlink_aops;
                        set_nlink(i, 1);
                        i->i_size = ea_size;
index ae4d5a1fa4c9b7f75ce188d8ec80e69d0a820892..506765afa1a3135d1ff9bccc48f06634439fa69e 100644 (file)
@@ -332,6 +332,7 @@ static int hpfs_symlink(struct inode *dir, struct dentry *dentry, const char *sy
        result->i_blocks = 1;
        set_nlink(result, 1);
        result->i_size = strlen(symlink);
+       inode_nohighmem(result);
        result->i_op = &page_symlink_inode_operations;
        result->i_data.a_ops = &hpfs_symlink_aops;
 
@@ -500,7 +501,7 @@ out:
 
 static int hpfs_symlink_readpage(struct file *file, struct page *page)
 {
-       char *link = kmap(page);
+       char *link = page_address(page);
        struct inode *i = page->mapping->host;
        struct fnode *fnode;
        struct buffer_head *bh;
@@ -516,14 +517,12 @@ static int hpfs_symlink_readpage(struct file *file, struct page *page)
                goto fail;
        hpfs_unlock(i->i_sb);
        SetPageUptodate(page);
-       kunmap(page);
        unlock_page(page);
        return 0;
 
 fail:
        hpfs_unlock(i->i_sb);
        SetPageError(page);
-       kunmap(page);
        unlock_page(page);
        return err;
 }
index de4bdfac0cec36f7f3e1d5cee94ec4aecef3e311..d8f51ee8126b3282156721d2d2639e24d3aa536e 100644 (file)
@@ -760,6 +760,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb,
                        break;
                case S_IFLNK:
                        inode->i_op = &page_symlink_inode_operations;
+                       inode_nohighmem(inode);
                        break;
                }
                lockdep_annotate_inode_mutex_key(inode);
index 1be5f9003eb38852f68957fcd287cdd5b820b310..5bb85a064ce7fade86383db89c252fe920032279 100644 (file)
@@ -2028,3 +2028,9 @@ void inode_set_flags(struct inode *inode, unsigned int flags,
                                  new_flags) != old_flags));
 }
 EXPORT_SYMBOL(inode_set_flags);
+
+void inode_nohighmem(struct inode *inode)
+{
+       mapping_set_gfp_mask(inode->i_mapping, GFP_USER);
+}
+EXPORT_SYMBOL(inode_nohighmem);
index 71859c4d0b41b820dfe22bca4d30d8863ad86df7..e38c08ca437dcdeed706b1cb0d043fd99d53600c 100644 (file)
@@ -151,3 +151,10 @@ extern void mnt_pin_kill(struct mount *m);
  * fs/nsfs.c
  */
 extern struct dentry_operations ns_dentry_operations;
+
+/*
+ * fs/ioctl.c
+ */
+extern int do_vfs_ioctl(struct file *file, unsigned int fd, unsigned int cmd,
+                   unsigned long arg);
+extern long vfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
index 5d01d2638ca5482cc4edb2144be7ba3fc5f16aa4..41c352e8119381dc646e94e89c18becd40206ec8 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/writeback.h>
 #include <linux/buffer_head.h>
 #include <linux/falloc.h>
+#include "internal.h"
 
 #include <asm/ioctls.h>
 
@@ -32,8 +33,7 @@
  *
  * Returns 0 on success, -errno on error.
  */
-static long vfs_ioctl(struct file *filp, unsigned int cmd,
-                     unsigned long arg)
+long vfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
        int error = -ENOTTY;
 
index d67a16f2a45df8fcce56b9ff3ec56f334d951c9c..61abdc4920dab0056e998682f01038ef0a17f178 100644 (file)
@@ -1417,6 +1417,7 @@ static int isofs_read_inode(struct inode *inode, int relocated)
                inode->i_fop = &isofs_dir_operations;
        } else if (S_ISLNK(inode->i_mode)) {
                inode->i_op = &page_symlink_inode_operations;
+               inode_nohighmem(inode);
                inode->i_data.a_ops = &isofs_symlink_aops;
        } else
                /* XXX - parse_rock_ridge_inode() had already set i_rdev. */
index 735d7522a3a911f19af593d6b5f7d366d6cf448d..5384ceb35b1cc829442d6aa440db19c553a6eed8 100644 (file)
@@ -687,7 +687,7 @@ static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
        struct inode *inode = page->mapping->host;
        struct iso_inode_info *ei = ISOFS_I(inode);
        struct isofs_sb_info *sbi = ISOFS_SB(inode->i_sb);
-       char *link = kmap(page);
+       char *link = page_address(page);
        unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
        struct buffer_head *bh;
        char *rpnt = link;
@@ -774,7 +774,6 @@ repeat:
        brelse(bh);
        *rpnt = '\0';
        SetPageUptodate(page);
-       kunmap(page);
        unlock_page(page);
        return 0;
 
@@ -791,7 +790,6 @@ fail:
        brelse(bh);
 error:
        SetPageError(page);
-       kunmap(page);
        unlock_page(page);
        return -EIO;
 }
index 89463eee67914643a02ce711463e62fac0b83c8d..ca181e81c765518d4a599025c914adbac626e739 100644 (file)
@@ -1009,7 +1009,8 @@ out:
 }
 
 /* Fast check whether buffer is already attached to the required transaction */
-static bool jbd2_write_access_granted(handle_t *handle, struct buffer_head *bh)
+static bool jbd2_write_access_granted(handle_t *handle, struct buffer_head *bh,
+                                                       bool undo)
 {
        struct journal_head *jh;
        bool ret = false;
@@ -1036,6 +1037,9 @@ static bool jbd2_write_access_granted(handle_t *handle, struct buffer_head *bh)
        jh = READ_ONCE(bh->b_private);
        if (!jh)
                goto out;
+       /* For undo access buffer must have data copied */
+       if (undo && !jh->b_committed_data)
+               goto out;
        if (jh->b_transaction != handle->h_transaction &&
            jh->b_next_transaction != handle->h_transaction)
                goto out;
@@ -1073,7 +1077,7 @@ int jbd2_journal_get_write_access(handle_t *handle, struct buffer_head *bh)
        struct journal_head *jh;
        int rc;
 
-       if (jbd2_write_access_granted(handle, bh))
+       if (jbd2_write_access_granted(handle, bh, false))
                return 0;
 
        jh = jbd2_journal_add_journal_head(bh);
@@ -1210,7 +1214,7 @@ int jbd2_journal_get_undo_access(handle_t *handle, struct buffer_head *bh)
        char *committed_data = NULL;
 
        JBUFFER_TRACE(jh, "entry");
-       if (jbd2_write_access_granted(handle, bh))
+       if (jbd2_write_access_granted(handle, bh, true))
                return 0;
 
        jh = jbd2_journal_add_journal_head(bh);
@@ -2152,6 +2156,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh,
 
                if (!buffer_dirty(bh)) {
                        /* bdflush has written it.  We can drop it now */
+                       __jbd2_journal_remove_checkpoint(jh);
                        goto zap_buffer;
                }
 
@@ -2181,6 +2186,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh,
                                /* The orphan record's transaction has
                                 * committed.  We can cleanse this buffer */
                                clear_buffer_jbddirty(bh);
+                               __jbd2_journal_remove_checkpoint(jh);
                                goto zap_buffer;
                        }
                }
index 8ce2f240125b39803b4ebf2d681b6a95d40c33f5..2cabd649d4fb69dbdbd22aeb40d19f605f605f20 100644 (file)
@@ -14,7 +14,7 @@
 const struct inode_operations jffs2_symlink_inode_operations =
 {
        .readlink =     generic_readlink,
-       .follow_link =  simple_follow_link,
+       .get_link =     simple_get_link,
        .setattr =      jffs2_setattr,
        .setxattr =     jffs2_setxattr,
        .getxattr =     jffs2_getxattr,
index 41aa3ca6a6a4995104d12f38cc5945ebb63a0f7d..9d9bae63ae2a2d44b36c4b1bcd53adae2158e896 100644 (file)
@@ -60,6 +60,7 @@ struct inode *jfs_iget(struct super_block *sb, unsigned long ino)
        } else if (S_ISLNK(inode->i_mode)) {
                if (inode->i_size >= IDATASIZE) {
                        inode->i_op = &page_symlink_inode_operations;
+                       inode_nohighmem(inode);
                        inode->i_mapping->a_ops = &jfs_aops;
                } else {
                        inode->i_op = &jfs_fast_symlink_inode_operations;
index 9d7551f5c32a9ffb9a166f588e5f2211d62d0249..701f89370de7afb7d9a7402f1cbe4fe0d42b19fa 100644 (file)
@@ -983,6 +983,7 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
                jfs_info("jfs_symlink: allocate extent ip:0x%p", ip);
 
                ip->i_op = &jfs_symlink_inode_operations;
+               inode_nohighmem(ip);
                ip->i_mapping->a_ops = &jfs_aops;
 
                /*
index 5929e2363cb85eddc0d54bf3a04754383cb395db..f8db4fde0b0b65502ce89887efaec7b40c4d8a6e 100644 (file)
@@ -23,7 +23,7 @@
 
 const struct inode_operations jfs_fast_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = simple_follow_link,
+       .get_link       = simple_get_link,
        .setattr        = jfs_setattr,
        .setxattr       = jfs_setxattr,
        .getxattr       = jfs_getxattr,
@@ -33,8 +33,7 @@ const struct inode_operations jfs_fast_symlink_inode_operations = {
 
 const struct inode_operations jfs_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = page_follow_link_light,
-       .put_link       = page_put_link,
+       .get_link       = page_get_link,
        .setattr        = jfs_setattr,
        .setxattr       = jfs_setxattr,
        .getxattr       = jfs_getxattr,
index db272528ab5bb01c192b5502650f29e0784663ce..117b8b3416f9e761dacf36e8a3e3ff1e84f9e29b 100644 (file)
@@ -112,18 +112,25 @@ static int kernfs_getlink(struct dentry *dentry, char *path)
        return error;
 }
 
-static const char *kernfs_iop_follow_link(struct dentry *dentry, void **cookie)
+static const char *kernfs_iop_get_link(struct dentry *dentry,
+                                      struct inode *inode,
+                                      struct delayed_call *done)
 {
-       int error = -ENOMEM;
-       unsigned long page = get_zeroed_page(GFP_KERNEL);
-       if (!page)
+       char *body;
+       int error;
+
+       if (!dentry)
+               return ERR_PTR(-ECHILD);
+       body = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!body)
                return ERR_PTR(-ENOMEM);
-       error = kernfs_getlink(dentry, (char *)page);
+       error = kernfs_getlink(dentry, body);
        if (unlikely(error < 0)) {
-               free_page((unsigned long)page);
+               kfree(body);
                return ERR_PTR(error);
        }
-       return *cookie = (char *)page;
+       set_delayed_call(done, kfree_link, body);
+       return body;
 }
 
 const struct inode_operations kernfs_symlink_iops = {
@@ -132,8 +139,7 @@ const struct inode_operations kernfs_symlink_iops = {
        .getxattr       = kernfs_iop_getxattr,
        .listxattr      = kernfs_iop_listxattr,
        .readlink       = generic_readlink,
-       .follow_link    = kernfs_iop_follow_link,
-       .put_link       = free_page_put_link,
+       .get_link       = kernfs_iop_get_link,
        .setattr        = kernfs_iop_setattr,
        .getattr        = kernfs_iop_getattr,
        .permission     = kernfs_iop_permission,
index c7cbfb092e9467db1795145816faa91e1eda731f..01491299f348c965adc27cbcd70340ab2d980946 100644 (file)
@@ -1019,17 +1019,12 @@ int noop_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 }
 EXPORT_SYMBOL(noop_fsync);
 
-void kfree_put_link(struct inode *unused, void *cookie)
+/* Because kfree isn't assignment-compatible with void(void*) ;-/ */
+void kfree_link(void *p)
 {
-       kfree(cookie);
+       kfree(p);
 }
-EXPORT_SYMBOL(kfree_put_link);
-
-void free_page_put_link(struct inode *unused, void *cookie)
-{
-       free_page((unsigned long) cookie);
-}
-EXPORT_SYMBOL(free_page_put_link);
+EXPORT_SYMBOL(kfree_link);
 
 /*
  * nop .set_page_dirty method so that people can use .page_mkwrite on
@@ -1092,14 +1087,15 @@ simple_nosetlease(struct file *filp, long arg, struct file_lock **flp,
 }
 EXPORT_SYMBOL(simple_nosetlease);
 
-const char *simple_follow_link(struct dentry *dentry, void **cookie)
+const char *simple_get_link(struct dentry *dentry, struct inode *inode,
+                           struct delayed_call *done)
 {
-       return d_inode(dentry)->i_link;
+       return inode->i_link;
 }
-EXPORT_SYMBOL(simple_follow_link);
+EXPORT_SYMBOL(simple_get_link);
 
 const struct inode_operations simple_symlink_inode_operations = {
-       .follow_link = simple_follow_link,
+       .get_link = simple_get_link,
        .readlink = generic_readlink
 };
 EXPORT_SYMBOL(simple_symlink_inode_operations);
index f9b45d46d4c483ea0be1ceca4c35b9b3075b56b9..542468e9bfb492f8333221a80bcfbcc4b01aa39a 100644 (file)
@@ -528,7 +528,8 @@ static int logfs_symlink(struct inode *dir, struct dentry *dentry,
        if (IS_ERR(inode))
                return PTR_ERR(inode);
 
-       inode->i_op = &logfs_symlink_iops;
+       inode->i_op = &page_symlink_inode_operations;
+       inode_nohighmem(inode);
        inode->i_mapping->a_ops = &logfs_reg_aops;
 
        return __logfs_create(dir, dentry, inode, target, destlen);
@@ -776,12 +777,6 @@ fail:
        return -EIO;
 }
 
-const struct inode_operations logfs_symlink_iops = {
-       .readlink       = generic_readlink,
-       .follow_link    = page_follow_link_light,
-       .put_link       = page_put_link,
-};
-
 const struct inode_operations logfs_dir_iops = {
        .create         = logfs_create,
        .link           = logfs_link,
index af49e2d6941a7c2f8120ee3ca99095e0bb2ea767..0fce46d62b9c20491a9fb248f55a39b2273def74 100644 (file)
@@ -64,7 +64,8 @@ static void logfs_inode_setops(struct inode *inode)
                inode->i_mapping->a_ops = &logfs_reg_aops;
                break;
        case S_IFLNK:
-               inode->i_op = &logfs_symlink_iops;
+               inode->i_op = &page_symlink_inode_operations;
+               inode_nohighmem(inode);
                inode->i_mapping->a_ops = &logfs_reg_aops;
                break;
        case S_IFSOCK:  /* fall through */
index 5f09376094651c76c7ded9f52535fe1a1351ed6b..209a26d84c3835eda1ae30638e5edc2d3896cc49 100644 (file)
@@ -495,7 +495,6 @@ static inline int logfs_get_sb_mtd(struct logfs_super *s, int mtdnr)
 #endif
 
 /* dir.c */
-extern const struct inode_operations logfs_symlink_iops;
 extern const struct inode_operations logfs_dir_iops;
 extern const struct file_operations logfs_dir_fops;
 int logfs_replay_journal(struct super_block *sb);
index 086cd0a61e8015e60ccebcb99464ab23e58bb266..cb1789ca1ee675d1d101fb272ec05c28557b0186 100644 (file)
@@ -435,8 +435,7 @@ static const struct address_space_operations minix_aops = {
 
 static const struct inode_operations minix_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = page_follow_link_light,
-       .put_link       = page_put_link,
+       .get_link       = page_get_link,
        .getattr        = minix_getattr,
 };
 
@@ -452,6 +451,7 @@ void minix_set_inode(struct inode *inode, dev_t rdev)
                inode->i_mapping->a_ops = &minix_aops;
        } else if (S_ISLNK(inode->i_mode)) {
                inode->i_op = &minix_symlink_inode_operations;
+               inode_nohighmem(inode);
                inode->i_mapping->a_ops = &minix_aops;
        } else
                init_special_inode(inode, inode->i_mode, rdev);
index 0c3974cd3ecd55670ccab51c596b0b141cbdd721..3c909aebef70f8a8a091960bd3ba434a15e2f829 100644 (file)
@@ -505,13 +505,13 @@ struct nameidata {
        int             total_link_count;
        struct saved {
                struct path link;
-               void *cookie;
+               struct delayed_call done;
                const char *name;
-               struct inode *inode;
                unsigned seq;
        } *stack, internal[EMBEDDED_LEVELS];
        struct filename *name;
        struct nameidata *saved;
+       struct inode    *link_inode;
        unsigned        root_seq;
        int             dfd;
 };
@@ -592,11 +592,8 @@ static void drop_links(struct nameidata *nd)
        int i = nd->depth;
        while (i--) {
                struct saved *last = nd->stack + i;
-               struct inode *inode = last->inode;
-               if (last->cookie && inode->i_op->put_link) {
-                       inode->i_op->put_link(inode, last->cookie);
-                       last->cookie = NULL;
-               }
+               do_delayed_call(&last->done);
+               clear_delayed_call(&last->done);
        }
 }
 
@@ -842,7 +839,7 @@ static inline void path_to_nameidata(const struct path *path,
 }
 
 /*
- * Helper to directly jump to a known parsed path from ->follow_link,
+ * Helper to directly jump to a known parsed path from ->get_link,
  * caller must have taken a reference to path beforehand.
  */
 void nd_jump_link(struct path *path)
@@ -858,9 +855,7 @@ void nd_jump_link(struct path *path)
 static inline void put_link(struct nameidata *nd)
 {
        struct saved *last = nd->stack + --nd->depth;
-       struct inode *inode = last->inode;
-       if (last->cookie && inode->i_op->put_link)
-               inode->i_op->put_link(inode, last->cookie);
+       do_delayed_call(&last->done);
        if (!(nd->flags & LOOKUP_RCU))
                path_put(&last->link);
 }
@@ -892,7 +887,7 @@ static inline int may_follow_link(struct nameidata *nd)
                return 0;
 
        /* Allowed if owner and follower match. */
-       inode = nd->stack[0].inode;
+       inode = nd->link_inode;
        if (uid_eq(current_cred()->fsuid, inode->i_uid))
                return 0;
 
@@ -983,7 +978,7 @@ const char *get_link(struct nameidata *nd)
 {
        struct saved *last = nd->stack + nd->depth - 1;
        struct dentry *dentry = last->link.dentry;
-       struct inode *inode = last->inode;
+       struct inode *inode = nd->link_inode;
        int error;
        const char *res;
 
@@ -1004,15 +999,21 @@ const char *get_link(struct nameidata *nd)
        nd->last_type = LAST_BIND;
        res = inode->i_link;
        if (!res) {
+               const char * (*get)(struct dentry *, struct inode *,
+                               struct delayed_call *);
+               get = inode->i_op->get_link;
                if (nd->flags & LOOKUP_RCU) {
-                       if (unlikely(unlazy_walk(nd, NULL, 0)))
-                               return ERR_PTR(-ECHILD);
+                       res = get(NULL, inode, &last->done);
+                       if (res == ERR_PTR(-ECHILD)) {
+                               if (unlikely(unlazy_walk(nd, NULL, 0)))
+                                       return ERR_PTR(-ECHILD);
+                               res = get(dentry, inode, &last->done);
+                       }
+               } else {
+                       res = get(dentry, inode, &last->done);
                }
-               res = inode->i_op->follow_link(dentry, &last->cookie);
-               if (IS_ERR_OR_NULL(res)) {
-                       last->cookie = NULL;
+               if (IS_ERR_OR_NULL(res))
                        return res;
-               }
        }
        if (*res == '/') {
                if (nd->flags & LOOKUP_RCU) {
@@ -1691,8 +1692,8 @@ static int pick_link(struct nameidata *nd, struct path *link,
 
        last = nd->stack + nd->depth++;
        last->link = *link;
-       last->cookie = NULL;
-       last->inode = inode;
+       clear_delayed_call(&last->done);
+       nd->link_inode = inode;
        last->seq = seq;
        return 1;
 }
@@ -4495,72 +4496,73 @@ EXPORT_SYMBOL(readlink_copy);
 
 /*
  * A helper for ->readlink().  This should be used *ONLY* for symlinks that
- * have ->follow_link() touching nd only in nd_set_link().  Using (or not
- * using) it for any given inode is up to filesystem.
+ * have ->get_link() not calling nd_jump_link().  Using (or not using) it
+ * for any given inode is up to filesystem.
  */
 int generic_readlink(struct dentry *dentry, char __user *buffer, int buflen)
 {
-       void *cookie;
+       DEFINE_DELAYED_CALL(done);
        struct inode *inode = d_inode(dentry);
        const char *link = inode->i_link;
        int res;
 
        if (!link) {
-               link = inode->i_op->follow_link(dentry, &cookie);
+               link = inode->i_op->get_link(dentry, inode, &done);
                if (IS_ERR(link))
                        return PTR_ERR(link);
        }
        res = readlink_copy(buffer, buflen, link);
-       if (inode->i_op->put_link)
-               inode->i_op->put_link(inode, cookie);
+       do_delayed_call(&done);
        return res;
 }
 EXPORT_SYMBOL(generic_readlink);
 
 /* get the link contents into pagecache */
-static char *page_getlink(struct dentry * dentry, struct page **ppage)
+const char *page_get_link(struct dentry *dentry, struct inode *inode,
+                         struct delayed_call *callback)
 {
        char *kaddr;
        struct page *page;
-       struct address_space *mapping = dentry->d_inode->i_mapping;
-       page = read_mapping_page(mapping, 0, NULL);
-       if (IS_ERR(page))
-               return (char*)page;
-       *ppage = page;
-       kaddr = kmap(page);
-       nd_terminate_link(kaddr, dentry->d_inode->i_size, PAGE_SIZE - 1);
+       struct address_space *mapping = inode->i_mapping;
+
+       if (!dentry) {
+               page = find_get_page(mapping, 0);
+               if (!page)
+                       return ERR_PTR(-ECHILD);
+               if (!PageUptodate(page)) {
+                       put_page(page);
+                       return ERR_PTR(-ECHILD);
+               }
+       } else {
+               page = read_mapping_page(mapping, 0, NULL);
+               if (IS_ERR(page))
+                       return (char*)page;
+       }
+       set_delayed_call(callback, page_put_link, page);
+       BUG_ON(mapping_gfp_mask(mapping) & __GFP_HIGHMEM);
+       kaddr = page_address(page);
+       nd_terminate_link(kaddr, inode->i_size, PAGE_SIZE - 1);
        return kaddr;
 }
 
-int page_readlink(struct dentry *dentry, char __user *buffer, int buflen)
-{
-       struct page *page = NULL;
-       int res = readlink_copy(buffer, buflen, page_getlink(dentry, &page));
-       if (page) {
-               kunmap(page);
-               page_cache_release(page);
-       }
-       return res;
-}
-EXPORT_SYMBOL(page_readlink);
+EXPORT_SYMBOL(page_get_link);
 
-const char *page_follow_link_light(struct dentry *dentry, void **cookie)
+void page_put_link(void *arg)
 {
-       struct page *page = NULL;
-       char *res = page_getlink(dentry, &page);
-       if (!IS_ERR(res))
-               *cookie = page;
-       return res;
+       put_page(arg);
 }
-EXPORT_SYMBOL(page_follow_link_light);
+EXPORT_SYMBOL(page_put_link);
 
-void page_put_link(struct inode *unused, void *cookie)
+int page_readlink(struct dentry *dentry, char __user *buffer, int buflen)
 {
-       struct page *page = cookie;
-       kunmap(page);
-       page_cache_release(page);
+       DEFINE_DELAYED_CALL(done);
+       int res = readlink_copy(buffer, buflen,
+                               page_get_link(dentry, d_inode(dentry),
+                                             &done));
+       do_delayed_call(&done);
+       return res;
 }
-EXPORT_SYMBOL(page_put_link);
+EXPORT_SYMBOL(page_readlink);
 
 /*
  * The nofs argument instructs pagecache_write_begin to pass AOP_FLAG_NOFS
@@ -4571,7 +4573,6 @@ int __page_symlink(struct inode *inode, const char *symname, int len, int nofs)
        struct page *page;
        void *fsdata;
        int err;
-       char *kaddr;
        unsigned int flags = AOP_FLAG_UNINTERRUPTIBLE;
        if (nofs)
                flags |= AOP_FLAG_NOFS;
@@ -4582,9 +4583,7 @@ retry:
        if (err)
                goto fail;
 
-       kaddr = kmap_atomic(page);
-       memcpy(kaddr, symname, len-1);
-       kunmap_atomic(kaddr);
+       memcpy(page_address(page), symname, len-1);
 
        err = pagecache_write_end(NULL, mapping, 0, len-1, len-1,
                                                        page, fsdata);
@@ -4609,7 +4608,6 @@ EXPORT_SYMBOL(page_symlink);
 
 const struct inode_operations page_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = page_follow_link_light,
-       .put_link       = page_put_link,
+       .get_link       = page_get_link,
 };
 EXPORT_SYMBOL(page_symlink_inode_operations);
index 9605a2f635490ddf498c72049d7b40d84e7f977b..ce1eb3f9dfe8005e34567bab5cbb04d3f8ce10a5 100644 (file)
@@ -244,8 +244,7 @@ static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo)
 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
 static const struct inode_operations ncp_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = page_follow_link_light,
-       .put_link       = page_put_link,
+       .get_link       = page_get_link,
        .setattr        = ncp_notify_change,
 };
 #endif
@@ -283,6 +282,7 @@ ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
 #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
                } else if (S_ISLNK(inode->i_mode)) {
                        inode->i_op = &ncp_symlink_inode_operations;
+                       inode_nohighmem(inode);
                        inode->i_data.a_ops = &ncp_symlink_aops;
 #endif
                } else {
index beac58b0e09cbbb0a3cc74fbb55bfe6853c1d616..646cdac73488e96041f2bcad33b4220b096da684 100644 (file)
@@ -78,8 +78,7 @@ static __be32 *read_buf(struct xdr_stream *xdr, int nbytes)
 
        p = xdr_inline_decode(xdr, nbytes);
        if (unlikely(p == NULL))
-               printk(KERN_WARNING "NFS: NFSv4 callback reply buffer overflowed "
-                                                       "or truncated request.\n");
+               printk(KERN_WARNING "NFS: NFSv4 callback reply buffer overflowed!\n");
        return p;
 }
 
@@ -890,7 +889,6 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
        struct cb_compound_hdr_arg hdr_arg = { 0 };
        struct cb_compound_hdr_res hdr_res = { NULL };
        struct xdr_stream xdr_in, xdr_out;
-       struct xdr_buf *rq_arg = &rqstp->rq_arg;
        __be32 *p, status;
        struct cb_process_state cps = {
                .drc_status = 0,
@@ -902,8 +900,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
 
        dprintk("%s: start\n", __func__);
 
-       rq_arg->len = rq_arg->head[0].iov_len + rq_arg->page_len;
-       xdr_init_decode(&xdr_in, rq_arg, rq_arg->head[0].iov_base);
+       xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base);
 
        p = (__be32*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len);
        xdr_init_encode(&xdr_out, &rqstp->rq_res, p);
index 31b0a52223a73758c385d18bea4ec22ed63c2884..bdb4dc7b4ecde1531d6801b6cacbab3a004d1fb4 100644 (file)
@@ -75,11 +75,11 @@ nfs_fattr_to_ino_t(struct nfs_fattr *fattr)
  * nfs_wait_bit_killable - helper for functions that are sleeping on bit locks
  * @word: long word containing the bit lock
  */
-int nfs_wait_bit_killable(struct wait_bit_key *key)
+int nfs_wait_bit_killable(struct wait_bit_key *key, int mode)
 {
-       if (fatal_signal_pending(current))
-               return -ERESTARTSYS;
        freezable_schedule_unsafe();
+       if (signal_pending_state(mode, current))
+               return -ERESTARTSYS;
        return 0;
 }
 EXPORT_SYMBOL_GPL(nfs_wait_bit_killable);
@@ -408,9 +408,10 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
                                inode->i_fop = NULL;
                                inode->i_flags |= S_AUTOMOUNT;
                        }
-               } else if (S_ISLNK(inode->i_mode))
+               } else if (S_ISLNK(inode->i_mode)) {
                        inode->i_op = &nfs_symlink_inode_operations;
-               else
+                       inode_nohighmem(inode);
+               } else
                        init_special_inode(inode, inode->i_mode, fattr->rdev);
 
                memset(&inode->i_atime, 0, sizeof(inode->i_atime));
@@ -1086,6 +1087,27 @@ static bool nfs_mapping_need_revalidate_inode(struct inode *inode)
                || NFS_STALE(inode);
 }
 
+int nfs_revalidate_mapping_rcu(struct inode *inode)
+{
+       struct nfs_inode *nfsi = NFS_I(inode);
+       unsigned long *bitlock = &nfsi->flags;
+       int ret = 0;
+
+       if (IS_SWAPFILE(inode))
+               goto out;
+       if (nfs_mapping_need_revalidate_inode(inode)) {
+               ret = -ECHILD;
+               goto out;
+       }
+       spin_lock(&inode->i_lock);
+       if (test_bit(NFS_INO_INVALIDATING, bitlock) ||
+           (nfsi->cache_validity & NFS_INO_INVALID_DATA))
+               ret = -ECHILD;
+       spin_unlock(&inode->i_lock);
+out:
+       return ret;
+}
+
 /**
  * __nfs_revalidate_mapping - Revalidate the pagecache
  * @inode - pointer to host inode
index 56cfde26fb9cea0100a99bb7c3fe8a2be813dc63..9dea85f7f918ec410c5281f959e6f546c1700bf2 100644 (file)
@@ -379,7 +379,7 @@ extern int nfs_drop_inode(struct inode *);
 extern void nfs_clear_inode(struct inode *);
 extern void nfs_evict_inode(struct inode *);
 void nfs_zap_acl_cache(struct inode *inode);
-extern int nfs_wait_bit_killable(struct wait_bit_key *key);
+extern int nfs_wait_bit_killable(struct wait_bit_key *key, int mode);
 
 /* super.c */
 extern const struct super_operations nfs_sops;
index 5c0c6b58157f906d6c35ce737a6d4a5623027bf1..9aebffb4050597e1daae74f28375d86335f73e0c 100644 (file)
@@ -476,10 +476,7 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate)
                }
                unlock_page(page);
        }
-       if (PageDirty(page) || PageWriteback(page))
-               *uptodate = true;
-       else
-               *uptodate = PageUptodate(page);
+       *uptodate = PageUptodate(page);
        dprintk("%s: index=0x%lx uptodate=%d\n", __func__, index, *uptodate);
        return page;
 }
index fe3ddd20ff89095331ad854bafb4b26bc019e01e..452a011ba0d8a33e9e4b9afd858f82858185f57e 100644 (file)
@@ -129,7 +129,7 @@ __nfs_iocounter_wait(struct nfs_io_counter *c)
                set_bit(NFS_IO_INPROGRESS, &c->flags);
                if (atomic_read(&c->io_count) == 0)
                        break;
-               ret = nfs_wait_bit_killable(&q.key);
+               ret = nfs_wait_bit_killable(&q.key, TASK_KILLABLE);
        } while (atomic_read(&c->io_count) != 0 && !ret);
        finish_wait(wq, &q.wait);
        return ret;
index 5a8ae2125b50855d6f9f304ffd737fbbb57bb02a..bec0384499f76dd1acc8fb13bbf34c2ee17e6a9b 100644 (file)
@@ -1466,11 +1466,11 @@ static bool pnfs_within_mdsthreshold(struct nfs_open_context *ctx,
 }
 
 /* stop waiting if someone clears NFS_LAYOUT_RETRY_LAYOUTGET bit. */
-static int pnfs_layoutget_retry_bit_wait(struct wait_bit_key *key)
+static int pnfs_layoutget_retry_bit_wait(struct wait_bit_key *key, int mode)
 {
        if (!test_bit(NFS_LAYOUT_RETRY_LAYOUTGET, key->flags))
                return 1;
-       return nfs_wait_bit_killable(key);
+       return nfs_wait_bit_killable(key, mode);
 }
 
 static bool pnfs_prepare_to_retry_layoutget(struct pnfs_layout_hdr *lo)
index b6de433da5db14ab788ba358ce94b5952d5c601f..4fe3eead3868ebe418432b4593c10464188fb4ed 100644 (file)
@@ -42,21 +42,35 @@ error:
        return -EIO;
 }
 
-static const char *nfs_follow_link(struct dentry *dentry, void **cookie)
+static const char *nfs_get_link(struct dentry *dentry,
+                               struct inode *inode,
+                               struct delayed_call *done)
 {
-       struct inode *inode = d_inode(dentry);
        struct page *page;
        void *err;
 
-       err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping));
-       if (err)
-               return err;
-       page = read_cache_page(&inode->i_data, 0,
-                               (filler_t *)nfs_symlink_filler, inode);
-       if (IS_ERR(page))
-               return ERR_CAST(page);
-       *cookie = page;
-       return kmap(page);
+       if (!dentry) {
+               err = ERR_PTR(nfs_revalidate_mapping_rcu(inode));
+               if (err)
+                       return err;
+               page = find_get_page(inode->i_mapping, 0);
+               if (!page)
+                       return ERR_PTR(-ECHILD);
+               if (!PageUptodate(page)) {
+                       put_page(page);
+                       return ERR_PTR(-ECHILD);
+               }
+       } else {
+               err = ERR_PTR(nfs_revalidate_mapping(inode, inode->i_mapping));
+               if (err)
+                       return err;
+               page = read_cache_page(&inode->i_data, 0,
+                                       (filler_t *)nfs_symlink_filler, inode);
+               if (IS_ERR(page))
+                       return ERR_CAST(page);
+       }
+       set_delayed_call(done, page_put_link, page);
+       return page_address(page);
 }
 
 /*
@@ -64,8 +78,7 @@ static const char *nfs_follow_link(struct dentry *dentry, void **cookie)
  */
 const struct inode_operations nfs_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = nfs_follow_link,
-       .put_link       = page_put_link,
+       .get_link       = nfs_get_link,
        .getattr        = nfs_getattr,
        .setattr        = nfs_setattr,
 };
index 9ffef06b30d51e2acb2ae1a6570f14c2c47eac59..c9d6c715c0fb7e3187ffd1f2105f9527aa32259b 100644 (file)
@@ -616,6 +616,7 @@ nfsd4_cb_layout_prepare(struct nfsd4_callback *cb)
 
        mutex_lock(&ls->ls_mutex);
        nfs4_inc_and_copy_stateid(&ls->ls_recall_sid, &ls->ls_stid);
+       mutex_unlock(&ls->ls_mutex);
 }
 
 static int
@@ -659,7 +660,6 @@ nfsd4_cb_layout_release(struct nfsd4_callback *cb)
 
        trace_layout_recall_release(&ls->ls_stid.sc_stateid);
 
-       mutex_unlock(&ls->ls_mutex);
        nfsd4_return_all_layouts(ls, &reaplist);
        nfsd4_free_layouts(&reaplist);
        nfs4_put_stid(&ls->ls_stid);
index ac2f64943ff4c257f3fe2cd8d32de581de601cc6..10b22527a617dcdefc36d36ce4fc3d3658e20330 100644 (file)
@@ -510,6 +510,7 @@ static int __nilfs_read_inode(struct super_block *sb,
                inode->i_mapping->a_ops = &nilfs_aops;
        } else if (S_ISLNK(inode->i_mode)) {
                inode->i_op = &nilfs_symlink_inode_operations;
+               inode_nohighmem(inode);
                inode->i_mapping->a_ops = &nilfs_aops;
        } else {
                inode->i_op = &nilfs_special_inode_operations;
index c9a1a491aa9124b4cad5941e477f7ac3ae5de8b1..7ccdb961eea90d2ed313ef688feca1451112f5ba 100644 (file)
@@ -161,6 +161,7 @@ static int nilfs_symlink(struct inode *dir, struct dentry *dentry,
 
        /* slow symlink */
        inode->i_op = &nilfs_symlink_inode_operations;
+       inode_nohighmem(inode);
        inode->i_mapping->a_ops = &nilfs_aops;
        err = page_symlink(inode, symname, l);
        if (err)
@@ -568,8 +569,7 @@ const struct inode_operations nilfs_special_inode_operations = {
 
 const struct inode_operations nilfs_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = page_follow_link_light,
-       .put_link       = page_put_link,
+       .get_link       = page_get_link,
        .permission     = nilfs_permission,
 };
 
index ce38b4ccc9ab6c52c796a148b496bab0d8d46510..84f2f8079466a7fc07c8a4fda50d3513a02b68f9 100644 (file)
@@ -2843,6 +2843,8 @@ again:
        res->state &= ~DLM_LOCK_RES_BLOCK_DIRTY;
        if (!ret)
                BUG_ON(!(res->state & DLM_LOCK_RES_MIGRATING));
+       else
+               res->migration_pending = 0;
        spin_unlock(&res->spinlock);
 
        /*
index 8f87e05ee25d3824524c7f6e040a5f43d87c723d..97a563bab9a871ee3e371a9796b990c24835f47f 100644 (file)
@@ -361,6 +361,7 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
                    break;
            case S_IFLNK:
                    inode->i_op = &ocfs2_symlink_inode_operations;
+                   inode_nohighmem(inode);
                    i_size_write(inode, le64_to_cpu(fe->i_size));
                    break;
            default:
index 652ece4a9d9e2e90a72a95b4be1d910ea46cfc9f..d56f0079b858081241357b26667bf7fba9de5e3e 100644 (file)
@@ -67,7 +67,10 @@ static int ocfs2_do_flock(struct file *file, struct inode *inode,
                 */
 
                locks_lock_file_wait(file,
-                                    &(struct file_lock){.fl_type = F_UNLCK});
+                               &(struct file_lock) {
+                                       .fl_type = F_UNLCK,
+                                       .fl_flags = FL_FLOCK
+                               });
 
                ocfs2_file_unlock(file);
        }
index a03f6f433075c02d3c87c192b362d2c7f2e96952..afb81eae2c1876f595e8f24446fb19bb992bb313 100644 (file)
@@ -367,13 +367,11 @@ static int ocfs2_mknod(struct inode *dir,
                goto leave;
        }
 
-       status = posix_acl_create(dir, &mode, &default_acl, &acl);
+       status = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
        if (status) {
                mlog_errno(status);
                goto leave;
        }
-       /* update inode->i_mode after mask with "umask". */
-       inode->i_mode = mode;
 
        handle = ocfs2_start_trans(osb, ocfs2_mknod_credits(osb->sb,
                                                            S_ISDIR(mode),
@@ -1960,6 +1958,7 @@ static int ocfs2_symlink(struct inode *dir,
        inode->i_rdev = 0;
        newsize = l - 1;
        inode->i_op = &ocfs2_symlink_inode_operations;
+       inode_nohighmem(inode);
        if (l > ocfs2_fast_symlink_chars(sb)) {
                u32 offset = 0;
 
index d5da6f624142812ab63e83f5ab1b90e05151fed3..79b8021302b3eed84b9c59637cddd0e4844eb78b 100644 (file)
 static u16 ocfs2_calc_new_backup_super(struct inode *inode,
                                       struct ocfs2_group_desc *gd,
                                       u16 cl_cpg,
+                                      u16 old_bg_clusters,
                                       int set)
 {
        int i;
        u16 backups = 0;
-       u32 cluster;
+       u32 cluster, lgd_cluster;
        u64 blkno, gd_blkno, lgd_blkno = le64_to_cpu(gd->bg_blkno);
 
        for (i = 0; i < OCFS2_MAX_BACKUP_SUPERBLOCKS; i++) {
@@ -71,6 +72,12 @@ static u16 ocfs2_calc_new_backup_super(struct inode *inode,
                else if (gd_blkno > lgd_blkno)
                        break;
 
+               /* check if already done backup super */
+               lgd_cluster = ocfs2_blocks_to_clusters(inode->i_sb, lgd_blkno);
+               lgd_cluster += old_bg_clusters;
+               if (lgd_cluster >= cluster)
+                       continue;
+
                if (set)
                        ocfs2_set_bit(cluster % cl_cpg,
                                      (unsigned long *)gd->bg_bitmap);
@@ -99,6 +106,7 @@ static int ocfs2_update_last_group_and_inode(handle_t *handle,
        u16 chain, num_bits, backups = 0;
        u16 cl_bpc = le16_to_cpu(cl->cl_bpc);
        u16 cl_cpg = le16_to_cpu(cl->cl_cpg);
+       u16 old_bg_clusters;
 
        trace_ocfs2_update_last_group_and_inode(new_clusters,
                                                first_new_cluster);
@@ -112,6 +120,7 @@ static int ocfs2_update_last_group_and_inode(handle_t *handle,
 
        group = (struct ocfs2_group_desc *)group_bh->b_data;
 
+       old_bg_clusters = le16_to_cpu(group->bg_bits) / cl_bpc;
        /* update the group first. */
        num_bits = new_clusters * cl_bpc;
        le16_add_cpu(&group->bg_bits, num_bits);
@@ -125,7 +134,7 @@ static int ocfs2_update_last_group_and_inode(handle_t *handle,
                                     OCFS2_FEATURE_COMPAT_BACKUP_SB)) {
                backups = ocfs2_calc_new_backup_super(bm_inode,
                                                     group,
-                                                    cl_cpg, 1);
+                                                    cl_cpg, old_bg_clusters, 1);
                le16_add_cpu(&group->bg_free_bits_count, -1 * backups);
        }
 
@@ -163,7 +172,7 @@ out_rollback:
        if (ret < 0) {
                ocfs2_calc_new_backup_super(bm_inode,
                                            group,
-                                           cl_cpg, 0);
+                                           cl_cpg, old_bg_clusters, 0);
                le16_add_cpu(&group->bg_free_bits_count, backups);
                le16_add_cpu(&group->bg_bits, -1 * num_bits);
                le16_add_cpu(&group->bg_free_bits_count, -1 * num_bits);
index 66edce7ecfd78f807451bdbf724cfabc071dbd5a..6c2a3e3c521ce66fbd6085840ae69897628ca45b 100644 (file)
@@ -88,8 +88,7 @@ const struct address_space_operations ocfs2_fast_symlink_aops = {
 
 const struct inode_operations ocfs2_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = page_follow_link_light,
-       .put_link       = page_put_link,
+       .get_link       = page_get_link,
        .getattr        = ocfs2_getattr,
        .setattr        = ocfs2_setattr,
        .setxattr       = generic_setxattr,
index 4060ffde87225c81114d086c000773d4019255b5..964a60fa7afc53ad902c05b23daac017ba78fc1e 100644 (file)
@@ -131,57 +131,23 @@ out_dput:
        return err;
 }
 
-
-struct ovl_link_data {
-       struct dentry *realdentry;
-       void *cookie;
-};
-
-static const char *ovl_follow_link(struct dentry *dentry, void **cookie)
+static const char *ovl_get_link(struct dentry *dentry,
+                               struct inode *inode,
+                               struct delayed_call *done)
 {
        struct dentry *realdentry;
        struct inode *realinode;
-       struct ovl_link_data *data = NULL;
-       const char *ret;
+
+       if (!dentry)
+               return ERR_PTR(-ECHILD);
 
        realdentry = ovl_dentry_real(dentry);
        realinode = realdentry->d_inode;
 
-       if (WARN_ON(!realinode->i_op->follow_link))
+       if (WARN_ON(!realinode->i_op->get_link))
                return ERR_PTR(-EPERM);
 
-       if (realinode->i_op->put_link) {
-               data = kmalloc(sizeof(struct ovl_link_data), GFP_KERNEL);
-               if (!data)
-                       return ERR_PTR(-ENOMEM);
-               data->realdentry = realdentry;
-       }
-
-       ret = realinode->i_op->follow_link(realdentry, cookie);
-       if (IS_ERR_OR_NULL(ret)) {
-               kfree(data);
-               return ret;
-       }
-
-       if (data)
-               data->cookie = *cookie;
-
-       *cookie = data;
-
-       return ret;
-}
-
-static void ovl_put_link(struct inode *unused, void *c)
-{
-       struct inode *realinode;
-       struct ovl_link_data *data = c;
-
-       if (!data)
-               return;
-
-       realinode = data->realdentry->d_inode;
-       realinode->i_op->put_link(realinode, data->cookie);
-       kfree(data);
+       return realinode->i_op->get_link(realdentry, realinode, done);
 }
 
 static int ovl_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
@@ -378,8 +344,7 @@ static const struct inode_operations ovl_file_inode_operations = {
 
 static const struct inode_operations ovl_symlink_inode_operations = {
        .setattr        = ovl_setattr,
-       .follow_link    = ovl_follow_link,
-       .put_link       = ovl_put_link,
+       .get_link       = ovl_get_link,
        .readlink       = ovl_readlink,
        .getattr        = ovl_getattr,
        .setxattr       = ovl_setxattr,
index bd3e9e68125b8933b2e32a4fea2e2282397dc1cd..55e01f88eac9d1156e240700598fd9688c6c503e 100644 (file)
@@ -1564,12 +1564,16 @@ static int proc_exe_link(struct dentry *dentry, struct path *exe_path)
                return -ENOENT;
 }
 
-static const char *proc_pid_follow_link(struct dentry *dentry, void **cookie)
+static const char *proc_pid_get_link(struct dentry *dentry,
+                                    struct inode *inode,
+                                    struct delayed_call *done)
 {
-       struct inode *inode = d_inode(dentry);
        struct path path;
        int error = -EACCES;
 
+       if (!dentry)
+               return ERR_PTR(-ECHILD);
+
        /* Are we allowed to snoop on the tasks file descriptors? */
        if (!proc_fd_access_allowed(inode))
                goto out;
@@ -1630,7 +1634,7 @@ out:
 
 const struct inode_operations proc_pid_link_inode_operations = {
        .readlink       = proc_pid_readlink,
-       .follow_link    = proc_pid_follow_link,
+       .get_link       = proc_pid_get_link,
        .setattr        = proc_setattr,
 };
 
@@ -1895,7 +1899,7 @@ static const struct dentry_operations tid_map_files_dentry_operations = {
        .d_delete       = pid_delete_dentry,
 };
 
-static int proc_map_files_get_link(struct dentry *dentry, struct path *path)
+static int map_files_get_link(struct dentry *dentry, struct path *path)
 {
        unsigned long vm_start, vm_end;
        struct vm_area_struct *vma;
@@ -1945,20 +1949,22 @@ struct map_files_info {
  * path to the file in question.
  */
 static const char *
-proc_map_files_follow_link(struct dentry *dentry, void **cookie)
+proc_map_files_get_link(struct dentry *dentry,
+                       struct inode *inode,
+                       struct delayed_call *done)
 {
        if (!capable(CAP_SYS_ADMIN))
                return ERR_PTR(-EPERM);
 
-       return proc_pid_follow_link(dentry, NULL);
+       return proc_pid_get_link(dentry, inode, done);
 }
 
 /*
- * Identical to proc_pid_link_inode_operations except for follow_link()
+ * Identical to proc_pid_link_inode_operations except for get_link()
  */
 static const struct inode_operations proc_map_files_link_inode_operations = {
        .readlink       = proc_pid_readlink,
-       .follow_link    = proc_map_files_follow_link,
+       .get_link       = proc_map_files_get_link,
        .setattr        = proc_setattr,
 };
 
@@ -1975,7 +1981,7 @@ proc_map_files_instantiate(struct inode *dir, struct dentry *dentry,
                return -ENOENT;
 
        ei = PROC_I(inode);
-       ei->op.proc_get_link = proc_map_files_get_link;
+       ei->op.proc_get_link = map_files_get_link;
 
        inode->i_op = &proc_map_files_link_inode_operations;
        inode->i_size = 64;
@@ -2494,6 +2500,7 @@ static ssize_t proc_coredump_filter_write(struct file *file,
        mm = get_task_mm(task);
        if (!mm)
                goto out_no_mm;
+       ret = 0;
 
        for (i = 0, mask = 1; i < MMF_DUMP_FILTER_BITS; i++, mask <<= 1) {
                if (val & mask)
index bd95b9fdebb005cd9912c3b80027cfc1659fc530..d0e9b9b6223e984879620839effb830fb7937219 100644 (file)
@@ -393,24 +393,25 @@ static const struct file_operations proc_reg_file_ops_no_compat = {
 };
 #endif
 
-static const char *proc_follow_link(struct dentry *dentry, void **cookie)
+static void proc_put_link(void *p)
 {
-       struct proc_dir_entry *pde = PDE(d_inode(dentry));
-       if (unlikely(!use_pde(pde)))
-               return ERR_PTR(-EINVAL);
-       *cookie = pde;
-       return pde->data;
+       unuse_pde(p);
 }
 
-static void proc_put_link(struct inode *unused, void *p)
+static const char *proc_get_link(struct dentry *dentry,
+                                struct inode *inode,
+                                struct delayed_call *done)
 {
-       unuse_pde(p);
+       struct proc_dir_entry *pde = PDE(inode);
+       if (unlikely(!use_pde(pde)))
+               return ERR_PTR(-EINVAL);
+       set_delayed_call(done, proc_put_link, pde);
+       return pde->data;
 }
 
 const struct inode_operations proc_link_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = proc_follow_link,
-       .put_link       = proc_put_link,
+       .get_link       = proc_get_link,
 };
 
 struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
index f6e8354b8cea20a936f6a4f8ae0335fd7fa36bd4..1dece8781f91687307155c38a4c85a3ffba5c6b9 100644 (file)
@@ -30,14 +30,18 @@ static const struct proc_ns_operations *ns_entries[] = {
        &mntns_operations,
 };
 
-static const char *proc_ns_follow_link(struct dentry *dentry, void **cookie)
+static const char *proc_ns_get_link(struct dentry *dentry,
+                                   struct inode *inode,
+                                   struct delayed_call *done)
 {
-       struct inode *inode = d_inode(dentry);
        const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
        struct task_struct *task;
        struct path ns_path;
        void *error = ERR_PTR(-EACCES);
 
+       if (!dentry)
+               return ERR_PTR(-ECHILD);
+
        task = get_proc_task(inode);
        if (!task)
                return error;
@@ -74,7 +78,7 @@ static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int bufl
 
 static const struct inode_operations proc_ns_link_inode_operations = {
        .readlink       = proc_ns_readlink,
-       .follow_link    = proc_ns_follow_link,
+       .get_link       = proc_ns_get_link,
        .setattr        = proc_setattr,
 };
 
index 113b8d061fc023858ab152a5033e029d085f27a6..67e8db442cf03802c7758a76dd8adf79b46a3a50 100644 (file)
@@ -18,26 +18,28 @@ static int proc_self_readlink(struct dentry *dentry, char __user *buffer,
        return readlink_copy(buffer, buflen, tmp);
 }
 
-static const char *proc_self_follow_link(struct dentry *dentry, void **cookie)
+static const char *proc_self_get_link(struct dentry *dentry,
+                                     struct inode *inode,
+                                     struct delayed_call *done)
 {
-       struct pid_namespace *ns = dentry->d_sb->s_fs_info;
+       struct pid_namespace *ns = inode->i_sb->s_fs_info;
        pid_t tgid = task_tgid_nr_ns(current, ns);
        char *name;
 
        if (!tgid)
                return ERR_PTR(-ENOENT);
        /* 11 for max length of signed int in decimal + NULL term */
-       name = kmalloc(12, GFP_KERNEL);
-       if (!name)
-               return ERR_PTR(-ENOMEM);
+       name = kmalloc(12, dentry ? GFP_KERNEL : GFP_ATOMIC);
+       if (unlikely(!name))
+               return dentry ? ERR_PTR(-ENOMEM) : ERR_PTR(-ECHILD);
        sprintf(name, "%d", tgid);
-       return *cookie = name;
+       set_delayed_call(done, kfree_link, name);
+       return name;
 }
 
 static const struct inode_operations proc_self_inode_operations = {
        .readlink       = proc_self_readlink,
-       .follow_link    = proc_self_follow_link,
-       .put_link       = kfree_put_link,
+       .get_link       = proc_self_get_link,
 };
 
 static unsigned self_inum;
index 947b0f4fd0a194057334762bafeff3548c276568..9eacd59e0360f1367a084a1e7bfa5dca0e3fe170 100644 (file)
@@ -19,26 +19,29 @@ static int proc_thread_self_readlink(struct dentry *dentry, char __user *buffer,
        return readlink_copy(buffer, buflen, tmp);
 }
 
-static const char *proc_thread_self_follow_link(struct dentry *dentry, void **cookie)
+static const char *proc_thread_self_get_link(struct dentry *dentry,
+                                            struct inode *inode,
+                                            struct delayed_call *done)
 {
-       struct pid_namespace *ns = dentry->d_sb->s_fs_info;
+       struct pid_namespace *ns = inode->i_sb->s_fs_info;
        pid_t tgid = task_tgid_nr_ns(current, ns);
        pid_t pid = task_pid_nr_ns(current, ns);
        char *name;
 
        if (!pid)
                return ERR_PTR(-ENOENT);
-       name = kmalloc(PROC_NUMBUF + 6 + PROC_NUMBUF, GFP_KERNEL);
-       if (!name)
-               return ERR_PTR(-ENOMEM);
+       name = kmalloc(PROC_NUMBUF + 6 + PROC_NUMBUF,
+                               dentry ? GFP_KERNEL : GFP_ATOMIC);
+       if (unlikely(!name))
+               return dentry ? ERR_PTR(-ENOMEM) : ERR_PTR(-ECHILD);
        sprintf(name, "%d/task/%d", tgid, pid);
-       return *cookie = name;
+       set_delayed_call(done, kfree_link, name);
+       return name;
 }
 
 static const struct inode_operations proc_thread_self_inode_operations = {
        .readlink       = proc_thread_self_readlink,
-       .follow_link    = proc_thread_self_follow_link,
-       .put_link       = kfree_put_link,
+       .get_link       = proc_thread_self_get_link,
 };
 
 static unsigned thread_self_inum;
index c4bcb778886e5c79c4dcc9381cf13f0a76358838..f37b3deb01b4d5f2d07ea90774a5bf99c39992bd 100644 (file)
@@ -316,6 +316,7 @@ struct inode *qnx4_iget(struct super_block *sb, unsigned long ino)
                inode->i_fop = &qnx4_dir_operations;
        } else if (S_ISLNK(inode->i_mode)) {
                inode->i_op = &page_symlink_inode_operations;
+               inode_nohighmem(inode);
                inode->i_mapping->a_ops = &qnx4_aops;
                qnx4_i(inode)->mmu_private = inode->i_size;
        } else {
index 32d2e1a9774ca66005d92786df99a70865efb3fa..9728b5499e1d5a1eae80344ff0e9e76dd1a04153 100644 (file)
@@ -582,6 +582,7 @@ struct inode *qnx6_iget(struct super_block *sb, unsigned ino)
                inode->i_mapping->a_ops = &qnx6_aops;
        } else if (S_ISLNK(inode->i_mode)) {
                inode->i_op = &page_symlink_inode_operations;
+               inode_nohighmem(inode);
                inode->i_mapping->a_ops = &qnx6_aops;
        } else
                init_special_inode(inode, inode->i_mode, 0);
index 889d558b4e05518e6b14280d8ffea7ec28d7f85c..38981b03752433de71197c5c724999a33dc2d53d 100644 (file)
@@ -79,6 +79,7 @@ struct inode *ramfs_get_inode(struct super_block *sb,
                        break;
                case S_IFLNK:
                        inode->i_op = &page_symlink_inode_operations;
+                       inode_nohighmem(inode);
                        break;
                }
        }
index 3d8e7e671d5ba7d15fe4a14e1b803673c220cdee..ae9e5b308cf9f5775300e7ee109e4e2f72720b12 100644 (file)
@@ -1361,6 +1361,7 @@ static void init_inode(struct inode *inode, struct treepath *path)
                inode->i_fop = &reiserfs_dir_operations;
        } else if (S_ISLNK(inode->i_mode)) {
                inode->i_op = &reiserfs_symlink_inode_operations;
+               inode_nohighmem(inode);
                inode->i_mapping->a_ops = &reiserfs_address_space_operations;
        } else {
                inode->i_blocks = 0;
index 47f96988fdd478dbc6ce325232d38754258864cc..2a12d46d7fb4154e2119ac94c50a7e74c998c437 100644 (file)
@@ -1170,6 +1170,7 @@ static int reiserfs_symlink(struct inode *parent_dir,
        reiserfs_update_inode_transaction(parent_dir);
 
        inode->i_op = &reiserfs_symlink_inode_operations;
+       inode_nohighmem(inode);
        inode->i_mapping->a_ops = &reiserfs_address_space_operations;
 
        retval = reiserfs_add_entry(&th, parent_dir, dentry->d_name.name,
@@ -1664,8 +1665,7 @@ const struct inode_operations reiserfs_dir_inode_operations = {
  */
 const struct inode_operations reiserfs_symlink_inode_operations = {
        .readlink = generic_readlink,
-       .follow_link = page_follow_link_light,
-       .put_link = page_put_link,
+       .get_link       = page_get_link,
        .setattr = reiserfs_setattr,
        .setxattr = reiserfs_setxattr,
        .getxattr = reiserfs_getxattr,
index 268733cda397eb7780f45d966cdca822daad16e8..bb894e78a821ef4643e25cbf684832b5baaf054c 100644 (file)
@@ -360,6 +360,7 @@ static struct inode *romfs_iget(struct super_block *sb, unsigned long pos)
                break;
        case ROMFH_SYM:
                i->i_op = &page_symlink_inode_operations;
+               inode_nohighmem(i);
                i->i_data.a_ops = &romfs_aops;
                mode |= S_IRWXUGO;
                break;
index a1ce5ce60632e892fc0f17859e99963eb1a67235..0927b1e80ab6e0b5a039f41840131c3f40988f75 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/fs.h>
 #include <linux/vfs.h>
 #include <linux/xattr.h>
+#include <linux/pagemap.h>
 
 #include "squashfs_fs.h"
 #include "squashfs_fs_sb.h"
@@ -291,6 +292,7 @@ int squashfs_read_inode(struct inode *inode, long long ino)
                set_nlink(inode, le32_to_cpu(sqsh_ino->nlink));
                inode->i_size = le32_to_cpu(sqsh_ino->symlink_size);
                inode->i_op = &squashfs_symlink_inode_ops;
+               inode_nohighmem(inode);
                inode->i_data.a_ops = &squashfs_symlink_aops;
                inode->i_mode |= S_IFLNK;
                squashfs_i(inode)->start = block;
index 12806dffb3454ed1a898bbdd7b2ca272d071694f..dbcc2f54bad46f9af564e37f4e9b153e439d0205 100644 (file)
@@ -119,8 +119,7 @@ const struct address_space_operations squashfs_symlink_aops = {
 
 const struct inode_operations squashfs_symlink_inode_ops = {
        .readlink = generic_readlink,
-       .follow_link = page_follow_link_light,
-       .put_link = page_put_link,
+       .get_link = page_get_link,
        .getxattr = generic_getxattr,
        .listxattr = squashfs_listxattr
 };
index 02fa1dcc5969f6b596a6c527170fcf9193c437e5..07ac18c355e777e0fe869225a70b5d6d9dba1f24 100644 (file)
@@ -146,8 +146,7 @@ static inline void write3byte(struct sysv_sb_info *sbi,
 
 static const struct inode_operations sysv_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = page_follow_link_light,
-       .put_link       = page_put_link,
+       .get_link       = page_get_link,
        .getattr        = sysv_getattr,
 };
 
@@ -163,6 +162,7 @@ void sysv_set_inode(struct inode *inode, dev_t rdev)
                inode->i_mapping->a_ops = &sysv_aops;
        } else if (S_ISLNK(inode->i_mode)) {
                inode->i_op = &sysv_symlink_inode_operations;
+               inode_nohighmem(inode);
                inode->i_mapping->a_ops = &sysv_aops;
        } else
                init_special_inode(inode, inode->i_mode, rdev);
index 0edc128561476a804656fba068810cf47a76fa32..eff62801acbf10524e31f8ad7816c160e6f88a90 100644 (file)
@@ -1608,7 +1608,7 @@ const struct inode_operations ubifs_file_inode_operations = {
 
 const struct inode_operations ubifs_symlink_inode_operations = {
        .readlink    = generic_readlink,
-       .follow_link = simple_follow_link,
+       .get_link    = simple_get_link,
        .setattr     = ubifs_setattr,
        .getattr     = ubifs_getattr,
        .setxattr    = ubifs_setxattr,
index 8d0b3ade0ff0ef8a65f8714330a3bfd49201c0d8..055746350d16f90be47fe892d093c51d4959eedb 100644 (file)
@@ -1540,7 +1540,8 @@ reread:
                break;
        case ICBTAG_FILE_TYPE_SYMLINK:
                inode->i_data.a_ops = &udf_symlink_aops;
-               inode->i_op = &udf_symlink_inode_operations;
+               inode->i_op = &page_symlink_inode_operations;
+               inode_nohighmem(inode);
                inode->i_mode = S_IFLNK | S_IRWXUGO;
                break;
        case ICBTAG_FILE_TYPE_MAIN:
index c97b5a8d1e24cfe831824e7beff18efc84340916..42eafb91f7ff3c092fd38f6fb6136862ca6508c8 100644 (file)
@@ -921,7 +921,8 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
        }
 
        inode->i_data.a_ops = &udf_symlink_aops;
-       inode->i_op = &udf_symlink_inode_operations;
+       inode->i_op = &page_symlink_inode_operations;
+       inode_nohighmem(inode);
 
        if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
                struct kernel_lb_addr eloc;
@@ -1344,8 +1345,3 @@ const struct inode_operations udf_dir_inode_operations = {
        .rename                         = udf_rename,
        .tmpfile                        = udf_tmpfile,
 };
-const struct inode_operations udf_symlink_inode_operations = {
-       .readlink       = generic_readlink,
-       .follow_link    = page_follow_link_light,
-       .put_link       = page_put_link,
-};
index 862535b3ba58a8a6f6ca3d23b35b0b66fee36c22..8d619773056b5ef0b0a3f2d7dd27b74a6eb76434 100644 (file)
@@ -107,7 +107,7 @@ static int udf_symlink_filler(struct file *file, struct page *page)
        struct buffer_head *bh = NULL;
        unsigned char *symlink;
        int err;
-       unsigned char *p = kmap(page);
+       unsigned char *p = page_address(page);
        struct udf_inode_info *iinfo;
        uint32_t pos;
 
@@ -141,7 +141,6 @@ static int udf_symlink_filler(struct file *file, struct page *page)
 
        up_read(&iinfo->i_data_sem);
        SetPageUptodate(page);
-       kunmap(page);
        unlock_page(page);
        return 0;
 
@@ -149,7 +148,6 @@ out_unlock_inode:
        up_read(&iinfo->i_data_sem);
        SetPageError(page);
 out_unmap:
-       kunmap(page);
        unlock_page(page);
        return err;
 }
index 47bb3f5ca360d4f1be8f92036685278868ab99e3..ce169b49429d86a2b18e84b1e1159fad2eb5651d 100644 (file)
@@ -85,7 +85,6 @@ extern const struct inode_operations udf_dir_inode_operations;
 extern const struct file_operations udf_dir_operations;
 extern const struct inode_operations udf_file_inode_operations;
 extern const struct file_operations udf_file_operations;
-extern const struct inode_operations udf_symlink_inode_operations;
 extern const struct address_space_operations udf_aops;
 extern const struct address_space_operations udf_adinicb_aops;
 extern const struct address_space_operations udf_symlink_aops;
index 392db25c0b567a7ddcd8eeaf403bd564875023df..ec4a6b49fa13fae382c9968bfb30a18943836c7f 100644 (file)
@@ -5,5 +5,5 @@
 obj-$(CONFIG_UFS_FS) += ufs.o
 
 ufs-objs := balloc.o cylinder.o dir.o file.o ialloc.o inode.o \
-           namei.o super.o symlink.o util.o
+           namei.o super.o util.o
 ccflags-$(CONFIG_UFS_DEBUG)    += -DDEBUG
index a064cf44b1435c838a5f446f048ed00b68d48e7b..d897e169ab9c4f240e1f4023955f37bf0fe8f266 100644 (file)
@@ -528,11 +528,12 @@ static void ufs_set_inode_ops(struct inode *inode)
                inode->i_mapping->a_ops = &ufs_aops;
        } else if (S_ISLNK(inode->i_mode)) {
                if (!inode->i_blocks) {
-                       inode->i_op = &ufs_fast_symlink_inode_operations;
                        inode->i_link = (char *)UFS_I(inode)->i_u1.i_symlink;
+                       inode->i_op = &simple_symlink_inode_operations;
                } else {
-                       inode->i_op = &ufs_symlink_inode_operations;
                        inode->i_mapping->a_ops = &ufs_aops;
+                       inode->i_op = &page_symlink_inode_operations;
+                       inode_nohighmem(inode);
                }
        } else
                init_special_inode(inode, inode->i_mode,
index 47966554317c922da9c73d904f0ea104ec0392f2..acf4a3b61b81fcc58342819eabbc768e6ba33bae 100644 (file)
@@ -123,14 +123,15 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry,
 
        if (l > UFS_SB(sb)->s_uspi->s_maxsymlinklen) {
                /* slow symlink */
-               inode->i_op = &ufs_symlink_inode_operations;
+               inode->i_op = &page_symlink_inode_operations;
+               inode_nohighmem(inode);
                inode->i_mapping->a_ops = &ufs_aops;
                err = page_symlink(inode, symname, l);
                if (err)
                        goto out_fail;
        } else {
                /* fast symlink */
-               inode->i_op = &ufs_fast_symlink_inode_operations;
+               inode->i_op = &simple_symlink_inode_operations;
                inode->i_link = (char *)UFS_I(inode)->i_u1.i_symlink;
                memcpy(inode->i_link, symname, l);
                inode->i_size = l-1;
diff --git a/fs/ufs/symlink.c b/fs/ufs/symlink.c
deleted file mode 100644 (file)
index 874480b..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *  linux/fs/ufs/symlink.c
- *
- * Only fast symlinks left here - the rest is done by generic code. AV, 1999
- *
- * Copyright (C) 1998
- * Daniel Pirkl <daniel.pirkl@emai.cz>
- * Charles University, Faculty of Mathematics and Physics
- *
- *  from
- *
- *  linux/fs/ext2/symlink.c
- *
- * Copyright (C) 1992, 1993, 1994, 1995
- * Remy Card (card@masi.ibp.fr)
- * Laboratoire MASI - Institut Blaise Pascal
- * Universite Pierre et Marie Curie (Paris VI)
- *
- *  from
- *
- *  linux/fs/minix/symlink.c
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *
- *  ext2 symlink handling code
- */
-
-#include "ufs_fs.h"
-#include "ufs.h"
-
-const struct inode_operations ufs_fast_symlink_inode_operations = {
-       .readlink       = generic_readlink,
-       .follow_link    = simple_follow_link,
-       .setattr        = ufs_setattr,
-};
-
-const struct inode_operations ufs_symlink_inode_operations = {
-       .readlink       = generic_readlink,
-       .follow_link    = page_follow_link_light,
-       .put_link       = page_put_link,
-       .setattr        = ufs_setattr,
-};
index 7da4aca868c067b57c9d012f12bdffdf788d1a05..c87f4c3fa9ddd87849403a58e817a63ebf441cf1 100644 (file)
@@ -136,10 +136,6 @@ extern __printf(3, 4)
 void ufs_panic(struct super_block *, const char *, const char *, ...);
 void ufs_mark_sb_dirty(struct super_block *sb);
 
-/* symlink.c */
-extern const struct inode_operations ufs_fast_symlink_inode_operations;
-extern const struct inode_operations ufs_symlink_inode_operations;
-
 static inline struct ufs_sb_info *UFS_SB(struct super_block *sb)
 {
        return sb->s_fs_info;
index 245268a0cdf06e4d518ee915a0add70ef5a42dc6..06eafafe636e20f90e8f696ee20c0bb01b64ea8f 100644 (file)
@@ -414,13 +414,17 @@ xfs_vn_rename(
  * uio is kmalloced for this reason...
  */
 STATIC const char *
-xfs_vn_follow_link(
+xfs_vn_get_link(
        struct dentry           *dentry,
-       void                    **cookie)
+       struct inode            *inode,
+       struct delayed_call     *done)
 {
        char                    *link;
        int                     error = -ENOMEM;
 
+       if (!dentry)
+               return ERR_PTR(-ECHILD);
+
        link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
        if (!link)
                goto out_err;
@@ -429,7 +433,8 @@ xfs_vn_follow_link(
        if (unlikely(error))
                goto out_kfree;
 
-       return *cookie = link;
+       set_delayed_call(done, kfree_link, link);
+       return link;
 
  out_kfree:
        kfree(link);
@@ -1172,8 +1177,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
 
 static const struct inode_operations xfs_symlink_inode_operations = {
        .readlink               = generic_readlink,
-       .follow_link            = xfs_vn_follow_link,
-       .put_link               = kfree_put_link,
+       .get_link               = xfs_vn_get_link,
        .getattr                = xfs_vn_getattr,
        .setattr                = xfs_vn_setattr,
        .setxattr               = generic_setxattr,
index db284bff29dcceb39360d458cec3a194745955f8..9dbb739cafa0c16dda9d011d30ce8cd9b4091fd4 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2001 Red Hat, Inc.
  * Based on code from mm/memory.c Copyright Linus Torvalds and others.
  *
- * Copyright 2011 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright 2011 Red Hat, Inc., Peter Zijlstra
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
index 2b8ed123ad36b26bc26956293452937d3ac1b90e..defeaac0745f1b26340d7a13f5b73810de743193 100644 (file)
@@ -107,7 +107,7 @@ static inline __u64 ror64(__u64 word, unsigned int shift)
  */
 static inline __u32 rol32(__u32 word, unsigned int shift)
 {
-       return (word << shift) | (word >> (32 - shift));
+       return (word << shift) | (word >> ((-shift) & 31));
 }
 
 /**
index 0169ba2e2e64b9c4bba07bf72b9c1194fe2db08a..c70e3588a48c723f4b7cd8536c0dabfc02871d5c 100644 (file)
@@ -797,6 +797,7 @@ extern int sg_scsi_ioctl(struct request_queue *, struct gendisk *, fmode_t,
 extern int blk_queue_enter(struct request_queue *q, gfp_t gfp);
 extern void blk_queue_exit(struct request_queue *q);
 extern void blk_start_queue(struct request_queue *q);
+extern void blk_start_queue_async(struct request_queue *q);
 extern void blk_stop_queue(struct request_queue *q);
 extern void blk_sync_queue(struct request_queue *q);
 extern void __blk_stop_queue(struct request_queue *q);
index 60d44b26276d84a77d7f7e3379ae12821a8b3eeb..06b77f9dd3f2052ac87f970b8aa8c195b78f7ada 100644 (file)
@@ -90,7 +90,6 @@ enum {
  */
 struct cgroup_file {
        /* do not access any fields from outside cgroup core */
-       struct list_head node;                  /* anchored at css->files */
        struct kernfs_node *kn;
 };
 
@@ -134,9 +133,6 @@ struct cgroup_subsys_state {
         */
        u64 serial_nr;
 
-       /* all cgroup_files associated with this css */
-       struct list_head files;
-
        /* percpu_ref killing and RCU release */
        struct rcu_head rcu_head;
        struct work_struct destroy_work;
@@ -426,12 +422,9 @@ struct cgroup_subsys {
        void (*css_reset)(struct cgroup_subsys_state *css);
        void (*css_e_css_changed)(struct cgroup_subsys_state *css);
 
-       int (*can_attach)(struct cgroup_subsys_state *css,
-                         struct cgroup_taskset *tset);
-       void (*cancel_attach)(struct cgroup_subsys_state *css,
-                             struct cgroup_taskset *tset);
-       void (*attach)(struct cgroup_subsys_state *css,
-                      struct cgroup_taskset *tset);
+       int (*can_attach)(struct cgroup_taskset *tset);
+       void (*cancel_attach)(struct cgroup_taskset *tset);
+       void (*attach)(struct cgroup_taskset *tset);
        int (*can_fork)(struct task_struct *task, void **priv_p);
        void (*cancel_fork)(struct task_struct *task, void *priv);
        void (*fork)(struct task_struct *task, void *priv);
index 22e3754f89c511374af4ca8ac5a518786dcd6d88..cb91b44f5f7877d5899403b26ca1d9231c1ac9b6 100644 (file)
@@ -88,6 +88,7 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from);
 int cgroup_add_dfl_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
 int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts);
 int cgroup_rm_cftypes(struct cftype *cfts);
+void cgroup_file_notify(struct cgroup_file *cfile);
 
 char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen);
 int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry);
@@ -119,8 +120,10 @@ struct cgroup_subsys_state *css_rightmost_descendant(struct cgroup_subsys_state
 struct cgroup_subsys_state *css_next_descendant_post(struct cgroup_subsys_state *pos,
                                                     struct cgroup_subsys_state *css);
 
-struct task_struct *cgroup_taskset_first(struct cgroup_taskset *tset);
-struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset);
+struct task_struct *cgroup_taskset_first(struct cgroup_taskset *tset,
+                                        struct cgroup_subsys_state **dst_cssp);
+struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset,
+                                       struct cgroup_subsys_state **dst_cssp);
 
 void css_task_iter_start(struct cgroup_subsys_state *css,
                         struct css_task_iter *it);
@@ -235,30 +238,39 @@ void css_task_iter_end(struct css_task_iter *it);
 /**
  * cgroup_taskset_for_each - iterate cgroup_taskset
  * @task: the loop cursor
+ * @dst_css: the destination css
  * @tset: taskset to iterate
  *
  * @tset may contain multiple tasks and they may belong to multiple
- * processes.  When there are multiple tasks in @tset, if a task of a
- * process is in @tset, all tasks of the process are in @tset.  Also, all
- * are guaranteed to share the same source and destination csses.
+ * processes.
+ *
+ * On the v2 hierarchy, there may be tasks from multiple processes and they
+ * may not share the source or destination csses.
+ *
+ * On traditional hierarchies, when there are multiple tasks in @tset, if a
+ * task of a process is in @tset, all tasks of the process are in @tset.
+ * Also, all are guaranteed to share the same source and destination csses.
  *
  * Iteration is not in any specific order.
  */
-#define cgroup_taskset_for_each(task, tset)                            \
-       for ((task) = cgroup_taskset_first((tset)); (task);             \
-            (task) = cgroup_taskset_next((tset)))
+#define cgroup_taskset_for_each(task, dst_css, tset)                   \
+       for ((task) = cgroup_taskset_first((tset), &(dst_css));         \
+            (task);                                                    \
+            (task) = cgroup_taskset_next((tset), &(dst_css)))
 
 /**
  * cgroup_taskset_for_each_leader - iterate group leaders in a cgroup_taskset
  * @leader: the loop cursor
+ * @dst_css: the destination css
  * @tset: takset to iterate
  *
  * Iterate threadgroup leaders of @tset.  For single-task migrations, @tset
  * may not contain any.
  */
-#define cgroup_taskset_for_each_leader(leader, tset)                   \
-       for ((leader) = cgroup_taskset_first((tset)); (leader);         \
-            (leader) = cgroup_taskset_next((tset)))                    \
+#define cgroup_taskset_for_each_leader(leader, dst_css, tset)          \
+       for ((leader) = cgroup_taskset_first((tset), &(dst_css));       \
+            (leader);                                                  \
+            (leader) = cgroup_taskset_next((tset), &(dst_css)))        \
                if ((leader) != (leader)->group_leader)                 \
                        ;                                               \
                else
@@ -516,19 +528,6 @@ static inline void pr_cont_cgroup_path(struct cgroup *cgrp)
        pr_cont_kernfs_path(cgrp->kn);
 }
 
-/**
- * cgroup_file_notify - generate a file modified event for a cgroup_file
- * @cfile: target cgroup_file
- *
- * @cfile must have been obtained by setting cftype->file_offset.
- */
-static inline void cgroup_file_notify(struct cgroup_file *cfile)
-{
-       /* might not have been created due to one of the CFTYPE selector flags */
-       if (cfile->kn)
-               kernfs_notify(cfile->kn);
-}
-
 #else /* !CONFIG_CGROUPS */
 
 struct cgroup_subsys_state;
diff --git a/include/linux/delayed_call.h b/include/linux/delayed_call.h
new file mode 100644 (file)
index 0000000..f7fa76a
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef _DELAYED_CALL_H
+#define _DELAYED_CALL_H
+
+/*
+ * Poor man's closures; I wish we could've done them sanely polymorphic,
+ * but...
+ */
+
+struct delayed_call {
+       void (*fn)(void *);
+       void *arg;
+};
+
+#define DEFINE_DELAYED_CALL(name) struct delayed_call name = {NULL, NULL}
+
+/* I really wish we had closures with sane typechecking... */
+static inline void set_delayed_call(struct delayed_call *call,
+               void (*fn)(void *), void *arg)
+{
+       call->fn = fn;
+       call->arg = arg;
+}
+
+static inline void do_delayed_call(struct delayed_call *call)
+{
+       if (call->fn)
+               call->fn(call->arg);
+}
+
+static inline void clear_delayed_call(struct delayed_call *call)
+{
+       call->fn = NULL;
+}
+#endif
index 7be22da321f38eb1327bbbcaabddd6cbca131d44..a4cf57cd0f7512d66b15a036cb76114d5bf633e0 100644 (file)
 /* A few generic types ... taken from ses-2 */
 enum enclosure_component_type {
        ENCLOSURE_COMPONENT_DEVICE = 0x01,
+       ENCLOSURE_COMPONENT_CONTROLLER_ELECTRONICS = 0x07,
+       ENCLOSURE_COMPONENT_SCSI_TARGET_PORT = 0x14,
+       ENCLOSURE_COMPONENT_SCSI_INITIATOR_PORT = 0x15,
        ENCLOSURE_COMPONENT_ARRAY_DEVICE = 0x17,
+       ENCLOSURE_COMPONENT_SAS_EXPANDER = 0x18,
 };
 
 /* ses-2 common element status */
index 4165e9ac9e36aa82735f40a790e25e0b7218c95b..5972ffe5719a4e14012328035450759c12f43bec 100644 (file)
@@ -493,6 +493,25 @@ static inline void bpf_jit_free(struct bpf_prog *fp)
 
 #define BPF_ANC                BIT(15)
 
+static inline bool bpf_needs_clear_a(const struct sock_filter *first)
+{
+       switch (first->code) {
+       case BPF_RET | BPF_K:
+       case BPF_LD | BPF_W | BPF_LEN:
+               return false;
+
+       case BPF_LD | BPF_W | BPF_ABS:
+       case BPF_LD | BPF_H | BPF_ABS:
+       case BPF_LD | BPF_B | BPF_ABS:
+               if (first->k == SKF_AD_OFF + SKF_AD_ALU_XOR_X)
+                       return true;
+               return false;
+
+       default:
+               return true;
+       }
+}
+
 static inline u16 bpf_anc_helper(const struct sock_filter *ftest)
 {
        BUG_ON(ftest->code & BPF_ANC);
index 3aa51425416148f5bec14b6faf4e6f4e81370a22..ef3cd36689f630df7bd895855f52e6d05f5df5b5 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/blk_types.h>
 #include <linux/workqueue.h>
 #include <linux/percpu-rwsem.h>
+#include <linux/delayed_call.h>
 
 #include <asm/byteorder.h>
 #include <uapi/linux/fs.h>
@@ -1633,12 +1634,11 @@ struct file_operations {
 
 struct inode_operations {
        struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
-       const char * (*follow_link) (struct dentry *, void **);
+       const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *);
        int (*permission) (struct inode *, int);
        struct posix_acl * (*get_acl)(struct inode *, int);
 
        int (*readlink) (struct dentry *, char __user *,int);
-       void (*put_link) (struct inode *, void *);
 
        int (*create) (struct inode *,struct dentry *, umode_t, bool);
        int (*link) (struct dentry *,struct inode *,struct dentry *);
@@ -2736,14 +2736,14 @@ extern const struct file_operations generic_ro_fops;
 
 extern int readlink_copy(char __user *, int, const char *);
 extern int page_readlink(struct dentry *, char __user *, int);
-extern const char *page_follow_link_light(struct dentry *, void **);
-extern void page_put_link(struct inode *, void *);
+extern const char *page_get_link(struct dentry *, struct inode *,
+                                struct delayed_call *);
+extern void page_put_link(void *);
 extern int __page_symlink(struct inode *inode, const char *symname, int len,
                int nofs);
 extern int page_symlink(struct inode *inode, const char *symname, int len);
 extern const struct inode_operations page_symlink_inode_operations;
-extern void kfree_put_link(struct inode *, void *);
-extern void free_page_put_link(struct inode *, void *);
+extern void kfree_link(void *);
 extern int generic_readlink(struct dentry *, char __user *, int);
 extern void generic_fillattr(struct inode *, struct kstat *);
 int vfs_getattr_nosec(struct path *path, struct kstat *stat);
@@ -2754,7 +2754,8 @@ void __inode_sub_bytes(struct inode *inode, loff_t bytes);
 void inode_sub_bytes(struct inode *inode, loff_t bytes);
 loff_t inode_get_bytes(struct inode *inode);
 void inode_set_bytes(struct inode *inode, loff_t bytes);
-const char *simple_follow_link(struct dentry *, void **);
+const char *simple_get_link(struct dentry *, struct inode *,
+                           struct delayed_call *);
 extern const struct inode_operations simple_symlink_inode_operations;
 
 extern int iterate_dir(struct file *, struct dir_context *);
@@ -2764,8 +2765,6 @@ extern int vfs_lstat(const char __user *, struct kstat *);
 extern int vfs_fstat(unsigned int, struct kstat *);
 extern int vfs_fstatat(int , const char __user *, struct kstat *, int);
 
-extern int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
-                   unsigned long arg);
 extern int __generic_block_fiemap(struct inode *inode,
                                  struct fiemap_extent_info *fieinfo,
                                  loff_t start, loff_t len,
@@ -3025,5 +3024,6 @@ static inline bool dir_relax(struct inode *inode)
 }
 
 extern bool path_noexec(const struct path *path);
+extern void inode_nohighmem(struct inode *inode);
 
 #endif /* _LINUX_FS_H */
index eae6548efbf060d9a2ec21bd716b0c0e2b6f2be7..60048c50404ee612aae6535ef8abfcf8475086d6 100644 (file)
@@ -586,6 +586,7 @@ extern int ftrace_arch_read_dyn_info(char *buf, int size);
 
 extern int skip_trace(unsigned long ip);
 extern void ftrace_module_init(struct module *mod);
+extern void ftrace_release_mod(struct module *mod);
 
 extern void ftrace_disable_daemon(void);
 extern void ftrace_enable_daemon(void);
index c9ae0c6ec050569fc592b6f07b3ce1fa052bcc59..d5d798b35c1f6c105c81d0993bce6140bc4fc83b 100644 (file)
@@ -330,6 +330,7 @@ struct rdists {
 };
 
 struct irq_domain;
+struct device_node;
 int its_cpu_init(void);
 int its_init(struct device_node *node, struct rdists *rdists,
             struct irq_domain *domain);
index 8dde55974f186bca7c1488866aaacdd805c347b3..0536524bb9eb6467013a51a70ed28b576494e649 100644 (file)
@@ -5,7 +5,7 @@
  * Jump label support
  *
  * Copyright (C) 2009-2012 Jason Baron <jbaron@redhat.com>
- * Copyright (C) 2011-2012 Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright (C) 2011-2012 Red Hat, Inc., Peter Zijlstra
  *
  * DEPRECATED API:
  *
index d0a1f99e24e3eb43219e9f8b8aad400c1cc867a9..4894c6888bc6cfb95e50d43366784769faf9b281 100644 (file)
@@ -25,7 +25,7 @@
 
 #ifdef CONFIG_DEBUG_KMEMLEAK
 
-extern void kmemleak_init(void) __ref;
+extern void kmemleak_init(void) __init;
 extern void kmemleak_alloc(const void *ptr, size_t size, int min_count,
                           gfp_t gfp) __ref;
 extern void kmemleak_alloc_percpu(const void __percpu *ptr, size_t size,
index 83577f8fd15bcd0f8693ef6a1a2a9fb216b32b2b..600c1e0626a5ff6c91df3a0b2f2fcf0ef485fedf 100644 (file)
@@ -210,6 +210,7 @@ enum {
        ATA_FLAG_SLAVE_POSS     = (1 << 0), /* host supports slave dev */
                                            /* (doesn't imply presence) */
        ATA_FLAG_SATA           = (1 << 1),
+       ATA_FLAG_NO_LOG_PAGE    = (1 << 5), /* do not issue log page read */
        ATA_FLAG_NO_ATAPI       = (1 << 6), /* No ATAPI support */
        ATA_FLAG_PIO_DMA        = (1 << 7), /* PIO cmds via DMA */
        ATA_FLAG_PIO_LBA48      = (1 << 8), /* Host DMA engine is LBA28 only */
index c6916aec43b66200033b5a2a2a155d8b72a947bf..034117b3be5f7d91e5e869ea9e856f51964ebac6 100644 (file)
@@ -50,9 +50,16 @@ enum {
        NVM_IO_DUAL_ACCESS      = 0x1,
        NVM_IO_QUAD_ACCESS      = 0x2,
 
+       /* NAND Access Modes */
        NVM_IO_SUSPEND          = 0x80,
        NVM_IO_SLC_MODE         = 0x100,
        NVM_IO_SCRAMBLE_DISABLE = 0x200,
+
+       /* Block Types */
+       NVM_BLK_T_FREE          = 0x0,
+       NVM_BLK_T_BAD           = 0x1,
+       NVM_BLK_T_DEV           = 0x2,
+       NVM_BLK_T_HOST          = 0x4,
 };
 
 struct nvm_id_group {
@@ -176,17 +183,17 @@ struct nvm_block;
 
 typedef int (nvm_l2p_update_fn)(u64, u32, __le64 *, void *);
 typedef int (nvm_bb_update_fn)(struct ppa_addr, int, u8 *, void *);
-typedef int (nvm_id_fn)(struct request_queue *, struct nvm_id *);
-typedef int (nvm_get_l2p_tbl_fn)(struct request_queue *, u64, u32,
+typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *);
+typedef int (nvm_get_l2p_tbl_fn)(struct nvm_dev *, u64, u32,
                                nvm_l2p_update_fn *, void *);
 typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, int,
                                nvm_bb_update_fn *, void *);
-typedef int (nvm_op_set_bb_fn)(struct request_queue *, struct nvm_rq *, int);
-typedef int (nvm_submit_io_fn)(struct request_queue *, struct nvm_rq *);
-typedef int (nvm_erase_blk_fn)(struct request_queue *, struct nvm_rq *);
-typedef void *(nvm_create_dma_pool_fn)(struct request_queue *, char *);
+typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct nvm_rq *, int);
+typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *);
+typedef int (nvm_erase_blk_fn)(struct nvm_dev *, struct nvm_rq *);
+typedef void *(nvm_create_dma_pool_fn)(struct nvm_dev *, char *);
 typedef void (nvm_destroy_dma_pool_fn)(void *);
-typedef void *(nvm_dev_dma_alloc_fn)(struct request_queue *, void *, gfp_t,
+typedef void *(nvm_dev_dma_alloc_fn)(struct nvm_dev *, void *, gfp_t,
                                                                dma_addr_t *);
 typedef void (nvm_dev_dma_free_fn)(void *, void*, dma_addr_t);
 
index 70400dc7660f72028cd6ce84cf6ec90b69537137..c57e424d914b70fc5032f9b6d1ec918e8e195c64 100644 (file)
@@ -2,7 +2,7 @@
  * Runtime locking correctness validator
  *
  *  Copyright (C) 2006,2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
- *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra
  *
  * see Documentation/locking/lockdep-design.txt for more details.
  */
index 7501626ab5293414c29df692edb6fa7122871c84..d3133be12d922521e24528480edbdb31659a7007 100644 (file)
@@ -426,6 +426,17 @@ enum {
        MLX4_MAX_FAST_REG_PAGES = 511,
 };
 
+enum {
+       /*
+        * Max wqe size for rdma read is 512 bytes, so this
+        * limits our max_sge_rd as the wqe needs to fit:
+        * - ctrl segment (16 bytes)
+        * - rdma segment (16 bytes)
+        * - scatter elements (16 bytes each)
+        */
+       MLX4_MAX_SGE_RD = (512 - 16 - 16) / 16
+};
+
 enum {
        MLX4_DEV_PMC_SUBTYPE_GUID_INFO   = 0x14,
        MLX4_DEV_PMC_SUBTYPE_PORT_INFO   = 0x15,
index 877ef226f90fb3b945831c7e8f9edbabba1e9775..772362adf4713b77be041b6232097c97a7f5aad7 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef LINUX_MM_DEBUG_H
 #define LINUX_MM_DEBUG_H 1
 
+#include <linux/bug.h>
 #include <linux/stringify.h>
 
 struct page;
index c8723b62c4cd286aa7b6b382507dbb25cd975ab1..bc742dac7d3a10da925776e9fc4a0ca283a2eda6 100644 (file)
@@ -25,7 +25,7 @@
 #define SNOR_MFR_MACRONIX      CFI_MFR_MACRONIX
 #define SNOR_MFR_SPANSION      CFI_MFR_AMD
 #define SNOR_MFR_SST           CFI_MFR_SST
-#define SNOR_MFR_WINBOND       0xef
+#define SNOR_MFR_WINBOND       0xef /* Also used by some Spansion */
 
 /*
  * Note on opcode nomenclature: some opcodes have a format like
index 3b5d134e945a9b1a5dda9b636c04909318fe8a67..3143c847bddbca47bed1a324bf85e58283e966a5 100644 (file)
@@ -2084,7 +2084,7 @@ struct pcpu_sw_netstats {
 })
 
 #define netdev_alloc_pcpu_stats(type)                                  \
-       __netdev_alloc_pcpu_stats(type, GFP_KERNEL);
+       __netdev_alloc_pcpu_stats(type, GFP_KERNEL)
 
 #include <linux/notifier.h>
 
index 249d1bb01e03b0367f56f251c02269b24be0dac6..5646b24bfc64040d595b6fd4109e0caadc21494d 100644 (file)
@@ -14,7 +14,7 @@ struct nfnl_callback {
        int (*call_rcu)(struct sock *nl, struct sk_buff *skb, 
                    const struct nlmsghdr *nlh,
                    const struct nlattr * const cda[]);
-       int (*call_batch)(struct sock *nl, struct sk_buff *skb,
+       int (*call_batch)(struct net *net, struct sock *nl, struct sk_buff *skb,
                          const struct nlmsghdr *nlh,
                          const struct nlattr * const cda[]);
        const struct nla_policy *policy;        /* netlink attribute policy */
index c0e961474a527058c8d1ac2aa72070c9b15e3db5..37a3d2981352940c0797e9a9e90e3c388cfb9c83 100644 (file)
@@ -359,6 +359,7 @@ extern int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode);
 extern int nfs_revalidate_inode_rcu(struct nfs_server *server, struct inode *inode);
 extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *);
 extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping);
+extern int nfs_revalidate_mapping_rcu(struct inode *inode);
 extern int nfs_revalidate_mapping_protected(struct inode *inode, struct address_space *mapping);
 extern int nfs_setattr(struct dentry *, struct iattr *);
 extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr, struct nfs_fattr *);
index 039f2eec49ced0ae1c638354d1a34c924cebde51..1e0deb8e849458ca179c1df4734bb24f0e4cd748 100644 (file)
@@ -46,12 +46,14 @@ extern int of_irq_get(struct device_node *dev, int index);
 extern int of_irq_get_byname(struct device_node *dev, const char *name);
 extern int of_irq_to_resource_table(struct device_node *dev,
                struct resource *res, int nr_irqs);
+extern struct device_node *of_irq_find_parent(struct device_node *child);
 extern struct irq_domain *of_msi_get_domain(struct device *dev,
                                            struct device_node *np,
                                            enum irq_domain_bus_token token);
 extern struct irq_domain *of_msi_map_get_device_domain(struct device *dev,
                                                       u32 rid);
 extern void of_msi_configure(struct device *dev, struct device_node *np);
+u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in);
 #else
 static inline int of_irq_count(struct device_node *dev)
 {
@@ -70,6 +72,11 @@ static inline int of_irq_to_resource_table(struct device_node *dev,
 {
        return 0;
 }
+static inline void *of_irq_find_parent(struct device_node *child)
+{
+       return NULL;
+}
+
 static inline struct irq_domain *of_msi_get_domain(struct device *dev,
                                                   struct device_node *np,
                                                   enum irq_domain_bus_token token)
@@ -84,6 +91,11 @@ static inline struct irq_domain *of_msi_map_get_device_domain(struct device *dev
 static inline void of_msi_configure(struct device *dev, struct device_node *np)
 {
 }
+static inline u32 of_msi_map_rid(struct device *dev,
+                                struct device_node *msi_np, u32 rid_in)
+{
+       return rid_in;
+}
 #endif
 
 #if defined(CONFIG_OF_IRQ) || defined(CONFIG_SPARC)
@@ -93,7 +105,6 @@ static inline void of_msi_configure(struct device *dev, struct device_node *np)
  * so declare it here regardless of the CONFIG_OF_IRQ setting.
  */
 extern unsigned int irq_of_parse_and_map(struct device_node *node, int index);
-u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in);
 
 #else /* !CONFIG_OF && !CONFIG_SPARC */
 static inline unsigned int irq_of_parse_and_map(struct device_node *dev,
@@ -101,12 +112,6 @@ static inline unsigned int irq_of_parse_and_map(struct device_node *dev,
 {
        return 0;
 }
-
-static inline u32 of_msi_map_rid(struct device *dev,
-                                struct device_node *msi_np, u32 rid_in)
-{
-       return rid_in;
-}
 #endif /* !CONFIG_OF */
 
 #endif /* __OF_IRQ_H */
index d841d33bcdc9c370742db6408e1f979594d37099..f9828a48f16addab4737683f3c8345ab87e52a0a 100644 (file)
@@ -697,9 +697,11 @@ struct perf_cgroup {
  * if there is no cgroup event for the current CPU context.
  */
 static inline struct perf_cgroup *
-perf_cgroup_from_task(struct task_struct *task)
+perf_cgroup_from_task(struct task_struct *task, struct perf_event_context *ctx)
 {
-       return container_of(task_css(task, perf_event_cgrp_id),
+       return container_of(task_css_check(task, perf_event_cgrp_id,
+                                          ctx ? lockdep_is_held(&ctx->lock)
+                                              : true),
                            struct perf_cgroup, css);
 }
 #endif /* CONFIG_CGROUP_PERF */
index e2878baeb90e8c804a27d90c37c7d79f14e95942..4299f4ba03bdde8a8eae4209f1cf537b63f0171f 100644 (file)
@@ -72,7 +72,7 @@ struct edma_soc_info {
        struct edma_rsv_info    *rsv;
 
        /* List of channels allocated for memcpy, terminated with -1 */
-       s16                     *memcpy_channels;
+       s32                     *memcpy_channels;
 
        s8      (*queue_priority_mapping)[2];
        const s16       (*xbar_chans)[2];
index 5440f64d2942a7957e0831a15918fc070ac63193..21221338ad18018b9b8c479efe1f938b67e6f685 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * FLoating proportions
  *
- *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra
  *
  * This file contains the public data structure and API definitions.
  */
index 6a4347639c0329235a735d723a564acecf59f022..1d1ba2c5ee7a26f6a35b1835c016a6bd7755fcd8 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef __COMMON_HSI__
 #define __COMMON_HSI__
 
+#define CORE_SPQE_PAGE_SIZE_BYTES                       4096
+
 #define FW_MAJOR_VERSION       8
 #define FW_MINOR_VERSION       4
 #define FW_REVISION_VERSION    2
index b920c3605c462ef0bdb9c8ba0c8cd9d8957addb7..41b9049b57e2475575d076b4f0728234618ce07e 100644 (file)
@@ -111,7 +111,8 @@ static inline u16 qed_chain_get_elem_left(struct qed_chain *p_chain)
        used = ((u32)0x10000u + (u32)(p_chain->prod_idx)) -
                (u32)p_chain->cons_idx;
        if (p_chain->mode == QED_CHAIN_MODE_NEXT_PTR)
-               used -= (used / p_chain->elem_per_page);
+               used -= p_chain->prod_idx / p_chain->elem_per_page -
+                       p_chain->cons_idx / p_chain->elem_per_page;
 
        return p_chain->capacity - used;
 }
index 843ceca9a21e5f1327fa5c82fa5f3089c5ebab23..e50b31d18462c02e5362e84bdeac4f0ab4e0f1ea 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/atomic.h>
 #include <linux/compiler.h>
+#include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/jhash.h>
 #include <linux/list_nulls.h>
@@ -339,10 +340,11 @@ static inline int lockdep_rht_bucket_is_held(const struct bucket_table *tbl,
 int rhashtable_init(struct rhashtable *ht,
                    const struct rhashtable_params *params);
 
-int rhashtable_insert_slow(struct rhashtable *ht, const void *key,
-                          struct rhash_head *obj,
-                          struct bucket_table *old_tbl);
-int rhashtable_insert_rehash(struct rhashtable *ht);
+struct bucket_table *rhashtable_insert_slow(struct rhashtable *ht,
+                                           const void *key,
+                                           struct rhash_head *obj,
+                                           struct bucket_table *old_tbl);
+int rhashtable_insert_rehash(struct rhashtable *ht, struct bucket_table *tbl);
 
 int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter);
 void rhashtable_walk_exit(struct rhashtable_iter *iter);
@@ -598,9 +600,11 @@ restart:
 
        new_tbl = rht_dereference_rcu(tbl->future_tbl, ht);
        if (unlikely(new_tbl)) {
-               err = rhashtable_insert_slow(ht, key, obj, new_tbl);
-               if (err == -EAGAIN)
+               tbl = rhashtable_insert_slow(ht, key, obj, new_tbl);
+               if (!IS_ERR_OR_NULL(tbl))
                        goto slow_path;
+
+               err = PTR_ERR(tbl);
                goto out;
        }
 
@@ -611,7 +615,7 @@ restart:
        if (unlikely(rht_grow_above_100(ht, tbl))) {
 slow_path:
                spin_unlock_bh(lock);
-               err = rhashtable_insert_rehash(ht);
+               err = rhashtable_insert_rehash(ht, tbl);
                rcu_read_unlock();
                if (err)
                        return err;
index edad7a43edea141b3ada89f7f12edac2add7b68e..fa39434e3fdd1c74eaf18dd4a31dae0b69a9db1c 100644 (file)
@@ -1455,14 +1455,15 @@ struct task_struct {
        /* Used for emulating ABI behavior of previous Linux versions */
        unsigned int personality;
 
-       unsigned in_execve:1;   /* Tell the LSMs that the process is doing an
-                                * execve */
-       unsigned in_iowait:1;
-
-       /* Revert to default priority/policy when forking */
+       /* scheduler bits, serialized by scheduler locks */
        unsigned sched_reset_on_fork:1;
        unsigned sched_contributes_to_load:1;
        unsigned sched_migrated:1;
+       unsigned :0; /* force alignment to the next boundary */
+
+       /* unserialized, strictly 'current' */
+       unsigned in_execve:1; /* bit to tell LSMs we're in execve */
+       unsigned in_iowait:1;
 #ifdef CONFIG_MEMCG
        unsigned memcg_may_oom:1;
 #endif
@@ -2002,7 +2003,8 @@ static inline int pid_alive(const struct task_struct *p)
 }
 
 /**
- * is_global_init - check if a task structure is init
+ * is_global_init - check if a task structure is init. Since init
+ * is free to have sub-threads we need to check tgid.
  * @tsk: Task structure to be checked.
  *
  * Check if a task structure is the first user space task the kernel created.
@@ -2011,7 +2013,7 @@ static inline int pid_alive(const struct task_struct *p)
  */
 static inline int is_global_init(struct task_struct *tsk)
 {
-       return tsk->pid == 1;
+       return task_tgid_nr(tsk) == 1;
 }
 
 extern struct pid *cad_pid;
index 0adedca24c5bfbd4ca7a25b80641e76e0e638738..0e1b1540597a47253b6a2e5cc3ef1709d4a42992 100644 (file)
@@ -99,7 +99,7 @@ static inline int try_stop_cpus(const struct cpumask *cpumask,
  * grabbing every spinlock (and more).  So the "read" side to such a
  * lock is anything which disables preemption.
  */
-#if defined(CONFIG_STOP_MACHINE) && defined(CONFIG_SMP)
+#if defined(CONFIG_SMP) || defined(CONFIG_HOTPLUG_CPU)
 
 /**
  * stop_machine: freeze the machine on all CPUs and run this function
@@ -118,7 +118,7 @@ int stop_machine(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus);
 
 int stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data,
                                   const struct cpumask *cpus);
-#else   /* CONFIG_STOP_MACHINE && CONFIG_SMP */
+#else  /* CONFIG_SMP || CONFIG_HOTPLUG_CPU */
 
 static inline int stop_machine(cpu_stop_fn_t fn, void *data,
                                 const struct cpumask *cpus)
@@ -137,5 +137,5 @@ static inline int stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data,
        return stop_machine(fn, data, cpus);
 }
 
-#endif /* CONFIG_STOP_MACHINE && CONFIG_SMP */
+#endif /* CONFIG_SMP || CONFIG_HOTPLUG_CPU */
 #endif /* _LINUX_STOP_MACHINE */
index 0bdc72f3690545dd3ac34d1f4b204f2e1db02eb6..4a29c75b146e1c9afc550c6c6bab58f17ed8e2da 100644 (file)
@@ -21,7 +21,7 @@
  * Authors:
  *     Srikar Dronamraju
  *     Jim Keniston
- * Copyright (C) 2011-2012 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright (C) 2011-2012 Red Hat, Inc., Peter Zijlstra
  */
 
 #include <linux/errno.h>
index 1f6526c76ee84f4068707bd0ecae16aaa25c0759..3a375d07d0dc0284441133228af266956ed94f89 100644 (file)
@@ -138,6 +138,7 @@ struct cdc_ncm_ctx {
 };
 
 u8 cdc_ncm_select_altsetting(struct usb_interface *intf);
+int cdc_ncm_change_mtu(struct net_device *net, int new_mtu);
 int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting, int drvflags);
 void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf);
 struct sk_buff *cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign);
index 9948c874e3f1e4e254ea666a3a7e623678edc26d..1d0043dc34e427403a1c82458249bed83e87d3a0 100644 (file)
@@ -47,4 +47,7 @@
 /* device generates spurious wakeup, ignore remote wakeup capability */
 #define USB_QUIRK_IGNORE_REMOTE_WAKEUP         BIT(9)
 
+/* device can't handle Link Power Management */
+#define USB_QUIRK_NO_LPM                       BIT(10)
+
 #endif /* __LINUX_USB_QUIRKS_H */
index 610a86a892b8896363ece505cdbe686096505cfc..ddb44097538245f17e882efff635143ada49e089 100644 (file)
@@ -44,9 +44,6 @@ struct vfio_device_ops {
        void    (*request)(void *device_data, unsigned int count);
 };
 
-extern struct iommu_group *vfio_iommu_group_get(struct device *dev);
-extern void vfio_iommu_group_put(struct iommu_group *group, struct device *dev);
-
 extern int vfio_add_group_dev(struct device *dev,
                              const struct vfio_device_ops *ops,
                              void *device_data);
index 5dbc8b0ee567a751cf8c60872ae692fccb6a86ab..3e5d9075960f6c756ead3c60013f84f873206932 100644 (file)
@@ -176,11 +176,11 @@ extern void zone_statistics(struct zone *, struct zone *, gfp_t gfp);
 #define sub_zone_page_state(__z, __i, __d) mod_zone_page_state(__z, __i, -(__d))
 
 #ifdef CONFIG_SMP
-void __mod_zone_page_state(struct zone *, enum zone_stat_item item, int);
+void __mod_zone_page_state(struct zone *, enum zone_stat_item item, long);
 void __inc_zone_page_state(struct page *, enum zone_stat_item);
 void __dec_zone_page_state(struct page *, enum zone_stat_item);
 
-void mod_zone_page_state(struct zone *, enum zone_stat_item, int);
+void mod_zone_page_state(struct zone *, enum zone_stat_item, long);
 void inc_zone_page_state(struct page *, enum zone_stat_item);
 void dec_zone_page_state(struct page *, enum zone_stat_item);
 
@@ -205,7 +205,7 @@ void set_pgdat_percpu_threshold(pg_data_t *pgdat,
  * The functions directly modify the zone and global counters.
  */
 static inline void __mod_zone_page_state(struct zone *zone,
-                       enum zone_stat_item item, int delta)
+                       enum zone_stat_item item, long delta)
 {
        zone_page_state_add(delta, zone, item);
 }
index 1e1bf9f963a947fc686125d0a2809ad63b8a13ed..513b36f04dfd80bbe9cf40a272e8d2cd2eab452b 100644 (file)
@@ -145,7 +145,7 @@ __remove_wait_queue(wait_queue_head_t *head, wait_queue_t *old)
        list_del(&old->task_list);
 }
 
-typedef int wait_bit_action_f(struct wait_bit_key *);
+typedef int wait_bit_action_f(struct wait_bit_key *, int mode);
 void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr, void *key);
 void __wake_up_locked_key(wait_queue_head_t *q, unsigned int mode, void *key);
 void __wake_up_sync_key(wait_queue_head_t *q, unsigned int mode, int nr, void *key);
@@ -960,10 +960,10 @@ int wake_bit_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
        } while (0)
 
 
-extern int bit_wait(struct wait_bit_key *);
-extern int bit_wait_io(struct wait_bit_key *);
-extern int bit_wait_timeout(struct wait_bit_key *);
-extern int bit_wait_io_timeout(struct wait_bit_key *);
+extern int bit_wait(struct wait_bit_key *, int);
+extern int bit_wait_io(struct wait_bit_key *, int);
+extern int bit_wait_timeout(struct wait_bit_key *, int);
+extern int bit_wait_io_timeout(struct wait_bit_key *, int);
 
 /**
  * wait_on_bit - wait for a bit to be cleared
index 1279f9b09791ace6885b0dd67c2c28d578b6cd8e..c7329dcd90cc0637e16fe65eb78246a5d8d21521 100644 (file)
@@ -322,6 +322,39 @@ static inline void skb_dst_force(struct sk_buff *skb)
        }
 }
 
+/**
+ * dst_hold_safe - Take a reference on a dst if possible
+ * @dst: pointer to dst entry
+ *
+ * This helper returns false if it could not safely
+ * take a reference on a dst.
+ */
+static inline bool dst_hold_safe(struct dst_entry *dst)
+{
+       if (dst->flags & DST_NOCACHE)
+               return atomic_inc_not_zero(&dst->__refcnt);
+       dst_hold(dst);
+       return true;
+}
+
+/**
+ * skb_dst_force_safe - makes sure skb dst is refcounted
+ * @skb: buffer
+ *
+ * If dst is not yet refcounted and not destroyed, grab a ref on it.
+ */
+static inline void skb_dst_force_safe(struct sk_buff *skb)
+{
+       if (skb_dst_is_noref(skb)) {
+               struct dst_entry *dst = skb_dst(skb);
+
+               if (!dst_hold_safe(dst))
+                       dst = NULL;
+
+               skb->_skb_refdst = (unsigned long)dst;
+       }
+}
+
 
 /**
  *     __skb_tunnel_rx - prepare skb for rx reinsert
index 2134e6d815bcb0611a2f65cd7b4da44cb7762b8c..625bdf95d673d16eda11884e9adf1595c9926d0f 100644 (file)
@@ -210,18 +210,37 @@ struct inet_sock {
 #define IP_CMSG_ORIGDSTADDR    BIT(6)
 #define IP_CMSG_CHECKSUM       BIT(7)
 
-/* SYNACK messages might be attached to request sockets.
+/**
+ * sk_to_full_sk - Access to a full socket
+ * @sk: pointer to a socket
+ *
+ * SYNACK messages might be attached to request sockets.
  * Some places want to reach the listener in this case.
  */
-static inline struct sock *skb_to_full_sk(const struct sk_buff *skb)
+static inline struct sock *sk_to_full_sk(struct sock *sk)
 {
-       struct sock *sk = skb->sk;
-
+#ifdef CONFIG_INET
        if (sk && sk->sk_state == TCP_NEW_SYN_RECV)
                sk = inet_reqsk(sk)->rsk_listener;
+#endif
+       return sk;
+}
+
+/* sk_to_full_sk() variant with a const argument */
+static inline const struct sock *sk_const_to_full_sk(const struct sock *sk)
+{
+#ifdef CONFIG_INET
+       if (sk && sk->sk_state == TCP_NEW_SYN_RECV)
+               sk = ((const struct request_sock *)sk)->rsk_listener;
+#endif
        return sk;
 }
 
+static inline struct sock *skb_to_full_sk(const struct sk_buff *skb)
+{
+       return sk_to_full_sk(skb->sk);
+}
+
 static inline struct inet_sock *inet_sk(const struct sock *sk)
 {
        return (struct inet_sock *)sk;
index 4a6009d4486b9cfc914d583c5065a3be3d23fa7e..235c7811a86a1df748d838c6b4fd453cea0cbf40 100644 (file)
@@ -78,6 +78,7 @@ void inet_initpeers(void) __init;
 static inline void inetpeer_set_addr_v4(struct inetpeer_addr *iaddr, __be32 ip)
 {
        iaddr->a4.addr = ip;
+       iaddr->a4.vif = 0;
        iaddr->family = AF_INET;
 }
 
index 774d85b2d5d97734b79eadea20f090ebf684b057..5689a0c749f76cd7ce5810b6ac165e43ddb0b59d 100644 (file)
@@ -29,7 +29,7 @@ struct l3mdev_ops {
        /* IPv4 ops */
        struct rtable * (*l3mdev_get_rtable)(const struct net_device *dev,
                                             const struct flowi4 *fl4);
-       void            (*l3mdev_get_saddr)(struct net_device *dev,
+       int             (*l3mdev_get_saddr)(struct net_device *dev,
                                            struct flowi4 *fl4);
 
        /* IPv6 ops */
@@ -112,10 +112,11 @@ static inline bool netif_index_is_l3_master(struct net *net, int ifindex)
        return rc;
 }
 
-static inline void l3mdev_get_saddr(struct net *net, int ifindex,
-                                   struct flowi4 *fl4)
+static inline int l3mdev_get_saddr(struct net *net, int ifindex,
+                                  struct flowi4 *fl4)
 {
        struct net_device *dev;
+       int rc = 0;
 
        if (ifindex) {
 
@@ -124,11 +125,13 @@ static inline void l3mdev_get_saddr(struct net *net, int ifindex,
                dev = dev_get_by_index_rcu(net, ifindex);
                if (dev && netif_is_l3_master(dev) &&
                    dev->l3mdev_ops->l3mdev_get_saddr) {
-                       dev->l3mdev_ops->l3mdev_get_saddr(dev, fl4);
+                       rc = dev->l3mdev_ops->l3mdev_get_saddr(dev, fl4);
                }
 
                rcu_read_unlock();
        }
+
+       return rc;
 }
 
 static inline struct dst_entry *l3mdev_get_rt6_dst(const struct net_device *dev,
@@ -200,9 +203,10 @@ static inline bool netif_index_is_l3_master(struct net *net, int ifindex)
        return false;
 }
 
-static inline void l3mdev_get_saddr(struct net *net, int ifindex,
-                                   struct flowi4 *fl4)
+static inline int l3mdev_get_saddr(struct net *net, int ifindex,
+                                  struct flowi4 *fl4)
 {
+       return 0;
 }
 
 static inline
index ee81307863d56329c097bb3ec30d06b07828b2d0..a3b9ef74a3895dbce95b0eba9b4bb298f7be9d71 100644 (file)
@@ -283,7 +283,12 @@ static inline struct rtable *ip_route_connect(struct flowi4 *fl4,
                              sport, dport, sk);
 
        if (!src && oif) {
-               l3mdev_get_saddr(net, oif, fl4);
+               int rc;
+
+               rc = l3mdev_get_saddr(net, oif, fl4);
+               if (rc < 0)
+                       return ERR_PTR(rc);
+
                src = fl4->saddr;
        }
        if (!dst || !src) {
index 7bbb71081aeb6cfdc9cb049cf7a094dbcd4603bb..eea9bdeecba27f0ecff39e9d821fc029028f8e5b 100644 (file)
@@ -1493,7 +1493,8 @@ struct sctp_association {
                 *             : SACK's are not delayed (see Section 6).
                 */
                __u8    sack_needed:1,     /* Do we need to sack the peer? */
-                       sack_generation:1;
+                       sack_generation:1,
+                       zero_window_announced:1;
                __u32   sack_cnt;
 
                __u32   adaptation_ind;  /* Adaptation Code point. */
index 52d27ee924f47867026d8f65c65551a9137219d3..14d3c07340079b7a3e9de54ee635011589247ffd 100644 (file)
@@ -388,7 +388,7 @@ struct sock {
                struct socket_wq        *sk_wq_raw;
        };
 #ifdef CONFIG_XFRM
-       struct xfrm_policy      *sk_policy[2];
+       struct xfrm_policy __rcu *sk_policy[2];
 #endif
        struct dst_entry        *sk_rx_dst;
        struct dst_entry __rcu  *sk_dst_cache;
@@ -404,6 +404,7 @@ struct sock {
                                sk_userlocks : 4,
                                sk_protocol  : 8,
                                sk_type      : 16;
+#define SK_PROTOCOL_MAX U8_MAX
        kmemcheck_bitfield_end(flags);
        int                     sk_wmem_queued;
        gfp_t                   sk_allocation;
@@ -740,6 +741,8 @@ enum sock_flags {
        SOCK_SELECT_ERR_QUEUE, /* Wake select on error queue */
 };
 
+#define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE))
+
 static inline void sock_copy_flags(struct sock *nsk, struct sock *osk)
 {
        nsk->sk_flags = osk->sk_flags;
@@ -814,7 +817,7 @@ void sk_stream_write_space(struct sock *sk);
 static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb)
 {
        /* dont let skb dst not refcounted, we are going to leave rcu lock */
-       skb_dst_force(skb);
+       skb_dst_force_safe(skb);
 
        if (!sk->sk_backlog.tail)
                sk->sk_backlog.head = skb;
index c1c899c3a51be42f680fff5ce0f5c5e997652daa..e289ada6adf6b0a7bd45debd46488a28b2642ee6 100644 (file)
@@ -79,7 +79,7 @@ struct vxlanhdr {
 };
 
 /* VXLAN header flags. */
-#define VXLAN_HF_RCO BIT(24)
+#define VXLAN_HF_RCO BIT(21)
 #define VXLAN_HF_VNI BIT(27)
 #define VXLAN_HF_GBP BIT(31)
 
index 4a9c21f9b4ea189075901a3f2c8c12ec6814f5fe..d6f6e5006ee9e3cb8dcd61e151fcc95ce165eab9 100644 (file)
@@ -548,6 +548,7 @@ struct xfrm_policy {
        u16                     family;
        struct xfrm_sec_ctx     *security;
        struct xfrm_tmpl        xfrm_vec[XFRM_MAX_DEPTH];
+       struct rcu_head         rcu;
 };
 
 static inline struct net *xp_net(const struct xfrm_policy *xp)
@@ -1141,12 +1142,14 @@ static inline int xfrm6_route_forward(struct sk_buff *skb)
        return xfrm_route_forward(skb, AF_INET6);
 }
 
-int __xfrm_sk_clone_policy(struct sock *sk);
+int __xfrm_sk_clone_policy(struct sock *sk, const struct sock *osk);
 
-static inline int xfrm_sk_clone_policy(struct sock *sk)
+static inline int xfrm_sk_clone_policy(struct sock *sk, const struct sock *osk)
 {
-       if (unlikely(sk->sk_policy[0] || sk->sk_policy[1]))
-               return __xfrm_sk_clone_policy(sk);
+       sk->sk_policy[0] = NULL;
+       sk->sk_policy[1] = NULL;
+       if (unlikely(osk->sk_policy[0] || osk->sk_policy[1]))
+               return __xfrm_sk_clone_policy(sk, osk);
        return 0;
 }
 
@@ -1154,12 +1157,16 @@ int xfrm_policy_delete(struct xfrm_policy *pol, int dir);
 
 static inline void xfrm_sk_free_policy(struct sock *sk)
 {
-       if (unlikely(sk->sk_policy[0] != NULL)) {
-               xfrm_policy_delete(sk->sk_policy[0], XFRM_POLICY_MAX);
+       struct xfrm_policy *pol;
+
+       pol = rcu_dereference_protected(sk->sk_policy[0], 1);
+       if (unlikely(pol != NULL)) {
+               xfrm_policy_delete(pol, XFRM_POLICY_MAX);
                sk->sk_policy[0] = NULL;
        }
-       if (unlikely(sk->sk_policy[1] != NULL)) {
-               xfrm_policy_delete(sk->sk_policy[1], XFRM_POLICY_MAX+1);
+       pol = rcu_dereference_protected(sk->sk_policy[1], 1);
+       if (unlikely(pol != NULL)) {
+               xfrm_policy_delete(pol, XFRM_POLICY_MAX+1);
                sk->sk_policy[1] = NULL;
        }
 }
@@ -1169,7 +1176,7 @@ void xfrm_garbage_collect(struct net *net);
 #else
 
 static inline void xfrm_sk_free_policy(struct sock *sk) {}
-static inline int xfrm_sk_clone_policy(struct sock *sk) { return 0; }
+static inline int xfrm_sk_clone_policy(struct sock *sk, const struct sock *osk) { return 0; }
 static inline int xfrm6_route_forward(struct sk_buff *skb) { return 1; }  
 static inline int xfrm4_route_forward(struct sk_buff *skb) { return 1; } 
 static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *skb)
index 188df91d58514a3248cab5b1b0d7ee09513295a6..ec9b44dd3d806b20d80920a0cb37487ea2d12c24 100644 (file)
@@ -237,6 +237,8 @@ struct ib_vendor_mad {
        u8                      data[IB_MGMT_VENDOR_DATA];
 };
 
+#define IB_MGMT_CLASSPORTINFO_ATTR_ID  cpu_to_be16(0x0001)
+
 struct ib_class_port_info {
        u8                      base_version;
        u8                      class_version;
index 9a68a19532ba57c27042cec499843f3cebfa273c..120da1d7f57eb578c327507ad2affa5b89488dbb 100644 (file)
@@ -1271,6 +1271,7 @@ struct ib_uobject {
        int                     id;             /* index into kernel idr */
        struct kref             ref;
        struct rw_semaphore     mutex;          /* protects .live */
+       struct rcu_head         rcu;            /* kfree_rcu() overhead */
        int                     live;
 };
 
index 2ae8812d7b1a37845789b7c0522c0ab1b4300c45..94dc6a9772e060ce31d97434b9972f6ff255a63b 100644 (file)
@@ -93,6 +93,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define AZX_REG_HSW_EM4                        0x100c
 #define AZX_REG_HSW_EM5                        0x1010
 
+/* Skylake/Broxton display HD-A controller Extended Mode registers */
+#define AZX_REG_SKL_EM4L               0x1040
+
 /* PCI space */
 #define AZX_PCIREG_TCSEL               0x44
 
index a8b4b9c8b1d2415e7220913715fc2cd4bd95212c..fb955e69a78ea29f79bd4382b492bca009cd6fe7 100644 (file)
@@ -1655,7 +1655,7 @@ extern const struct dev_pm_ops snd_soc_pm_ops;
 /* Helper functions */
 static inline void snd_soc_dapm_mutex_lock(struct snd_soc_dapm_context *dapm)
 {
-       mutex_lock(&dapm->card->dapm_mutex);
+       mutex_lock_nested(&dapm->card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME);
 }
 
 static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm)
index 628e6e64c2fb4ff2c858a57e0beeca3aa4fd49b6..c2e5d6cb34e36ba2e409985c7d66c70347dbebc7 100644 (file)
@@ -186,6 +186,7 @@ header-y += if_tunnel.h
 header-y += if_vlan.h
 header-y += if_x25.h
 header-y += igmp.h
+header-y += ila.h
 header-y += in6.h
 header-y += inet_diag.h
 header-y += in.h
index 28ccedd000f5720f6f41660ea6f049b9fd9f145c..a27222d5b413a85d4c773b5b43563bf9b57831d2 100644 (file)
@@ -628,7 +628,7 @@ struct ovs_action_hash {
  * @OVS_CT_ATTR_MARK: u32 value followed by u32 mask. For each bit set in the
  * mask, the corresponding bit in the value is copied to the connection
  * tracking mark field in the connection.
- * @OVS_CT_ATTR_LABEL: %OVS_CT_LABELS_LEN value followed by %OVS_CT_LABELS_LEN
+ * @OVS_CT_ATTR_LABELS: %OVS_CT_LABELS_LEN value followed by %OVS_CT_LABELS_LEN
  * mask. For each bit set in the mask, the corresponding bit in the value is
  * copied to the connection tracking label field in the connection.
  * @OVS_CT_ATTR_HELPER: variable length string defining conntrack ALG.
index 751b69f858c80411c910f21db7fb50c8902e94cf..9fd7b5d8df2fa357f434a899cccfa7810f826107 100644 (file)
 
 #define VFIO_SPAPR_TCE_v2_IOMMU                7
 
-/*
- * The No-IOMMU IOMMU offers no translation or isolation for devices and
- * supports no ioctls outside of VFIO_CHECK_EXTENSION.  Use of VFIO's No-IOMMU
- * code will taint the host kernel and should be used with extreme caution.
- */
-#define VFIO_NOIOMMU_IOMMU             8
-
 /*
  * The IOCTL interface is designed for extensibility by embedding the
  * structure length (argsz) and flags into structures passed between
index 7d28aff605c7eb600c4c3bfe93b8b5f1edbaebfe..7dc685b4057d33ad227d861a2a3115a5ca55cd3e 100644 (file)
@@ -181,6 +181,20 @@ struct __name##_back_ring {                                                \
 #define RING_GET_REQUEST(_r, _idx)                                     \
     (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req))
 
+/*
+ * Get a local copy of a request.
+ *
+ * Use this in preference to RING_GET_REQUEST() so all processing is
+ * done on a local copy that cannot be modified by the other end.
+ *
+ * Note that https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145 may cause this
+ * to be ineffective where _req is a struct which consists of only bitfields.
+ */
+#define RING_COPY_REQUEST(_r, _idx, _req) do {                         \
+       /* Use volatile to force the copy into _req. */                 \
+       *(_req) = *(volatile typeof(_req))RING_GET_REQUEST(_r, _idx);   \
+} while (0)
+
 #define RING_GET_RESPONSE(_r, _idx)                                    \
     (&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp))
 
index c24b6f767bf0f2a4d8a873388a5fbd59ba01c562..235c7a2c0d2004f1121b7d98f4140683ab45ef53 100644 (file)
@@ -2030,13 +2030,6 @@ config INIT_ALL_POSSIBLE
          it was better to provide this option than to break all the archs
          and have several arch maintainers pursuing me down dark alleys.
 
-config STOP_MACHINE
-       bool
-       default y
-       depends on (SMP && MODULE_UNLOAD) || HOTPLUG_CPU
-       help
-         Need stop_machine() primitive.
-
 source "block/Kconfig"
 
 config PREEMPT_NOTIFIERS
index f1603c153890d2b9dbd37a5c687fd297c6137f24..470f6536b9e8cfb029eedb5ecdb3c3e8c3c341be 100644 (file)
@@ -97,6 +97,12 @@ static DEFINE_SPINLOCK(css_set_lock);
  */
 static DEFINE_SPINLOCK(cgroup_idr_lock);
 
+/*
+ * Protects cgroup_file->kn for !self csses.  It synchronizes notifications
+ * against file removal/re-creation across css hiding.
+ */
+static DEFINE_SPINLOCK(cgroup_file_kn_lock);
+
 /*
  * Protects cgroup_subsys->release_agent_path.  Modifying it also requires
  * cgroup_mutex.  Reading requires either cgroup_mutex or this spinlock.
@@ -754,9 +760,11 @@ static void put_css_set_locked(struct css_set *cset)
        if (!atomic_dec_and_test(&cset->refcount))
                return;
 
-       /* This css_set is dead. unlink it and release cgroup refcounts */
-       for_each_subsys(ss, ssid)
+       /* This css_set is dead. unlink it and release cgroup and css refs */
+       for_each_subsys(ss, ssid) {
                list_del(&cset->e_cset_node[ssid]);
+               css_put(cset->subsys[ssid]);
+       }
        hash_del(&cset->hlist);
        css_set_count--;
 
@@ -1056,9 +1064,13 @@ static struct css_set *find_css_set(struct css_set *old_cset,
        key = css_set_hash(cset->subsys);
        hash_add(css_set_table, &cset->hlist, key);
 
-       for_each_subsys(ss, ssid)
+       for_each_subsys(ss, ssid) {
+               struct cgroup_subsys_state *css = cset->subsys[ssid];
+
                list_add_tail(&cset->e_cset_node[ssid],
-                             &cset->subsys[ssid]->cgroup->e_csets[ssid]);
+                             &css->cgroup->e_csets[ssid]);
+               css_get(css);
+       }
 
        spin_unlock_bh(&css_set_lock);
 
@@ -1393,6 +1405,16 @@ static void cgroup_rm_file(struct cgroup *cgrp, const struct cftype *cft)
        char name[CGROUP_FILE_NAME_MAX];
 
        lockdep_assert_held(&cgroup_mutex);
+
+       if (cft->file_offset) {
+               struct cgroup_subsys_state *css = cgroup_css(cgrp, cft->ss);
+               struct cgroup_file *cfile = (void *)css + cft->file_offset;
+
+               spin_lock_irq(&cgroup_file_kn_lock);
+               cfile->kn = NULL;
+               spin_unlock_irq(&cgroup_file_kn_lock);
+       }
+
        kernfs_remove_by_name(cgrp->kn, cgroup_file_name(cgrp, cft, name));
 }
 
@@ -1856,7 +1878,6 @@ static void init_cgroup_housekeeping(struct cgroup *cgrp)
 
        INIT_LIST_HEAD(&cgrp->self.sibling);
        INIT_LIST_HEAD(&cgrp->self.children);
-       INIT_LIST_HEAD(&cgrp->self.files);
        INIT_LIST_HEAD(&cgrp->cset_links);
        INIT_LIST_HEAD(&cgrp->pidlists);
        mutex_init(&cgrp->pidlist_mutex);
@@ -2216,6 +2237,9 @@ struct cgroup_taskset {
        struct list_head        src_csets;
        struct list_head        dst_csets;
 
+       /* the subsys currently being processed */
+       int                     ssid;
+
        /*
         * Fields for cgroup_taskset_*() iteration.
         *
@@ -2278,25 +2302,29 @@ static void cgroup_taskset_add(struct task_struct *task,
 /**
  * cgroup_taskset_first - reset taskset and return the first task
  * @tset: taskset of interest
+ * @dst_cssp: output variable for the destination css
  *
  * @tset iteration is initialized and the first task is returned.
  */
-struct task_struct *cgroup_taskset_first(struct cgroup_taskset *tset)
+struct task_struct *cgroup_taskset_first(struct cgroup_taskset *tset,
+                                        struct cgroup_subsys_state **dst_cssp)
 {
        tset->cur_cset = list_first_entry(tset->csets, struct css_set, mg_node);
        tset->cur_task = NULL;
 
-       return cgroup_taskset_next(tset);
+       return cgroup_taskset_next(tset, dst_cssp);
 }
 
 /**
  * cgroup_taskset_next - iterate to the next task in taskset
  * @tset: taskset of interest
+ * @dst_cssp: output variable for the destination css
  *
  * Return the next task in @tset.  Iteration must have been initialized
  * with cgroup_taskset_first().
  */
-struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset)
+struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset,
+                                       struct cgroup_subsys_state **dst_cssp)
 {
        struct css_set *cset = tset->cur_cset;
        struct task_struct *task = tset->cur_task;
@@ -2311,6 +2339,18 @@ struct task_struct *cgroup_taskset_next(struct cgroup_taskset *tset)
                if (&task->cg_list != &cset->mg_tasks) {
                        tset->cur_cset = cset;
                        tset->cur_task = task;
+
+                       /*
+                        * This function may be called both before and
+                        * after cgroup_taskset_migrate().  The two cases
+                        * can be distinguished by looking at whether @cset
+                        * has its ->mg_dst_cset set.
+                        */
+                       if (cset->mg_dst_cset)
+                               *dst_cssp = cset->mg_dst_cset->subsys[tset->ssid];
+                       else
+                               *dst_cssp = cset->subsys[tset->ssid];
+
                        return task;
                }
 
@@ -2346,7 +2386,8 @@ static int cgroup_taskset_migrate(struct cgroup_taskset *tset,
        /* check that we can legitimately attach to the cgroup */
        for_each_e_css(css, i, dst_cgrp) {
                if (css->ss->can_attach) {
-                       ret = css->ss->can_attach(css, tset);
+                       tset->ssid = i;
+                       ret = css->ss->can_attach(tset);
                        if (ret) {
                                failed_css = css;
                                goto out_cancel_attach;
@@ -2379,9 +2420,12 @@ static int cgroup_taskset_migrate(struct cgroup_taskset *tset,
         */
        tset->csets = &tset->dst_csets;
 
-       for_each_e_css(css, i, dst_cgrp)
-               if (css->ss->attach)
-                       css->ss->attach(css, tset);
+       for_each_e_css(css, i, dst_cgrp) {
+               if (css->ss->attach) {
+                       tset->ssid = i;
+                       css->ss->attach(tset);
+               }
+       }
 
        ret = 0;
        goto out_release_tset;
@@ -2390,8 +2434,10 @@ out_cancel_attach:
        for_each_e_css(css, i, dst_cgrp) {
                if (css == failed_css)
                        break;
-               if (css->ss->cancel_attach)
-                       css->ss->cancel_attach(css, tset);
+               if (css->ss->cancel_attach) {
+                       tset->ssid = i;
+                       css->ss->cancel_attach(tset);
+               }
        }
 out_release_tset:
        spin_lock_bh(&css_set_lock);
@@ -3313,9 +3359,9 @@ static int cgroup_add_file(struct cgroup_subsys_state *css, struct cgroup *cgrp,
        if (cft->file_offset) {
                struct cgroup_file *cfile = (void *)css + cft->file_offset;
 
-               kernfs_get(kn);
+               spin_lock_irq(&cgroup_file_kn_lock);
                cfile->kn = kn;
-               list_add(&cfile->node, &css->files);
+               spin_unlock_irq(&cgroup_file_kn_lock);
        }
 
        return 0;
@@ -3552,6 +3598,22 @@ int cgroup_add_legacy_cftypes(struct cgroup_subsys *ss, struct cftype *cfts)
        return cgroup_add_cftypes(ss, cfts);
 }
 
+/**
+ * cgroup_file_notify - generate a file modified event for a cgroup_file
+ * @cfile: target cgroup_file
+ *
+ * @cfile must have been obtained by setting cftype->file_offset.
+ */
+void cgroup_file_notify(struct cgroup_file *cfile)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cgroup_file_kn_lock, flags);
+       if (cfile->kn)
+               kernfs_notify(cfile->kn);
+       spin_unlock_irqrestore(&cgroup_file_kn_lock, flags);
+}
+
 /**
  * cgroup_task_count - count the number of tasks in a cgroup.
  * @cgrp: the cgroup in question
@@ -4613,13 +4675,9 @@ static void css_free_work_fn(struct work_struct *work)
                container_of(work, struct cgroup_subsys_state, destroy_work);
        struct cgroup_subsys *ss = css->ss;
        struct cgroup *cgrp = css->cgroup;
-       struct cgroup_file *cfile;
 
        percpu_ref_exit(&css->refcnt);
 
-       list_for_each_entry(cfile, &css->files, node)
-               kernfs_put(cfile->kn);
-
        if (ss) {
                /* css free path */
                int id = css->id;
@@ -4724,7 +4782,6 @@ static void init_and_link_css(struct cgroup_subsys_state *css,
        css->ss = ss;
        INIT_LIST_HEAD(&css->sibling);
        INIT_LIST_HEAD(&css->children);
-       INIT_LIST_HEAD(&css->files);
        css->serial_nr = css_serial_nr_next++;
 
        if (cgroup_parent(cgrp)) {
index f1b30ad5dc6d925685f92ecbc0918b7c78018f30..2d3df82c54f2dd84484e0b4d739551cb69861e4e 100644 (file)
@@ -155,12 +155,10 @@ static void freezer_css_free(struct cgroup_subsys_state *css)
  * @freezer->lock.  freezer_attach() makes the new tasks conform to the
  * current state and all following state changes can see the new tasks.
  */
-static void freezer_attach(struct cgroup_subsys_state *new_css,
-                          struct cgroup_taskset *tset)
+static void freezer_attach(struct cgroup_taskset *tset)
 {
-       struct freezer *freezer = css_freezer(new_css);
        struct task_struct *task;
-       bool clear_frozen = false;
+       struct cgroup_subsys_state *new_css;
 
        mutex_lock(&freezer_mutex);
 
@@ -174,22 +172,21 @@ static void freezer_attach(struct cgroup_subsys_state *new_css,
         * current state before executing the following - !frozen tasks may
         * be visible in a FROZEN cgroup and frozen tasks in a THAWED one.
         */
-       cgroup_taskset_for_each(task, tset) {
+       cgroup_taskset_for_each(task, new_css, tset) {
+               struct freezer *freezer = css_freezer(new_css);
+
                if (!(freezer->state & CGROUP_FREEZING)) {
                        __thaw_task(task);
                } else {
                        freeze_task(task);
-                       freezer->state &= ~CGROUP_FROZEN;
-                       clear_frozen = true;
+                       /* clear FROZEN and propagate upwards */
+                       while (freezer && (freezer->state & CGROUP_FROZEN)) {
+                               freezer->state &= ~CGROUP_FROZEN;
+                               freezer = parent_freezer(freezer);
+                       }
                }
        }
 
-       /* propagate FROZEN clearing upwards */
-       while (clear_frozen && (freezer = parent_freezer(freezer))) {
-               freezer->state &= ~CGROUP_FROZEN;
-               clear_frozen = freezer->state & CGROUP_FREEZING;
-       }
-
        mutex_unlock(&freezer_mutex);
 }
 
index cdd8df4e991c7781ac5996677d724bcd23314623..b50d5a167fda7d2ae6902efd55e551efed780007 100644 (file)
@@ -106,7 +106,7 @@ static void pids_uncharge(struct pids_cgroup *pids, int num)
 {
        struct pids_cgroup *p;
 
-       for (p = pids; p; p = parent_pids(p))
+       for (p = pids; parent_pids(p); p = parent_pids(p))
                pids_cancel(p, num);
 }
 
@@ -123,7 +123,7 @@ static void pids_charge(struct pids_cgroup *pids, int num)
 {
        struct pids_cgroup *p;
 
-       for (p = pids; p; p = parent_pids(p))
+       for (p = pids; parent_pids(p); p = parent_pids(p))
                atomic64_add(num, &p->counter);
 }
 
@@ -140,7 +140,7 @@ static int pids_try_charge(struct pids_cgroup *pids, int num)
 {
        struct pids_cgroup *p, *q;
 
-       for (p = pids; p; p = parent_pids(p)) {
+       for (p = pids; parent_pids(p); p = parent_pids(p)) {
                int64_t new = atomic64_add_return(num, &p->counter);
 
                /*
@@ -162,13 +162,13 @@ revert:
        return -EAGAIN;
 }
 
-static int pids_can_attach(struct cgroup_subsys_state *css,
-                          struct cgroup_taskset *tset)
+static int pids_can_attach(struct cgroup_taskset *tset)
 {
-       struct pids_cgroup *pids = css_pids(css);
        struct task_struct *task;
+       struct cgroup_subsys_state *dst_css;
 
-       cgroup_taskset_for_each(task, tset) {
+       cgroup_taskset_for_each(task, dst_css, tset) {
+               struct pids_cgroup *pids = css_pids(dst_css);
                struct cgroup_subsys_state *old_css;
                struct pids_cgroup *old_pids;
 
@@ -187,13 +187,13 @@ static int pids_can_attach(struct cgroup_subsys_state *css,
        return 0;
 }
 
-static void pids_cancel_attach(struct cgroup_subsys_state *css,
-                              struct cgroup_taskset *tset)
+static void pids_cancel_attach(struct cgroup_taskset *tset)
 {
-       struct pids_cgroup *pids = css_pids(css);
        struct task_struct *task;
+       struct cgroup_subsys_state *dst_css;
 
-       cgroup_taskset_for_each(task, tset) {
+       cgroup_taskset_for_each(task, dst_css, tset) {
+               struct pids_cgroup *pids = css_pids(dst_css);
                struct cgroup_subsys_state *old_css;
                struct pids_cgroup *old_pids;
 
@@ -205,65 +205,28 @@ static void pids_cancel_attach(struct cgroup_subsys_state *css,
        }
 }
 
+/*
+ * task_css_check(true) in pids_can_fork() and pids_cancel_fork() relies
+ * on threadgroup_change_begin() held by the copy_process().
+ */
 static int pids_can_fork(struct task_struct *task, void **priv_p)
 {
        struct cgroup_subsys_state *css;
        struct pids_cgroup *pids;
-       int err;
 
-       /*
-        * Use the "current" task_css for the pids subsystem as the tentative
-        * css. It is possible we will charge the wrong hierarchy, in which
-        * case we will forcefully revert/reapply the charge on the right
-        * hierarchy after it is committed to the task proper.
-        */
-       css = task_get_css(current, pids_cgrp_id);
+       css = task_css_check(current, pids_cgrp_id, true);
        pids = css_pids(css);
-
-       err = pids_try_charge(pids, 1);
-       if (err)
-               goto err_css_put;
-
-       *priv_p = css;
-       return 0;
-
-err_css_put:
-       css_put(css);
-       return err;
+       return pids_try_charge(pids, 1);
 }
 
 static void pids_cancel_fork(struct task_struct *task, void *priv)
-{
-       struct cgroup_subsys_state *css = priv;
-       struct pids_cgroup *pids = css_pids(css);
-
-       pids_uncharge(pids, 1);
-       css_put(css);
-}
-
-static void pids_fork(struct task_struct *task, void *priv)
 {
        struct cgroup_subsys_state *css;
-       struct cgroup_subsys_state *old_css = priv;
        struct pids_cgroup *pids;
-       struct pids_cgroup *old_pids = css_pids(old_css);
 
-       css = task_get_css(task, pids_cgrp_id);
+       css = task_css_check(current, pids_cgrp_id, true);
        pids = css_pids(css);
-
-       /*
-        * If the association has changed, we have to revert and reapply the
-        * charge/uncharge on the wrong hierarchy to the current one. Since
-        * the association can only change due to an organisation event, its
-        * okay for us to ignore the limit in this case.
-        */
-       if (pids != old_pids) {
-               pids_uncharge(old_pids, 1);
-               pids_charge(pids, 1);
-       }
-
-       css_put(css);
-       css_put(old_css);
+       pids_uncharge(pids, 1);
 }
 
 static void pids_free(struct task_struct *task)
@@ -335,6 +298,7 @@ static struct cftype pids_files[] = {
        {
                .name = "current",
                .read_s64 = pids_current_read,
+               .flags = CFTYPE_NOT_ON_ROOT,
        },
        { }     /* terminate */
 };
@@ -346,7 +310,6 @@ struct cgroup_subsys pids_cgrp_subsys = {
        .cancel_attach  = pids_cancel_attach,
        .can_fork       = pids_can_fork,
        .cancel_fork    = pids_cancel_fork,
-       .fork           = pids_fork,
        .free           = pids_free,
        .legacy_cftypes = pids_files,
        .dfl_cftypes    = pids_files,
index 10ae73611d80a560977aa554d6cbedee78bec19a..02a8ea5c99632907b2ae887015c59bd4ad35da9d 100644 (file)
@@ -1429,15 +1429,16 @@ static int fmeter_getrate(struct fmeter *fmp)
 static struct cpuset *cpuset_attach_old_cs;
 
 /* Called by cgroups to determine if a cpuset is usable; cpuset_mutex held */
-static int cpuset_can_attach(struct cgroup_subsys_state *css,
-                            struct cgroup_taskset *tset)
+static int cpuset_can_attach(struct cgroup_taskset *tset)
 {
-       struct cpuset *cs = css_cs(css);
+       struct cgroup_subsys_state *css;
+       struct cpuset *cs;
        struct task_struct *task;
        int ret;
 
        /* used later by cpuset_attach() */
-       cpuset_attach_old_cs = task_cs(cgroup_taskset_first(tset));
+       cpuset_attach_old_cs = task_cs(cgroup_taskset_first(tset, &css));
+       cs = css_cs(css);
 
        mutex_lock(&cpuset_mutex);
 
@@ -1447,7 +1448,7 @@ static int cpuset_can_attach(struct cgroup_subsys_state *css,
            (cpumask_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed)))
                goto out_unlock;
 
-       cgroup_taskset_for_each(task, tset) {
+       cgroup_taskset_for_each(task, css, tset) {
                ret = task_can_attach(task, cs->cpus_allowed);
                if (ret)
                        goto out_unlock;
@@ -1467,9 +1468,14 @@ out_unlock:
        return ret;
 }
 
-static void cpuset_cancel_attach(struct cgroup_subsys_state *css,
-                                struct cgroup_taskset *tset)
+static void cpuset_cancel_attach(struct cgroup_taskset *tset)
 {
+       struct cgroup_subsys_state *css;
+       struct cpuset *cs;
+
+       cgroup_taskset_first(tset, &css);
+       cs = css_cs(css);
+
        mutex_lock(&cpuset_mutex);
        css_cs(css)->attach_in_progress--;
        mutex_unlock(&cpuset_mutex);
@@ -1482,16 +1488,19 @@ static void cpuset_cancel_attach(struct cgroup_subsys_state *css,
  */
 static cpumask_var_t cpus_attach;
 
-static void cpuset_attach(struct cgroup_subsys_state *css,
-                         struct cgroup_taskset *tset)
+static void cpuset_attach(struct cgroup_taskset *tset)
 {
        /* static buf protected by cpuset_mutex */
        static nodemask_t cpuset_attach_nodemask_to;
        struct task_struct *task;
        struct task_struct *leader;
-       struct cpuset *cs = css_cs(css);
+       struct cgroup_subsys_state *css;
+       struct cpuset *cs;
        struct cpuset *oldcs = cpuset_attach_old_cs;
 
+       cgroup_taskset_first(tset, &css);
+       cs = css_cs(css);
+
        mutex_lock(&cpuset_mutex);
 
        /* prepare for attach */
@@ -1502,7 +1511,7 @@ static void cpuset_attach(struct cgroup_subsys_state *css,
 
        guarantee_online_mems(cs, &cpuset_attach_nodemask_to);
 
-       cgroup_taskset_for_each(task, tset) {
+       cgroup_taskset_for_each(task, css, tset) {
                /*
                 * can_attach beforehand should guarantee that this doesn't
                 * fail.  TODO: have a better way to handle failure here
@@ -1518,7 +1527,7 @@ static void cpuset_attach(struct cgroup_subsys_state *css,
         * sleep and should be moved outside migration path proper.
         */
        cpuset_attach_nodemask_to = cs->effective_mems;
-       cgroup_taskset_for_each_leader(leader, tset) {
+       cgroup_taskset_for_each_leader(leader, css, tset) {
                struct mm_struct *mm = get_task_mm(leader);
 
                if (mm) {
index d659487254d5d77de07f279ceb0ba0bebe93ed03..9c418002b8c1fa15217b3390250453b492849344 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
  *  Copyright (C) 2008-2011 Red Hat, Inc., Ingo Molnar
- *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra
  *  Copyright  Â©  2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
  *
  * For licensing details see kernel-base/COPYING
index 36babfd2064842c28d4951a656ea1e84500bbf8f..cfc227ccfcebc6e6843cf3e1c7edc5931d69e397 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
  *  Copyright (C) 2008-2011 Red Hat, Inc., Ingo Molnar
- *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra
  *  Copyright  Â©  2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
  *
  * For licensing details see kernel-base/COPYING
@@ -435,7 +435,7 @@ static inline void update_cgrp_time_from_event(struct perf_event *event)
        if (!is_cgroup_event(event))
                return;
 
-       cgrp = perf_cgroup_from_task(current);
+       cgrp = perf_cgroup_from_task(current, event->ctx);
        /*
         * Do not update time when cgroup is not active
         */
@@ -458,7 +458,7 @@ perf_cgroup_set_timestamp(struct task_struct *task,
        if (!task || !ctx->nr_cgroups)
                return;
 
-       cgrp = perf_cgroup_from_task(task);
+       cgrp = perf_cgroup_from_task(task, ctx);
        info = this_cpu_ptr(cgrp->info);
        info->timestamp = ctx->timestamp;
 }
@@ -489,7 +489,6 @@ static void perf_cgroup_switch(struct task_struct *task, int mode)
         * we reschedule only in the presence of cgroup
         * constrained events.
         */
-       rcu_read_lock();
 
        list_for_each_entry_rcu(pmu, &pmus, entry) {
                cpuctx = this_cpu_ptr(pmu->pmu_cpu_context);
@@ -522,8 +521,10 @@ static void perf_cgroup_switch(struct task_struct *task, int mode)
                                 * set cgrp before ctxsw in to allow
                                 * event_filter_match() to not have to pass
                                 * task around
+                                * we pass the cpuctx->ctx to perf_cgroup_from_task()
+                                * because cgorup events are only per-cpu
                                 */
-                               cpuctx->cgrp = perf_cgroup_from_task(task);
+                               cpuctx->cgrp = perf_cgroup_from_task(task, &cpuctx->ctx);
                                cpu_ctx_sched_in(cpuctx, EVENT_ALL, task);
                        }
                        perf_pmu_enable(cpuctx->ctx.pmu);
@@ -531,8 +532,6 @@ static void perf_cgroup_switch(struct task_struct *task, int mode)
                }
        }
 
-       rcu_read_unlock();
-
        local_irq_restore(flags);
 }
 
@@ -542,17 +541,20 @@ static inline void perf_cgroup_sched_out(struct task_struct *task,
        struct perf_cgroup *cgrp1;
        struct perf_cgroup *cgrp2 = NULL;
 
+       rcu_read_lock();
        /*
         * we come here when we know perf_cgroup_events > 0
+        * we do not need to pass the ctx here because we know
+        * we are holding the rcu lock
         */
-       cgrp1 = perf_cgroup_from_task(task);
+       cgrp1 = perf_cgroup_from_task(task, NULL);
 
        /*
         * next is NULL when called from perf_event_enable_on_exec()
         * that will systematically cause a cgroup_switch()
         */
        if (next)
-               cgrp2 = perf_cgroup_from_task(next);
+               cgrp2 = perf_cgroup_from_task(next, NULL);
 
        /*
         * only schedule out current cgroup events if we know
@@ -561,6 +563,8 @@ static inline void perf_cgroup_sched_out(struct task_struct *task,
         */
        if (cgrp1 != cgrp2)
                perf_cgroup_switch(task, PERF_CGROUP_SWOUT);
+
+       rcu_read_unlock();
 }
 
 static inline void perf_cgroup_sched_in(struct task_struct *prev,
@@ -569,13 +573,16 @@ static inline void perf_cgroup_sched_in(struct task_struct *prev,
        struct perf_cgroup *cgrp1;
        struct perf_cgroup *cgrp2 = NULL;
 
+       rcu_read_lock();
        /*
         * we come here when we know perf_cgroup_events > 0
+        * we do not need to pass the ctx here because we know
+        * we are holding the rcu lock
         */
-       cgrp1 = perf_cgroup_from_task(task);
+       cgrp1 = perf_cgroup_from_task(task, NULL);
 
        /* prev can never be NULL */
-       cgrp2 = perf_cgroup_from_task(prev);
+       cgrp2 = perf_cgroup_from_task(prev, NULL);
 
        /*
         * only need to schedule in cgroup events if we are changing
@@ -584,6 +591,8 @@ static inline void perf_cgroup_sched_in(struct task_struct *prev,
         */
        if (cgrp1 != cgrp2)
                perf_cgroup_switch(task, PERF_CGROUP_SWIN);
+
+       rcu_read_unlock();
 }
 
 static inline int perf_cgroup_connect(int fd, struct perf_event *event,
@@ -3145,15 +3154,16 @@ static int event_enable_on_exec(struct perf_event *event,
  * Enable all of a task's events that have been marked enable-on-exec.
  * This expects task == current.
  */
-static void perf_event_enable_on_exec(struct perf_event_context *ctx)
+static void perf_event_enable_on_exec(int ctxn)
 {
-       struct perf_event_context *clone_ctx = NULL;
+       struct perf_event_context *ctx, *clone_ctx = NULL;
        struct perf_event *event;
        unsigned long flags;
        int enabled = 0;
        int ret;
 
        local_irq_save(flags);
+       ctx = current->perf_event_ctxp[ctxn];
        if (!ctx || !ctx->nr_events)
                goto out;
 
@@ -3196,17 +3206,11 @@ out:
 
 void perf_event_exec(void)
 {
-       struct perf_event_context *ctx;
        int ctxn;
 
        rcu_read_lock();
-       for_each_task_context_nr(ctxn) {
-               ctx = current->perf_event_ctxp[ctxn];
-               if (!ctx)
-                       continue;
-
-               perf_event_enable_on_exec(ctx);
-       }
+       for_each_task_context_nr(ctxn)
+               perf_event_enable_on_exec(ctxn);
        rcu_read_unlock();
 }
 
@@ -4216,7 +4220,14 @@ retry:
                goto retry;
        }
 
-       __perf_event_period(&pe);
+       if (event->attr.freq) {
+               event->attr.sample_freq = value;
+       } else {
+               event->attr.sample_period = value;
+               event->hw.sample_period = value;
+       }
+
+       local64_set(&event->hw.period_left, 0);
        raw_spin_unlock_irq(&ctx->lock);
 
        return 0;
@@ -5666,6 +5677,17 @@ perf_event_aux_ctx(struct perf_event_context *ctx,
        }
 }
 
+static void
+perf_event_aux_task_ctx(perf_event_aux_output_cb output, void *data,
+                       struct perf_event_context *task_ctx)
+{
+       rcu_read_lock();
+       preempt_disable();
+       perf_event_aux_ctx(task_ctx, output, data);
+       preempt_enable();
+       rcu_read_unlock();
+}
+
 static void
 perf_event_aux(perf_event_aux_output_cb output, void *data,
               struct perf_event_context *task_ctx)
@@ -5675,14 +5697,23 @@ perf_event_aux(perf_event_aux_output_cb output, void *data,
        struct pmu *pmu;
        int ctxn;
 
+       /*
+        * If we have task_ctx != NULL we only notify
+        * the task context itself. The task_ctx is set
+        * only for EXIT events before releasing task
+        * context.
+        */
+       if (task_ctx) {
+               perf_event_aux_task_ctx(output, data, task_ctx);
+               return;
+       }
+
        rcu_read_lock();
        list_for_each_entry_rcu(pmu, &pmus, entry) {
                cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
                if (cpuctx->unique_pmu != pmu)
                        goto next;
                perf_event_aux_ctx(&cpuctx->ctx, output, data);
-               if (task_ctx)
-                       goto next;
                ctxn = pmu->task_ctx_nr;
                if (ctxn < 0)
                        goto next;
@@ -5692,12 +5723,6 @@ perf_event_aux(perf_event_aux_output_cb output, void *data,
 next:
                put_cpu_ptr(pmu->pmu_cpu_context);
        }
-
-       if (task_ctx) {
-               preempt_disable();
-               perf_event_aux_ctx(task_ctx, output, data);
-               preempt_enable();
-       }
        rcu_read_unlock();
 }
 
@@ -6463,9 +6488,6 @@ struct swevent_htable {
 
        /* Recursion avoidance in each contexts */
        int                             recursion[PERF_NR_CONTEXTS];
-
-       /* Keeps track of cpu being initialized/exited */
-       bool                            online;
 };
 
 static DEFINE_PER_CPU(struct swevent_htable, swevent_htable);
@@ -6723,14 +6745,8 @@ static int perf_swevent_add(struct perf_event *event, int flags)
        hwc->state = !(flags & PERF_EF_START);
 
        head = find_swevent_head(swhash, event);
-       if (!head) {
-               /*
-                * We can race with cpu hotplug code. Do not
-                * WARN if the cpu just got unplugged.
-                */
-               WARN_ON_ONCE(swhash->online);
+       if (WARN_ON_ONCE(!head))
                return -EINVAL;
-       }
 
        hlist_add_head_rcu(&event->hlist_entry, head);
        perf_event_update_userpage(event);
@@ -6798,7 +6814,6 @@ static int swevent_hlist_get_cpu(struct perf_event *event, int cpu)
        int err = 0;
 
        mutex_lock(&swhash->hlist_mutex);
-
        if (!swevent_hlist_deref(swhash) && cpu_online(cpu)) {
                struct swevent_hlist *hlist;
 
@@ -8787,10 +8802,8 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn)
        struct perf_event_context *child_ctx, *clone_ctx = NULL;
        unsigned long flags;
 
-       if (likely(!child->perf_event_ctxp[ctxn])) {
-               perf_event_task(child, NULL, 0);
+       if (likely(!child->perf_event_ctxp[ctxn]))
                return;
-       }
 
        local_irq_save(flags);
        /*
@@ -8874,6 +8887,14 @@ void perf_event_exit_task(struct task_struct *child)
 
        for_each_task_context_nr(ctxn)
                perf_event_exit_task_context(child, ctxn);
+
+       /*
+        * The perf_event_exit_task_context calls perf_event_task
+        * with child's task_ctx, which generates EXIT events for
+        * child contexts and sets child->perf_event_ctxp[] to NULL.
+        * At this point we need to send EXIT events to cpu contexts.
+        */
+       perf_event_task(child, NULL, 0);
 }
 
 static void perf_free_event(struct perf_event *event,
@@ -9255,7 +9276,6 @@ static void perf_event_init_cpu(int cpu)
        struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
 
        mutex_lock(&swhash->hlist_mutex);
-       swhash->online = true;
        if (swhash->hlist_refcount > 0) {
                struct swevent_hlist *hlist;
 
@@ -9297,14 +9317,7 @@ static void perf_event_exit_cpu_context(int cpu)
 
 static void perf_event_exit_cpu(int cpu)
 {
-       struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
-
        perf_event_exit_cpu_context(cpu);
-
-       mutex_lock(&swhash->hlist_mutex);
-       swhash->online = false;
-       swevent_hlist_release(swhash);
-       mutex_unlock(&swhash->hlist_mutex);
 }
 #else
 static inline void perf_event_exit_cpu(int cpu) { }
@@ -9452,16 +9465,18 @@ static void perf_cgroup_css_free(struct cgroup_subsys_state *css)
 static int __perf_cgroup_move(void *info)
 {
        struct task_struct *task = info;
+       rcu_read_lock();
        perf_cgroup_switch(task, PERF_CGROUP_SWOUT | PERF_CGROUP_SWIN);
+       rcu_read_unlock();
        return 0;
 }
 
-static void perf_cgroup_attach(struct cgroup_subsys_state *css,
-                              struct cgroup_taskset *tset)
+static void perf_cgroup_attach(struct cgroup_taskset *tset)
 {
        struct task_struct *task;
+       struct cgroup_subsys_state *css;
 
-       cgroup_taskset_for_each(task, tset)
+       cgroup_taskset_for_each(task, css, tset)
                task_function_call(task, __perf_cgroup_move, task);
 }
 
index b5d1ea79c5953e2a2c7a5ee843de5f76ad47077a..adfdc0536117c1f10bf8f0dd8014798011e1f855 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
  *  Copyright (C) 2008-2011 Red Hat, Inc., Ingo Molnar
- *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008-2011 Red Hat, Inc., Peter Zijlstra
  *  Copyright  Â©  2009 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
  *
  * For licensing details see kernel-base/COPYING
index 4e5e9798aa0c0d426962642b69985b9eb09021d6..7dad84913abfb06df2495fae555e7f8bcac2b104 100644 (file)
@@ -19,7 +19,7 @@
  * Authors:
  *     Srikar Dronamraju
  *     Jim Keniston
- * Copyright (C) 2011-2012 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright (C) 2011-2012 Red Hat, Inc., Peter Zijlstra
  */
 
 #include <linux/kernel.h>
index f97f2c449f5cf556ea6c54cb4aec6e894dd8bab5..1155eac616878b5494ae94f2f1d0294812ddda72 100644 (file)
@@ -380,6 +380,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
 #endif
        tsk->splice_pipe = NULL;
        tsk->task_frag.page = NULL;
+       tsk->wake_q.next = NULL;
 
        account_kernel_stack(ti, 1);
 
@@ -1368,8 +1369,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        p->real_start_time = ktime_get_boot_ns();
        p->io_context = NULL;
        p->audit_context = NULL;
-       if (clone_flags & CLONE_THREAD)
-               threadgroup_change_begin(current);
+       threadgroup_change_begin(current);
        cgroup_fork(p);
 #ifdef CONFIG_NUMA
        p->mempolicy = mpol_dup(p->mempolicy);
@@ -1610,8 +1610,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
 
        proc_fork_connector(p);
        cgroup_post_fork(p, cgrp_ss_priv);
-       if (clone_flags & CLONE_THREAD)
-               threadgroup_change_end(current);
+       threadgroup_change_end(current);
        perf_event_fork(p);
 
        trace_task_newtask(p, clone_flags);
@@ -1652,8 +1651,7 @@ bad_fork_cleanup_policy:
        mpol_put(p->mempolicy);
 bad_fork_cleanup_threadgroup_lock:
 #endif
-       if (clone_flags & CLONE_THREAD)
-               threadgroup_change_end(current);
+       threadgroup_change_end(current);
        delayacct_tsk_free(p);
 bad_fork_cleanup_count:
        atomic_dec(&p->cred->user->processes);
index 0eebaeef317bc990e3ee1b1bd1719b9e89211685..6ead200370da0cfe15b9c6732ec5ec4e3a7523a9 100644 (file)
@@ -1434,6 +1434,7 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
        if (!desc)
                return NULL;
 
+       chip_bus_lock(desc);
        raw_spin_lock_irqsave(&desc->lock, flags);
 
        /*
@@ -1447,7 +1448,7 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
                if (!action) {
                        WARN(1, "Trying to free already-free IRQ %d\n", irq);
                        raw_spin_unlock_irqrestore(&desc->lock, flags);
-
+                       chip_bus_sync_unlock(desc);
                        return NULL;
                }
 
@@ -1475,6 +1476,7 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
 #endif
 
        raw_spin_unlock_irqrestore(&desc->lock, flags);
+       chip_bus_sync_unlock(desc);
 
        unregister_handler_proc(irq, action);
 
@@ -1553,9 +1555,7 @@ void free_irq(unsigned int irq, void *dev_id)
                desc->affinity_notify = NULL;
 #endif
 
-       chip_bus_lock(desc);
        kfree(__free_irq(irq, dev_id));
-       chip_bus_sync_unlock(desc);
 }
 EXPORT_SYMBOL(free_irq);
 
index cbf9fb899d929bfc52a2d803b64643732b0b7bbd..bcf107ce085450552c17d6b045816cd4656e97c0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright (C) 2010 Red Hat, Inc., Peter Zijlstra
  *
  * Provides a framework for enqueueing and running callbacks from hardirq
  * context. The enqueueing is NMI-safe.
index f7dd15d537f9b1135eb01036bf2fa3a5594ed9b6..05254eeb4b4e485be75bacff667c8ed3aab4a200 100644 (file)
@@ -2,7 +2,7 @@
  * jump label support
  *
  * Copyright (C) 2009 Jason Baron <jbaron@redhat.com>
- * Copyright (C) 2011 Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright (C) 2011 Peter Zijlstra
  *
  */
 #include <linux/memory.h>
index deae3907ac1eec585bbe71a44f6dc57ad024784a..60ace56618f6c222de90e569bf1702b6dba05e26 100644 (file)
@@ -6,7 +6,7 @@
  * Started by Ingo Molnar:
  *
  *  Copyright (C) 2006,2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
- *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra
  *
  * this code maps all the lock dependencies as they occur in a live kernel
  * and will warn about the following classes of locking bugs:
index d83d798bef95a042e1060a35bf4b79e7c7a6c05c..dbb61a3025484b4d38bd090bd5923c21a3960ced 100644 (file)
@@ -6,7 +6,7 @@
  * Started by Ingo Molnar:
  *
  *  Copyright (C) 2006,2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
- *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra
  *
  * Code for /proc/lockdep and /proc/lockdep_stats:
  *
index d092a0c9c2d4ed838004215cdf038691a14f4598..05a37857ab5516012949ca64b31cff3d133c61e7 100644 (file)
@@ -93,10 +93,12 @@ bool osq_lock(struct optimistic_spin_queue *lock)
        node->cpu = curr;
 
        /*
-        * ACQUIRE semantics, pairs with corresponding RELEASE
-        * in unlock() uncontended, or fastpath.
+        * We need both ACQUIRE (pairs with corresponding RELEASE in
+        * unlock() uncontended, or fastpath) and RELEASE (to publish
+        * the node fields we just initialised) semantics when updating
+        * the lock tail.
         */
-       old = atomic_xchg_acquire(&lock->tail, curr);
+       old = atomic_xchg(&lock->tail, curr);
        if (old == OSQ_UNLOCKED_VAL)
                return true;
 
index 8f051a106676fb8f2d5457a9104340cce81ce37a..38c7bd5583fff036c0f993ac2c15077882d61501 100644 (file)
@@ -3571,6 +3571,12 @@ static int load_module(struct load_info *info, const char __user *uargs,
        synchronize_sched();
        mutex_unlock(&module_mutex);
  free_module:
+       /*
+        * Ftrace needs to clean up what it initialized.
+        * This does nothing if ftrace_module_init() wasn't called,
+        * but it must be called outside of module_mutex.
+        */
+       ftrace_release_mod(mod);
        /* Free lock-classes; relies on the preceding sync_rcu() */
        lockdep_free_key_range(mod->module_core, mod->core_size);
 
index c0a205101c231a5b6e29e786228fb69c46772f5e..caf4041f5b0ae6769bc562fccc189852eae77fcf 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * sched_clock for unstable cpu clocks
  *
- *  Copyright (C) 2008 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2008 Red Hat, Inc., Peter Zijlstra
  *
  *  Updates and enhancements:
  *    Copyright (C) 2008 Red Hat, Inc. Steven Rostedt <srostedt@redhat.com>
index 7063c6a0744055c367eb82159677cfe6522b6c60..732e993b564b8179e5723bb88839329eec6df8f5 100644 (file)
@@ -8241,12 +8241,12 @@ static void cpu_cgroup_fork(struct task_struct *task, void *private)
        sched_move_task(task);
 }
 
-static int cpu_cgroup_can_attach(struct cgroup_subsys_state *css,
-                                struct cgroup_taskset *tset)
+static int cpu_cgroup_can_attach(struct cgroup_taskset *tset)
 {
        struct task_struct *task;
+       struct cgroup_subsys_state *css;
 
-       cgroup_taskset_for_each(task, tset) {
+       cgroup_taskset_for_each(task, css, tset) {
 #ifdef CONFIG_RT_GROUP_SCHED
                if (!sched_rt_can_attach(css_tg(css), task))
                        return -EINVAL;
@@ -8259,12 +8259,12 @@ static int cpu_cgroup_can_attach(struct cgroup_subsys_state *css,
        return 0;
 }
 
-static void cpu_cgroup_attach(struct cgroup_subsys_state *css,
-                             struct cgroup_taskset *tset)
+static void cpu_cgroup_attach(struct cgroup_taskset *tset)
 {
        struct task_struct *task;
+       struct cgroup_subsys_state *css;
 
-       cgroup_taskset_for_each(task, tset)
+       cgroup_taskset_for_each(task, css, tset)
                sched_move_task(task);
 }
 
index f04fda8f669c8eff57e936fcb1334b13a4140ce5..cfdc0e61066c20b926e0d5ca7ed5d9732a1c903b 100644 (file)
@@ -17,7 +17,7 @@
  *  Copyright (C) 2007, Thomas Gleixner <tglx@linutronix.de>
  *
  *  Adaptive scheduling granularity, math enhancements by Peter Zijlstra
- *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra
  */
 
 #include <linux/latencytop.h>
@@ -2689,7 +2689,7 @@ static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq)
        int decayed, removed = 0;
 
        if (atomic_long_read(&cfs_rq->removed_load_avg)) {
-               long r = atomic_long_xchg(&cfs_rq->removed_load_avg, 0);
+               s64 r = atomic_long_xchg(&cfs_rq->removed_load_avg, 0);
                sa->load_avg = max_t(long, sa->load_avg - r, 0);
                sa->load_sum = max_t(s64, sa->load_sum - r * LOAD_AVG_MAX, 0);
                removed = 1;
index f10bd873e6840441ed4750a5eb1c2d462ad0b436..f15d6b6a538a9d01c2d7c4045af0a661d34c3c4a 100644 (file)
@@ -392,7 +392,7 @@ __wait_on_bit(wait_queue_head_t *wq, struct wait_bit_queue *q,
        do {
                prepare_to_wait(wq, &q->wait, mode);
                if (test_bit(q->key.bit_nr, q->key.flags))
-                       ret = (*action)(&q->key);
+                       ret = (*action)(&q->key, mode);
        } while (test_bit(q->key.bit_nr, q->key.flags) && !ret);
        finish_wait(wq, &q->wait);
        return ret;
@@ -431,7 +431,7 @@ __wait_on_bit_lock(wait_queue_head_t *wq, struct wait_bit_queue *q,
                prepare_to_wait_exclusive(wq, &q->wait, mode);
                if (!test_bit(q->key.bit_nr, q->key.flags))
                        continue;
-               ret = action(&q->key);
+               ret = action(&q->key, mode);
                if (!ret)
                        continue;
                abort_exclusive_wait(wq, &q->wait, mode, &q->key);
@@ -581,43 +581,43 @@ void wake_up_atomic_t(atomic_t *p)
 }
 EXPORT_SYMBOL(wake_up_atomic_t);
 
-__sched int bit_wait(struct wait_bit_key *word)
+__sched int bit_wait(struct wait_bit_key *word, int mode)
 {
        schedule();
-       if (signal_pending(current))
+       if (signal_pending_state(mode, current))
                return -EINTR;
        return 0;
 }
 EXPORT_SYMBOL(bit_wait);
 
-__sched int bit_wait_io(struct wait_bit_key *word)
+__sched int bit_wait_io(struct wait_bit_key *word, int mode)
 {
        io_schedule();
-       if (signal_pending(current))
+       if (signal_pending_state(mode, current))
                return -EINTR;
        return 0;
 }
 EXPORT_SYMBOL(bit_wait_io);
 
-__sched int bit_wait_timeout(struct wait_bit_key *word)
+__sched int bit_wait_timeout(struct wait_bit_key *word, int mode)
 {
        unsigned long now = READ_ONCE(jiffies);
        if (time_after_eq(now, word->timeout))
                return -EAGAIN;
        schedule_timeout(word->timeout - now);
-       if (signal_pending(current))
+       if (signal_pending_state(mode, current))
                return -EINTR;
        return 0;
 }
 EXPORT_SYMBOL_GPL(bit_wait_timeout);
 
-__sched int bit_wait_io_timeout(struct wait_bit_key *word)
+__sched int bit_wait_io_timeout(struct wait_bit_key *word, int mode)
 {
        unsigned long now = READ_ONCE(jiffies);
        if (time_after_eq(now, word->timeout))
                return -EAGAIN;
        io_schedule_timeout(word->timeout - now);
-       if (signal_pending(current))
+       if (signal_pending_state(mode, current))
                return -EINTR;
        return 0;
 }
index 867bc20e1ef142a63349c345932af24b26a1adfc..a3bbaee77c586e9836567f900012aa5231e94dbd 100644 (file)
@@ -531,7 +531,7 @@ static int __init cpu_stop_init(void)
 }
 early_initcall(cpu_stop_init);
 
-#ifdef CONFIG_STOP_MACHINE
+#if defined(CONFIG_SMP) || defined(CONFIG_HOTPLUG_CPU)
 
 static int __stop_machine(cpu_stop_fn_t fn, void *data, const struct cpumask *cpus)
 {
@@ -631,4 +631,4 @@ int stop_machine_from_inactive_cpu(cpu_stop_fn_t fn, void *data,
        return ret ?: done.ret;
 }
 
-#endif /* CONFIG_STOP_MACHINE */
+#endif /* CONFIG_SMP || CONFIG_HOTPLUG_CPU */
index abfc903e741e8550d67bd638ead8a338a0c95fec..cc9f7a9319bea63104ef05c97634c43286a5268c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * trace event based perf event profiling/tracing
  *
- * Copyright (C) 2009 Red Hat Inc, Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright (C) 2009 Red Hat Inc, Peter Zijlstra
  * Copyright (C) 2009-2010 Frederic Weisbecker <fweisbec@gmail.com>
  */
 
index 1c2b28536feb8113a408b2335c38fb0a0c4272e1..060df67dbdd1d038dba8ec35909890f3e892b6d7 100644 (file)
@@ -273,6 +273,7 @@ static const char **find_next(void *v, loff_t *pos)
        if (*pos < last_index + start_index)
                return __start___tracepoint_str + (*pos - last_index);
 
+       start_index += last_index;
        return find_next_mod_format(start_index, v, fmt, pos);
 }
 
index 4264871ea1a00194750116a82c48e18d18edbd44..f93a945274af12575f8fbbceb821552b2a13e61e 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 2007-2008 Joern Engel <joern@logfs.org>
  * Bits and pieces stolen from Peter Zijlstra's code, which is
- * Copyright 2007, Red Hat Inc. Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright 2007, Red Hat Inc. Peter Zijlstra
  * GPLv2
  *
  * see http://programming.kicks-ass.net/kernel-patches/vma_lookup/btree.patch
index 8855f019ebe8a61957795b0d5f5c3339fe180f5a..d34bd24c2c84779c38c300f470b22df52e76cb58 100644 (file)
@@ -1464,7 +1464,7 @@ void debug_dma_alloc_coherent(struct device *dev, size_t size,
        entry->type      = dma_debug_coherent;
        entry->dev       = dev;
        entry->pfn       = page_to_pfn(virt_to_page(virt));
-       entry->offset    = (size_t) virt & PAGE_MASK;
+       entry->offset    = (size_t) virt & ~PAGE_MASK;
        entry->size      = size;
        entry->dev_addr  = dma_addr;
        entry->direction = DMA_BIDIRECTIONAL;
@@ -1480,7 +1480,7 @@ void debug_dma_free_coherent(struct device *dev, size_t size,
                .type           = dma_debug_coherent,
                .dev            = dev,
                .pfn            = page_to_pfn(virt_to_page(virt)),
-               .offset         = (size_t) virt & PAGE_MASK,
+               .offset         = (size_t) virt & ~PAGE_MASK,
                .dev_addr       = addr,
                .size           = size,
                .direction      = DMA_BIDIRECTIONAL,
index 6f724298f67a11199407870e2dbb1541ee55db6c..efa54f259ea9d316176c03c66badd9c23cfc8e20 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Floating proportions
  *
- *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ *  Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra
  *
  * Description:
  *
index a54ff8949f9116184631414086a9fa2d956c8031..51282f5797606545330a29e93b3728d843616ea9 100644 (file)
@@ -389,33 +389,31 @@ static bool rhashtable_check_elasticity(struct rhashtable *ht,
        return false;
 }
 
-int rhashtable_insert_rehash(struct rhashtable *ht)
+int rhashtable_insert_rehash(struct rhashtable *ht,
+                            struct bucket_table *tbl)
 {
        struct bucket_table *old_tbl;
        struct bucket_table *new_tbl;
-       struct bucket_table *tbl;
        unsigned int size;
        int err;
 
        old_tbl = rht_dereference_rcu(ht->tbl, ht);
-       tbl = rhashtable_last_table(ht, old_tbl);
 
        size = tbl->size;
 
+       err = -EBUSY;
+
        if (rht_grow_above_75(ht, tbl))
                size *= 2;
        /* Do not schedule more than one rehash */
        else if (old_tbl != tbl)
-               return -EBUSY;
+               goto fail;
+
+       err = -ENOMEM;
 
        new_tbl = bucket_table_alloc(ht, size, GFP_ATOMIC);
-       if (new_tbl == NULL) {
-               /* Schedule async resize/rehash to try allocation
-                * non-atomic context.
-                */
-               schedule_work(&ht->run_work);
-               return -ENOMEM;
-       }
+       if (new_tbl == NULL)
+               goto fail;
 
        err = rhashtable_rehash_attach(ht, tbl, new_tbl);
        if (err) {
@@ -426,12 +424,24 @@ int rhashtable_insert_rehash(struct rhashtable *ht)
                schedule_work(&ht->run_work);
 
        return err;
+
+fail:
+       /* Do not fail the insert if someone else did a rehash. */
+       if (likely(rcu_dereference_raw(tbl->future_tbl)))
+               return 0;
+
+       /* Schedule async rehash to retry allocation in process context. */
+       if (err == -ENOMEM)
+               schedule_work(&ht->run_work);
+
+       return err;
 }
 EXPORT_SYMBOL_GPL(rhashtable_insert_rehash);
 
-int rhashtable_insert_slow(struct rhashtable *ht, const void *key,
-                          struct rhash_head *obj,
-                          struct bucket_table *tbl)
+struct bucket_table *rhashtable_insert_slow(struct rhashtable *ht,
+                                           const void *key,
+                                           struct rhash_head *obj,
+                                           struct bucket_table *tbl)
 {
        struct rhash_head *head;
        unsigned int hash;
@@ -467,7 +477,12 @@ int rhashtable_insert_slow(struct rhashtable *ht, const void *key,
 exit:
        spin_unlock(rht_bucket_lock(tbl, hash));
 
-       return err;
+       if (err == 0)
+               return NULL;
+       else if (err == -EAGAIN)
+               return tbl;
+       else
+               return ERR_PTR(err);
 }
 EXPORT_SYMBOL_GPL(rhashtable_insert_slow);
 
@@ -503,10 +518,11 @@ int rhashtable_walk_init(struct rhashtable *ht, struct rhashtable_iter *iter)
        if (!iter->walker)
                return -ENOMEM;
 
-       mutex_lock(&ht->mutex);
-       iter->walker->tbl = rht_dereference(ht->tbl, ht);
+       spin_lock(&ht->lock);
+       iter->walker->tbl =
+               rcu_dereference_protected(ht->tbl, lockdep_is_held(&ht->lock));
        list_add(&iter->walker->list, &iter->walker->tbl->walkers);
-       mutex_unlock(&ht->mutex);
+       spin_unlock(&ht->lock);
 
        return 0;
 }
@@ -520,10 +536,10 @@ EXPORT_SYMBOL_GPL(rhashtable_walk_init);
  */
 void rhashtable_walk_exit(struct rhashtable_iter *iter)
 {
-       mutex_lock(&iter->ht->mutex);
+       spin_lock(&iter->ht->lock);
        if (iter->walker->tbl)
                list_del(&iter->walker->list);
-       mutex_unlock(&iter->ht->mutex);
+       spin_unlock(&iter->ht->lock);
        kfree(iter->walker);
 }
 EXPORT_SYMBOL_GPL(rhashtable_walk_exit);
@@ -547,14 +563,12 @@ int rhashtable_walk_start(struct rhashtable_iter *iter)
 {
        struct rhashtable *ht = iter->ht;
 
-       mutex_lock(&ht->mutex);
+       rcu_read_lock();
 
+       spin_lock(&ht->lock);
        if (iter->walker->tbl)
                list_del(&iter->walker->list);
-
-       rcu_read_lock();
-
-       mutex_unlock(&ht->mutex);
+       spin_unlock(&ht->lock);
 
        if (!iter->walker->tbl) {
                iter->walker->tbl = rht_dereference_rcu(ht->tbl, ht);
@@ -723,9 +737,6 @@ int rhashtable_init(struct rhashtable *ht,
        if (params->nulls_base && params->nulls_base < (1U << RHT_BASE_SHIFT))
                return -EINVAL;
 
-       if (params->nelem_hint)
-               size = rounded_hashtable_size(params);
-
        memset(ht, 0, sizeof(*ht));
        mutex_init(&ht->mutex);
        spin_lock_init(&ht->lock);
@@ -745,6 +756,9 @@ int rhashtable_init(struct rhashtable *ht,
 
        ht->p.min_size = max(ht->p.min_size, HASH_MIN_SIZE);
 
+       if (params->nelem_hint)
+               size = rounded_hashtable_size(&ht->p);
+
        /* The maximum (not average) chain length grows with the
         * size of the hash table, at a rate of (log N)/(log log N).
         * The value of 16 is selected so that even if the hash
index 8ed2ffd963c53b910f91e1b60b04c56385a3129f..7340353f8aea08ef428edcf7b287c45b312aeb1a 100644 (file)
@@ -957,8 +957,9 @@ EXPORT_SYMBOL(congestion_wait);
  * jiffies for either a BDI to exit congestion of the given @sync queue
  * or a write to complete.
  *
- * In the absence of zone congestion, cond_resched() is called to yield
- * the processor if necessary but otherwise does not sleep.
+ * In the absence of zone congestion, a short sleep or a cond_resched is
+ * performed to yield the processor and to allow other subsystems to make
+ * a forward progress.
  *
  * The return value is 0 if the sleep is for the full timeout. Otherwise,
  * it is the number of jiffies that were still remaining when the function
@@ -978,7 +979,19 @@ long wait_iff_congested(struct zone *zone, int sync, long timeout)
         */
        if (atomic_read(&nr_wb_congested[sync]) == 0 ||
            !test_bit(ZONE_CONGESTED, &zone->flags)) {
-               cond_resched();
+
+               /*
+                * Memory allocation/reclaim might be called from a WQ
+                * context and the current implementation of the WQ
+                * concurrency control doesn't recognize that a particular
+                * WQ is congested if the worker thread is looping without
+                * ever sleeping. Therefore we have to do a short sleep
+                * here rather than calling cond_resched().
+                */
+               if (current->flags & PF_WQ_WORKER)
+                       schedule_timeout(1);
+               else
+                       cond_resched();
 
                /* In case we scheduled, work out time remaining */
                ret = timeout - (jiffies - start);
index 827bb02a43a4e425393c296db89e7a49d6adf02b..ef6963b577fd2920c1a4857f7b74b50e91c98b7a 100644 (file)
@@ -372,8 +372,10 @@ retry_locked:
                spin_unlock(&resv->lock);
 
                trg = kmalloc(sizeof(*trg), GFP_KERNEL);
-               if (!trg)
+               if (!trg) {
+                       kfree(nrg);
                        return -ENOMEM;
+               }
 
                spin_lock(&resv->lock);
                list_add(&trg->link, &resv->region_cache);
@@ -483,8 +485,16 @@ static long region_del(struct resv_map *resv, long f, long t)
 retry:
        spin_lock(&resv->lock);
        list_for_each_entry_safe(rg, trg, head, link) {
-               if (rg->to <= f)
+               /*
+                * Skip regions before the range to be deleted.  file_region
+                * ranges are normally of the form [from, to).  However, there
+                * may be a "placeholder" entry in the map which is of the form
+                * (from, to) with from == to.  Check for placeholder entries
+                * at the beginning of the range to be deleted.
+                */
+               if (rg->to <= f && (rg->to != rg->from || rg->to != f))
                        continue;
+
                if (rg->from >= t)
                        break;
 
@@ -1886,7 +1896,10 @@ struct page *alloc_huge_page(struct vm_area_struct *vma,
                page = __alloc_buddy_huge_page_with_mpol(h, vma, addr);
                if (!page)
                        goto out_uncharge_cgroup;
-
+               if (!avoid_reserve && vma_has_reserves(vma, gbl_chg)) {
+                       SetPagePrivate(page);
+                       h->resv_huge_pages--;
+               }
                spin_lock(&hugetlb_lock);
                list_move(&page->lru, &h->hugepage_activelist);
                /* Fall through */
@@ -3693,12 +3706,12 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                } else if (unlikely(is_hugetlb_entry_hwpoisoned(entry)))
                        return VM_FAULT_HWPOISON_LARGE |
                                VM_FAULT_SET_HINDEX(hstate_index(h));
+       } else {
+               ptep = huge_pte_alloc(mm, address, huge_page_size(h));
+               if (!ptep)
+                       return VM_FAULT_OOM;
        }
 
-       ptep = huge_pte_alloc(mm, address, huge_page_size(h));
-       if (!ptep)
-               return VM_FAULT_OOM;
-
        mapping = vma->vm_file->f_mapping;
        idx = vma_hugecache_offset(h, vma, address);
 
index 9acfb165eb52eeff2271888ec61fe093c9015641..fc10620967c79d7b8fbbcc0f82fd9804b1562f13 100644 (file)
@@ -903,14 +903,20 @@ struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root,
                if (prev && reclaim->generation != iter->generation)
                        goto out_unlock;
 
-               do {
+               while (1) {
                        pos = READ_ONCE(iter->position);
+                       if (!pos || css_tryget(&pos->css))
+                               break;
                        /*
-                        * A racing update may change the position and
-                        * put the last reference, hence css_tryget(),
-                        * or retry to see the updated position.
+                        * css reference reached zero, so iter->position will
+                        * be cleared by ->css_released. However, we should not
+                        * rely on this happening soon, because ->css_released
+                        * is called from a work queue, and by busy-waiting we
+                        * might block it. So we clear iter->position right
+                        * away.
                         */
-               } while (pos && !css_tryget(&pos->css));
+                       (void)cmpxchg(&iter->position, pos, NULL);
+               }
        }
 
        if (pos)
@@ -956,17 +962,13 @@ struct mem_cgroup *mem_cgroup_iter(struct mem_cgroup *root,
        }
 
        if (reclaim) {
-               if (cmpxchg(&iter->position, pos, memcg) == pos) {
-                       if (memcg)
-                               css_get(&memcg->css);
-                       if (pos)
-                               css_put(&pos->css);
-               }
-
                /*
-                * pairs with css_tryget when dereferencing iter->position
-                * above.
+                * The position could have already been updated by a competing
+                * thread, so check that the value hasn't changed since we read
+                * it to avoid reclaiming from the same cgroup twice.
                 */
+               (void)cmpxchg(&iter->position, pos, memcg);
+
                if (pos)
                        css_put(&pos->css);
 
@@ -999,6 +1001,28 @@ void mem_cgroup_iter_break(struct mem_cgroup *root,
                css_put(&prev->css);
 }
 
+static void invalidate_reclaim_iterators(struct mem_cgroup *dead_memcg)
+{
+       struct mem_cgroup *memcg = dead_memcg;
+       struct mem_cgroup_reclaim_iter *iter;
+       struct mem_cgroup_per_zone *mz;
+       int nid, zid;
+       int i;
+
+       while ((memcg = parent_mem_cgroup(memcg))) {
+               for_each_node(nid) {
+                       for (zid = 0; zid < MAX_NR_ZONES; zid++) {
+                               mz = &memcg->nodeinfo[nid]->zoneinfo[zid];
+                               for (i = 0; i <= DEF_PRIORITY; i++) {
+                                       iter = &mz->iter[i];
+                                       cmpxchg(&iter->position,
+                                               dead_memcg, NULL);
+                               }
+                       }
+               }
+       }
+}
+
 /*
  * Iteration constructs for visiting all cgroups (under a tree).  If
  * loops are exited prematurely (break), mem_cgroup_iter_break() must
@@ -2128,7 +2152,7 @@ done_restock:
         */
        do {
                if (page_counter_read(&memcg->memory) > memcg->high) {
-                       current->memcg_nr_pages_over_high += nr_pages;
+                       current->memcg_nr_pages_over_high += batch;
                        set_notify_resume(current);
                        break;
                }
@@ -4324,6 +4348,13 @@ static void mem_cgroup_css_offline(struct cgroup_subsys_state *css)
        wb_memcg_offline(memcg);
 }
 
+static void mem_cgroup_css_released(struct cgroup_subsys_state *css)
+{
+       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
+
+       invalidate_reclaim_iterators(memcg);
+}
+
 static void mem_cgroup_css_free(struct cgroup_subsys_state *css)
 {
        struct mem_cgroup *memcg = mem_cgroup_from_css(css);
@@ -4779,23 +4810,18 @@ static void mem_cgroup_clear_mc(void)
        spin_unlock(&mc.lock);
 }
 
-static int mem_cgroup_can_attach(struct cgroup_subsys_state *css,
-                                struct cgroup_taskset *tset)
+static int mem_cgroup_can_attach(struct cgroup_taskset *tset)
 {
-       struct mem_cgroup *memcg = mem_cgroup_from_css(css);
+       struct cgroup_subsys_state *css;
+       struct mem_cgroup *memcg;
        struct mem_cgroup *from;
        struct task_struct *leader, *p;
        struct mm_struct *mm;
        unsigned long move_flags;
        int ret = 0;
 
-       /*
-        * We are now commited to this value whatever it is. Changes in this
-        * tunable will only affect upcoming migrations, not the current one.
-        * So we need to save it, and keep it going.
-        */
-       move_flags = READ_ONCE(memcg->move_charge_at_immigrate);
-       if (!move_flags)
+       /* charge immigration isn't supported on the default hierarchy */
+       if (cgroup_subsys_on_dfl(memory_cgrp_subsys))
                return 0;
 
        /*
@@ -4805,13 +4831,23 @@ static int mem_cgroup_can_attach(struct cgroup_subsys_state *css,
         * multiple.
         */
        p = NULL;
-       cgroup_taskset_for_each_leader(leader, tset) {
+       cgroup_taskset_for_each_leader(leader, css, tset) {
                WARN_ON_ONCE(p);
                p = leader;
+               memcg = mem_cgroup_from_css(css);
        }
        if (!p)
                return 0;
 
+       /*
+        * We are now commited to this value whatever it is. Changes in this
+        * tunable will only affect upcoming migrations, not the current one.
+        * So we need to save it, and keep it going.
+        */
+       move_flags = READ_ONCE(memcg->move_charge_at_immigrate);
+       if (!move_flags)
+               return 0;
+
        from = mem_cgroup_from_task(p);
 
        VM_BUG_ON(from == memcg);
@@ -4842,8 +4878,7 @@ static int mem_cgroup_can_attach(struct cgroup_subsys_state *css,
        return ret;
 }
 
-static void mem_cgroup_cancel_attach(struct cgroup_subsys_state *css,
-                                    struct cgroup_taskset *tset)
+static void mem_cgroup_cancel_attach(struct cgroup_taskset *tset)
 {
        if (mc.to)
                mem_cgroup_clear_mc();
@@ -4985,10 +5020,10 @@ retry:
        atomic_dec(&mc.from->moving_account);
 }
 
-static void mem_cgroup_move_task(struct cgroup_subsys_state *css,
-                                struct cgroup_taskset *tset)
+static void mem_cgroup_move_task(struct cgroup_taskset *tset)
 {
-       struct task_struct *p = cgroup_taskset_first(tset);
+       struct cgroup_subsys_state *css;
+       struct task_struct *p = cgroup_taskset_first(tset, &css);
        struct mm_struct *mm = get_task_mm(p);
 
        if (mm) {
@@ -5000,17 +5035,14 @@ static void mem_cgroup_move_task(struct cgroup_subsys_state *css,
                mem_cgroup_clear_mc();
 }
 #else  /* !CONFIG_MMU */
-static int mem_cgroup_can_attach(struct cgroup_subsys_state *css,
-                                struct cgroup_taskset *tset)
+static int mem_cgroup_can_attach(struct cgroup_taskset *tset)
 {
        return 0;
 }
-static void mem_cgroup_cancel_attach(struct cgroup_subsys_state *css,
-                                    struct cgroup_taskset *tset)
+static void mem_cgroup_cancel_attach(struct cgroup_taskset *tset)
 {
 }
-static void mem_cgroup_move_task(struct cgroup_subsys_state *css,
-                                struct cgroup_taskset *tset)
+static void mem_cgroup_move_task(struct cgroup_taskset *tset)
 {
 }
 #endif
@@ -5184,6 +5216,7 @@ struct cgroup_subsys memory_cgrp_subsys = {
        .css_alloc = mem_cgroup_css_alloc,
        .css_online = mem_cgroup_css_online,
        .css_offline = mem_cgroup_css_offline,
+       .css_released = mem_cgroup_css_released,
        .css_free = mem_cgroup_css_free,
        .css_reset = mem_cgroup_css_reset,
        .can_attach = mem_cgroup_can_attach,
@@ -5511,11 +5544,11 @@ void mem_cgroup_uncharge_list(struct list_head *page_list)
  * mem_cgroup_replace_page - migrate a charge to another page
  * @oldpage: currently charged page
  * @newpage: page to transfer the charge to
- * @lrucare: either or both pages might be on the LRU already
  *
  * Migrate the charge from @oldpage to @newpage.
  *
  * Both pages must be locked, @newpage->mapping must be set up.
+ * Either or both pages might be on the LRU already.
  */
 void mem_cgroup_replace_page(struct page *oldpage, struct page *newpage)
 {
index 67d488ab495e57b9018484932e135078c787903c..a042a9d537bb31984d6b2a8d3cc8ae1e54361e4f 100644 (file)
@@ -1375,23 +1375,30 @@ int is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages)
  */
 int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn)
 {
-       unsigned long pfn;
+       unsigned long pfn, sec_end_pfn;
        struct zone *zone = NULL;
        struct page *page;
        int i;
-       for (pfn = start_pfn;
+       for (pfn = start_pfn, sec_end_pfn = SECTION_ALIGN_UP(start_pfn);
             pfn < end_pfn;
-            pfn += MAX_ORDER_NR_PAGES) {
-               i = 0;
-               /* This is just a CONFIG_HOLES_IN_ZONE check.*/
-               while ((i < MAX_ORDER_NR_PAGES) && !pfn_valid_within(pfn + i))
-                       i++;
-               if (i == MAX_ORDER_NR_PAGES)
+            pfn = sec_end_pfn + 1, sec_end_pfn += PAGES_PER_SECTION) {
+               /* Make sure the memory section is present first */
+               if (!present_section_nr(pfn_to_section_nr(pfn)))
                        continue;
-               page = pfn_to_page(pfn + i);
-               if (zone && page_zone(page) != zone)
-                       return 0;
-               zone = page_zone(page);
+               for (; pfn < sec_end_pfn && pfn < end_pfn;
+                    pfn += MAX_ORDER_NR_PAGES) {
+                       i = 0;
+                       /* This is just a CONFIG_HOLES_IN_ZONE check.*/
+                       while ((i < MAX_ORDER_NR_PAGES) &&
+                               !pfn_valid_within(pfn + i))
+                               i++;
+                       if (i == MAX_ORDER_NR_PAGES)
+                               continue;
+                       page = pfn_to_page(pfn + i);
+                       if (zone && page_zone(page) != zone)
+                               return 0;
+                       zone = page_zone(page);
+               }
        }
        return 1;
 }
index d13a33918fa23e685bc629bc23f58d97729beb62..c12680993ff334560dbfc84ffcee4e0bd0487650 100644 (file)
@@ -608,6 +608,8 @@ void oom_kill_process(struct oom_control *oc, struct task_struct *p,
                        continue;
                if (unlikely(p->flags & PF_KTHREAD))
                        continue;
+               if (is_global_init(p))
+                       continue;
                if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
                        continue;
 
index 3e4d65445fa71d7d629868c1db70af2bfb1fab28..d15d88c8efa1e25bf76fe3bf07f6eeb08fd14fd5 100644 (file)
@@ -2,7 +2,7 @@
  * mm/page-writeback.c
  *
  * Copyright (C) 2002, Linus Torvalds.
- * Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
+ * Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra
  *
  * Contains functions related to writing back dirty pages at the
  * address_space level.
index 17a3c66639a9cd6625f333b4f64ab012e2cb56c4..9d666df5ef9502b70cf7ba0aedef5eb805fdd811 100644 (file)
@@ -3647,8 +3647,9 @@ static void show_migration_types(unsigned char type)
 {
        static const char types[MIGRATE_TYPES] = {
                [MIGRATE_UNMOVABLE]     = 'U',
-               [MIGRATE_RECLAIMABLE]   = 'E',
                [MIGRATE_MOVABLE]       = 'M',
+               [MIGRATE_RECLAIMABLE]   = 'E',
+               [MIGRATE_HIGHATOMIC]    = 'H',
 #ifdef CONFIG_CMA
                [MIGRATE_CMA]           = 'C',
 #endif
index 297390f4e50ffee8068a3adc585925ea4ef08d63..5813b7fa85b64667c7ea7f9c73da84e073b6d325 100644 (file)
@@ -843,14 +843,14 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
                list_add_tail(&info->swaplist, &shmem_swaplist);
 
        if (add_to_swap_cache(page, swap, GFP_ATOMIC) == 0) {
-               swap_shmem_alloc(swap);
-               shmem_delete_from_page_cache(page, swp_to_radix_entry(swap));
-
                spin_lock(&info->lock);
-               info->swapped++;
                shmem_recalc_inode(inode);
+               info->swapped++;
                spin_unlock(&info->lock);
 
+               swap_shmem_alloc(swap);
+               shmem_delete_from_page_cache(page, swp_to_radix_entry(swap));
+
                mutex_unlock(&shmem_swaplist_mutex);
                BUG_ON(page_mapped(page));
                swap_writepage(page, wbc);
@@ -1078,7 +1078,7 @@ repeat:
        if (sgp != SGP_WRITE && sgp != SGP_FALLOC &&
            ((loff_t)index << PAGE_CACHE_SHIFT) >= i_size_read(inode)) {
                error = -EINVAL;
-               goto failed;
+               goto unlock;
        }
 
        if (page && sgp == SGP_WRITE)
@@ -1246,11 +1246,15 @@ clear:
        /* Perhaps the file has been truncated since we checked */
        if (sgp != SGP_WRITE && sgp != SGP_FALLOC &&
            ((loff_t)index << PAGE_CACHE_SHIFT) >= i_size_read(inode)) {
+               if (alloced) {
+                       ClearPageDirty(page);
+                       delete_from_page_cache(page);
+                       spin_lock(&info->lock);
+                       shmem_recalc_inode(inode);
+                       spin_unlock(&info->lock);
+               }
                error = -EINVAL;
-               if (alloced)
-                       goto trunc;
-               else
-                       goto failed;
+               goto unlock;
        }
        *pagep = page;
        return 0;
@@ -1258,23 +1262,13 @@ clear:
        /*
         * Error recovery.
         */
-trunc:
-       info = SHMEM_I(inode);
-       ClearPageDirty(page);
-       delete_from_page_cache(page);
-       spin_lock(&info->lock);
-       info->alloced--;
-       inode->i_blocks -= BLOCKS_PER_PAGE;
-       spin_unlock(&info->lock);
 decused:
-       sbinfo = SHMEM_SB(inode->i_sb);
        if (sbinfo->max_blocks)
                percpu_counter_add(&sbinfo->used_blocks, -1);
 unacct:
        shmem_unacct_blocks(info->flags, 1);
 failed:
-       if (swap.val && error != -EINVAL &&
-           !shmem_confirm_swap(mapping, index, swap))
+       if (swap.val && !shmem_confirm_swap(mapping, index, swap))
                error = -EEXIST;
 unlock:
        if (page) {
@@ -2444,7 +2438,6 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
        int len;
        struct inode *inode;
        struct page *page;
-       char *kaddr;
        struct shmem_inode_info *info;
 
        len = strlen(symname) + 1;
@@ -2483,9 +2476,8 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
                }
                inode->i_mapping->a_ops = &shmem_aops;
                inode->i_op = &shmem_symlink_inode_operations;
-               kaddr = kmap_atomic(page);
-               memcpy(kaddr, symname, len);
-               kunmap_atomic(kaddr);
+               inode_nohighmem(inode);
+               memcpy(page_address(page), symname, len);
                SetPageUptodate(page);
                set_page_dirty(page);
                unlock_page(page);
@@ -2498,23 +2490,34 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
        return 0;
 }
 
-static const char *shmem_follow_link(struct dentry *dentry, void **cookie)
+static void shmem_put_link(void *arg)
 {
-       struct page *page = NULL;
-       int error = shmem_getpage(d_inode(dentry), 0, &page, SGP_READ, NULL);
-       if (error)
-               return ERR_PTR(error);
-       unlock_page(page);
-       *cookie = page;
-       return kmap(page);
+       mark_page_accessed(arg);
+       put_page(arg);
 }
 
-static void shmem_put_link(struct inode *unused, void *cookie)
+static const char *shmem_get_link(struct dentry *dentry,
+                                 struct inode *inode,
+                                 struct delayed_call *done)
 {
-       struct page *page = cookie;
-       kunmap(page);
-       mark_page_accessed(page);
-       page_cache_release(page);
+       struct page *page = NULL;
+       int error;
+       if (!dentry) {
+               page = find_get_page(inode->i_mapping, 0);
+               if (!page)
+                       return ERR_PTR(-ECHILD);
+               if (!PageUptodate(page)) {
+                       put_page(page);
+                       return ERR_PTR(-ECHILD);
+               }
+       } else {
+               error = shmem_getpage(inode, 0, &page, SGP_READ, NULL);
+               if (error)
+                       return ERR_PTR(error);
+               unlock_page(page);
+       }
+       set_delayed_call(done, shmem_put_link, page);
+       return page_address(page);
 }
 
 #ifdef CONFIG_TMPFS_XATTR
@@ -2612,7 +2615,7 @@ static ssize_t shmem_listxattr(struct dentry *dentry, char *buffer, size_t size)
 
 static const struct inode_operations shmem_short_symlink_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = simple_follow_link,
+       .get_link       = simple_get_link,
 #ifdef CONFIG_TMPFS_XATTR
        .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
@@ -2623,8 +2626,7 @@ static const struct inode_operations shmem_short_symlink_operations = {
 
 static const struct inode_operations shmem_symlink_inode_operations = {
        .readlink       = generic_readlink,
-       .follow_link    = shmem_follow_link,
-       .put_link       = shmem_put_link,
+       .get_link       = shmem_get_link,
 #ifdef CONFIG_TMPFS_XATTR
        .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
index 879a2be23325ce73158e097eb381628a5fd5f548..c54fd2924f25af960462e474fa3583c633f9fcc8 100644 (file)
@@ -219,7 +219,7 @@ void set_pgdat_percpu_threshold(pg_data_t *pgdat,
  * particular counter cannot be updated from interrupt context.
  */
 void __mod_zone_page_state(struct zone *zone, enum zone_stat_item item,
-                               int delta)
+                          long delta)
 {
        struct per_cpu_pageset __percpu *pcp = zone->pageset;
        s8 __percpu *p = pcp->vm_stat_diff + item;
@@ -318,8 +318,8 @@ EXPORT_SYMBOL(__dec_zone_page_state);
  *     1       Overstepping half of threshold
  *     -1      Overstepping minus half of threshold
 */
-static inline void mod_state(struct zone *zone,
-       enum zone_stat_item item, int delta, int overstep_mode)
+static inline void mod_state(struct zone *zone, enum zone_stat_item item,
+                            long delta, int overstep_mode)
 {
        struct per_cpu_pageset __percpu *pcp = zone->pageset;
        s8 __percpu *p = pcp->vm_stat_diff + item;
@@ -357,7 +357,7 @@ static inline void mod_state(struct zone *zone,
 }
 
 void mod_zone_page_state(struct zone *zone, enum zone_stat_item item,
-                                       int delta)
+                        long delta)
 {
        mod_state(zone, item, delta, 0);
 }
@@ -384,7 +384,7 @@ EXPORT_SYMBOL(dec_zone_page_state);
  * Use interrupt disable to serialize counter updates
  */
 void mod_zone_page_state(struct zone *zone, enum zone_stat_item item,
-                                       int delta)
+                        long delta)
 {
        unsigned long flags;
 
@@ -921,8 +921,8 @@ static void walk_zones_in_node(struct seq_file *m, pg_data_t *pgdat,
 #ifdef CONFIG_PROC_FS
 static char * const migratetype_names[MIGRATE_TYPES] = {
        "Unmovable",
-       "Reclaimable",
        "Movable",
+       "Reclaimable",
        "HighAtomic",
 #ifdef CONFIG_CMA
        "CMA",
@@ -1379,6 +1379,7 @@ static const struct file_operations proc_vmstat_file_operations = {
 #endif /* CONFIG_PROC_FS */
 
 #ifdef CONFIG_SMP
+static struct workqueue_struct *vmstat_wq;
 static DEFINE_PER_CPU(struct delayed_work, vmstat_work);
 int sysctl_stat_interval __read_mostly = HZ;
 static cpumask_var_t cpu_stat_off;
@@ -1391,7 +1392,7 @@ static void vmstat_update(struct work_struct *w)
                 * to occur in the future. Keep on running the
                 * update worker thread.
                 */
-               schedule_delayed_work_on(smp_processor_id(),
+               queue_delayed_work_on(smp_processor_id(), vmstat_wq,
                        this_cpu_ptr(&vmstat_work),
                        round_jiffies_relative(sysctl_stat_interval));
        } else {
@@ -1460,7 +1461,7 @@ static void vmstat_shepherd(struct work_struct *w)
                if (need_update(cpu) &&
                        cpumask_test_and_clear_cpu(cpu, cpu_stat_off))
 
-                       schedule_delayed_work_on(cpu,
+                       queue_delayed_work_on(cpu, vmstat_wq,
                                &per_cpu(vmstat_work, cpu), 0);
 
        put_online_cpus();
@@ -1482,6 +1483,7 @@ static void __init start_shepherd_timer(void)
                BUG();
        cpumask_copy(cpu_stat_off, cpu_online_mask);
 
+       vmstat_wq = alloc_workqueue("vmstat", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
        schedule_delayed_work(&shepherd,
                round_jiffies_relative(sysctl_stat_interval));
 }
index 025f8dc723dedf60da7d2d9d580ac208e75cd8f6..bf14508afd64573d8310a5a3e12b99b629fc8c02 100644 (file)
@@ -541,6 +541,7 @@ static struct zswap_pool *zswap_pool_last_get(void)
        return last;
 }
 
+/* type and compressor must be null-terminated */
 static struct zswap_pool *zswap_pool_find_get(char *type, char *compressor)
 {
        struct zswap_pool *pool;
@@ -548,10 +549,9 @@ static struct zswap_pool *zswap_pool_find_get(char *type, char *compressor)
        assert_spin_locked(&zswap_pools_lock);
 
        list_for_each_entry_rcu(pool, &zswap_pools, list) {
-               if (strncmp(pool->tfm_name, compressor, sizeof(pool->tfm_name)))
+               if (strcmp(pool->tfm_name, compressor))
                        continue;
-               if (strncmp(zpool_get_type(pool->zpool), type,
-                           sizeof(zswap_zpool_type)))
+               if (strcmp(zpool_get_type(pool->zpool), type))
                        continue;
                /* if we can't get it, it's about to be destroyed */
                if (!zswap_pool_get(pool))
index ae3a47f9d1d5298406ca33900624fe49c9c85719..fbd0acf80b13236bd8c768bc8bf5d69d6a7e7125 100644 (file)
@@ -805,6 +805,9 @@ static int ax25_create(struct net *net, struct socket *sock, int protocol,
        struct sock *sk;
        ax25_cb *ax25;
 
+       if (protocol < 0 || protocol > SK_PROTOCOL_MAX)
+               return -EINVAL;
+
        if (!net_eq(net, &init_net))
                return -EAFNOSUPPORT;
 
index 83bc1aaf5800cbc68aa8a33f967a2ae5533af801..a49c705fb86b861f5595c8c0cfb7b8b1e1010589 100644 (file)
@@ -566,6 +566,7 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
        int select;
        batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, ip_key;
        struct batadv_dat_candidate *res;
+       struct batadv_dat_entry dat;
 
        if (!bat_priv->orig_hash)
                return NULL;
@@ -575,7 +576,9 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
        if (!res)
                return NULL;
 
-       ip_key = (batadv_dat_addr_t)batadv_hash_dat(&ip_dst,
+       dat.ip = ip_dst;
+       dat.vid = 0;
+       ip_key = (batadv_dat_addr_t)batadv_hash_dat(&dat,
                                                    BATADV_DAT_ADDR_MAX);
 
        batadv_dbg(BATADV_DBG_DAT, bat_priv,
index 8d990b070a2e87db6a6e71f9e3eaad93dbf4a59e..3207667e69de30e92499c705f39319c55f36732f 100644 (file)
@@ -836,6 +836,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
        u8 *orig_addr;
        struct batadv_orig_node *orig_node = NULL;
        int check, hdr_size = sizeof(*unicast_packet);
+       enum batadv_subtype subtype;
        bool is4addr;
 
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
@@ -863,10 +864,20 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
        /* packet for me */
        if (batadv_is_my_mac(bat_priv, unicast_packet->dest)) {
                if (is4addr) {
-                       batadv_dat_inc_counter(bat_priv,
-                                              unicast_4addr_packet->subtype);
-                       orig_addr = unicast_4addr_packet->src;
-                       orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
+                       subtype = unicast_4addr_packet->subtype;
+                       batadv_dat_inc_counter(bat_priv, subtype);
+
+                       /* Only payload data should be considered for speedy
+                        * join. For example, DAT also uses unicast 4addr
+                        * types, but those packets should not be considered
+                        * for speedy join, since the clients do not actually
+                        * reside at the sending originator.
+                        */
+                       if (subtype == BATADV_P_DATA) {
+                               orig_addr = unicast_4addr_packet->src;
+                               orig_node = batadv_orig_hash_find(bat_priv,
+                                                                 orig_addr);
+                       }
                }
 
                if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb,
index 4228b10c47ead06db9284997afc1899e181d6505..76f19ba62462bf03fadba72171d3ae01a565ba57 100644 (file)
@@ -68,13 +68,15 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv,
                                 unsigned short vid, const char *message,
                                 bool roaming);
 
-/* returns 1 if they are the same mac addr */
+/* returns 1 if they are the same mac addr and vid */
 static int batadv_compare_tt(const struct hlist_node *node, const void *data2)
 {
        const void *data1 = container_of(node, struct batadv_tt_common_entry,
                                         hash_entry);
+       const struct batadv_tt_common_entry *tt1 = data1;
+       const struct batadv_tt_common_entry *tt2 = data2;
 
-       return batadv_compare_eth(data1, data2);
+       return (tt1->vid == tt2->vid) && batadv_compare_eth(data1, data2);
 }
 
 /**
@@ -1427,9 +1429,15 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
                }
 
                /* if the client was temporary added before receiving the first
-                * OGM announcing it, we have to clear the TEMP flag
+                * OGM announcing it, we have to clear the TEMP flag. Also,
+                * remove the previous temporary orig node and re-add it
+                * if required. If the orig entry changed, the new one which
+                * is a non-temporary entry is preferred.
                 */
-               common->flags &= ~BATADV_TT_CLIENT_TEMP;
+               if (common->flags & BATADV_TT_CLIENT_TEMP) {
+                       batadv_tt_global_del_orig_list(tt_global_entry);
+                       common->flags &= ~BATADV_TT_CLIENT_TEMP;
+               }
 
                /* the change can carry possible "attribute" flags like the
                 * TT_CLIENT_WIFI, therefore they have to be copied in the
index fe129663bd3f7faeb39f20d02a8425d525da071d..f52bcbf2e58cd8b8ded4c3d65c8dd9b87034b002 100644 (file)
@@ -526,6 +526,9 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr,
        if (!addr || addr->sa_family != AF_BLUETOOTH)
                return -EINVAL;
 
+       if (addr_len < sizeof(struct sockaddr_sco))
+               return -EINVAL;
+
        lock_sock(sk);
 
        if (sk->sk_state != BT_OPEN) {
index 5396ff08af3215d1a532b853c8859fb64dfc6a1f..8a7ada8bb947f5129375e549c22af5a5b32c5a99 100644 (file)
@@ -39,7 +39,7 @@ void br_init_port(struct net_bridge_port *p)
        struct switchdev_attr attr = {
                .id = SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME,
                .flags = SWITCHDEV_F_SKIP_EOPNOTSUPP | SWITCHDEV_F_DEFER,
-               .u.ageing_time = p->br->ageing_time,
+               .u.ageing_time = jiffies_to_clock_t(p->br->ageing_time),
        };
        int err;
 
@@ -142,7 +142,10 @@ static void br_stp_start(struct net_bridge *br)
        char *envp[] = { NULL };
        struct net_bridge_port *p;
 
-       r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC);
+       if (net_eq(dev_net(br->dev), &init_net))
+               r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC);
+       else
+               r = -ENOENT;
 
        spin_lock_bh(&br->lock);
 
index e6dc77252fe9fa3e401529426079f094c9f6f999..a1656e3b8d72a66ff56656284205129ecfd30b3e 100644 (file)
@@ -301,12 +301,13 @@ void dst_release(struct dst_entry *dst)
 {
        if (dst) {
                int newrefcnt;
+               unsigned short nocache = dst->flags & DST_NOCACHE;
 
                newrefcnt = atomic_dec_return(&dst->__refcnt);
                if (unlikely(newrefcnt < 0))
                        net_warn_ratelimited("%s: dst:%p refcnt:%d\n",
                                             __func__, dst, newrefcnt);
-               if (!newrefcnt && unlikely(dst->flags & DST_NOCACHE))
+               if (!newrefcnt && unlikely(nocache))
                        call_rcu(&dst->rcu_head, dst_destroy_rcu);
        }
 }
index 2e4df84c34a194ad61d818f282d1124521b9a828..d9ee8d08a3a6944ebb6e5d8dafe6fb5032aa7a52 100644 (file)
@@ -81,9 +81,11 @@ static void update_classid(struct cgroup_subsys_state *css, void *v)
        css_task_iter_end(&it);
 }
 
-static void cgrp_attach(struct cgroup_subsys_state *css,
-                       struct cgroup_taskset *tset)
+static void cgrp_attach(struct cgroup_taskset *tset)
 {
+       struct cgroup_subsys_state *css;
+
+       cgroup_taskset_first(tset, &css);
        update_classid(css,
                       (void *)(unsigned long)css_cls_state(css)->classid);
 }
index cbd0a199bf52c79780e7935f1ed123f3f86758ec..40fd09fe06ae91e133bbf1fe499e38870903c8ca 100644 (file)
@@ -218,13 +218,14 @@ static int update_netprio(const void *v, struct file *file, unsigned n)
        return 0;
 }
 
-static void net_prio_attach(struct cgroup_subsys_state *css,
-                           struct cgroup_taskset *tset)
+static void net_prio_attach(struct cgroup_taskset *tset)
 {
        struct task_struct *p;
-       void *v = (void *)(unsigned long)css->cgroup->id;
+       struct cgroup_subsys_state *css;
+
+       cgroup_taskset_for_each(p, css, tset) {
+               void *v = (void *)(unsigned long)css->cgroup->id;
 
-       cgroup_taskset_for_each(p, tset) {
                task_lock(p);
                iterate_fd(p->files, 0, update_netprio, v);
                task_unlock(p);
index 152b9c70e25255f1c104c00db3867fd6b21bfa99..b2df375ec9c2173a8132b8efa1c3062f0510284b 100644 (file)
@@ -3643,7 +3643,8 @@ static void __skb_complete_tx_timestamp(struct sk_buff *skb,
        serr->ee.ee_info = tstype;
        if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) {
                serr->ee.ee_data = skb_shinfo(skb)->tskey;
-               if (sk->sk_protocol == IPPROTO_TCP)
+               if (sk->sk_protocol == IPPROTO_TCP &&
+                   sk->sk_type == SOCK_STREAM)
                        serr->ee.ee_data -= sk->sk_tskey;
        }
 
@@ -4268,7 +4269,7 @@ static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb)
                return NULL;
        }
 
-       memmove(skb->data - ETH_HLEN, skb->data - skb->mac_len,
+       memmove(skb->data - ETH_HLEN, skb->data - skb->mac_len - VLAN_HLEN,
                2 * ETH_ALEN);
        skb->mac_header += VLAN_HLEN;
        return skb;
index e31dfcee1729aa23bdd2ed692fda1b90bd75afb8..0d91f7dca751efc3e32348ba217c29e8ed55e80b 100644 (file)
@@ -433,8 +433,6 @@ static bool sock_needs_netstamp(const struct sock *sk)
        }
 }
 
-#define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE))
-
 static void sock_disable_timestamp(struct sock *sk, unsigned long flags)
 {
        if (sk->sk_flags & flags) {
@@ -874,7 +872,8 @@ set_rcvbuf:
 
                if (val & SOF_TIMESTAMPING_OPT_ID &&
                    !(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)) {
-                       if (sk->sk_protocol == IPPROTO_TCP) {
+                       if (sk->sk_protocol == IPPROTO_TCP &&
+                           sk->sk_type == SOCK_STREAM) {
                                if (sk->sk_state != TCP_ESTABLISHED) {
                                        ret = -EINVAL;
                                        break;
@@ -1552,7 +1551,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority)
                         */
                        is_charged = sk_filter_charge(newsk, filter);
 
-               if (unlikely(!is_charged || xfrm_sk_clone_policy(newsk))) {
+               if (unlikely(!is_charged || xfrm_sk_clone_policy(newsk, sk))) {
                        /* It is still raw copy of parent, so invalidate
                         * destructor and make plain sk_free() */
                        newsk->sk_destruct = NULL;
index eebf5ac8ce18abdb7ac094a1e6de081fcbfa79aa..13d6b1a6e0fc2b0730827d93d154d6464a3e58ec 100644 (file)
@@ -678,6 +678,9 @@ static int dn_create(struct net *net, struct socket *sock, int protocol,
 {
        struct sock *sk;
 
+       if (protocol < 0 || protocol > SK_PROTOCOL_MAX)
+               return -EINVAL;
+
        if (!net_eq(net, &init_net))
                return -EAFNOSUPPORT;
 
index 11c4ca13ec3b0434090b3d5cbdd7a0aae784952f..5c5db6636704daa0c49fc13e84b2c5b282a44ed3 100644 (file)
@@ -257,6 +257,9 @@ static int inet_create(struct net *net, struct socket *sock, int protocol,
        int try_loading_module = 0;
        int err;
 
+       if (protocol < 0 || protocol >= IPPROTO_MAX)
+               return -EINVAL;
+
        sock->state = SS_UNCONNECTED;
 
        /* Look for the requested type/protocol pair. */
index cc8f3e506cded3fbcc9a64bbd369577c5f7cb52d..47344759306011b5bb940e9cab9237b9e9f624b4 100644 (file)
@@ -1155,6 +1155,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event,
 static int fib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+       struct netdev_notifier_changeupper_info *info;
        struct in_device *in_dev;
        struct net *net = dev_net(dev);
        unsigned int flags;
@@ -1193,6 +1194,14 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo
        case NETDEV_CHANGEMTU:
                rt_cache_flush(net);
                break;
+       case NETDEV_CHANGEUPPER:
+               info = ptr;
+               /* flush all routes if dev is linked to or unlinked from
+                * an L3 master device (e.g., VRF)
+                */
+               if (info->upper_dev && netif_is_l3_master(info->upper_dev))
+                       fib_disable_ip(dev, NETDEV_DOWN, true);
+               break;
        }
        return NOTIFY_DONE;
 }
index e0fcbbbcfe54d0b35b46597b5f217075ffbc745c..bd903fe0f7508d9d7a94c4ce1e0a825f3e35c398 100644 (file)
@@ -24,6 +24,7 @@ struct fou {
        u16 type;
        struct udp_offload udp_offloads;
        struct list_head list;
+       struct rcu_head rcu;
 };
 
 #define FOU_F_REMCSUM_NOPARTIAL BIT(0)
@@ -417,7 +418,7 @@ static void fou_release(struct fou *fou)
        list_del(&fou->list);
        udp_tunnel_sock_release(sock);
 
-       kfree(fou);
+       kfree_rcu(fou, rcu);
 }
 
 static int fou_encap_init(struct sock *sk, struct fou *fou, struct fou_cfg *cfg)
index f34c31defafe083fcc9146affff5c39745150d04..a09fb0dec725a8827ba5d1e928597c103d1f9322 100644 (file)
@@ -253,9 +253,6 @@ ipip_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 
        p.i_key = p.o_key = 0;
        p.i_flags = p.o_flags = 0;
-       if (p.iph.ttl)
-               p.iph.frag_off |= htons(IP_DF);
-
        err = ip_tunnel_ioctl(dev, &p, cmd);
        if (err)
                return err;
index a3558417653567ffe3a83d06515fb1b68ec36dcf..c187c60e3e0c75e0f9c298eaa831c2f19d9a73fc 100644 (file)
@@ -60,6 +60,7 @@ config NFT_REJECT_IPV4
 
 config NFT_DUP_IPV4
        tristate "IPv4 nf_tables packet duplication support"
+       depends on !NF_CONNTRACK || NF_CONNTRACK
        select NF_DUP_IPV4
        help
          This module enables IPv4 packet duplication support for nf_tables.
index 63e5be0abd86ddab6476221161c48aacef34d8c4..bc35f1842512bef8e4d87e76542d7bf11f8946fa 100644 (file)
@@ -601,8 +601,11 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
                            (inet->hdrincl ? FLOWI_FLAG_KNOWN_NH : 0),
                           daddr, saddr, 0, 0);
 
-       if (!saddr && ipc.oif)
-               l3mdev_get_saddr(net, ipc.oif, &fl4);
+       if (!saddr && ipc.oif) {
+               err = l3mdev_get_saddr(net, ipc.oif, &fl4);
+               if (err < 0)
+                       goto done;
+       }
 
        if (!inet->hdrincl) {
                rfv.msg = msg;
index 2d656eef7f8e16458127ba591e0a4154365f6a83..d4c51158470f5afb7cee8a5c875b5f9ed5b04e14 100644 (file)
@@ -2478,6 +2478,9 @@ static void tcp_cwnd_reduction(struct sock *sk, const int prior_unsacked,
        int newly_acked_sacked = prior_unsacked -
                                 (tp->packets_out - tp->sacked_out);
 
+       if (newly_acked_sacked <= 0 || WARN_ON_ONCE(!tp->prior_cwnd))
+               return;
+
        tp->prr_delivered += newly_acked_sacked;
        if (delta < 0) {
                u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered +
index db003438aaf5f6a2b27319c4669be1b1f62c7ae3..d8841a2f15691fd80c46fbaa62e2431e9ca16003 100644 (file)
@@ -1493,7 +1493,7 @@ bool tcp_prequeue(struct sock *sk, struct sk_buff *skb)
        if (likely(sk->sk_rx_dst))
                skb_dst_drop(skb);
        else
-               skb_dst_force(skb);
+               skb_dst_force_safe(skb);
 
        __skb_queue_tail(&tp->ucopy.prequeue, skb);
        tp->ucopy.memory += skb->truesize;
@@ -1721,8 +1721,7 @@ void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb)
 {
        struct dst_entry *dst = skb_dst(skb);
 
-       if (dst) {
-               dst_hold(dst);
+       if (dst && dst_hold_safe(dst)) {
                sk->sk_rx_dst = dst;
                inet_sk(sk)->rx_dst_ifindex = skb->skb_iif;
        }
index cb7ca569052c5b69f78418e9c966cb285eff1d50..9bfc39ff2285aecaab86f519a017b84282cb6597 100644 (file)
@@ -3150,7 +3150,7 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        struct tcp_fastopen_request *fo = tp->fastopen_req;
-       int syn_loss = 0, space, err = 0, copied;
+       int syn_loss = 0, space, err = 0;
        unsigned long last_syn_loss = 0;
        struct sk_buff *syn_data;
 
@@ -3188,17 +3188,18 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn)
                goto fallback;
        syn_data->ip_summed = CHECKSUM_PARTIAL;
        memcpy(syn_data->cb, syn->cb, sizeof(syn->cb));
-       copied = copy_from_iter(skb_put(syn_data, space), space,
-                               &fo->data->msg_iter);
-       if (unlikely(!copied)) {
-               kfree_skb(syn_data);
-               goto fallback;
-       }
-       if (copied != space) {
-               skb_trim(syn_data, copied);
-               space = copied;
+       if (space) {
+               int copied = copy_from_iter(skb_put(syn_data, space), space,
+                                           &fo->data->msg_iter);
+               if (unlikely(!copied)) {
+                       kfree_skb(syn_data);
+                       goto fallback;
+               }
+               if (copied != space) {
+                       skb_trim(syn_data, copied);
+                       space = copied;
+               }
        }
-
        /* No more data pending in inet_wait_for_connect() */
        if (space == fo->size)
                fo->data = NULL;
index 0c7b0e61b917158af7e431f9e7781f7bce313c83..c43890848641948b1e9c55244614ac9a48756753 100644 (file)
@@ -1025,8 +1025,11 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
                                   flow_flags,
                                   faddr, saddr, dport, inet->inet_sport);
 
-               if (!saddr && ipc.oif)
-                       l3mdev_get_saddr(net, ipc.oif, fl4);
+               if (!saddr && ipc.oif) {
+                       err = l3mdev_get_saddr(net, ipc.oif, fl4);
+                       if (err < 0)
+                               goto out;
+               }
 
                security_sk_classify_flow(sk, flowi4_to_flowi(fl4));
                rt = ip_route_output_flow(net, fl4, sk);
index 1e0c3c835a6349eedca54e2dff191ed56b437613..7b0edb37a1150427ef3b0d9a7f2be11421ef67b0 100644 (file)
@@ -259,7 +259,7 @@ static void xfrm4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
        xfrm_dst_ifdown(dst, dev);
 }
 
-static struct dst_ops xfrm4_dst_ops = {
+static struct dst_ops xfrm4_dst_ops_template = {
        .family =               AF_INET,
        .gc =                   xfrm4_garbage_collect,
        .update_pmtu =          xfrm4_update_pmtu,
@@ -273,7 +273,7 @@ static struct dst_ops xfrm4_dst_ops = {
 
 static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
        .family =               AF_INET,
-       .dst_ops =              &xfrm4_dst_ops,
+       .dst_ops =              &xfrm4_dst_ops_template,
        .dst_lookup =           xfrm4_dst_lookup,
        .get_saddr =            xfrm4_get_saddr,
        .decode_session =       _decode_session4,
@@ -295,7 +295,7 @@ static struct ctl_table xfrm4_policy_table[] = {
        { }
 };
 
-static int __net_init xfrm4_net_init(struct net *net)
+static int __net_init xfrm4_net_sysctl_init(struct net *net)
 {
        struct ctl_table *table;
        struct ctl_table_header *hdr;
@@ -323,7 +323,7 @@ err_alloc:
        return -ENOMEM;
 }
 
-static void __net_exit xfrm4_net_exit(struct net *net)
+static void __net_exit xfrm4_net_sysctl_exit(struct net *net)
 {
        struct ctl_table *table;
 
@@ -335,12 +335,44 @@ static void __net_exit xfrm4_net_exit(struct net *net)
        if (!net_eq(net, &init_net))
                kfree(table);
 }
+#else /* CONFIG_SYSCTL */
+static int inline xfrm4_net_sysctl_init(struct net *net)
+{
+       return 0;
+}
+
+static void inline xfrm4_net_sysctl_exit(struct net *net)
+{
+}
+#endif
+
+static int __net_init xfrm4_net_init(struct net *net)
+{
+       int ret;
+
+       memcpy(&net->xfrm.xfrm4_dst_ops, &xfrm4_dst_ops_template,
+              sizeof(xfrm4_dst_ops_template));
+       ret = dst_entries_init(&net->xfrm.xfrm4_dst_ops);
+       if (ret)
+               return ret;
+
+       ret = xfrm4_net_sysctl_init(net);
+       if (ret)
+               dst_entries_destroy(&net->xfrm.xfrm4_dst_ops);
+
+       return ret;
+}
+
+static void __net_exit xfrm4_net_exit(struct net *net)
+{
+       xfrm4_net_sysctl_exit(net);
+       dst_entries_destroy(&net->xfrm.xfrm4_dst_ops);
+}
 
 static struct pernet_operations __net_initdata xfrm4_net_ops = {
        .init   = xfrm4_net_init,
        .exit   = xfrm4_net_exit,
 };
-#endif
 
 static void __init xfrm4_policy_init(void)
 {
@@ -349,13 +381,9 @@ static void __init xfrm4_policy_init(void)
 
 void __init xfrm4_init(void)
 {
-       dst_entries_init(&xfrm4_dst_ops);
-
        xfrm4_state_init();
        xfrm4_policy_init();
        xfrm4_protocol_init();
-#ifdef CONFIG_SYSCTL
        register_pernet_subsys(&xfrm4_net_ops);
-#endif
 }
 
index 61f26851655ccd23200278d34ceda44351da1c17..1f21087accab258e5be6cc104f8b8ced13fedd6d 100644 (file)
@@ -350,6 +350,12 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
        setup_timer(&ndev->rs_timer, addrconf_rs_timer,
                    (unsigned long)ndev);
        memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf));
+
+       if (ndev->cnf.stable_secret.initialized)
+               ndev->addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY;
+       else
+               ndev->addr_gen_mode = IN6_ADDR_GEN_MODE_EUI64;
+
        ndev->cnf.mtu6 = dev->mtu;
        ndev->cnf.sysctl = NULL;
        ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl);
@@ -2455,7 +2461,7 @@ ok:
 #ifdef CONFIG_IPV6_OPTIMISTIC_DAD
                        if (in6_dev->cnf.optimistic_dad &&
                            !net->ipv6.devconf_all->forwarding && sllao)
-                               addr_flags = IFA_F_OPTIMISTIC;
+                               addr_flags |= IFA_F_OPTIMISTIC;
 #endif
 
                        /* Do not allow to create too much of autoconfigured
@@ -5363,13 +5369,10 @@ static int addrconf_sysctl_stable_secret(struct ctl_table *ctl, int write,
                goto out;
        }
 
-       if (!write) {
-               err = snprintf(str, sizeof(str), "%pI6",
-                              &secret->secret);
-               if (err >= sizeof(str)) {
-                       err = -EIO;
-                       goto out;
-               }
+       err = snprintf(str, sizeof(str), "%pI6", &secret->secret);
+       if (err >= sizeof(str)) {
+               err = -EIO;
+               goto out;
        }
 
        err = proc_dostring(&lctl, write, buffer, lenp, ppos);
index 882124ebb438bd033765c4284ddf7ada9834d39d..a8f6986dcbe5ea5a36a3cc6fcf51becebb50c33b 100644 (file)
@@ -552,7 +552,7 @@ static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr *nlh)
 
        rcu_read_lock();
        p = __ipv6_addr_label(net, addr, ipv6_addr_type(addr), ifal->ifal_index);
-       if (p && ip6addrlbl_hold(p))
+       if (p && !ip6addrlbl_hold(p))
                p = NULL;
        lseq = ip6addrlbl_table.seq;
        rcu_read_unlock();
index 8ec0df75f1c4f81bea71cb466c4da802c39099d8..9f5137cd604e51316c6c3a85ca5423b30ed7ce30 100644 (file)
@@ -109,6 +109,9 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol,
        int try_loading_module = 0;
        int err;
 
+       if (protocol < 0 || protocol >= IPPROTO_MAX)
+               return -EINVAL;
+
        /* Look for the requested type/protocol pair. */
 lookup_protocol:
        err = -ESOCKTNOSUPPORT;
index 3c7b9310b33fdb052e2b97d4cd502482524b4dd8..e5ea177d34c6492713d5271032394a69874a300c 100644 (file)
@@ -1571,13 +1571,11 @@ static int ip6gre_changelink(struct net_device *dev, struct nlattr *tb[],
                        return -EEXIST;
        } else {
                t = nt;
-
-               ip6gre_tunnel_unlink(ign, t);
-               ip6gre_tnl_change(t, &p, !tb[IFLA_MTU]);
-               ip6gre_tunnel_link(ign, t);
-               netdev_state_change(dev);
        }
 
+       ip6gre_tunnel_unlink(ign, t);
+       ip6gre_tnl_change(t, &p, !tb[IFLA_MTU]);
+       ip6gre_tunnel_link(ign, t);
        return 0;
 }
 
index d6161e1c48c86f4a5dfa5cedc89d4b93f8e3d24a..84afb9a7727848038b51ee7a60eebb28d555f693 100644 (file)
@@ -1183,7 +1183,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
         */
        if (!in6_dev->cnf.accept_ra_from_local &&
            ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr,
-                         NULL, 0)) {
+                         in6_dev->dev, 0)) {
                ND_PRINTK(2, info,
                          "RA from local address detected on dev: %s: default router ignored\n",
                          skb->dev->name);
@@ -1337,7 +1337,7 @@ skip_linkparms:
 #ifdef CONFIG_IPV6_ROUTE_INFO
        if (!in6_dev->cnf.accept_ra_from_local &&
            ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr,
-                         NULL, 0)) {
+                         in6_dev->dev, 0)) {
                ND_PRINTK(2, info,
                          "RA from local address detected on dev: %s: router info ignored.\n",
                          skb->dev->name);
index f6a024e141e595541009cb24c172e0c52a8a879f..e10a04c9cdc7be6bd8fc18f960e7bf51f43cbd81 100644 (file)
@@ -49,6 +49,7 @@ config NFT_REJECT_IPV6
 
 config NFT_DUP_IPV6
        tristate "IPv6 nf_tables packet duplication support"
+       depends on !NF_CONNTRACK || NF_CONNTRACK
        select NF_DUP_IPV6
        help
          This module enables IPv6 packet duplication support for nf_tables.
index e7aab561b7b463d4bfbdd7e7a89302403e252560..6b8a8a9091fa113ee28906c570e78811e6f29815 100644 (file)
@@ -93,10 +93,9 @@ static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb)
 {
        struct dst_entry *dst = skb_dst(skb);
 
-       if (dst) {
+       if (dst && dst_hold_safe(dst)) {
                const struct rt6_info *rt = (const struct rt6_info *)dst;
 
-               dst_hold(dst);
                sk->sk_rx_dst = dst;
                inet_sk(sk)->rx_dst_ifindex = skb->skb_iif;
                inet6_sk(sk)->rx_dst_cookie = rt6_get_cookie(rt);
index 5643423fe67a238c05aee5398ac4064a77bafc16..c074771a10f761253f99611de8294172bdb0e142 100644 (file)
@@ -279,7 +279,7 @@ static void xfrm6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
        xfrm_dst_ifdown(dst, dev);
 }
 
-static struct dst_ops xfrm6_dst_ops = {
+static struct dst_ops xfrm6_dst_ops_template = {
        .family =               AF_INET6,
        .gc =                   xfrm6_garbage_collect,
        .update_pmtu =          xfrm6_update_pmtu,
@@ -293,7 +293,7 @@ static struct dst_ops xfrm6_dst_ops = {
 
 static struct xfrm_policy_afinfo xfrm6_policy_afinfo = {
        .family =               AF_INET6,
-       .dst_ops =              &xfrm6_dst_ops,
+       .dst_ops =              &xfrm6_dst_ops_template,
        .dst_lookup =           xfrm6_dst_lookup,
        .get_saddr =            xfrm6_get_saddr,
        .decode_session =       _decode_session6,
@@ -325,7 +325,7 @@ static struct ctl_table xfrm6_policy_table[] = {
        { }
 };
 
-static int __net_init xfrm6_net_init(struct net *net)
+static int __net_init xfrm6_net_sysctl_init(struct net *net)
 {
        struct ctl_table *table;
        struct ctl_table_header *hdr;
@@ -353,7 +353,7 @@ err_alloc:
        return -ENOMEM;
 }
 
-static void __net_exit xfrm6_net_exit(struct net *net)
+static void __net_exit xfrm6_net_sysctl_exit(struct net *net)
 {
        struct ctl_table *table;
 
@@ -365,24 +365,52 @@ static void __net_exit xfrm6_net_exit(struct net *net)
        if (!net_eq(net, &init_net))
                kfree(table);
 }
+#else /* CONFIG_SYSCTL */
+static int inline xfrm6_net_sysctl_init(struct net *net)
+{
+       return 0;
+}
+
+static void inline xfrm6_net_sysctl_exit(struct net *net)
+{
+}
+#endif
+
+static int __net_init xfrm6_net_init(struct net *net)
+{
+       int ret;
+
+       memcpy(&net->xfrm.xfrm6_dst_ops, &xfrm6_dst_ops_template,
+              sizeof(xfrm6_dst_ops_template));
+       ret = dst_entries_init(&net->xfrm.xfrm6_dst_ops);
+       if (ret)
+               return ret;
+
+       ret = xfrm6_net_sysctl_init(net);
+       if (ret)
+               dst_entries_destroy(&net->xfrm.xfrm6_dst_ops);
+
+       return ret;
+}
+
+static void __net_exit xfrm6_net_exit(struct net *net)
+{
+       xfrm6_net_sysctl_exit(net);
+       dst_entries_destroy(&net->xfrm.xfrm6_dst_ops);
+}
 
 static struct pernet_operations xfrm6_net_ops = {
        .init   = xfrm6_net_init,
        .exit   = xfrm6_net_exit,
 };
-#endif
 
 int __init xfrm6_init(void)
 {
        int ret;
 
-       dst_entries_init(&xfrm6_dst_ops);
-
        ret = xfrm6_policy_init();
-       if (ret) {
-               dst_entries_destroy(&xfrm6_dst_ops);
+       if (ret)
                goto out;
-       }
        ret = xfrm6_state_init();
        if (ret)
                goto out_policy;
@@ -391,9 +419,7 @@ int __init xfrm6_init(void)
        if (ret)
                goto out_state;
 
-#ifdef CONFIG_SYSCTL
        register_pernet_subsys(&xfrm6_net_ops);
-#endif
 out:
        return ret;
 out_state:
@@ -405,11 +431,8 @@ out_policy:
 
 void xfrm6_fini(void)
 {
-#ifdef CONFIG_SYSCTL
        unregister_pernet_subsys(&xfrm6_net_ops);
-#endif
        xfrm6_protocol_fini();
        xfrm6_policy_fini();
        xfrm6_state_fini();
-       dst_entries_destroy(&xfrm6_dst_ops);
 }
index e6aa48b5395c67e2600eed9482c97b9a626d01bd..923abd6b3064074f39f84644b2d3d1f068403f51 100644 (file)
@@ -1086,6 +1086,9 @@ static int irda_create(struct net *net, struct socket *sock, int protocol,
        struct sock *sk;
        struct irda_sock *self;
 
+       if (protocol < 0 || protocol > SK_PROTOCOL_MAX)
+               return -EINVAL;
+
        if (net != &init_net)
                return -EAFNOSUPPORT;
 
index da471eef07bb1a6ba6e42d3e5b570dbdff6c21e3..c12f348138acf7075297e5854b6e17391646d52b 100644 (file)
@@ -1169,8 +1169,7 @@ static int sta_apply_parameters(struct ieee80211_local *local,
                 * rc isn't initialized here yet, so ignore it
                 */
                __ieee80211_vht_handle_opmode(sdata, sta,
-                                             params->opmode_notif,
-                                             band, false);
+                                             params->opmode_notif, band);
        }
 
        if (ieee80211_vif_is_mesh(&sdata->vif))
index d832bd59236be15c5a6bb86dbb1efc4547025f51..5322b4c716307f90710153bdb91e5425221b1742 100644 (file)
@@ -1709,10 +1709,10 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta);
 void ieee80211_sta_set_rx_nss(struct sta_info *sta);
 u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
                                   struct sta_info *sta, u8 opmode,
-                                  enum ieee80211_band band, bool nss_only);
+                                 enum ieee80211_band band);
 void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
                                 struct sta_info *sta, u8 opmode,
-                                enum ieee80211_band band, bool nss_only);
+                                enum ieee80211_band band);
 void ieee80211_apply_vhtcap_overrides(struct ieee80211_sub_if_data *sdata,
                                      struct ieee80211_sta_vht_cap *vht_cap);
 void ieee80211_get_vht_mask_from_cap(__le16 vht_cap,
index b140cc6651f4a7a650380965c0901b60c800746c..3aa04344942bfc06c75341abf841646745c58c7f 100644 (file)
@@ -1379,21 +1379,26 @@ static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
         */
        if (has_80211h_pwr &&
            (!has_cisco_pwr || pwr_level_80211h <= pwr_level_cisco)) {
+               new_ap_level = pwr_level_80211h;
+
+               if (sdata->ap_power_level == new_ap_level)
+                       return 0;
+
                sdata_dbg(sdata,
                          "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
                          pwr_level_80211h, chan_pwr, pwr_reduction_80211h,
                          sdata->u.mgd.bssid);
-               new_ap_level = pwr_level_80211h;
        } else {  /* has_cisco_pwr is always true here. */
+               new_ap_level = pwr_level_cisco;
+
+               if (sdata->ap_power_level == new_ap_level)
+                       return 0;
+
                sdata_dbg(sdata,
                          "Limiting TX power to %d dBm as advertised by %pM\n",
                          pwr_level_cisco, sdata->u.mgd.bssid);
-               new_ap_level = pwr_level_cisco;
        }
 
-       if (sdata->ap_power_level == new_ap_level)
-               return 0;
-
        sdata->ap_power_level = new_ap_level;
        if (__ieee80211_recalc_txpower(sdata))
                return BSS_CHANGED_TXPOWER;
@@ -3575,7 +3580,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 
        if (sta && elems.opmode_notif)
                ieee80211_vht_handle_opmode(sdata, sta, *elems.opmode_notif,
-                                           rx_status->band, true);
+                                           rx_status->band);
        mutex_unlock(&local->sta_mtx);
 
        changed |= ieee80211_handle_pwr_constr(sdata, chan, mgmt,
index 8bae5de0dc44299146993df3581a951078eed733..82af407fea7a094db5f08e6426ae670a4cab3729 100644 (file)
@@ -2736,8 +2736,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                        opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
 
                        ieee80211_vht_handle_opmode(rx->sdata, rx->sta,
-                                                   opmode, status->band,
-                                                   false);
+                                                   opmode, status->band);
                        goto handled;
                }
                default:
index 74058020b7d6154c1ea1613e9a8a9775789736fa..33344f5a66a85e8a4c0842807249aee3e9d3d02e 100644 (file)
@@ -1641,6 +1641,29 @@ void ieee80211_stop_device(struct ieee80211_local *local)
        drv_stop(local);
 }
 
+static void ieee80211_flush_completed_scan(struct ieee80211_local *local,
+                                          bool aborted)
+{
+       /* It's possible that we don't handle the scan completion in
+        * time during suspend, so if it's still marked as completed
+        * here, queue the work and flush it to clean things up.
+        * Instead of calling the worker function directly here, we
+        * really queue it to avoid potential races with other flows
+        * scheduling the same work.
+        */
+       if (test_bit(SCAN_COMPLETED, &local->scanning)) {
+               /* If coming from reconfiguration failure, abort the scan so
+                * we don't attempt to continue a partial HW scan - which is
+                * possible otherwise if (e.g.) the 2.4 GHz portion was the
+                * completed scan, and a 5 GHz portion is still pending.
+                */
+               if (aborted)
+                       set_bit(SCAN_ABORTED, &local->scanning);
+               ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0);
+               flush_delayed_work(&local->scan_work);
+       }
+}
+
 static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local)
 {
        struct ieee80211_sub_if_data *sdata;
@@ -1660,6 +1683,8 @@ static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local)
        local->suspended = false;
        local->in_reconfig = false;
 
+       ieee80211_flush_completed_scan(local, true);
+
        /* scheduled scan clearly can't be running any more, but tell
         * cfg80211 and clear local state
         */
@@ -1698,6 +1723,27 @@ static void ieee80211_assign_chanctx(struct ieee80211_local *local,
        mutex_unlock(&local->chanctx_mtx);
 }
 
+static void ieee80211_reconfig_stations(struct ieee80211_sub_if_data *sdata)
+{
+       struct ieee80211_local *local = sdata->local;
+       struct sta_info *sta;
+
+       /* add STAs back */
+       mutex_lock(&local->sta_mtx);
+       list_for_each_entry(sta, &local->sta_list, list) {
+               enum ieee80211_sta_state state;
+
+               if (!sta->uploaded || sta->sdata != sdata)
+                       continue;
+
+               for (state = IEEE80211_STA_NOTEXIST;
+                    state < sta->sta_state; state++)
+                       WARN_ON(drv_sta_state(local, sta->sdata, sta, state,
+                                             state + 1));
+       }
+       mutex_unlock(&local->sta_mtx);
+}
+
 int ieee80211_reconfig(struct ieee80211_local *local)
 {
        struct ieee80211_hw *hw = &local->hw;
@@ -1833,50 +1879,11 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                                WARN_ON(drv_add_chanctx(local, ctx));
                mutex_unlock(&local->chanctx_mtx);
 
-               list_for_each_entry(sdata, &local->interfaces, list) {
-                       if (!ieee80211_sdata_running(sdata))
-                               continue;
-                       ieee80211_assign_chanctx(local, sdata);
-               }
-
                sdata = rtnl_dereference(local->monitor_sdata);
                if (sdata && ieee80211_sdata_running(sdata))
                        ieee80211_assign_chanctx(local, sdata);
        }
 
-       /* add STAs back */
-       mutex_lock(&local->sta_mtx);
-       list_for_each_entry(sta, &local->sta_list, list) {
-               enum ieee80211_sta_state state;
-
-               if (!sta->uploaded)
-                       continue;
-
-               /* AP-mode stations will be added later */
-               if (sta->sdata->vif.type == NL80211_IFTYPE_AP)
-                       continue;
-
-               for (state = IEEE80211_STA_NOTEXIST;
-                    state < sta->sta_state; state++)
-                       WARN_ON(drv_sta_state(local, sta->sdata, sta, state,
-                                             state + 1));
-       }
-       mutex_unlock(&local->sta_mtx);
-
-       /* reconfigure tx conf */
-       if (hw->queues >= IEEE80211_NUM_ACS) {
-               list_for_each_entry(sdata, &local->interfaces, list) {
-                       if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
-                           sdata->vif.type == NL80211_IFTYPE_MONITOR ||
-                           !ieee80211_sdata_running(sdata))
-                               continue;
-
-                       for (i = 0; i < IEEE80211_NUM_ACS; i++)
-                               drv_conf_tx(local, sdata, i,
-                                           &sdata->tx_conf[i]);
-               }
-       }
-
        /* reconfigure hardware */
        ieee80211_hw_config(local, ~0);
 
@@ -1889,6 +1896,22 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                if (!ieee80211_sdata_running(sdata))
                        continue;
 
+               ieee80211_assign_chanctx(local, sdata);
+
+               switch (sdata->vif.type) {
+               case NL80211_IFTYPE_AP_VLAN:
+               case NL80211_IFTYPE_MONITOR:
+                       break;
+               default:
+                       ieee80211_reconfig_stations(sdata);
+                       /* fall through */
+               case NL80211_IFTYPE_AP: /* AP stations are handled later */
+                       for (i = 0; i < IEEE80211_NUM_ACS; i++)
+                               drv_conf_tx(local, sdata, i,
+                                           &sdata->tx_conf[i]);
+                       break;
+               }
+
                /* common change flags for all interface types */
                changed = BSS_CHANGED_ERP_CTS_PROT |
                          BSS_CHANGED_ERP_PREAMBLE |
@@ -2074,17 +2097,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        mb();
        local->resuming = false;
 
-       /* It's possible that we don't handle the scan completion in
-        * time during suspend, so if it's still marked as completed
-        * here, queue the work and flush it to clean things up.
-        * Instead of calling the worker function directly here, we
-        * really queue it to avoid potential races with other flows
-        * scheduling the same work.
-        */
-       if (test_bit(SCAN_COMPLETED, &local->scanning)) {
-               ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0);
-               flush_delayed_work(&local->scan_work);
-       }
+       ieee80211_flush_completed_scan(local, false);
 
        if (local->open_count && !reconfig_due_to_wowlan)
                drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND);
index ff1c798921a6acc90181923456cf92bed0973f61..c38b2f07a919e20dc22363fe80911f5f5a0b004f 100644 (file)
@@ -378,7 +378,7 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta)
 
 u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
                                  struct sta_info *sta, u8 opmode,
-                                 enum ieee80211_band band, bool nss_only)
+                                 enum ieee80211_band band)
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_supported_band *sband;
@@ -401,9 +401,6 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
                changed |= IEEE80211_RC_NSS_CHANGED;
        }
 
-       if (nss_only)
-               return changed;
-
        switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) {
        case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ:
                sta->cur_max_bandwidth = IEEE80211_STA_RX_BW_20;
@@ -430,13 +427,12 @@ u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
 
 void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata,
                                 struct sta_info *sta, u8 opmode,
-                                enum ieee80211_band band, bool nss_only)
+                                enum ieee80211_band band)
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
 
-       u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode,
-                                                   band, nss_only);
+       u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, band);
 
        if (changed > 0)
                rate_control_rate_update(local, sband, sta, changed);
index c70d750148b66759ce47525c6f6b348c2e69efaa..c32fc411a911a414db2d0c1e141cb76093079d33 100644 (file)
@@ -27,6 +27,8 @@
  */
 #define MAX_MP_SELECT_LABELS 4
 
+#define MPLS_NEIGH_TABLE_UNSPEC (NEIGH_LINK_TABLE + 1)
+
 static int zero = 0;
 static int label_limit = (1 << 20) - 1;
 
@@ -317,7 +319,13 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
                }
        }
 
-       err = neigh_xmit(nh->nh_via_table, out_dev, mpls_nh_via(rt, nh), skb);
+       /* If via wasn't specified then send out using device address */
+       if (nh->nh_via_table == MPLS_NEIGH_TABLE_UNSPEC)
+               err = neigh_xmit(NEIGH_LINK_TABLE, out_dev,
+                                out_dev->dev_addr, skb);
+       else
+               err = neigh_xmit(nh->nh_via_table, out_dev,
+                                mpls_nh_via(rt, nh), skb);
        if (err)
                net_dbg_ratelimited("%s: packet transmission failed: %d\n",
                                    __func__, err);
@@ -534,6 +542,10 @@ static int mpls_nh_assign_dev(struct net *net, struct mpls_route *rt,
        if (!mpls_dev_get(dev))
                goto errout;
 
+       if ((nh->nh_via_table == NEIGH_LINK_TABLE) &&
+           (dev->addr_len != nh->nh_via_alen))
+               goto errout;
+
        RCU_INIT_POINTER(nh->nh_dev, dev);
 
        return 0;
@@ -592,10 +604,14 @@ static int mpls_nh_build(struct net *net, struct mpls_route *rt,
                        goto errout;
        }
 
-       err = nla_get_via(via, &nh->nh_via_alen, &nh->nh_via_table,
-                         __mpls_nh_via(rt, nh));
-       if (err)
-               goto errout;
+       if (via) {
+               err = nla_get_via(via, &nh->nh_via_alen, &nh->nh_via_table,
+                                 __mpls_nh_via(rt, nh));
+               if (err)
+                       goto errout;
+       } else {
+               nh->nh_via_table = MPLS_NEIGH_TABLE_UNSPEC;
+       }
 
        err = mpls_nh_assign_dev(net, rt, nh, oif);
        if (err)
@@ -677,9 +693,6 @@ static int mpls_nh_build_multi(struct mpls_route_config *cfg,
                        nla_newdst = nla_find(attrs, attrlen, RTA_NEWDST);
                }
 
-               if (!nla_via)
-                       goto errout;
-
                err = mpls_nh_build(cfg->rc_nlinfo.nl_net, rt, nh,
                                    rtnh->rtnh_ifindex, nla_via,
                                    nla_newdst);
@@ -1118,6 +1131,7 @@ static int rtm_to_route_config(struct sk_buff *skb,  struct nlmsghdr *nlh,
 
        cfg->rc_label           = LABEL_NOT_SPECIFIED;
        cfg->rc_protocol        = rtm->rtm_protocol;
+       cfg->rc_via_table       = MPLS_NEIGH_TABLE_UNSPEC;
        cfg->rc_nlflags         = nlh->nlmsg_flags;
        cfg->rc_nlinfo.portid   = NETLINK_CB(skb).portid;
        cfg->rc_nlinfo.nlh      = nlh;
@@ -1231,7 +1245,8 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event,
                    nla_put_labels(skb, RTA_NEWDST, nh->nh_labels,
                                   nh->nh_label))
                        goto nla_put_failure;
-               if (nla_put_via(skb, nh->nh_via_table, mpls_nh_via(rt, nh),
+               if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC &&
+                   nla_put_via(skb, nh->nh_via_table, mpls_nh_via(rt, nh),
                                nh->nh_via_alen))
                        goto nla_put_failure;
                dev = rtnl_dereference(nh->nh_dev);
@@ -1257,7 +1272,8 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event,
                                                            nh->nh_labels,
                                                            nh->nh_label))
                                goto nla_put_failure;
-                       if (nla_put_via(skb, nh->nh_via_table,
+                       if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC &&
+                           nla_put_via(skb, nh->nh_via_table,
                                        mpls_nh_via(rt, nh),
                                        nh->nh_via_alen))
                                goto nla_put_failure;
@@ -1319,7 +1335,8 @@ static inline size_t lfib_nlmsg_size(struct mpls_route *rt)
 
                if (nh->nh_dev)
                        payload += nla_total_size(4); /* RTA_OIF */
-               payload += nla_total_size(2 + nh->nh_via_alen); /* RTA_VIA */
+               if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC) /* RTA_VIA */
+                       payload += nla_total_size(2 + nh->nh_via_alen);
                if (nh->nh_labels) /* RTA_NEWDST */
                        payload += nla_total_size(nh->nh_labels * 4);
        } else {
@@ -1328,7 +1345,9 @@ static inline size_t lfib_nlmsg_size(struct mpls_route *rt)
 
                for_nexthops(rt) {
                        nhsize += nla_total_size(sizeof(struct rtnexthop));
-                       nhsize += nla_total_size(2 + nh->nh_via_alen);
+                       /* RTA_VIA */
+                       if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC)
+                               nhsize += nla_total_size(2 + nh->nh_via_alen);
                        if (nh->nh_labels)
                                nhsize += nla_total_size(nh->nh_labels * 4);
                } endfor_nexthops(rt);
index 67591aef9cae6fb203ef802272baad6e5b191000..64afd3d0b14407c252a766ab2280a30452a684c5 100644 (file)
@@ -54,10 +54,10 @@ int mpls_output(struct net *net, struct sock *sk, struct sk_buff *skb)
        unsigned int ttl;
 
        /* Obtain the ttl */
-       if (skb->protocol == htons(ETH_P_IP)) {
+       if (dst->ops->family == AF_INET) {
                ttl = ip_hdr(skb)->ttl;
                rt = (struct rtable *)dst;
-       } else if (skb->protocol == htons(ETH_P_IPV6)) {
+       } else if (dst->ops->family == AF_INET6) {
                ttl = ipv6_hdr(skb)->hop_limit;
                rt6 = (struct rt6_info *)dst;
        } else {
index 93cc4737018fdf3d13a2896c19a9c65891355f9e..2cb429d34c03c99e2e030becede22b05db604a76 100644 (file)
@@ -89,6 +89,7 @@ nf_tables_afinfo_lookup(struct net *net, int family, bool autoload)
 }
 
 static void nft_ctx_init(struct nft_ctx *ctx,
+                        struct net *net,
                         const struct sk_buff *skb,
                         const struct nlmsghdr *nlh,
                         struct nft_af_info *afi,
@@ -96,7 +97,7 @@ static void nft_ctx_init(struct nft_ctx *ctx,
                         struct nft_chain *chain,
                         const struct nlattr * const *nla)
 {
-       ctx->net        = sock_net(skb->sk);
+       ctx->net        = net;
        ctx->afi        = afi;
        ctx->table      = table;
        ctx->chain      = chain;
@@ -672,15 +673,14 @@ err:
        return ret;
 }
 
-static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb,
-                             const struct nlmsghdr *nlh,
+static int nf_tables_newtable(struct net *net, struct sock *nlsk,
+                             struct sk_buff *skb, const struct nlmsghdr *nlh,
                              const struct nlattr * const nla[])
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
        const struct nlattr *name;
        struct nft_af_info *afi;
        struct nft_table *table;
-       struct net *net = sock_net(skb->sk);
        int family = nfmsg->nfgen_family;
        u32 flags = 0;
        struct nft_ctx ctx;
@@ -706,7 +706,7 @@ static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb,
                if (nlh->nlmsg_flags & NLM_F_REPLACE)
                        return -EOPNOTSUPP;
 
-               nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla);
+               nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
                return nf_tables_updtable(&ctx);
        }
 
@@ -730,7 +730,7 @@ static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb,
        INIT_LIST_HEAD(&table->sets);
        table->flags = flags;
 
-       nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla);
+       nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
        err = nft_trans_table_add(&ctx, NFT_MSG_NEWTABLE);
        if (err < 0)
                goto err3;
@@ -810,18 +810,17 @@ out:
        return err;
 }
 
-static int nf_tables_deltable(struct sock *nlsk, struct sk_buff *skb,
-                             const struct nlmsghdr *nlh,
+static int nf_tables_deltable(struct net *net, struct sock *nlsk,
+                             struct sk_buff *skb, const struct nlmsghdr *nlh,
                              const struct nlattr * const nla[])
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
        struct nft_af_info *afi;
        struct nft_table *table;
-       struct net *net = sock_net(skb->sk);
        int family = nfmsg->nfgen_family;
        struct nft_ctx ctx;
 
-       nft_ctx_init(&ctx, skb, nlh, NULL, NULL, NULL, nla);
+       nft_ctx_init(&ctx, net, skb, nlh, NULL, NULL, NULL, nla);
        if (family == AF_UNSPEC || nla[NFTA_TABLE_NAME] == NULL)
                return nft_flush(&ctx, family);
 
@@ -1221,8 +1220,8 @@ static void nf_tables_chain_destroy(struct nft_chain *chain)
        }
 }
 
-static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
-                             const struct nlmsghdr *nlh,
+static int nf_tables_newchain(struct net *net, struct sock *nlsk,
+                             struct sk_buff *skb, const struct nlmsghdr *nlh,
                              const struct nlattr * const nla[])
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
@@ -1232,7 +1231,6 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
        struct nft_chain *chain;
        struct nft_base_chain *basechain = NULL;
        struct nlattr *ha[NFTA_HOOK_MAX + 1];
-       struct net *net = sock_net(skb->sk);
        int family = nfmsg->nfgen_family;
        struct net_device *dev = NULL;
        u8 policy = NF_ACCEPT;
@@ -1313,7 +1311,7 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
                                return PTR_ERR(stats);
                }
 
-               nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
+               nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla);
                trans = nft_trans_alloc(&ctx, NFT_MSG_NEWCHAIN,
                                        sizeof(struct nft_trans_chain));
                if (trans == NULL) {
@@ -1461,7 +1459,7 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
        if (err < 0)
                goto err1;
 
-       nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
+       nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla);
        err = nft_trans_chain_add(&ctx, NFT_MSG_NEWCHAIN);
        if (err < 0)
                goto err2;
@@ -1476,15 +1474,14 @@ err1:
        return err;
 }
 
-static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb,
-                             const struct nlmsghdr *nlh,
+static int nf_tables_delchain(struct net *net, struct sock *nlsk,
+                             struct sk_buff *skb, const struct nlmsghdr *nlh,
                              const struct nlattr * const nla[])
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
        struct nft_af_info *afi;
        struct nft_table *table;
        struct nft_chain *chain;
-       struct net *net = sock_net(skb->sk);
        int family = nfmsg->nfgen_family;
        struct nft_ctx ctx;
 
@@ -1506,7 +1503,7 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb,
        if (chain->use > 0)
                return -EBUSY;
 
-       nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
+       nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla);
 
        return nft_delchain(&ctx);
 }
@@ -2010,13 +2007,12 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
 
 static struct nft_expr_info *info;
 
-static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
-                            const struct nlmsghdr *nlh,
+static int nf_tables_newrule(struct net *net, struct sock *nlsk,
+                            struct sk_buff *skb, const struct nlmsghdr *nlh,
                             const struct nlattr * const nla[])
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
        struct nft_af_info *afi;
-       struct net *net = sock_net(skb->sk);
        struct nft_table *table;
        struct nft_chain *chain;
        struct nft_rule *rule, *old_rule = NULL;
@@ -2075,7 +2071,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
                        return PTR_ERR(old_rule);
        }
 
-       nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
+       nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla);
 
        n = 0;
        size = 0;
@@ -2176,13 +2172,12 @@ err1:
        return err;
 }
 
-static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
-                            const struct nlmsghdr *nlh,
+static int nf_tables_delrule(struct net *net, struct sock *nlsk,
+                            struct sk_buff *skb, const struct nlmsghdr *nlh,
                             const struct nlattr * const nla[])
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
        struct nft_af_info *afi;
-       struct net *net = sock_net(skb->sk);
        struct nft_table *table;
        struct nft_chain *chain = NULL;
        struct nft_rule *rule;
@@ -2205,7 +2200,7 @@ static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
                        return PTR_ERR(chain);
        }
 
-       nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
+       nft_ctx_init(&ctx, net, skb, nlh, afi, table, chain, nla);
 
        if (chain) {
                if (nla[NFTA_RULE_HANDLE]) {
@@ -2344,12 +2339,11 @@ static const struct nla_policy nft_set_desc_policy[NFTA_SET_DESC_MAX + 1] = {
        [NFTA_SET_DESC_SIZE]            = { .type = NLA_U32 },
 };
 
-static int nft_ctx_init_from_setattr(struct nft_ctx *ctx,
+static int nft_ctx_init_from_setattr(struct nft_ctx *ctx, struct net *net,
                                     const struct sk_buff *skb,
                                     const struct nlmsghdr *nlh,
                                     const struct nlattr * const nla[])
 {
-       struct net *net = sock_net(skb->sk);
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
        struct nft_af_info *afi = NULL;
        struct nft_table *table = NULL;
@@ -2371,7 +2365,7 @@ static int nft_ctx_init_from_setattr(struct nft_ctx *ctx,
                        return -ENOENT;
        }
 
-       nft_ctx_init(ctx, skb, nlh, afi, table, NULL, nla);
+       nft_ctx_init(ctx, net, skb, nlh, afi, table, NULL, nla);
        return 0;
 }
 
@@ -2623,6 +2617,7 @@ static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb,
                            const struct nlmsghdr *nlh,
                            const struct nlattr * const nla[])
 {
+       struct net *net = sock_net(skb->sk);
        const struct nft_set *set;
        struct nft_ctx ctx;
        struct sk_buff *skb2;
@@ -2630,7 +2625,7 @@ static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb,
        int err;
 
        /* Verify existence before starting dump */
-       err = nft_ctx_init_from_setattr(&ctx, skb, nlh, nla);
+       err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla);
        if (err < 0)
                return err;
 
@@ -2693,14 +2688,13 @@ static int nf_tables_set_desc_parse(const struct nft_ctx *ctx,
        return 0;
 }
 
-static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
-                           const struct nlmsghdr *nlh,
+static int nf_tables_newset(struct net *net, struct sock *nlsk,
+                           struct sk_buff *skb, const struct nlmsghdr *nlh,
                            const struct nlattr * const nla[])
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
        const struct nft_set_ops *ops;
        struct nft_af_info *afi;
-       struct net *net = sock_net(skb->sk);
        struct nft_table *table;
        struct nft_set *set;
        struct nft_ctx ctx;
@@ -2798,7 +2792,7 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
        if (IS_ERR(table))
                return PTR_ERR(table);
 
-       nft_ctx_init(&ctx, skb, nlh, afi, table, NULL, nla);
+       nft_ctx_init(&ctx, net, skb, nlh, afi, table, NULL, nla);
 
        set = nf_tables_set_lookup(table, nla[NFTA_SET_NAME]);
        if (IS_ERR(set)) {
@@ -2882,8 +2876,8 @@ static void nf_tables_set_destroy(const struct nft_ctx *ctx, struct nft_set *set
        nft_set_destroy(set);
 }
 
-static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb,
-                           const struct nlmsghdr *nlh,
+static int nf_tables_delset(struct net *net, struct sock *nlsk,
+                           struct sk_buff *skb, const struct nlmsghdr *nlh,
                            const struct nlattr * const nla[])
 {
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
@@ -2896,7 +2890,7 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb,
        if (nla[NFTA_SET_TABLE] == NULL)
                return -EINVAL;
 
-       err = nft_ctx_init_from_setattr(&ctx, skb, nlh, nla);
+       err = nft_ctx_init_from_setattr(&ctx, net, skb, nlh, nla);
        if (err < 0)
                return err;
 
@@ -3024,7 +3018,7 @@ static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX +
        [NFTA_SET_ELEM_LIST_SET_ID]     = { .type = NLA_U32 },
 };
 
-static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx,
+static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx, struct net *net,
                                      const struct sk_buff *skb,
                                      const struct nlmsghdr *nlh,
                                      const struct nlattr * const nla[],
@@ -3033,7 +3027,6 @@ static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx,
        const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
        struct nft_af_info *afi;
        struct nft_table *table;
-       struct net *net = sock_net(skb->sk);
 
        afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, false);
        if (IS_ERR(afi))
@@ -3045,7 +3038,7 @@ static int nft_ctx_init_from_elemattr(struct nft_ctx *ctx,
        if (!trans && (table->flags & NFT_TABLE_INACTIVE))
                return -ENOENT;
 
-       nft_ctx_init(ctx, skb, nlh, afi, table, NULL, nla);
+       nft_ctx_init(ctx, net, skb, nlh, afi, table, NULL, nla);
        return 0;
 }
 
@@ -3135,6 +3128,7 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx,
 
 static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
 {
+       struct net *net = sock_net(skb->sk);
        const struct nft_set *set;
        struct nft_set_dump_args args;
        struct nft_ctx ctx;
@@ -3150,8 +3144,8 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
        if (err < 0)
                return err;
 
-       err = nft_ctx_init_from_elemattr(&ctx, cb->skb, cb->nlh, (void *)nla,
-                                        false);
+       err = nft_ctx_init_from_elemattr(&ctx, net, cb->skb, cb->nlh,
+                                        (void *)nla, false);
        if (err < 0)
                return err;
 
@@ -3212,11 +3206,12 @@ static int nf_tables_getsetelem(struct sock *nlsk, struct sk_buff *skb,
                                const struct nlmsghdr *nlh,
                                const struct nlattr * const nla[])
 {
+       struct net *net = sock_net(skb->sk);
        const struct nft_set *set;
        struct nft_ctx ctx;
        int err;
 
-       err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, false);
+       err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, false);
        if (err < 0)
                return err;
 
@@ -3528,11 +3523,10 @@ err1:
        return err;
 }
 
-static int nf_tables_newsetelem(struct sock *nlsk, struct sk_buff *skb,
-                               const struct nlmsghdr *nlh,
+static int nf_tables_newsetelem(struct net *net, struct sock *nlsk,
+                               struct sk_buff *skb, const struct nlmsghdr *nlh,
                                const struct nlattr * const nla[])
 {
-       struct net *net = sock_net(skb->sk);
        const struct nlattr *attr;
        struct nft_set *set;
        struct nft_ctx ctx;
@@ -3541,7 +3535,7 @@ static int nf_tables_newsetelem(struct sock *nlsk, struct sk_buff *skb,
        if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
                return -EINVAL;
 
-       err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, true);
+       err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, true);
        if (err < 0)
                return err;
 
@@ -3623,8 +3617,8 @@ err1:
        return err;
 }
 
-static int nf_tables_delsetelem(struct sock *nlsk, struct sk_buff *skb,
-                               const struct nlmsghdr *nlh,
+static int nf_tables_delsetelem(struct net *net, struct sock *nlsk,
+                               struct sk_buff *skb, const struct nlmsghdr *nlh,
                                const struct nlattr * const nla[])
 {
        const struct nlattr *attr;
@@ -3635,7 +3629,7 @@ static int nf_tables_delsetelem(struct sock *nlsk, struct sk_buff *skb,
        if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
                return -EINVAL;
 
-       err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, false);
+       err = nft_ctx_init_from_elemattr(&ctx, net, skb, nlh, nla, false);
        if (err < 0)
                return err;
 
@@ -4030,7 +4024,8 @@ static int nf_tables_abort(struct sk_buff *skb)
        struct nft_trans *trans, *next;
        struct nft_trans_elem *te;
 
-       list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
+       list_for_each_entry_safe_reverse(trans, next, &net->nft.commit_list,
+                                        list) {
                switch (trans->msg_type) {
                case NFT_MSG_NEWTABLE:
                        if (nft_trans_table_update(trans)) {
index 7b9c053ba75072276ee9227ea8d1e67ce3307715..edb3502f20161cf53d44e3fe84d9f0c63072be6a 100644 (file)
@@ -94,7 +94,7 @@ nft_do_chain_netdev(void *priv, struct sk_buff *skb,
 {
        struct nft_pktinfo pkt;
 
-       switch (eth_hdr(skb)->h_proto) {
+       switch (skb->protocol) {
        case htons(ETH_P_IP):
                nft_netdev_set_pktinfo_ipv4(&pkt, skb, state);
                break;
index 46453ab318db0bf2a4bc957dcad6742ccbcacc92..77afe913d03db73c65631fba8c42732cb3f33f32 100644 (file)
@@ -295,8 +295,6 @@ replay:
        if (!skb)
                return netlink_ack(oskb, nlh, -ENOMEM);
 
-       skb->sk = oskb->sk;
-
        nfnl_lock(subsys_id);
        ss = rcu_dereference_protected(table[subsys_id].subsys,
                                       lockdep_is_held(&table[subsys_id].mutex));
@@ -381,7 +379,7 @@ replay:
                                goto ack;
 
                        if (nc->call_batch) {
-                               err = nc->call_batch(net->nfnl, skb, nlh,
+                               err = nc->call_batch(net, net->nfnl, skb, nlh,
                                                     (const struct nlattr **)cda);
                        }
 
index 7d81d280cb4ff3e8878af96bd644930f68a4340c..861c6615253bfe3b45e648d9c98a7715d873cbf9 100644 (file)
@@ -365,8 +365,9 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
                break;
        }
 
+       nfnl_ct = rcu_dereference(nfnl_ct_hook);
+
        if (queue->flags & NFQA_CFG_F_CONNTRACK) {
-               nfnl_ct = rcu_dereference(nfnl_ct_hook);
                if (nfnl_ct != NULL) {
                        ct = nfnl_ct->get_ct(entskb, &ctinfo);
                        if (ct != NULL)
@@ -1064,9 +1065,10 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
        if (entry == NULL)
                return -ENOENT;
 
+       /* rcu lock already held from nfnl->call_rcu. */
+       nfnl_ct = rcu_dereference(nfnl_ct_hook);
+
        if (nfqa[NFQA_CT]) {
-               /* rcu lock already held from nfnl->call_rcu. */
-               nfnl_ct = rcu_dereference(nfnl_ct_hook);
                if (nfnl_ct != NULL)
                        ct = nfqnl_ct_parse(nfnl_ct, nlh, nfqa, entry, &ctinfo);
        }
@@ -1417,6 +1419,7 @@ static int __init nfnetlink_queue_init(void)
 
 cleanup_netlink_notifier:
        netlink_unregister_notifier(&nfqnl_rtnl_notifier);
+       unregister_pernet_subsys(&nfnl_queue_net_ops);
 out:
        return status;
 }
index 8cbca3432f90324f8a28df2bd67da88cdaf72b12..939921532764acdd61a4d33c352abd2b8e1d4756 100644 (file)
@@ -366,6 +366,7 @@ static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr)
                goto nla_put_failure;
 
        switch (priv->key) {
+       case NFT_CT_L3PROTOCOL:
        case NFT_CT_PROTOCOL:
        case NFT_CT_SRC:
        case NFT_CT_DST:
index c2cc11168fd5e164fa122da5dd44f7aa47279a1e..e004067ec24ac448467c0bd5a552eea019975e56 100644 (file)
@@ -53,6 +53,8 @@ struct ovs_conntrack_info {
        struct md_labels labels;
 };
 
+static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info);
+
 static u16 key_to_nfproto(const struct sw_flow_key *key)
 {
        switch (ntohs(key->eth.type)) {
@@ -141,6 +143,7 @@ static void __ovs_ct_update_key(struct sw_flow_key *key, u8 state,
  * previously sent the packet to conntrack via the ct action.
  */
 static void ovs_ct_update_key(const struct sk_buff *skb,
+                             const struct ovs_conntrack_info *info,
                              struct sw_flow_key *key, bool post_ct)
 {
        const struct nf_conntrack_zone *zone = &nf_ct_zone_dflt;
@@ -158,13 +161,15 @@ static void ovs_ct_update_key(const struct sk_buff *skb,
                zone = nf_ct_zone(ct);
        } else if (post_ct) {
                state = OVS_CS_F_TRACKED | OVS_CS_F_INVALID;
+               if (info)
+                       zone = &info->zone;
        }
        __ovs_ct_update_key(key, state, zone, ct);
 }
 
 void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key)
 {
-       ovs_ct_update_key(skb, key, false);
+       ovs_ct_update_key(skb, NULL, key, false);
 }
 
 int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb)
@@ -418,7 +423,7 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,
                }
        }
 
-       ovs_ct_update_key(skb, key, true);
+       ovs_ct_update_key(skb, info, key, true);
 
        return 0;
 }
@@ -693,6 +698,10 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr,
                OVS_NLERR(log, "Failed to allocate conntrack template");
                return -ENOMEM;
        }
+
+       __set_bit(IPS_CONFIRMED_BIT, &ct_info.ct->status);
+       nf_conntrack_get(&ct_info.ct->ct_general);
+
        if (helper) {
                err = ovs_ct_add_helper(&ct_info, helper, key, log);
                if (err)
@@ -704,11 +713,9 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr,
        if (err)
                goto err_free_ct;
 
-       __set_bit(IPS_CONFIRMED_BIT, &ct_info.ct->status);
-       nf_conntrack_get(&ct_info.ct->ct_general);
        return 0;
 err_free_ct:
-       nf_conntrack_free(ct_info.ct);
+       __ovs_ct_free_action(&ct_info);
        return err;
 }
 
@@ -750,6 +757,11 @@ void ovs_ct_free_action(const struct nlattr *a)
 {
        struct ovs_conntrack_info *ct_info = nla_data(a);
 
+       __ovs_ct_free_action(ct_info);
+}
+
+static void __ovs_ct_free_action(struct ovs_conntrack_info *ct_info)
+{
        if (ct_info->helper)
                module_put(ct_info->helper->me);
        if (ct_info->ct)
index 907d6fd28ede695cc1b876570c101883ed0b4b0e..d1bd4a45ca2d64eca6439335d967aa21feff2b8b 100644 (file)
@@ -2434,7 +2434,10 @@ static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb)
                if (!start)
                        return -EMSGSIZE;
 
-               err = ovs_nla_put_tunnel_info(skb, tun_info);
+               err =  ip_tun_to_nlattr(skb, &tun_info->key,
+                                       ip_tunnel_info_opts(tun_info),
+                                       tun_info->options_len,
+                                       ip_tunnel_info_af(tun_info));
                if (err)
                        return err;
                nla_nest_end(skb, start);
index b41e9ea2ffff461847465d621a3284480f433cc5..f53bf3b6558b094b6e1b379568620157b4ffae17 100644 (file)
@@ -49,7 +49,6 @@
 struct rfkill {
        spinlock_t              lock;
 
-       const char              *name;
        enum rfkill_type        type;
 
        unsigned long           state;
@@ -73,6 +72,7 @@ struct rfkill {
        struct delayed_work     poll_work;
        struct work_struct      uevent_work;
        struct work_struct      sync_work;
+       char                    name[];
 };
 #define to_rfkill(d)   container_of(d, struct rfkill, dev)
 
@@ -876,14 +876,14 @@ struct rfkill * __must_check rfkill_alloc(const char *name,
        if (WARN_ON(type == RFKILL_TYPE_ALL || type >= NUM_RFKILL_TYPES))
                return NULL;
 
-       rfkill = kzalloc(sizeof(*rfkill), GFP_KERNEL);
+       rfkill = kzalloc(sizeof(*rfkill) + strlen(name) + 1, GFP_KERNEL);
        if (!rfkill)
                return NULL;
 
        spin_lock_init(&rfkill->lock);
        INIT_LIST_HEAD(&rfkill->node);
        rfkill->type = type;
-       rfkill->name = name;
+       strcpy(rfkill->name, name);
        rfkill->ops = ops;
        rfkill->data = ops_data;
 
index 7ec667dd4ce1d01deef3698af8c291da0722a657..b5c2cf2aa6d4bc00e5c4bac2b3326db3d785c8be 100644 (file)
@@ -950,7 +950,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
                }
                lockdep_set_class(qdisc_lock(sch), &qdisc_tx_lock);
                if (!netif_is_multiqueue(dev))
-                       sch->flags |= TCQ_F_ONETXQUEUE | TCQ_F_NOPARENT;
+                       sch->flags |= TCQ_F_ONETXQUEUE;
        }
 
        sch->handle = handle;
index e82a1ad80aa521291fba4e704bb3828e88a009db..16bc83b2842a74616cd58dd923a5981942321f3e 100644 (file)
@@ -658,8 +658,10 @@ static void qdisc_rcu_free(struct rcu_head *head)
 {
        struct Qdisc *qdisc = container_of(head, struct Qdisc, rcu_head);
 
-       if (qdisc_is_percpu_stats(qdisc))
+       if (qdisc_is_percpu_stats(qdisc)) {
                free_percpu(qdisc->cpu_bstats);
+               free_percpu(qdisc->cpu_qstats);
+       }
 
        kfree((char *) qdisc - qdisc->padded);
 }
index acb45b8c2a9d6ce902af7a2ffb9cbd53309a1bdc..ec529121f38a03c4b3e2317249cd0694fd619d3f 100644 (file)
@@ -323,14 +323,13 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
                        }
                }
        }
-       rcu_read_unlock();
-
        if (baddr) {
                fl6->saddr = baddr->v6.sin6_addr;
                fl6->fl6_sport = baddr->v6.sin6_port;
                final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final);
                dst = ip6_dst_lookup_flow(sk, fl6, final_p);
        }
+       rcu_read_unlock();
 
 out:
        if (!IS_ERR_OR_NULL(dst)) {
@@ -642,6 +641,7 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
        struct sock *newsk;
        struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
        struct sctp6_sock *newsctp6sk;
+       struct ipv6_txoptions *opt;
 
        newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, 0);
        if (!newsk)
@@ -661,6 +661,13 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
 
        memcpy(newnp, np, sizeof(struct ipv6_pinfo));
 
+       rcu_read_lock();
+       opt = rcu_dereference(np->opt);
+       if (opt)
+               opt = ipv6_dup_options(newsk, opt);
+       RCU_INIT_POINTER(newnp->opt, opt);
+       rcu_read_unlock();
+
        /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()
         * and getpeername().
         */
index 7e8f0a117106cabbf043e24e33f56b307cf4fc88..c0380cfb16ae4eb77bdab457e8310c0cb15a1c4a 100644 (file)
@@ -324,6 +324,7 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk)
                                 sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) :
                                 "illegal chunk");
 
+                       sctp_chunk_hold(chunk);
                        sctp_outq_tail_data(q, chunk);
                        if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
                                SCTP_INC_STATS(net, SCTP_MIB_OUTUNORDERCHUNKS);
@@ -1251,6 +1252,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
         */
 
        sack_a_rwnd = ntohl(sack->a_rwnd);
+       asoc->peer.zero_window_announced = !sack_a_rwnd;
        outstanding = q->outstanding_bytes;
 
        if (outstanding < sack_a_rwnd)
index 763e06a55155b2a9e0a9d918ecc1fe2dd6d9e0c0..5d6a03fad3789a12290f5f14c5a7efa69c98f41a 100644 (file)
@@ -1652,7 +1652,7 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
 
        /* Set an expiration time for the cookie.  */
        cookie->c.expiration = ktime_add(asoc->cookie_life,
-                                        ktime_get());
+                                        ktime_get_real());
 
        /* Copy the peer's init packet.  */
        memcpy(&cookie->c.peer_init[0], init_chunk->chunk_hdr,
@@ -1780,7 +1780,7 @@ no_hmac:
        if (sock_flag(ep->base.sk, SOCK_TIMESTAMP))
                kt = skb_get_ktime(skb);
        else
-               kt = ktime_get();
+               kt = ktime_get_real();
 
        if (!asoc && ktime_before(bear_cookie->expiration, kt)) {
                /*
index 6f46aa16cb76963de27cb87e5e8cedf617a259a9..22c2bf367d7e8c7025065f33eabfd7e93a7f4021 100644 (file)
@@ -4829,7 +4829,8 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(
 
        retval = SCTP_DISPOSITION_CONSUME;
 
-       sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
+       if (abort)
+               sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
 
        /* Even if we can't send the ABORT due to low memory delete the
         * TCB.  This is a departure from our typical NOMEM handling.
@@ -4966,7 +4967,8 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
                        SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
        retval = SCTP_DISPOSITION_CONSUME;
 
-       sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
+       if (abort)
+               sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
 
        sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
                        SCTP_STATE(SCTP_STATE_CLOSED));
@@ -5412,7 +5414,8 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(struct net *net,
        SCTP_INC_STATS(net, SCTP_MIB_T3_RTX_EXPIREDS);
 
        if (asoc->overall_error_count >= asoc->max_retrans) {
-               if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING) {
+               if (asoc->peer.zero_window_announced &&
+                   asoc->state == SCTP_STATE_SHUTDOWN_PENDING) {
                        /*
                         * We are here likely because the receiver had its rwnd
                         * closed for a while and we have not been able to
index 03c8256063ec6355fcce034366aa5d005d75b5f7..ef1d90fdc773d2ca4104c9dabc96d1058e99629a 100644 (file)
@@ -1301,8 +1301,9 @@ static int __sctp_setsockopt_connectx(struct sock *sk,
                                      int addrs_size,
                                      sctp_assoc_t *assoc_id)
 {
-       int err = 0;
        struct sockaddr *kaddrs;
+       gfp_t gfp = GFP_KERNEL;
+       int err = 0;
 
        pr_debug("%s: sk:%p addrs:%p addrs_size:%d\n",
                 __func__, sk, addrs, addrs_size);
@@ -1315,7 +1316,9 @@ static int __sctp_setsockopt_connectx(struct sock *sk,
                return -EFAULT;
 
        /* Alloc space for the address array in kernel memory.  */
-       kaddrs = kmalloc(addrs_size, GFP_KERNEL);
+       if (sk->sk_socket->file)
+               gfp = GFP_USER | __GFP_NOWARN;
+       kaddrs = kmalloc(addrs_size, gfp);
        if (unlikely(!kaddrs))
                return -ENOMEM;
 
@@ -1513,8 +1516,7 @@ static void sctp_close(struct sock *sk, long timeout)
                        struct sctp_chunk *chunk;
 
                        chunk = sctp_make_abort_user(asoc, NULL, 0);
-                       if (chunk)
-                               sctp_primitive_ABORT(net, asoc, chunk);
+                       sctp_primitive_ABORT(net, asoc, chunk);
                } else
                        sctp_primitive_SHUTDOWN(net, asoc, NULL);
        }
@@ -1952,8 +1954,6 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
 
        /* Now send the (possibly) fragmented message. */
        list_for_each_entry(chunk, &datamsg->chunks, frag_list) {
-               sctp_chunk_hold(chunk);
-
                /* Do accounting for the write space.  */
                sctp_set_owner_w(chunk);
 
@@ -1966,15 +1966,13 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
         * breaks.
         */
        err = sctp_primitive_SEND(net, asoc, datamsg);
+       sctp_datamsg_put(datamsg);
        /* Did the lower layer accept the chunk? */
-       if (err) {
-               sctp_datamsg_free(datamsg);
+       if (err)
                goto out_free;
-       }
 
        pr_debug("%s: we sent primitively\n", __func__);
 
-       sctp_datamsg_put(datamsg);
        err = msg_len;
 
        if (unlikely(wait_connect)) {
@@ -5777,7 +5775,7 @@ static int sctp_getsockopt_assoc_ids(struct sock *sk, int len,
 
        len = sizeof(struct sctp_assoc_ids) + sizeof(sctp_assoc_t) * num;
 
-       ids = kmalloc(len, GFP_KERNEL);
+       ids = kmalloc(len, GFP_USER | __GFP_NOWARN);
        if (unlikely(!ids))
                return -ENOMEM;
 
@@ -7167,6 +7165,7 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
        newsk->sk_type = sk->sk_type;
        newsk->sk_bound_dev_if = sk->sk_bound_dev_if;
        newsk->sk_flags = sk->sk_flags;
+       newsk->sk_tsflags = sk->sk_tsflags;
        newsk->sk_no_check_tx = sk->sk_no_check_tx;
        newsk->sk_no_check_rx = sk->sk_no_check_rx;
        newsk->sk_reuse = sk->sk_reuse;
@@ -7199,6 +7198,11 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
        newinet->mc_ttl = 1;
        newinet->mc_index = 0;
        newinet->mc_list = NULL;
+
+       if (newsk->sk_flags & SK_FLAGS_TIMESTAMP)
+               net_enable_timestamp();
+
+       security_sk_clone(sk, newsk);
 }
 
 static inline void sctp_copy_descendant(struct sock *sk_to,
index 456fadb3d8193a2238bf30881506cd66dbe11957..d730ef9dfbf02aba150d5229a0d2875ddc23aa4d 100644 (file)
@@ -257,6 +257,7 @@ static struct inode *sock_alloc_inode(struct super_block *sb)
        }
        init_waitqueue_head(&wq->wait);
        wq->fasync_list = NULL;
+       wq->flags = 0;
        RCU_INIT_POINTER(ei->socket.wq, wq);
 
        ei->socket.state = SS_UNCONNECTED;
@@ -1695,6 +1696,7 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
        msg.msg_name = addr ? (struct sockaddr *)&address : NULL;
        /* We assume all kernel code knows the size of sockaddr_storage */
        msg.msg_namelen = 0;
+       msg.msg_iocb = NULL;
        if (sock->file->f_flags & O_NONBLOCK)
                flags |= MSG_DONTWAIT;
        err = sock_recvmsg(sock, &msg, iov_iter_count(&msg.msg_iter), flags);
index 95f82d8d488871e5cc8337acc9073e2aa569b4e6..229956bf84577f81d380536b76d1e57d16de53ae 100644 (file)
@@ -353,20 +353,12 @@ void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied)
 {
        struct rpc_xprt *xprt = req->rq_xprt;
        struct svc_serv *bc_serv = xprt->bc_serv;
-       struct xdr_buf *rq_rcv_buf = &req->rq_rcv_buf;
 
        spin_lock(&xprt->bc_pa_lock);
        list_del(&req->rq_bc_pa_list);
        xprt_dec_alloc_count(xprt, 1);
        spin_unlock(&xprt->bc_pa_lock);
 
-       if (copied <= rq_rcv_buf->head[0].iov_len) {
-               rq_rcv_buf->head[0].iov_len = copied;
-               rq_rcv_buf->page_len = 0;
-       } else {
-               rq_rcv_buf->page_len = copied - rq_rcv_buf->head[0].iov_len;
-       }
-
        req->rq_private_buf.len = copied;
        set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state);
 
index f14f24ee998344f5c356ef49e3b3fc52d581a39c..73ad57a59989cb9234d06c1d399e02408e50c7d3 100644 (file)
@@ -250,11 +250,11 @@ void rpc_destroy_wait_queue(struct rpc_wait_queue *queue)
 }
 EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue);
 
-static int rpc_wait_bit_killable(struct wait_bit_key *key)
+static int rpc_wait_bit_killable(struct wait_bit_key *key, int mode)
 {
-       if (fatal_signal_pending(current))
-               return -ERESTARTSYS;
        freezable_schedule_unsafe();
+       if (signal_pending_state(mode, current))
+               return -ERESTARTSYS;
        return 0;
 }
 
index 7fccf9675df8c238e4cc1d1f437540e48a3df9d2..cc9852897395c6f6db42653c773788446a9c5d3e 100644 (file)
@@ -1363,7 +1363,19 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req,
        memcpy(&rqstp->rq_addr, &req->rq_xprt->addr, rqstp->rq_addrlen);
        memcpy(&rqstp->rq_arg, &req->rq_rcv_buf, sizeof(rqstp->rq_arg));
        memcpy(&rqstp->rq_res, &req->rq_snd_buf, sizeof(rqstp->rq_res));
+
+       /* Adjust the argument buffer length */
        rqstp->rq_arg.len = req->rq_private_buf.len;
+       if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len) {
+               rqstp->rq_arg.head[0].iov_len = rqstp->rq_arg.len;
+               rqstp->rq_arg.page_len = 0;
+       } else if (rqstp->rq_arg.len <= rqstp->rq_arg.head[0].iov_len +
+                       rqstp->rq_arg.page_len)
+               rqstp->rq_arg.page_len = rqstp->rq_arg.len -
+                       rqstp->rq_arg.head[0].iov_len;
+       else
+               rqstp->rq_arg.len = rqstp->rq_arg.head[0].iov_len +
+                       rqstp->rq_arg.page_len;
 
        /* reset result send buffer "put" position */
        resv->iov_len = 0;
index 45aebd966978bdc6abb886487d029957036bdda4..ef05cd9403d4bb2c2ad0a3faddc71de611d892df 100644 (file)
@@ -953,32 +953,20 @@ fail:
        return NULL;
 }
 
-static int unix_mknod(const char *sun_path, umode_t mode, struct path *res)
+static int unix_mknod(struct dentry *dentry, struct path *path, umode_t mode,
+                     struct path *res)
 {
-       struct dentry *dentry;
-       struct path path;
-       int err = 0;
-       /*
-        * Get the parent directory, calculate the hash for last
-        * component.
-        */
-       dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0);
-       err = PTR_ERR(dentry);
-       if (IS_ERR(dentry))
-               return err;
+       int err;
 
-       /*
-        * All right, let's create it.
-        */
-       err = security_path_mknod(&path, dentry, mode, 0);
+       err = security_path_mknod(path, dentry, mode, 0);
        if (!err) {
-               err = vfs_mknod(d_inode(path.dentry), dentry, mode, 0);
+               err = vfs_mknod(d_inode(path->dentry), dentry, mode, 0);
                if (!err) {
-                       res->mnt = mntget(path.mnt);
+                       res->mnt = mntget(path->mnt);
                        res->dentry = dget(dentry);
                }
        }
-       done_path_create(&path, dentry);
+
        return err;
 }
 
@@ -989,10 +977,12 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        struct unix_sock *u = unix_sk(sk);
        struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
        char *sun_path = sunaddr->sun_path;
-       int err;
+       int err, name_err;
        unsigned int hash;
        struct unix_address *addr;
        struct hlist_head *list;
+       struct path path;
+       struct dentry *dentry;
 
        err = -EINVAL;
        if (sunaddr->sun_family != AF_UNIX)
@@ -1008,14 +998,34 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                goto out;
        addr_len = err;
 
+       name_err = 0;
+       dentry = NULL;
+       if (sun_path[0]) {
+               /* Get the parent directory, calculate the hash for last
+                * component.
+                */
+               dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0);
+
+               if (IS_ERR(dentry)) {
+                       /* delay report until after 'already bound' check */
+                       name_err = PTR_ERR(dentry);
+                       dentry = NULL;
+               }
+       }
+
        err = mutex_lock_interruptible(&u->readlock);
        if (err)
-               goto out;
+               goto out_path;
 
        err = -EINVAL;
        if (u->addr)
                goto out_up;
 
+       if (name_err) {
+               err = name_err == -EEXIST ? -EADDRINUSE : name_err;
+               goto out_up;
+       }
+
        err = -ENOMEM;
        addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL);
        if (!addr)
@@ -1026,11 +1036,11 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        addr->hash = hash ^ sk->sk_type;
        atomic_set(&addr->refcnt, 1);
 
-       if (sun_path[0]) {
-               struct path path;
+       if (dentry) {
+               struct path u_path;
                umode_t mode = S_IFSOCK |
                       (SOCK_INODE(sock)->i_mode & ~current_umask());
-               err = unix_mknod(sun_path, mode, &path);
+               err = unix_mknod(dentry, &path, mode, &u_path);
                if (err) {
                        if (err == -EEXIST)
                                err = -EADDRINUSE;
@@ -1038,9 +1048,9 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                        goto out_up;
                }
                addr->hash = UNIX_HASH_SIZE;
-               hash = d_backing_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE-1);
+               hash = d_backing_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1);
                spin_lock(&unix_table_lock);
-               u->path = path;
+               u->path = u_path;
                list = &unix_socket_table[hash];
        } else {
                spin_lock(&unix_table_lock);
@@ -1063,6 +1073,10 @@ out_unlock:
        spin_unlock(&unix_table_lock);
 out_up:
        mutex_unlock(&u->readlock);
+out_path:
+       if (dentry)
+               done_path_create(&path, dentry);
+
 out:
        return err;
 }
@@ -2256,14 +2270,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state)
        /* Lock the socket to prevent queue disordering
         * while sleeps in memcpy_tomsg
         */
-       err = mutex_lock_interruptible(&u->readlock);
-       if (unlikely(err)) {
-               /* recvmsg() in non blocking mode is supposed to return -EAGAIN
-                * sk_rcvtimeo is not honored by mutex_lock_interruptible()
-                */
-               err = noblock ? -EAGAIN : -ERESTARTSYS;
-               goto out;
-       }
+       mutex_lock(&u->readlock);
 
        if (flags & MSG_PEEK)
                skip = sk_peek_offset(sk, flags);
@@ -2307,12 +2314,12 @@ again:
                        timeo = unix_stream_data_wait(sk, timeo, last,
                                                      last_len);
 
-                       if (signal_pending(current) ||
-                           mutex_lock_interruptible(&u->readlock)) {
+                       if (signal_pending(current)) {
                                err = sock_intr_errno(timeo);
                                goto out;
                        }
 
+                       mutex_lock(&u->readlock);
                        continue;
 unlock:
                        unix_state_unlock(sk);
index c71e274c810ac6610df652ec029838000ee7c69d..75b0d23ee882293a07fb9e236757931780def482 100644 (file)
@@ -7941,8 +7941,10 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
        if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
                if (!(rdev->wiphy.features &
                      NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) ||
-                   !(rdev->wiphy.features & NL80211_FEATURE_QUIET))
+                   !(rdev->wiphy.features & NL80211_FEATURE_QUIET)) {
+                       kzfree(connkeys);
                        return -EINVAL;
+               }
                connect.flags |= ASSOC_REQ_USE_RRM;
        }
 
@@ -9503,6 +9505,7 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
        if (new_triggers.tcp && new_triggers.tcp->sock)
                sock_release(new_triggers.tcp->sock);
        kfree(new_triggers.tcp);
+       kfree(new_triggers.nd_config);
        return err;
 }
 #endif
index 2e8d6f39ed564ac7111be036a1f735da1d87d68b..06d050da0d94720cb40d3ad28425b06da22b3e89 100644 (file)
@@ -3029,6 +3029,7 @@ int set_regdom(const struct ieee80211_regdomain *rd,
                break;
        default:
                WARN(1, "invalid initiator %d\n", lr->initiator);
+               kfree(rd);
                return -EINVAL;
        }
 
@@ -3221,8 +3222,10 @@ int __init regulatory_init(void)
        /* We always try to get an update for the static regdomain */
        err = regulatory_hint_core(cfg80211_world_regdom->alpha2);
        if (err) {
-               if (err == -ENOMEM)
+               if (err == -ENOMEM) {
+                       platform_device_unregister(reg_pdev);
                        return err;
+               }
                /*
                 * N.B. kobject_uevent_env() can fail mainly for when we're out
                 * memory which is handled and propagated appropriately above
index 09bfcbac63bb3f75d909aecd840b63d36b169eec..b5e665b3cfb05f4d08970387802fee8aec8243dd 100644 (file)
@@ -303,6 +303,14 @@ struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp)
 }
 EXPORT_SYMBOL(xfrm_policy_alloc);
 
+static void xfrm_policy_destroy_rcu(struct rcu_head *head)
+{
+       struct xfrm_policy *policy = container_of(head, struct xfrm_policy, rcu);
+
+       security_xfrm_policy_free(policy->security);
+       kfree(policy);
+}
+
 /* Destroy xfrm_policy: descendant resources must be released to this moment. */
 
 void xfrm_policy_destroy(struct xfrm_policy *policy)
@@ -312,8 +320,7 @@ void xfrm_policy_destroy(struct xfrm_policy *policy)
        if (del_timer(&policy->timer) || del_timer(&policy->polq.hold_timer))
                BUG();
 
-       security_xfrm_policy_free(policy->security);
-       kfree(policy);
+       call_rcu(&policy->rcu, xfrm_policy_destroy_rcu);
 }
 EXPORT_SYMBOL(xfrm_policy_destroy);
 
@@ -1214,8 +1221,10 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
        struct xfrm_policy *pol;
        struct net *net = sock_net(sk);
 
+       rcu_read_lock();
        read_lock_bh(&net->xfrm.xfrm_policy_lock);
-       if ((pol = sk->sk_policy[dir]) != NULL) {
+       pol = rcu_dereference(sk->sk_policy[dir]);
+       if (pol != NULL) {
                bool match = xfrm_selector_match(&pol->selector, fl,
                                                 sk->sk_family);
                int err = 0;
@@ -1239,6 +1248,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
        }
 out:
        read_unlock_bh(&net->xfrm.xfrm_policy_lock);
+       rcu_read_unlock();
        return pol;
 }
 
@@ -1307,13 +1317,14 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol)
 #endif
 
        write_lock_bh(&net->xfrm.xfrm_policy_lock);
-       old_pol = sk->sk_policy[dir];
-       sk->sk_policy[dir] = pol;
+       old_pol = rcu_dereference_protected(sk->sk_policy[dir],
+                               lockdep_is_held(&net->xfrm.xfrm_policy_lock));
        if (pol) {
                pol->curlft.add_time = get_seconds();
                pol->index = xfrm_gen_index(net, XFRM_POLICY_MAX+dir, 0);
                xfrm_sk_policy_link(pol, dir);
        }
+       rcu_assign_pointer(sk->sk_policy[dir], pol);
        if (old_pol) {
                if (pol)
                        xfrm_policy_requeue(old_pol, pol);
@@ -1361,17 +1372,26 @@ static struct xfrm_policy *clone_policy(const struct xfrm_policy *old, int dir)
        return newp;
 }
 
-int __xfrm_sk_clone_policy(struct sock *sk)
+int __xfrm_sk_clone_policy(struct sock *sk, const struct sock *osk)
 {
-       struct xfrm_policy *p0 = sk->sk_policy[0],
-                          *p1 = sk->sk_policy[1];
+       const struct xfrm_policy *p;
+       struct xfrm_policy *np;
+       int i, ret = 0;
 
-       sk->sk_policy[0] = sk->sk_policy[1] = NULL;
-       if (p0 && (sk->sk_policy[0] = clone_policy(p0, 0)) == NULL)
-               return -ENOMEM;
-       if (p1 && (sk->sk_policy[1] = clone_policy(p1, 1)) == NULL)
-               return -ENOMEM;
-       return 0;
+       rcu_read_lock();
+       for (i = 0; i < 2; i++) {
+               p = rcu_dereference(osk->sk_policy[i]);
+               if (p) {
+                       np = clone_policy(p, i);
+                       if (unlikely(!np)) {
+                               ret = -ENOMEM;
+                               break;
+                       }
+                       rcu_assign_pointer(sk->sk_policy[i], np);
+               }
+       }
+       rcu_read_unlock();
+       return ret;
 }
 
 static int
@@ -2198,6 +2218,7 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
        xdst = NULL;
        route = NULL;
 
+       sk = sk_const_to_full_sk(sk);
        if (sk && sk->sk_policy[XFRM_POLICY_OUT]) {
                num_pols = 1;
                pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
@@ -2477,6 +2498,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
        }
 
        pol = NULL;
+       sk = sk_to_full_sk(sk);
        if (sk && sk->sk_policy[dir]) {
                pol = xfrm_sk_policy_lookup(sk, dir, &fl);
                if (IS_ERR(pol)) {
@@ -2804,7 +2826,6 @@ static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst,
 
 int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
 {
-       struct net *net;
        int err = 0;
        if (unlikely(afinfo == NULL))
                return -EINVAL;
@@ -2835,26 +2856,6 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
        }
        spin_unlock(&xfrm_policy_afinfo_lock);
 
-       rtnl_lock();
-       for_each_net(net) {
-               struct dst_ops *xfrm_dst_ops;
-
-               switch (afinfo->family) {
-               case AF_INET:
-                       xfrm_dst_ops = &net->xfrm.xfrm4_dst_ops;
-                       break;
-#if IS_ENABLED(CONFIG_IPV6)
-               case AF_INET6:
-                       xfrm_dst_ops = &net->xfrm.xfrm6_dst_ops;
-                       break;
-#endif
-               default:
-                       BUG();
-               }
-               *xfrm_dst_ops = *afinfo->dst_ops;
-       }
-       rtnl_unlock();
-
        return err;
 }
 EXPORT_SYMBOL(xfrm_policy_register_afinfo);
@@ -2890,22 +2891,6 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
 }
 EXPORT_SYMBOL(xfrm_policy_unregister_afinfo);
 
-static void __net_init xfrm_dst_ops_init(struct net *net)
-{
-       struct xfrm_policy_afinfo *afinfo;
-
-       rcu_read_lock();
-       afinfo = rcu_dereference(xfrm_policy_afinfo[AF_INET]);
-       if (afinfo)
-               net->xfrm.xfrm4_dst_ops = *afinfo->dst_ops;
-#if IS_ENABLED(CONFIG_IPV6)
-       afinfo = rcu_dereference(xfrm_policy_afinfo[AF_INET6]);
-       if (afinfo)
-               net->xfrm.xfrm6_dst_ops = *afinfo->dst_ops;
-#endif
-       rcu_read_unlock();
-}
-
 static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
@@ -3054,7 +3039,6 @@ static int __net_init xfrm_net_init(struct net *net)
        rv = xfrm_policy_init(net);
        if (rv < 0)
                goto out_policy;
-       xfrm_dst_ops_init(net);
        rv = xfrm_sysctl_init(net);
        if (rv < 0)
                goto out_sysctl;
index 1a10d8ac81620faad519d4f95ca8552ac4a958c1..dacf71a43ad41f678e3a0574c84321bacd0ff30e 100755 (executable)
@@ -62,7 +62,7 @@ vmlinux_link()
                        -Wl,--start-group                                    \
                                 ${KBUILD_VMLINUX_MAIN}                      \
                        -Wl,--end-group                                      \
-                       -lutil ${1}
+                       -lutil -lrt ${1}
                rm -f linux
        fi
 }
index 698768bdc5815021b61814ddabc408d4310c3c0e..e167592793a70e8a1bac057d58ca7456e064db8e 100644 (file)
 
 static int fd_map;     /* File descriptor for file being modified. */
 static int mmap_failed; /* Boolean flag. */
-static void *ehdr_curr; /* current ElfXX_Ehdr *  for resource cleanup */
 static char gpfx;      /* prefix for global symbol name (sometimes '_') */
 static struct stat sb; /* Remember .st_size, etc. */
 static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */
 static const char *altmcount;  /* alternate mcount symbol name */
 static int warn_on_notrace_sect; /* warn when section has mcount not being recorded */
+static void *file_map; /* pointer of the mapped file */
+static void *file_end; /* pointer to the end of the mapped file */
+static int file_updated; /* flag to state file was changed */
+static void *file_ptr; /* current file pointer location */
+static void *file_append; /* added to the end of the file */
+static size_t file_append_size; /* how much is added to end of file */
 
 /* setjmp() return values */
 enum {
@@ -67,10 +72,14 @@ static void
 cleanup(void)
 {
        if (!mmap_failed)
-               munmap(ehdr_curr, sb.st_size);
+               munmap(file_map, sb.st_size);
        else
-               free(ehdr_curr);
-       close(fd_map);
+               free(file_map);
+       file_map = NULL;
+       free(file_append);
+       file_append = NULL;
+       file_append_size = 0;
+       file_updated = 0;
 }
 
 static void __attribute__((noreturn))
@@ -92,12 +101,22 @@ succeed_file(void)
 static off_t
 ulseek(int const fd, off_t const offset, int const whence)
 {
-       off_t const w = lseek(fd, offset, whence);
-       if (w == (off_t)-1) {
-               perror("lseek");
+       switch (whence) {
+       case SEEK_SET:
+               file_ptr = file_map + offset;
+               break;
+       case SEEK_CUR:
+               file_ptr += offset;
+               break;
+       case SEEK_END:
+               file_ptr = file_map + (sb.st_size - offset);
+               break;
+       }
+       if (file_ptr < file_map) {
+               fprintf(stderr, "lseek: seek before file\n");
                fail_file();
        }
-       return w;
+       return file_ptr - file_map;
 }
 
 static size_t
@@ -114,12 +133,38 @@ uread(int const fd, void *const buf, size_t const count)
 static size_t
 uwrite(int const fd, void const *const buf, size_t const count)
 {
-       size_t const n = write(fd, buf, count);
-       if (n != count) {
-               perror("write");
-               fail_file();
+       size_t cnt = count;
+       off_t idx = 0;
+
+       file_updated = 1;
+
+       if (file_ptr + count >= file_end) {
+               off_t aoffset = (file_ptr + count) - file_end;
+
+               if (aoffset > file_append_size) {
+                       file_append = realloc(file_append, aoffset);
+                       file_append_size = aoffset;
+               }
+               if (!file_append) {
+                       perror("write");
+                       fail_file();
+               }
+               if (file_ptr < file_end) {
+                       cnt = file_end - file_ptr;
+               } else {
+                       cnt = 0;
+                       idx = aoffset - count;
+               }
        }
-       return n;
+
+       if (cnt)
+               memcpy(file_ptr, buf, cnt);
+
+       if (cnt < count)
+               memcpy(file_append + idx, buf + cnt, count - cnt);
+
+       file_ptr += count;
+       return count;
 }
 
 static void *
@@ -192,9 +237,7 @@ static int make_nop_arm64(void *map, size_t const offset)
  */
 static void *mmap_file(char const *fname)
 {
-       void *addr;
-
-       fd_map = open(fname, O_RDWR);
+       fd_map = open(fname, O_RDONLY);
        if (fd_map < 0 || fstat(fd_map, &sb) < 0) {
                perror(fname);
                fail_file();
@@ -203,15 +246,58 @@ static void *mmap_file(char const *fname)
                fprintf(stderr, "not a regular file: %s\n", fname);
                fail_file();
        }
-       addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
-                   fd_map, 0);
+       file_map = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
+                       fd_map, 0);
        mmap_failed = 0;
-       if (addr == MAP_FAILED) {
+       if (file_map == MAP_FAILED) {
                mmap_failed = 1;
-               addr = umalloc(sb.st_size);
-               uread(fd_map, addr, sb.st_size);
+               file_map = umalloc(sb.st_size);
+               uread(fd_map, file_map, sb.st_size);
+       }
+       close(fd_map);
+
+       file_end = file_map + sb.st_size;
+
+       return file_map;
+}
+
+static void write_file(const char *fname)
+{
+       char tmp_file[strlen(fname) + 4];
+       size_t n;
+
+       if (!file_updated)
+               return;
+
+       sprintf(tmp_file, "%s.rc", fname);
+
+       /*
+        * After reading the entire file into memory, delete it
+        * and write it back, to prevent weird side effects of modifying
+        * an object file in place.
+        */
+       fd_map = open(tmp_file, O_WRONLY | O_TRUNC | O_CREAT, sb.st_mode);
+       if (fd_map < 0) {
+               perror(fname);
+               fail_file();
+       }
+       n = write(fd_map, file_map, sb.st_size);
+       if (n != sb.st_size) {
+               perror("write");
+               fail_file();
+       }
+       if (file_append_size) {
+               n = write(fd_map, file_append, file_append_size);
+               if (n != file_append_size) {
+                       perror("write");
+                       fail_file();
+               }
+       }
+       close(fd_map);
+       if (rename(tmp_file, fname) < 0) {
+               perror(fname);
+               fail_file();
        }
-       return addr;
 }
 
 /* w8rev, w8nat, ...: Handle endianness. */
@@ -318,7 +404,6 @@ do_file(char const *const fname)
        Elf32_Ehdr *const ehdr = mmap_file(fname);
        unsigned int reltype = 0;
 
-       ehdr_curr = ehdr;
        w = w4nat;
        w2 = w2nat;
        w8 = w8nat;
@@ -441,6 +526,7 @@ do_file(char const *const fname)
        }
        }  /* end switch */
 
+       write_file(fname);
        cleanup();
 }
 
@@ -493,11 +579,14 @@ main(int argc, char *argv[])
                case SJ_SETJMP:    /* normal sequence */
                        /* Avoid problems if early cleanup() */
                        fd_map = -1;
-                       ehdr_curr = NULL;
                        mmap_failed = 1;
+                       file_map = NULL;
+                       file_ptr = NULL;
+                       file_updated = 0;
                        do_file(file);
                        break;
                case SJ_FAIL:    /* error in do_file or below */
+                       fprintf(stderr, "%s: failed\n", file);
                        ++n_error;
                        break;
                case SJ_SUCCEED:    /* premature success */
index fb111eafcb893e4f5146c74a84f8499d4e1553c4..1c3872aeed14ace421a9d43fc396c43afdd5b93c 100644 (file)
@@ -751,16 +751,16 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
 
        /* the key is probably readable - now try to read it */
 can_read_key:
-       ret = key_validate(key);
-       if (ret == 0) {
-               ret = -EOPNOTSUPP;
-               if (key->type->read) {
-                       /* read the data with the semaphore held (since we
-                        * might sleep) */
-                       down_read(&key->sem);
+       ret = -EOPNOTSUPP;
+       if (key->type->read) {
+               /* Read the data with the semaphore held (since we might sleep)
+                * to protect against the key being updated or revoked.
+                */
+               down_read(&key->sem);
+               ret = key_validate(key);
+               if (ret == 0)
                        ret = key->type->read(key, buffer, buflen);
-                       up_read(&key->sem);
-               }
+               up_read(&key->sem);
        }
 
 error2:
index 963f82430938a976826074bfe41f33f286e3fbe1..3b36582970702219f0e1b28f16093b4de6425b48 100644 (file)
@@ -355,6 +355,8 @@ enum {
                                        ((pci)->device == 0x0d0c) || \
                                        ((pci)->device == 0x160c))
 
+#define IS_BROXTON(pci)        ((pci)->device == 0x5a98)
+
 static char *driver_short_names[] = {
        [AZX_DRIVER_ICH] = "HDA Intel",
        [AZX_DRIVER_PCH] = "HDA Intel PCH",
@@ -506,15 +508,36 @@ static void azx_init_pci(struct azx *chip)
         }
 }
 
+/*
+ * In BXT-P A0, HD-Audio DMA requests is later than expected,
+ * and makes an audio stream sensitive to system latencies when
+ * 24/32 bits are playing.
+ * Adjusting threshold of DMA fifo to force the DMA request
+ * sooner to improve latency tolerance at the expense of power.
+ */
+static void bxt_reduce_dma_latency(struct azx *chip)
+{
+       u32 val;
+
+       val = azx_readl(chip, SKL_EM4L);
+       val &= (0x3 << 20);
+       azx_writel(chip, SKL_EM4L, val);
+}
+
 static void hda_intel_init_chip(struct azx *chip, bool full_reset)
 {
        struct hdac_bus *bus = azx_bus(chip);
+       struct pci_dev *pci = chip->pci;
 
        if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
                snd_hdac_set_codec_wakeup(bus, true);
        azx_init_chip(chip, full_reset);
        if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
                snd_hdac_set_codec_wakeup(bus, false);
+
+       /* reduce dma latency to avoid noise */
+       if (IS_BROXTON(pci))
+               bxt_reduce_dma_latency(chip);
 }
 
 /* calculate runtime delay from LPIB */
@@ -931,6 +954,36 @@ static int azx_resume(struct device *dev)
 }
 #endif /* CONFIG_PM_SLEEP || SUPPORT_VGA_SWITCHEROO */
 
+#ifdef CONFIG_PM_SLEEP
+/* put codec down to D3 at hibernation for Intel SKL+;
+ * otherwise BIOS may still access the codec and screw up the driver
+ */
+#define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170)
+#define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70)
+#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
+#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci))
+
+static int azx_freeze_noirq(struct device *dev)
+{
+       struct pci_dev *pci = to_pci_dev(dev);
+
+       if (IS_SKL_PLUS(pci))
+               pci_set_power_state(pci, PCI_D3hot);
+
+       return 0;
+}
+
+static int azx_thaw_noirq(struct device *dev)
+{
+       struct pci_dev *pci = to_pci_dev(dev);
+
+       if (IS_SKL_PLUS(pci))
+               pci_set_power_state(pci, PCI_D0);
+
+       return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
 #ifdef CONFIG_PM
 static int azx_runtime_suspend(struct device *dev)
 {
@@ -1040,6 +1093,10 @@ static int azx_runtime_idle(struct device *dev)
 
 static const struct dev_pm_ops azx_pm = {
        SET_SYSTEM_SLEEP_PM_OPS(azx_suspend, azx_resume)
+#ifdef CONFIG_PM_SLEEP
+       .freeze_noirq = azx_freeze_noirq,
+       .thaw_noirq = azx_thaw_noirq,
+#endif
        SET_RUNTIME_PM_OPS(azx_runtime_suspend, azx_runtime_resume, azx_runtime_idle)
 };
 
index f8a12ca477f1ab775a101c8bb41876a11707477e..4ef2259f88cae3b1cf328880447dbf528ad42a95 100644 (file)
@@ -778,7 +778,8 @@ static const struct hda_pintbl alienware_pincfgs[] = {
 };
 
 static const struct snd_pci_quirk ca0132_quirks[] = {
-       SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15", QUIRK_ALIENWARE),
+       SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE),
+       SND_PCI_QUIRK(0x1028, 0x0688, "Alienware 17 2015", QUIRK_ALIENWARE),
        {}
 };
 
index 9bedf7c85e295d6dab65c04093abf7a58cab1a5a..3a89d82f805759f5c4016c47df40d1a3b5522f49 100644 (file)
@@ -67,6 +67,10 @@ enum {
        ALC_HEADSET_TYPE_OMTP,
 };
 
+enum {
+       ALC_KEY_MICMUTE_INDEX,
+};
+
 struct alc_customize_define {
        unsigned int  sku_cfg;
        unsigned char port_connectivity;
@@ -111,6 +115,7 @@ struct alc_spec {
        void (*power_hook)(struct hda_codec *codec);
 #endif
        void (*shutup)(struct hda_codec *codec);
+       void (*reboot_notify)(struct hda_codec *codec);
 
        int init_amp;
        int codec_variant;      /* flag for other variants */
@@ -122,6 +127,7 @@ struct alc_spec {
        unsigned int pll_coef_idx, pll_coef_bit;
        unsigned int coef0;
        struct input_dev *kb_dev;
+       u8 alc_mute_keycode_map[1];
 };
 
 /*
@@ -773,6 +779,25 @@ static inline void alc_shutup(struct hda_codec *codec)
                snd_hda_shutup_pins(codec);
 }
 
+static void alc_reboot_notify(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+
+       if (spec && spec->reboot_notify)
+               spec->reboot_notify(codec);
+       else
+               alc_shutup(codec);
+}
+
+/* power down codec to D3 at reboot/shutdown; set as reboot_notify ops */
+static void alc_d3_at_reboot(struct hda_codec *codec)
+{
+       snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
+       snd_hda_codec_write(codec, codec->core.afg, 0,
+                           AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+       msleep(10);
+}
+
 #define alc_free       snd_hda_gen_free
 
 #ifdef CONFIG_PM
@@ -818,7 +843,7 @@ static const struct hda_codec_ops alc_patch_ops = {
        .suspend = alc_suspend,
        .check_power_status = snd_hda_gen_check_power_status,
 #endif
-       .reboot_notify = alc_shutup,
+       .reboot_notify = alc_reboot_notify,
 };
 
 
@@ -1755,6 +1780,7 @@ enum {
        ALC889_FIXUP_MBA11_VREF,
        ALC889_FIXUP_MBA21_VREF,
        ALC889_FIXUP_MP11_VREF,
+       ALC889_FIXUP_MP41_VREF,
        ALC882_FIXUP_INV_DMIC,
        ALC882_FIXUP_NO_PRIMARY_HP,
        ALC887_FIXUP_ASUS_BASS,
@@ -1843,7 +1869,7 @@ static void alc889_fixup_mbp_vref(struct hda_codec *codec,
                                  const struct hda_fixup *fix, int action)
 {
        struct alc_spec *spec = codec->spec;
-       static hda_nid_t nids[2] = { 0x14, 0x15 };
+       static hda_nid_t nids[3] = { 0x14, 0x15, 0x19 };
        int i;
 
        if (action != HDA_FIXUP_ACT_INIT)
@@ -2133,6 +2159,12 @@ static const struct hda_fixup alc882_fixups[] = {
                .chained = true,
                .chain_id = ALC885_FIXUP_MACPRO_GPIO,
        },
+       [ALC889_FIXUP_MP41_VREF] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc889_fixup_mbp_vref,
+               .chained = true,
+               .chain_id = ALC885_FIXUP_MACPRO_GPIO,
+       },
        [ALC882_FIXUP_INV_DMIC] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_inv_dmic,
@@ -2215,7 +2247,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF),
-       SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO),
+       SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 4,1/5,1", ALC889_FIXUP_MP41_VREF),
        SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF),
@@ -3435,12 +3467,43 @@ static void gpio2_mic_hotkey_event(struct hda_codec *codec,
 
        /* GPIO2 just toggles on a keypress/keyrelease cycle. Therefore
           send both key on and key off event for every interrupt. */
-       input_report_key(spec->kb_dev, KEY_MICMUTE, 1);
+       input_report_key(spec->kb_dev, spec->alc_mute_keycode_map[ALC_KEY_MICMUTE_INDEX], 1);
        input_sync(spec->kb_dev);
-       input_report_key(spec->kb_dev, KEY_MICMUTE, 0);
+       input_report_key(spec->kb_dev, spec->alc_mute_keycode_map[ALC_KEY_MICMUTE_INDEX], 0);
        input_sync(spec->kb_dev);
 }
 
+static int alc_register_micmute_input_device(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       int i;
+
+       spec->kb_dev = input_allocate_device();
+       if (!spec->kb_dev) {
+               codec_err(codec, "Out of memory (input_allocate_device)\n");
+               return -ENOMEM;
+       }
+
+       spec->alc_mute_keycode_map[ALC_KEY_MICMUTE_INDEX] = KEY_MICMUTE;
+
+       spec->kb_dev->name = "Microphone Mute Button";
+       spec->kb_dev->evbit[0] = BIT_MASK(EV_KEY);
+       spec->kb_dev->keycodesize = sizeof(spec->alc_mute_keycode_map[0]);
+       spec->kb_dev->keycodemax = ARRAY_SIZE(spec->alc_mute_keycode_map);
+       spec->kb_dev->keycode = spec->alc_mute_keycode_map;
+       for (i = 0; i < ARRAY_SIZE(spec->alc_mute_keycode_map); i++)
+               set_bit(spec->alc_mute_keycode_map[i], spec->kb_dev->keybit);
+
+       if (input_register_device(spec->kb_dev)) {
+               codec_err(codec, "input_register_device failed\n");
+               input_free_device(spec->kb_dev);
+               spec->kb_dev = NULL;
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
 static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec,
                                             const struct hda_fixup *fix, int action)
 {
@@ -3458,20 +3521,8 @@ static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec,
        struct alc_spec *spec = codec->spec;
 
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
-               spec->kb_dev = input_allocate_device();
-               if (!spec->kb_dev) {
-                       codec_err(codec, "Out of memory (input_allocate_device)\n");
-                       return;
-               }
-               spec->kb_dev->name = "Microphone Mute Button";
-               spec->kb_dev->evbit[0] = BIT_MASK(EV_KEY);
-               spec->kb_dev->keybit[BIT_WORD(KEY_MICMUTE)] = BIT_MASK(KEY_MICMUTE);
-               if (input_register_device(spec->kb_dev)) {
-                       codec_err(codec, "input_register_device failed\n");
-                       input_free_device(spec->kb_dev);
-                       spec->kb_dev = NULL;
+               if (alc_register_micmute_input_device(codec) != 0)
                        return;
-               }
 
                snd_hda_add_verbs(codec, gpio_init);
                snd_hda_codec_write_cache(codec, codec->core.afg, 0,
@@ -3501,6 +3552,47 @@ static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec,
        }
 }
 
+static void alc233_fixup_lenovo_line2_mic_hotkey(struct hda_codec *codec,
+                                            const struct hda_fixup *fix, int action)
+{
+       /* Line2 = mic mute hotkey
+          GPIO2 = mic mute LED */
+       static const struct hda_verb gpio_init[] = {
+               { 0x01, AC_VERB_SET_GPIO_MASK, 0x04 },
+               { 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04 },
+               {}
+       };
+
+       struct alc_spec *spec = codec->spec;
+
+       if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+               if (alc_register_micmute_input_device(codec) != 0)
+                       return;
+
+               snd_hda_add_verbs(codec, gpio_init);
+               snd_hda_jack_detect_enable_callback(codec, 0x1b,
+                                                   gpio2_mic_hotkey_event);
+
+               spec->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook;
+               spec->gpio_led = 0;
+               spec->mute_led_polarity = 0;
+               spec->gpio_mic_led_mask = 0x04;
+               return;
+       }
+
+       if (!spec->kb_dev)
+               return;
+
+       switch (action) {
+       case HDA_FIXUP_ACT_PROBE:
+               spec->init_amp = ALC_INIT_DEFAULT;
+               break;
+       case HDA_FIXUP_ACT_FREE:
+               input_unregister_device(spec->kb_dev);
+               spec->kb_dev = NULL;
+       }
+}
+
 static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
                                const struct hda_fixup *fix, int action)
 {
@@ -4198,6 +4290,8 @@ static void alc_fixup_tpt440_dock(struct hda_codec *codec,
        struct alc_spec *spec = codec->spec;
 
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+               spec->shutup = alc_no_shutup; /* reduce click noise */
+               spec->reboot_notify = alc_d3_at_reboot; /* reduce noise */
                spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
                codec->power_save_node = 0; /* avoid click noises */
                snd_hda_apply_pincfgs(codec, pincfgs);
@@ -4578,6 +4672,7 @@ enum {
        ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC,
        ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
        ALC292_FIXUP_TPT440_DOCK,
+       ALC292_FIXUP_TPT440,
        ALC283_FIXUP_BXBT2807_MIC,
        ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED,
        ALC282_FIXUP_ASPIRE_V5_PINS,
@@ -4593,9 +4688,12 @@ enum {
        ALC288_FIXUP_DISABLE_AAMIX,
        ALC292_FIXUP_DELL_E7X,
        ALC292_FIXUP_DISABLE_AAMIX,
+       ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK,
        ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
        ALC275_FIXUP_DELL_XPS,
        ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE,
+       ALC293_FIXUP_LENOVO_SPK_NOISE,
+       ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -5050,6 +5148,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
        },
+       [ALC292_FIXUP_TPT440] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_disable_aamix,
+               .chained = true,
+               .chain_id = ALC292_FIXUP_TPT440_DOCK,
+       },
        [ALC283_FIXUP_BXBT2807_MIC] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
@@ -5149,6 +5253,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC269_FIXUP_DELL2_MIC_NO_PRESENCE
        },
+       [ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_disable_aamix,
+               .chained = true,
+               .chain_id = ALC293_FIXUP_DELL1_MIC_NO_PRESENCE
+       },
        [ALC292_FIXUP_DELL_E7X] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_dell_xps13,
@@ -5187,6 +5297,16 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
        },
+       [ALC293_FIXUP_LENOVO_SPK_NOISE] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_disable_aamix,
+               .chained = true,
+               .chain_id = ALC269_FIXUP_THINKPAD_ACPI
+       },
+       [ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc233_fixup_lenovo_line2_mic_hotkey,
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -5221,11 +5341,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x06c7, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x06d9, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x06da, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
-       SND_PCI_QUIRK(0x1028, 0x06db, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
-       SND_PCI_QUIRK(0x1028, 0x06dd, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
-       SND_PCI_QUIRK(0x1028, 0x06de, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
-       SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
-       SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
+       SND_PCI_QUIRK(0x1028, 0x06db, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
+       SND_PCI_QUIRK(0x1028, 0x06dd, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
+       SND_PCI_QUIRK(0x1028, 0x06de, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
+       SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
+       SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
        SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
        SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
@@ -5325,15 +5445,18 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2208, "Thinkpad T431s", ALC269_FIXUP_LENOVO_DOCK),
-       SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad T440s", ALC292_FIXUP_TPT440_DOCK),
+       SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad T440s", ALC292_FIXUP_TPT440),
        SND_PCI_QUIRK(0x17aa, 0x220e, "Thinkpad T440p", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2210, "Thinkpad T540p", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2211, "Thinkpad W541", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad T440", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad X240", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
+       SND_PCI_QUIRK(0x17aa, 0x2218, "Thinkpad X1 Carbon 2nd", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2223, "ThinkPad T550", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2226, "ThinkPad X250", ALC292_FIXUP_TPT440_DOCK),
+       SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC293_FIXUP_LENOVO_SPK_NOISE),
+       SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
        SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
        SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP),
        SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -5343,6 +5466,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x5034, "Thinkpad T450", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x5036, "Thinkpad T450s", ALC292_FIXUP_TPT440_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x503c, "Thinkpad L450", ALC292_FIXUP_TPT440_DOCK),
+       SND_PCI_QUIRK(0x17aa, 0x504b, "Thinkpad", ALC293_FIXUP_LENOVO_SPK_NOISE),
        SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
        SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
@@ -5423,6 +5547,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {.id = ALC283_FIXUP_CHROME_BOOK, .name = "alc283-dac-wcaps"},
        {.id = ALC283_FIXUP_SENSE_COMBO_JACK, .name = "alc283-sense-combo"},
        {.id = ALC292_FIXUP_TPT440_DOCK, .name = "tpt440-dock"},
+       {.id = ALC292_FIXUP_TPT440, .name = "tpt440"},
        {}
 };
 
@@ -6409,6 +6534,7 @@ static const struct hda_fixup alc662_fixups[] = {
 static const struct snd_pci_quirk alc662_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2),
        SND_PCI_QUIRK(0x1025, 0x022f, "Acer Aspire One", ALC662_FIXUP_INV_DMIC),
+       SND_PCI_QUIRK(0x1025, 0x0241, "Packard Bell DOTS", ALC662_FIXUP_INV_DMIC),
        SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
        SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x1025, 0x0349, "eMachines eM250", ALC662_FIXUP_INV_DMIC),
index 714df906249eab42c54816fed4630cc4890d7603..41c31db650390c651617530ce08b44e11a889e2f 100644 (file)
@@ -741,10 +741,11 @@ snd_rme96_playback_setrate(struct rme96 *rme96,
        {
                /* change to/from double-speed: reset the DAC (if available) */
                snd_rme96_reset_dac(rme96);
+               return 1; /* need to restore volume */
        } else {
                writel(rme96->wcreg, rme96->iobase + RME96_IO_CONTROL_REGISTER);
+               return 0;
        }
-       return 0;
 }
 
 static int
@@ -980,6 +981,7 @@ snd_rme96_playback_hw_params(struct snd_pcm_substream *substream,
        struct rme96 *rme96 = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
        int err, rate, dummy;
+       bool apply_dac_volume = false;
 
        runtime->dma_area = (void __force *)(rme96->iobase +
                                             RME96_IO_PLAY_BUFFER);
@@ -993,24 +995,26 @@ snd_rme96_playback_hw_params(struct snd_pcm_substream *substream,
        {
                 /* slave clock */
                 if ((int)params_rate(params) != rate) {
-                       spin_unlock_irq(&rme96->lock);
-                       return -EIO;                    
-                }
-       } else if ((err = snd_rme96_playback_setrate(rme96, params_rate(params))) < 0) {
-               spin_unlock_irq(&rme96->lock);
-               return err;
-       }
-       if ((err = snd_rme96_playback_setformat(rme96, params_format(params))) < 0) {
-               spin_unlock_irq(&rme96->lock);
-               return err;
+                       err = -EIO;
+                       goto error;
+               }
+       } else {
+               err = snd_rme96_playback_setrate(rme96, params_rate(params));
+               if (err < 0)
+                       goto error;
+               apply_dac_volume = err > 0; /* need to restore volume later? */
        }
+
+       err = snd_rme96_playback_setformat(rme96, params_format(params));
+       if (err < 0)
+               goto error;
        snd_rme96_setframelog(rme96, params_channels(params), 1);
        if (rme96->capture_periodsize != 0) {
                if (params_period_size(params) << rme96->playback_frlog !=
                    rme96->capture_periodsize)
                {
-                       spin_unlock_irq(&rme96->lock);
-                       return -EBUSY;
+                       err = -EBUSY;
+                       goto error;
                }
        }
        rme96->playback_periodsize =
@@ -1021,9 +1025,16 @@ snd_rme96_playback_hw_params(struct snd_pcm_substream *substream,
                rme96->wcreg &= ~(RME96_WCR_PRO | RME96_WCR_DOLBY | RME96_WCR_EMP);
                writel(rme96->wcreg |= rme96->wcreg_spdif_stream, rme96->iobase + RME96_IO_CONTROL_REGISTER);
        }
+
+       err = 0;
+ error:
        spin_unlock_irq(&rme96->lock);
-               
-       return 0;
+       if (apply_dac_volume) {
+               usleep_range(3000, 10000);
+               snd_rme96_apply_dac_volume(rme96);
+       }
+
+       return err;
 }
 
 static int
index b3ea24d64c5009cf4cc77e1877c894e3f21f4ee7..93b400800905d2fee18b066f11761cca524d9369 100644 (file)
@@ -1537,7 +1537,7 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
        bool reconfig;
        unsigned int aif_tx_state, aif_rx_state;
 
-       if (params_rate(params) % 8000)
+       if (params_rate(params) % 4000)
                rates = &arizona_44k1_bclk_rates[0];
        else
                rates = &arizona_48k_bclk_rates[0];
index 84f5eb07a91b1d27274f595cf595d97f36663484..afa6c5db9dccc9b00f049f8421b04e3091a1bcfc 100644 (file)
@@ -85,7 +85,15 @@ static const DECLARE_TLV_DB_SCALE(pga_tlv, 0, 300, 0);
 static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
 static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 300, 0);
 
-static const int deemph_settings[] = { 0, 32000, 44100, 48000 };
+static const struct {
+       int rate;
+       unsigned int val;
+} deemph_settings[] = {
+       { 0,     ES8328_DACCONTROL6_DEEMPH_OFF },
+       { 32000, ES8328_DACCONTROL6_DEEMPH_32k },
+       { 44100, ES8328_DACCONTROL6_DEEMPH_44_1k },
+       { 48000, ES8328_DACCONTROL6_DEEMPH_48k },
+};
 
 static int es8328_set_deemph(struct snd_soc_codec *codec)
 {
@@ -97,21 +105,22 @@ static int es8328_set_deemph(struct snd_soc_codec *codec)
         * rate.
         */
        if (es8328->deemph) {
-               best = 1;
-               for (i = 2; i < ARRAY_SIZE(deemph_settings); i++) {
-                       if (abs(deemph_settings[i] - es8328->playback_fs) <
-                           abs(deemph_settings[best] - es8328->playback_fs))
+               best = 0;
+               for (i = 1; i < ARRAY_SIZE(deemph_settings); i++) {
+                       if (abs(deemph_settings[i].rate - es8328->playback_fs) <
+                           abs(deemph_settings[best].rate - es8328->playback_fs))
                                best = i;
                }
 
-               val = best << 1;
+               val = deemph_settings[best].val;
        } else {
-               val = 0;
+               val = ES8328_DACCONTROL6_DEEMPH_OFF;
        }
 
        dev_dbg(codec->dev, "Set deemphasis %d\n", val);
 
-       return snd_soc_update_bits(codec, ES8328_DACCONTROL6, 0x6, val);
+       return snd_soc_update_bits(codec, ES8328_DACCONTROL6,
+                       ES8328_DACCONTROL6_DEEMPH_MASK, val);
 }
 
 static int es8328_get_deemph(struct snd_kcontrol *kcontrol,
index cb36afe10c0ecdf0b51183bea6eb8446e01271d3..156c748c89c7e55d86421b27522b22f9b16d6f76 100644 (file)
@@ -153,6 +153,7 @@ int es8328_probe(struct device *dev, struct regmap *regmap);
 #define ES8328_DACCONTROL6_CLICKFREE (1 << 3)
 #define ES8328_DACCONTROL6_DAC_INVR (1 << 4)
 #define ES8328_DACCONTROL6_DAC_INVL (1 << 5)
+#define ES8328_DACCONTROL6_DEEMPH_MASK (3 << 6)
 #define ES8328_DACCONTROL6_DEEMPH_OFF (0 << 6)
 #define ES8328_DACCONTROL6_DEEMPH_32k (1 << 6)
 #define ES8328_DACCONTROL6_DEEMPH_44_1k (2 << 6)
index ef76940f9dcb63196b10798f80d54528adc6109d..3e3c7f6be29d9a463f3b07bdefa78e0f2f29ace2 100644 (file)
@@ -1667,9 +1667,13 @@ static int rt5645_spk_event(struct snd_soc_dapm_widget *w,
                        RT5645_PWR_CLS_D_L,
                        RT5645_PWR_CLS_D | RT5645_PWR_CLS_D_R |
                        RT5645_PWR_CLS_D_L);
+               snd_soc_update_bits(codec, RT5645_GEN_CTRL3,
+                       RT5645_DET_CLK_MASK, RT5645_DET_CLK_MODE1);
                break;
 
        case SND_SOC_DAPM_PRE_PMD:
+               snd_soc_update_bits(codec, RT5645_GEN_CTRL3,
+                       RT5645_DET_CLK_MASK, RT5645_DET_CLK_DIS);
                snd_soc_write(codec, RT5645_EQ_CTRL2, 0);
                snd_soc_update_bits(codec, RT5645_PWR_DIG1,
                        RT5645_PWR_CLS_D | RT5645_PWR_CLS_D_R |
index 093e46d559fbab24aa05efc5c74a2e8488fa49d0..205e0715c99abad45e771c0504b92a512f5b6adf 100644 (file)
@@ -2122,6 +2122,10 @@ enum {
 /* General Control3 (0xfc) */
 #define RT5645_JD_PSV_MODE                     (0x1 << 12)
 #define RT5645_IRQ_CLK_GATE_CTRL               (0x1 << 11)
+#define RT5645_DET_CLK_MASK                    (0x3 << 9)
+#define RT5645_DET_CLK_DIS                     (0x0 << 9)
+#define RT5645_DET_CLK_MODE1                   (0x1 << 9)
+#define RT5645_DET_CLK_MODE2                   (0x2 << 9)
 #define RT5645_MICINDET_MANU                   (0x1 << 7)
 #define RT5645_RING2_SLEEVE_GND                        (0x1 << 5)
 
index f540f82b1f271ec4833d9ea43aa7f4567c0df712..08b40460663c2f28bd450261889cd365116f0bf9 100644 (file)
@@ -189,6 +189,7 @@ static int power_vag_event(struct snd_soc_dapm_widget *w,
        case SND_SOC_DAPM_POST_PMU:
                snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
                        SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP);
+               msleep(400);
                break;
 
        case SND_SOC_DAPM_PRE_PMD:
index 0a60677397b3dedb0b9652e112137e9b3c03f3d4..4c29bd2ae75cf987b34e28e28298ab026bb8c40e 100644 (file)
@@ -574,6 +574,7 @@ static const struct regmap_config wm8974_regmap = {
        .max_register = WM8974_MONOMIX,
        .reg_defaults = wm8974_reg_defaults,
        .num_reg_defaults = ARRAY_SIZE(wm8974_reg_defaults),
+       .cache_type = REGCACHE_FLAT,
 };
 
 static int wm8974_probe(struct snd_soc_codec *codec)
index c1c9c2e3525bf88f8cf6de409fcc9370320dd3b2..2ccb8bccc9d4cc4a79c6a94abe4dfb1566872737 100644 (file)
@@ -223,8 +223,8 @@ static void mcasp_start_tx(struct davinci_mcasp *mcasp)
 
        /* wait for XDATA to be cleared */
        cnt = 0;
-       while (!(mcasp_get_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG) &
-                ~XRDATA) && (cnt < 100000))
+       while ((mcasp_get_reg(mcasp, DAVINCI_MCASP_TXSTAT_REG) & XRDATA) &&
+              (cnt < 100000))
                cnt++;
 
        /* Release TX state machine */
index ffd5f9acc849ffb3d8152bdfa1e5c13a26342668..08b460ba06efc28906fe1094e9e68b7c4e1e66cf 100644 (file)
@@ -505,6 +505,24 @@ static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
                                           FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
                        regmap_update_bits(sai->regmap, FSL_SAI_RCSR,
                                           FSL_SAI_CSR_FR, FSL_SAI_CSR_FR);
+
+                       /*
+                        * For sai master mode, after several open/close sai,
+                        * there will be no frame clock, and can't recover
+                        * anymore. Add software reset to fix this issue.
+                        * This is a hardware bug, and will be fix in the
+                        * next sai version.
+                        */
+                       if (!sai->is_slave_mode) {
+                               /* Software Reset for both Tx and Rx */
+                               regmap_write(sai->regmap,
+                                            FSL_SAI_TCSR, FSL_SAI_CSR_SR);
+                               regmap_write(sai->regmap,
+                                            FSL_SAI_RCSR, FSL_SAI_CSR_SR);
+                               /* Clear SR bit to finish the reset */
+                               regmap_write(sai->regmap, FSL_SAI_TCSR, 0);
+                               regmap_write(sai->regmap, FSL_SAI_RCSR, 0);
+                       }
                }
                break;
        default:
index ffea427aeca8eab29809f049c53ba27f71b54393..ad4d0f82603e7f65292a6c02530d66413a80ca91 100644 (file)
@@ -1240,7 +1240,6 @@ int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus)
         */
        ret = snd_soc_tplg_component_load(&platform->component,
                                        &skl_tplg_ops, fw, 0);
-       release_firmware(fw);
        if (ret < 0) {
                dev_err(bus->dev, "tplg component load failed%d\n", ret);
                return -EINVAL;
@@ -1249,5 +1248,7 @@ int skl_tplg_init(struct snd_soc_platform *platform, struct hdac_ext_bus *ebus)
        skl->resource.max_mcps = SKL_MAX_MCPS;
        skl->resource.max_mem = SKL_FW_MAX_MEM;
 
+       skl->tplg = fw;
+
        return 0;
 }
index 5319529aedf7ae5030dbf47ce9b6056512f05c2d..caa69c4598a6f14eb27c91575b49aae9fd7d3e8a 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/pci.h>
 #include <linux/pm_runtime.h>
 #include <linux/platform_device.h>
+#include <linux/firmware.h>
 #include <sound/pcm.h>
 #include "skl.h"
 
@@ -520,6 +521,9 @@ static void skl_remove(struct pci_dev *pci)
        struct hdac_ext_bus *ebus = pci_get_drvdata(pci);
        struct skl *skl = ebus_to_skl(ebus);
 
+       if (skl->tplg)
+               release_firmware(skl->tplg);
+
        if (pci_dev_run_wake(pci))
                pm_runtime_get_noresume(&pci->dev);
        pci_dev_put(pci);
index dd2e79ae45a8e6294c2766ef5eff7f4fac37befe..a0709e344d4419f4a37d28636cc3c79f368acd36 100644 (file)
@@ -68,6 +68,8 @@ struct skl {
        struct skl_dsp_resource resource;
        struct list_head ppl_list;
        struct list_head dapm_path_list;
+
+       const struct firmware *tplg;
 };
 
 #define skl_to_ebus(s) (&(s)->ebus)
index ac72ff5055bbce626550c4fd277a96c351321b25..5a806da89f42b49967ea52d15eac0f3348b7b873 100644 (file)
@@ -152,8 +152,10 @@ static int rk_spdif_trigger(struct snd_pcm_substream *substream,
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                ret = regmap_update_bits(spdif->regmap, SPDIF_DMACR,
-                                  SPDIF_DMACR_TDE_ENABLE,
-                                  SPDIF_DMACR_TDE_ENABLE);
+                                  SPDIF_DMACR_TDE_ENABLE |
+                                  SPDIF_DMACR_TDL_MASK,
+                                  SPDIF_DMACR_TDE_ENABLE |
+                                  SPDIF_DMACR_TDL(16));
 
                if (ret != 0)
                        return ret;
index 921b4095fb92c98d7b09fb8d7ec8bbea7f9139bb..3ef12770ae124d705d59b1916e5c400210aa0bf5 100644 (file)
@@ -42,7 +42,7 @@
 
 #define SPDIF_DMACR_TDL_SHIFT  0
 #define SPDIF_DMACR_TDL(x)     ((x) << SPDIF_DMACR_TDL_SHIFT)
-#define SPDIF_DMACR_TDL_MASK   (0x1f << SDPIF_DMACR_TDL_SHIFT)
+#define SPDIF_DMACR_TDL_MASK   (0x1f << SPDIF_DMACR_TDL_SHIFT)
 
 /*
  * XFER
index f494dced3c11e3a662b93d95df9ea53ff2767dfc..4f85757009b3e44e2246cc21f4387d0948056da3 100644 (file)
@@ -1354,6 +1354,8 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
                }
        }
 
+       snd_usb_mixer_fu_apply_quirk(state->mixer, cval, unitid, kctl);
+
        range = (cval->max - cval->min) / cval->res;
        /*
         * Are there devices with volume range more than 255? I use a bit more
index 6a803eff87f71110049d9c39cb07025d2c64d828..ddca6547399b0103b37abbdf73cfa5c9e710a7fd 100644 (file)
@@ -348,13 +348,6 @@ static struct usbmix_name_map bose_companion5_map[] = {
        { 0 }   /* terminator */
 };
 
-/* Dragonfly DAC 1.2, the dB conversion factor is 1 instead of 256 */
-static struct usbmix_dB_map dragonfly_1_2_dB = {0, 5000};
-static struct usbmix_name_map dragonfly_1_2_map[] = {
-       { 7, NULL, .dB = &dragonfly_1_2_dB },
-       { 0 }   /* terminator */
-};
-
 /*
  * Control map entries
  */
@@ -470,11 +463,6 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
                .id = USB_ID(0x05a7, 0x1020),
                .map = bose_companion5_map,
        },
-       {
-               /* Dragonfly DAC 1.2 */
-               .id = USB_ID(0x21b4, 0x0081),
-               .map = dragonfly_1_2_map,
-       },
        { 0 } /* terminator */
 };
 
index fe91184ce83247d8b0360bab09e94c8f7cb720d8..0ce888dceed0ea24db7b677eeb93b05c728ab40a 100644 (file)
@@ -37,6 +37,7 @@
 #include <sound/control.h>
 #include <sound/hwdep.h>
 #include <sound/info.h>
+#include <sound/tlv.h>
 
 #include "usbaudio.h"
 #include "mixer.h"
@@ -1825,3 +1826,39 @@ void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer,
        }
 }
 
+static void snd_dragonfly_quirk_db_scale(struct usb_mixer_interface *mixer,
+                                        struct snd_kcontrol *kctl)
+{
+       /* Approximation using 10 ranges based on output measurement on hw v1.2.
+        * This seems close to the cubic mapping e.g. alsamixer uses. */
+       static const DECLARE_TLV_DB_RANGE(scale,
+                0,  1, TLV_DB_MINMAX_ITEM(-5300, -4970),
+                2,  5, TLV_DB_MINMAX_ITEM(-4710, -4160),
+                6,  7, TLV_DB_MINMAX_ITEM(-3884, -3710),
+                8, 14, TLV_DB_MINMAX_ITEM(-3443, -2560),
+               15, 16, TLV_DB_MINMAX_ITEM(-2475, -2324),
+               17, 19, TLV_DB_MINMAX_ITEM(-2228, -2031),
+               20, 26, TLV_DB_MINMAX_ITEM(-1910, -1393),
+               27, 31, TLV_DB_MINMAX_ITEM(-1322, -1032),
+               32, 40, TLV_DB_MINMAX_ITEM(-968, -490),
+               41, 50, TLV_DB_MINMAX_ITEM(-441, 0),
+       );
+
+       usb_audio_info(mixer->chip, "applying DragonFly dB scale quirk\n");
+       kctl->tlv.p = scale;
+       kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
+       kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
+}
+
+void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer,
+                                 struct usb_mixer_elem_info *cval, int unitid,
+                                 struct snd_kcontrol *kctl)
+{
+       switch (mixer->chip->usb_id) {
+       case USB_ID(0x21b4, 0x0081): /* AudioQuest DragonFly */
+               if (unitid == 7 && cval->min == 0 && cval->max == 50)
+                       snd_dragonfly_quirk_db_scale(mixer, kctl);
+               break;
+       }
+}
+
index bdbfab093816a59772353635fd38eae79ddb3b38..177c329cd4ddb792e144f4ecd945976e6ab9b1a4 100644 (file)
@@ -9,5 +9,9 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
 void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer,
                                    int unitid);
 
+void snd_usb_mixer_fu_apply_quirk(struct usb_mixer_interface *mixer,
+                                 struct usb_mixer_elem_info *cval, int unitid,
+                                 struct snd_kcontrol *kctl);
+
 #endif /* SND_USB_MIXER_QUIRKS_H */
 
index 7016ad8981873ca046000d631ac112c12ed62dc1..b6c0c8e3b450c5f0dd41ea308f61efe15b3446b8 100644 (file)
@@ -1125,6 +1125,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
        case USB_ID(0x045E, 0x0779): /* MS Lifecam HD-3000 */
        case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
        case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */
+       case USB_ID(0x21B4, 0x0081): /* AudioQuest DragonFly */
                return true;
        }
        return false;
index 918b4de29de4ea86fc27cd40db49861618869d34..6419f57b08507ccea527f98bd050e41ead204b9b 100644 (file)
@@ -110,7 +110,7 @@ int cmd_buildid_list(int argc, const char **argv,
        setup_pager();
 
        if (show_kernel)
-               return sysfs__fprintf_build_id(stdout);
+               return !(sysfs__fprintf_build_id(stdout) > 0);
 
        return perf_session__list_build_ids(force, with_hits);
 }
index fa9eb92c9e24a477e45623c1017a2791fc68dd07..81def6c3f24bf16397c8e15d26178cd4957bd86f 100644 (file)
@@ -298,6 +298,9 @@ static bool hist_browser__toggle_fold(struct hist_browser *browser)
        struct callchain_list *cl = container_of(ms, struct callchain_list, ms);
        bool has_children;
 
+       if (!he || !ms)
+               return false;
+
        if (ms == &he->ms)
                has_children = hist_entry__toggle_fold(he);
        else
@@ -928,6 +931,8 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser)
        }
 
        ui_browser__hists_init_top(browser);
+       hb->he_selection = NULL;
+       hb->selection = NULL;
 
        for (nd = browser->top; nd; nd = rb_next(nd)) {
                struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
@@ -1033,6 +1038,9 @@ static void ui_browser__hists_seek(struct ui_browser *browser,
         * and stop when we printed enough lines to fill the screen.
         */
 do_offset:
+       if (!nd)
+               return;
+
        if (offset > 0) {
                do {
                        h = rb_entry(nd, struct hist_entry, rb_node);
index 217b5a60e2ab0e000fbd4ff75445665d08833ba6..6a7e273a514a642b30a477c3119696dc7fa09975 100644 (file)
@@ -91,7 +91,7 @@ int build_id__sprintf(const u8 *build_id, int len, char *bf)
                bid += 2;
        }
 
-       return raw - build_id;
+       return (bid - bf) + 1;
 }
 
 int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id)
index e48d9da757078f0c35afae590ce87ac7892dafab..6fc8cd753e1a7dc791e1e165c0808d8fd509e3de 100644 (file)
@@ -124,6 +124,10 @@ struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
                .symbol = "dummy",
                .alias  = "",
        },
+       [PERF_COUNT_SW_BPF_OUTPUT] = {
+               .symbol = "bpf-output",
+               .alias  = "",
+       },
 };
 
 #define __PERF_EVENT_FIELD(config, name) \
@@ -1879,7 +1883,7 @@ restart:
 
        for (i = 0; i < max; i++, syms++) {
 
-               if (event_glob != NULL &&
+               if (event_glob != NULL && syms->symbol != NULL &&
                    !(strglobmatch(syms->symbol, event_glob) ||
                      (syms->alias && strglobmatch(syms->alias, event_glob))))
                        continue;
index 0a3da64638ceda0e94df98f9651fc241ae1f34c1..4db7d5691ba71b33d2bda8c85d634fe3781ae6d6 100644 (file)
@@ -110,4 +110,10 @@ static inline void free_page(unsigned long addr)
        (void) (&_min1 == &_min2);              \
        _min1 < _min2 ? _min1 : _min2; })
 
+/* TODO: empty stubs for now. Broken but enough for virtio_ring.c */
+#define list_add_tail(a, b) do {} while (0)
+#define list_del(a) do {} while (0)
+#define list_for_each_entry(a, b, c) while (0)
+/* end of stubs */
+
 #endif /* KERNEL_H */
index a3e07016a44017c8c9f25c5dd51e77a09152e127..ee125e714053a91a76658d417a46232349927450 100644 (file)
@@ -3,12 +3,6 @@
 #include <linux/scatterlist.h>
 #include <linux/kernel.h>
 
-/* TODO: empty stubs for now. Broken but enough for virtio_ring.c */
-#define list_add_tail(a, b) do {} while (0)
-#define list_del(a) do {} while (0)
-#define list_for_each_entry(a, b, c) while (0)
-/* end of stubs */
-
 struct virtio_device {
        void *dev;
        u64 features;
index 806d683ab10789a659edfe1c96d15bb08e107356..57a6964a1e355b8daa154adff9bd007c93f8374f 100644 (file)
@@ -40,33 +40,39 @@ static inline void __virtio_clear_bit(struct virtio_device *vdev,
 #define virtio_has_feature(dev, feature) \
        (__virtio_test_bit((dev), feature))
 
+static inline bool virtio_is_little_endian(struct virtio_device *vdev)
+{
+       return virtio_has_feature(vdev, VIRTIO_F_VERSION_1) ||
+               virtio_legacy_is_little_endian();
+}
+
+/* Memory accessors */
 static inline u16 virtio16_to_cpu(struct virtio_device *vdev, __virtio16 val)
 {
-       return __virtio16_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
+       return __virtio16_to_cpu(virtio_is_little_endian(vdev), val);
 }
 
 static inline __virtio16 cpu_to_virtio16(struct virtio_device *vdev, u16 val)
 {
-       return __cpu_to_virtio16(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
+       return __cpu_to_virtio16(virtio_is_little_endian(vdev), val);
 }
 
 static inline u32 virtio32_to_cpu(struct virtio_device *vdev, __virtio32 val)
 {
-       return __virtio32_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
+       return __virtio32_to_cpu(virtio_is_little_endian(vdev), val);
 }
 
 static inline __virtio32 cpu_to_virtio32(struct virtio_device *vdev, u32 val)
 {
-       return __cpu_to_virtio32(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
+       return __cpu_to_virtio32(virtio_is_little_endian(vdev), val);
 }
 
 static inline u64 virtio64_to_cpu(struct virtio_device *vdev, __virtio64 val)
 {
-       return __virtio64_to_cpu(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
+       return __virtio64_to_cpu(virtio_is_little_endian(vdev), val);
 }
 
 static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val)
 {
-       return __cpu_to_virtio64(virtio_has_feature(vdev, VIRTIO_F_VERSION_1), val);
+       return __cpu_to_virtio64(virtio_is_little_endian(vdev), val);
 }
-
index 65461f821a75a7ffd3d0bdab471052e7061c8824..7a2f449bd85d02d7f6571fa4f5b3091df81a04d9 100644 (file)
@@ -1114,7 +1114,7 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, struct irq_phys_map *map)
                        return true;
        }
 
-       return dist_active_irq(vcpu);
+       return vgic_irq_is_active(vcpu, map->virt_irq);
 }
 
 /*